diff options
author | Neil Alexander <neilalexander@users.noreply.github.com> | 2022-11-15 15:05:23 +0000 |
---|---|---|
committer | Neil Alexander <neilalexander@users.noreply.github.com> | 2022-11-15 15:05:23 +0000 |
commit | 6650712a1c0dec282b47b7ba14bc8c2e06a385d8 (patch) | |
tree | 12ca755c5c33d3489417f9355dda3f1b7983c779 /setup | |
parent | f4ee3977340c84d321767d347795b1dcd05ac459 (diff) |
Federation fixes for virtual hosting
Diffstat (limited to 'setup')
-rw-r--r-- | setup/base/base.go | 7 | ||||
-rw-r--r-- | setup/config/config.go | 15 | ||||
-rw-r--r-- | setup/config/config_global.go | 82 | ||||
-rw-r--r-- | setup/mscs/msc2836/msc2836.go | 6 | ||||
-rw-r--r-- | setup/mscs/msc2946/msc2946.go | 2 |
5 files changed, 101 insertions, 11 deletions
diff --git a/setup/base/base.go b/setup/base/base.go index 2e3a3a19..14edadd9 100644 --- a/setup/base/base.go +++ b/setup/base/base.go @@ -364,10 +364,10 @@ func (b *BaseDendrite) CreateClient() *gomatrixserverlib.Client { // CreateFederationClient creates a new federation client. Should only be called // once per component. func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationClient { + identities := b.Cfg.Global.SigningIdentities() if b.Cfg.Global.DisableFederation { return gomatrixserverlib.NewFederationClient( - b.Cfg.Global.ServerName, b.Cfg.Global.KeyID, b.Cfg.Global.PrivateKey, - gomatrixserverlib.WithTransport(noOpHTTPTransport), + identities, gomatrixserverlib.WithTransport(noOpHTTPTransport), ) } opts := []gomatrixserverlib.ClientOption{ @@ -379,8 +379,7 @@ func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationCli opts = append(opts, gomatrixserverlib.WithDNSCache(b.DNSCache)) } client := gomatrixserverlib.NewFederationClient( - b.Cfg.Global.ServerName, b.Cfg.Global.KeyID, - b.Cfg.Global.PrivateKey, opts..., + identities, opts..., ) client.SetUserAgent(fmt.Sprintf("Dendrite/%s", internal.VersionString())) return client diff --git a/setup/config/config.go b/setup/config/config.go index e99852ec..918bcbe3 100644 --- a/setup/config/config.go +++ b/setup/config/config.go @@ -231,6 +231,21 @@ func loadConfig( return nil, err } + for _, v := range c.Global.VirtualHosts { + if v.KeyValidityPeriod == 0 { + v.KeyValidityPeriod = c.Global.KeyValidityPeriod + } + if v.PrivateKeyPath == "" { + v.KeyID = c.Global.KeyID + v.PrivateKey = c.Global.PrivateKey + continue + } + privateKeyPath := absPath(basePath, v.PrivateKeyPath) + if v.KeyID, v.PrivateKey, err = LoadMatrixKey(privateKeyPath, readFile); err != nil { + return nil, err + } + } + for _, key := range c.Global.OldVerifyKeys { switch { case key.PrivateKeyPath != "": diff --git a/setup/config/config_global.go b/setup/config/config_global.go index 82577282..f2fdd021 100644 --- a/setup/config/config_global.go +++ b/setup/config/config_global.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "math/rand" "strconv" "strings" @@ -15,7 +16,7 @@ type Global struct { ServerName gomatrixserverlib.ServerName `yaml:"server_name"` // The secondary server names, used for virtual hosting. - SecondaryServerNames []gomatrixserverlib.ServerName `yaml:"-"` + VirtualHosts []*VirtualHost `yaml:"virtual_hosts"` // Path to the private key which will be used to sign requests and events. PrivateKeyPath Path `yaml:"private_key"` @@ -114,6 +115,10 @@ func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) { checkNotEmpty(configErrs, "global.server_name", string(c.ServerName)) checkNotEmpty(configErrs, "global.private_key", string(c.PrivateKeyPath)) + for _, v := range c.VirtualHosts { + v.Verify(configErrs) + } + c.JetStream.Verify(configErrs, isMonolith) c.Metrics.Verify(configErrs, isMonolith) c.Sentry.Verify(configErrs, isMonolith) @@ -127,14 +132,85 @@ func (c *Global) IsLocalServerName(serverName gomatrixserverlib.ServerName) bool if c.ServerName == serverName { return true } - for _, secondaryName := range c.SecondaryServerNames { - if secondaryName == serverName { + for _, v := range c.VirtualHosts { + if v.ServerName == serverName { return true } } return false } +func (c *Global) SplitLocalID(sigil byte, id string) (string, gomatrixserverlib.ServerName, error) { + u, s, err := gomatrixserverlib.SplitID(sigil, id) + if err != nil { + return u, s, err + } + if !c.IsLocalServerName(s) { + return u, s, fmt.Errorf("server name %q not known", s) + } + return u, s, nil +} + +func (c *Global) SigningIdentityFor(serverName gomatrixserverlib.ServerName) (*gomatrixserverlib.SigningIdentity, error) { + for _, id := range c.SigningIdentities() { + if id.ServerName == serverName { + return id, nil + } + } + return nil, fmt.Errorf("no signing identity %q", serverName) +} + +func (c *Global) SigningIdentities() []*gomatrixserverlib.SigningIdentity { + identities := make([]*gomatrixserverlib.SigningIdentity, 0, len(c.VirtualHosts)+1) + identities = append(identities, &gomatrixserverlib.SigningIdentity{ + ServerName: c.ServerName, + KeyID: c.KeyID, + PrivateKey: c.PrivateKey, + }) + for _, v := range c.VirtualHosts { + identities = append(identities, v.SigningIdentity()) + } + return identities +} + +type VirtualHost struct { + // The server name of the virtual host. + ServerName gomatrixserverlib.ServerName `yaml:"server_name"` + + // The key ID of the private key. If not specified, the default global key ID + // will be used instead. + KeyID gomatrixserverlib.KeyID `yaml:"key_id"` + + // Path to the private key. If not specified, the default global private key + // will be used instead. + PrivateKeyPath Path `yaml:"private_key"` + + // The private key itself. + PrivateKey ed25519.PrivateKey `yaml:"-"` + + // How long a remote server can cache our server key for before requesting it again. + // Increasing this number will reduce the number of requests made by remote servers + // for our key, but increases the period a compromised key will be considered valid + // by remote servers. + // Defaults to 24 hours. + KeyValidityPeriod time.Duration `yaml:"key_validity_period"` + + // Is registration enabled on this virtual host? + AllowRegistration bool `json:"allow_registration"` +} + +func (v *VirtualHost) Verify(configErrs *ConfigErrors) { + checkNotEmpty(configErrs, "virtual_host.*.server_name", string(v.ServerName)) +} + +func (v *VirtualHost) SigningIdentity() *gomatrixserverlib.SigningIdentity { + return &gomatrixserverlib.SigningIdentity{ + ServerName: v.ServerName, + KeyID: v.KeyID, + PrivateKey: v.PrivateKey, + } +} + type OldVerifyKeys struct { // Path to the private key. PrivateKeyPath Path `yaml:"private_key"` diff --git a/setup/mscs/msc2836/msc2836.go b/setup/mscs/msc2836/msc2836.go index 98502f5c..bc369c16 100644 --- a/setup/mscs/msc2836/msc2836.go +++ b/setup/mscs/msc2836/msc2836.go @@ -397,7 +397,7 @@ func (rc *reqCtx) includeChildren(db Database, parentID string, limit int, recen serversToQuery := rc.getServersForEventID(parentID) var result *MSC2836EventRelationshipsResponse for _, srv := range serversToQuery { - res, err := rc.fsAPI.MSC2836EventRelationships(rc.ctx, srv, gomatrixserverlib.MSC2836EventRelationshipsRequest{ + res, err := rc.fsAPI.MSC2836EventRelationships(rc.ctx, rc.serverName, srv, gomatrixserverlib.MSC2836EventRelationshipsRequest{ EventID: parentID, Direction: "down", Limit: 100, @@ -484,7 +484,7 @@ func walkThread( // MSC2836EventRelationships performs an /event_relationships request to a remote server func (rc *reqCtx) MSC2836EventRelationships(eventID string, srv gomatrixserverlib.ServerName, ver gomatrixserverlib.RoomVersion) (*MSC2836EventRelationshipsResponse, error) { - res, err := rc.fsAPI.MSC2836EventRelationships(rc.ctx, srv, gomatrixserverlib.MSC2836EventRelationshipsRequest{ + res, err := rc.fsAPI.MSC2836EventRelationships(rc.ctx, rc.serverName, srv, gomatrixserverlib.MSC2836EventRelationshipsRequest{ EventID: eventID, DepthFirst: rc.req.DepthFirst, Direction: rc.req.Direction, @@ -665,7 +665,7 @@ func (rc *reqCtx) injectResponseToRoomserver(res *MSC2836EventRelationshipsRespo }) } // we've got the data by this point so use a background context - err := roomserver.SendInputRoomEvents(context.Background(), rc.rsAPI, ires, false) + err := roomserver.SendInputRoomEvents(context.Background(), rc.rsAPI, rc.serverName, ires, false) if err != nil { util.GetLogger(rc.ctx).WithError(err).Error("failed to inject MSC2836EventRelationshipsResponse into the roomserver") } diff --git a/setup/mscs/msc2946/msc2946.go b/setup/mscs/msc2946/msc2946.go index d7c02254..56c06359 100644 --- a/setup/mscs/msc2946/msc2946.go +++ b/setup/mscs/msc2946/msc2946.go @@ -433,7 +433,7 @@ func (w *walker) federatedRoomInfo(roomID string, vias []string) *gomatrixserver if serverName == string(w.thisServer) { continue } - res, err := w.fsAPI.MSC2946Spaces(ctx, gomatrixserverlib.ServerName(serverName), roomID, w.suggestedOnly) + res, err := w.fsAPI.MSC2946Spaces(ctx, w.thisServer, gomatrixserverlib.ServerName(serverName), roomID, w.suggestedOnly) if err != nil { util.GetLogger(w.ctx).WithError(err).Warnf("failed to call MSC2946Spaces on server %s", serverName) continue |