From 7d6461dd3c4429303148a115d72b1b3b0ebaba72 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 27 May 2020 10:19:24 +0100 Subject: [PATCH] Server key component (#1050) * Server key API (works for monolith but not for polylith yet) * Re-enable caching on server key API component * Groundwork for HTTP APIs for server key API * Hopefully implement HTTP for server key API * Simplify public key request marshalling from map keys * Update gomatrixserverlib * go mod tidy * Common -> internal * remove keyring.go * Update Docker Hub for server key API * YAML is funny about indentation * Wire in new server key API into hybrid monolith mode * Create maps * Route server key API endpoints on internal API mux * Fix server key API URLs * Add fetcher behaviour into server key API implementation * Return error if we failed to fetch some keys * Return results anyway * Move things about a bit * Remove unused code * Fix comments, don't use federation sender URL in polylith mode * Add server_key_api to sample config * Review comments * HTTP API to cache keys that have been requested * Overwrite server_key_api listen in monolith hybrid mode --- build/docker/hub/config/dendrite-config.yaml | 2 + build/docker/hub/docker-compose.polylith.yml | 13 +- build/docker/hub/images-build.sh | 25 ++-- cmd/dendrite-client-api-server/main.go | 8 +- cmd/dendrite-demo-libp2p/main.go | 32 +++-- cmd/dendrite-demo-libp2p/mdnslistener.go | 3 +- cmd/dendrite-federation-api-server/main.go | 9 +- cmd/dendrite-federation-sender-server/main.go | 9 +- cmd/dendrite-monolith-server/main.go | 19 ++- cmd/dendrite-room-server/main.go | 6 +- cmd/dendrite-server-key-api-server/main.go | 32 +++++ cmd/dendritejs/main.go | 8 +- dendrite-config.yaml | 3 +- go.mod | 2 +- go.sum | 4 +- internal/basecomponent/base.go | 40 +++---- internal/config/config.go | 12 ++ internal/keydb/keyring.go | 74 ------------ serverkeyapi/api/api.go | 113 ++++++++++++++++++ serverkeyapi/api/http.go | 57 +++++++++ serverkeyapi/internal/api.go | 76 ++++++++++++ serverkeyapi/internal/http.go | 60 ++++++++++ serverkeyapi/serverkeyapi.go | 83 +++++++++++++ .../storage}/cache/keydb.go | 5 +- .../storage}/interface.go | 2 +- .../keydb => serverkeyapi/storage}/keydb.go | 6 +- .../storage}/keydb_wasm.go | 8 +- .../storage}/postgres/keydb.go | 0 .../storage}/postgres/server_key_table.go | 0 .../storage}/sqlite3/keydb.go | 0 .../storage}/sqlite3/server_key_table.go | 0 31 files changed, 542 insertions(+), 169 deletions(-) create mode 100644 cmd/dendrite-server-key-api-server/main.go delete mode 100644 internal/keydb/keyring.go create mode 100644 serverkeyapi/api/api.go create mode 100644 serverkeyapi/api/http.go create mode 100644 serverkeyapi/internal/api.go create mode 100644 serverkeyapi/internal/http.go create mode 100644 serverkeyapi/serverkeyapi.go rename {internal/keydb => serverkeyapi/storage}/cache/keydb.go (91%) rename {internal/keydb => serverkeyapi/storage}/interface.go (96%) rename {internal/keydb => serverkeyapi/storage}/keydb.go (91%) rename {internal/keydb => serverkeyapi/storage}/keydb_wasm.go (88%) rename {internal/keydb => serverkeyapi/storage}/postgres/keydb.go (100%) rename {internal/keydb => serverkeyapi/storage}/postgres/server_key_table.go (100%) rename {internal/keydb => serverkeyapi/storage}/sqlite3/keydb.go (100%) rename {internal/keydb => serverkeyapi/storage}/sqlite3/server_key_table.go (100%) diff --git a/build/docker/hub/config/dendrite-config.yaml b/build/docker/hub/config/dendrite-config.yaml index 23d6479b5..26dc272ab 100644 --- a/build/docker/hub/config/dendrite-config.yaml +++ b/build/docker/hub/config/dendrite-config.yaml @@ -110,11 +110,13 @@ listen: room_server: "room_server:7770" client_api: "client_api:7771" federation_api: "federation_api:7772" + server_key_api: "server_key_api:7778" sync_api: "sync_api:7773" media_api: "media_api:7774" public_rooms_api: "public_rooms_api:7775" federation_sender: "federation_sender:7776" edu_server: "edu_server:7777" + key_server: "key_server:7779" # The configuration for tracing the dendrite components. tracing: diff --git a/build/docker/hub/docker-compose.polylith.yml b/build/docker/hub/docker-compose.polylith.yml index d88e5bfb3..178604093 100644 --- a/build/docker/hub/docker-compose.polylith.yml +++ b/build/docker/hub/docker-compose.polylith.yml @@ -131,7 +131,7 @@ services: - internal key_server: - hostname: key_serverde + hostname: key_server image: matrixdotorg/dendrite:keyserver command: [ "--config=dendrite.yaml" @@ -141,6 +141,17 @@ services: networks: - internal + server_key_api: + hostname: server_key_api + image: matrixdotorg/dendrite:serverkeyapi + command: [ + "--config=dendrite.yaml" + ] + volumes: + - ./config:/etc/dendrite + networks: + - internal + networks: internal: attachable: true diff --git a/build/docker/hub/images-build.sh b/build/docker/hub/images-build.sh index 0c6a0eb7a..b162a0639 100755 --- a/build/docker/hub/images-build.sh +++ b/build/docker/hub/images-build.sh @@ -2,16 +2,17 @@ cd $(git rev-parse --show-toplevel) -docker build -f docker/hub/Dockerfile -t matrixdotorg/dendrite:latest . +docker build -f build/docker/hub/Dockerfile -t matrixdotorg/dendrite:latest . -docker build -t matrixdotorg/dendrite:clientapi --build-arg component=dendrite-client-api-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:clientproxy --build-arg component=client-api-proxy -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:eduserver --build-arg component=dendrite-edu-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:federationapi --build-arg component=dendrite-federation-api-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:federationsender --build-arg component=dendrite-federation-sender-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:federationproxy --build-arg component=federation-api-proxy -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:keyserver --build-arg component=dendrite-key-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:mediaapi --build-arg component=dendrite-media-api-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:publicroomsapi --build-arg component=dendrite-public-rooms-api-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:roomserver --build-arg component=dendrite-room-server -f docker/hub/Dockerfile.component . -docker build -t matrixdotorg/dendrite:syncapi --build-arg component=dendrite-sync-api-server -f docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:clientapi --build-arg component=dendrite-client-api-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:clientproxy --build-arg component=client-api-proxy -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:eduserver --build-arg component=dendrite-edu-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:federationapi --build-arg component=dendrite-federation-api-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:federationsender --build-arg component=dendrite-federation-sender-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:federationproxy --build-arg component=federation-api-proxy -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:keyserver --build-arg component=dendrite-key-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:mediaapi --build-arg component=dendrite-media-api-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:publicroomsapi --build-arg component=dendrite-public-rooms-api-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:roomserver --build-arg component=dendrite-room-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:syncapi --build-arg component=dendrite-sync-api-server -f build/docker/hub/Dockerfile.component . +docker build -t matrixdotorg/dendrite:serverkeyapi --build-arg component=dendrite-server-key-api-server -f build/docker/hub/Dockerfile.component . diff --git a/cmd/dendrite-client-api-server/main.go b/cmd/dendrite-client-api-server/main.go index 0815be799..e06adf8ff 100644 --- a/cmd/dendrite-client-api-server/main.go +++ b/cmd/dendrite-client-api-server/main.go @@ -19,7 +19,6 @@ import ( "github.com/matrix-org/dendrite/eduserver" "github.com/matrix-org/dendrite/eduserver/cache" "github.com/matrix-org/dendrite/internal/basecomponent" - "github.com/matrix-org/dendrite/internal/keydb" "github.com/matrix-org/dendrite/internal/transactions" ) @@ -31,9 +30,10 @@ func main() { accountDB := base.CreateAccountsDB() deviceDB := base.CreateDeviceDB() - keyDB := base.CreateKeyDB() federation := base.CreateFederationClient() - keyRing := keydb.CreateKeyRing(federation.Client, keyDB, cfg.Matrix.KeyPerspectives) + + serverKeyAPI := base.CreateHTTPServerKeyAPIs() + keyRing := serverKeyAPI.KeyRing() asQuery := base.CreateHTTPAppServiceAPIs() rsAPI := base.CreateHTTPRoomserverAPIs() @@ -42,7 +42,7 @@ func main() { eduInputAPI := eduserver.SetupEDUServerComponent(base, cache.New()) clientapi.SetupClientAPIComponent( - base, deviceDB, accountDB, federation, &keyRing, + base, deviceDB, accountDB, federation, keyRing, rsAPI, eduInputAPI, asQuery, transactions.New(), fsAPI, ) diff --git a/cmd/dendrite-demo-libp2p/main.go b/cmd/dendrite-demo-libp2p/main.go index 3f53cb429..fc56b9bbf 100644 --- a/cmd/dendrite-demo-libp2p/main.go +++ b/cmd/dendrite-demo-libp2p/main.go @@ -37,11 +37,11 @@ import ( "github.com/matrix-org/dendrite/federationsender" "github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/internal/config" - "github.com/matrix-org/dendrite/internal/keydb" "github.com/matrix-org/dendrite/internal/transactions" "github.com/matrix-org/dendrite/mediaapi" "github.com/matrix-org/dendrite/publicroomsapi" "github.com/matrix-org/dendrite/roomserver" + "github.com/matrix-org/dendrite/serverkeyapi" "github.com/matrix-org/dendrite/syncapi" "github.com/matrix-org/gomatrixserverlib" @@ -52,17 +52,8 @@ import ( func createKeyDB( base *P2PDendrite, -) keydb.Database { - db, err := keydb.NewDatabase( - string(base.Base.Cfg.Database.ServerKey), - base.Base.Cfg.DbProperties(), - base.Base.Cfg.Matrix.ServerName, - base.Base.Cfg.Matrix.PrivateKey.Public().(ed25519.PublicKey), - base.Base.Cfg.Matrix.KeyID, - ) - if err != nil { - logrus.WithError(err).Panicf("failed to connect to keys db") - } + db gomatrixserverlib.KeyDatabase, +) { mdns := mDNSListener{ host: base.LibP2P, keydb: db, @@ -77,7 +68,6 @@ func createKeyDB( panic(err) } serv.RegisterNotifee(&mdns) - return db } func createFederationClient( @@ -144,9 +134,15 @@ func main() { accountDB := base.Base.CreateAccountsDB() deviceDB := base.Base.CreateDeviceDB() - keyDB := createKeyDB(base) federation := createFederationClient(base) - keyRing := keydb.CreateKeyRing(federation.Client, keyDB, cfg.Matrix.KeyPerspectives) + + serverKeyAPI := serverkeyapi.SetupServerKeyAPIComponent( + &base.Base, federation, + ) + keyRing := serverKeyAPI.KeyRing() + createKeyDB( + base, serverKeyAPI, + ) rsAPI := roomserver.SetupRoomServerComponent( &base.Base, keyRing, federation, @@ -158,17 +154,17 @@ func main() { &base.Base, accountDB, deviceDB, federation, rsAPI, transactions.New(), ) fsAPI := federationsender.SetupFederationSenderComponent( - &base.Base, federation, rsAPI, &keyRing, + &base.Base, federation, rsAPI, keyRing, ) rsAPI.SetFederationSenderAPI(fsAPI) clientapi.SetupClientAPIComponent( &base.Base, deviceDB, accountDB, - federation, &keyRing, rsAPI, + federation, keyRing, rsAPI, eduInputAPI, asAPI, transactions.New(), fsAPI, ) eduProducer := producers.NewEDUServerProducer(eduInputAPI) - federationapi.SetupFederationAPIComponent(&base.Base, accountDB, deviceDB, federation, &keyRing, rsAPI, asAPI, fsAPI, eduProducer) + federationapi.SetupFederationAPIComponent(&base.Base, accountDB, deviceDB, federation, keyRing, rsAPI, asAPI, fsAPI, eduProducer) mediaapi.SetupMediaAPIComponent(&base.Base, deviceDB) publicRoomsDB, err := storage.NewPublicRoomsServerDatabaseWithPubSub(string(base.Base.Cfg.Database.PublicRoomsAPI), base.LibP2PPubsub) if err != nil { diff --git a/cmd/dendrite-demo-libp2p/mdnslistener.go b/cmd/dendrite-demo-libp2p/mdnslistener.go index c05c94d59..01705cf39 100644 --- a/cmd/dendrite-demo-libp2p/mdnslistener.go +++ b/cmd/dendrite-demo-libp2p/mdnslistener.go @@ -21,12 +21,11 @@ import ( "github.com/libp2p/go-libp2p-core/host" "github.com/libp2p/go-libp2p-core/peer" - "github.com/matrix-org/dendrite/internal/keydb" "github.com/matrix-org/gomatrixserverlib" ) type mDNSListener struct { - keydb keydb.Database + keydb gomatrixserverlib.KeyDatabase host host.Host } diff --git a/cmd/dendrite-federation-api-server/main.go b/cmd/dendrite-federation-api-server/main.go index be97bc9a0..5425d117f 100644 --- a/cmd/dendrite-federation-api-server/main.go +++ b/cmd/dendrite-federation-api-server/main.go @@ -20,7 +20,6 @@ import ( "github.com/matrix-org/dendrite/eduserver/cache" "github.com/matrix-org/dendrite/federationapi" "github.com/matrix-org/dendrite/internal/basecomponent" - "github.com/matrix-org/dendrite/internal/keydb" ) func main() { @@ -30,10 +29,12 @@ func main() { accountDB := base.CreateAccountsDB() deviceDB := base.CreateDeviceDB() - keyDB := base.CreateKeyDB() federation := base.CreateFederationClient() + + serverKeyAPI := base.CreateHTTPServerKeyAPIs() + keyRing := serverKeyAPI.KeyRing() + fsAPI := base.CreateHTTPFederationSenderAPIs() - keyRing := keydb.CreateKeyRing(federation.Client, keyDB, cfg.Matrix.KeyPerspectives) rsAPI := base.CreateHTTPRoomserverAPIs() asAPI := base.CreateHTTPAppServiceAPIs() @@ -42,7 +43,7 @@ func main() { eduProducer := producers.NewEDUServerProducer(eduInputAPI) federationapi.SetupFederationAPIComponent( - base, accountDB, deviceDB, federation, &keyRing, + base, accountDB, deviceDB, federation, keyRing, rsAPI, asAPI, fsAPI, eduProducer, ) diff --git a/cmd/dendrite-federation-sender-server/main.go b/cmd/dendrite-federation-sender-server/main.go index b6af8deb7..2b1e0ae8f 100644 --- a/cmd/dendrite-federation-sender-server/main.go +++ b/cmd/dendrite-federation-sender-server/main.go @@ -17,7 +17,6 @@ package main import ( "github.com/matrix-org/dendrite/federationsender" "github.com/matrix-org/dendrite/internal/basecomponent" - "github.com/matrix-org/dendrite/internal/keydb" ) func main() { @@ -26,11 +25,13 @@ func main() { defer base.Close() // nolint: errcheck federation := base.CreateFederationClient() - keyDB := base.CreateKeyDB() - keyRing := keydb.CreateKeyRing(federation.Client, keyDB, cfg.Matrix.KeyPerspectives) + + serverKeyAPI := base.CreateHTTPServerKeyAPIs() + keyRing := serverKeyAPI.KeyRing() + rsAPI := base.CreateHTTPRoomserverAPIs() fsAPI := federationsender.SetupFederationSenderComponent( - base, federation, rsAPI, &keyRing, + base, federation, rsAPI, keyRing, ) rsAPI.SetFederationSenderAPI(fsAPI) diff --git a/cmd/dendrite-monolith-server/main.go b/cmd/dendrite-monolith-server/main.go index f9993774f..8367cd9da 100644 --- a/cmd/dendrite-monolith-server/main.go +++ b/cmd/dendrite-monolith-server/main.go @@ -28,13 +28,13 @@ import ( "github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/internal/basecomponent" "github.com/matrix-org/dendrite/internal/config" - "github.com/matrix-org/dendrite/internal/keydb" "github.com/matrix-org/dendrite/internal/transactions" "github.com/matrix-org/dendrite/keyserver" "github.com/matrix-org/dendrite/mediaapi" "github.com/matrix-org/dendrite/publicroomsapi" "github.com/matrix-org/dendrite/publicroomsapi/storage" "github.com/matrix-org/dendrite/roomserver" + "github.com/matrix-org/dendrite/serverkeyapi" "github.com/matrix-org/dendrite/syncapi" "github.com/sirupsen/logrus" @@ -60,6 +60,7 @@ func main() { cfg.Listen.EDUServer = addr cfg.Listen.AppServiceAPI = addr cfg.Listen.FederationSender = addr + cfg.Listen.ServerKeyAPI = addr } base := basecomponent.NewBaseDendrite(cfg, "Monolith", *enableHTTPAPIs) @@ -67,9 +68,15 @@ func main() { accountDB := base.CreateAccountsDB() deviceDB := base.CreateDeviceDB() - keyDB := base.CreateKeyDB() federation := base.CreateFederationClient() - keyRing := keydb.CreateKeyRing(federation.Client, keyDB, cfg.Matrix.KeyPerspectives) + + serverKeyAPI := serverkeyapi.SetupServerKeyAPIComponent( + base, federation, + ) + if base.EnableHTTPAPIs { + serverKeyAPI = base.CreateHTTPServerKeyAPIs() + } + keyRing := serverKeyAPI.KeyRing() rsComponent := roomserver.SetupRoomServerComponent( base, keyRing, federation, @@ -94,7 +101,7 @@ func main() { } fsAPI := federationsender.SetupFederationSenderComponent( - base, federation, rsAPI, &keyRing, + base, federation, rsAPI, keyRing, ) if base.EnableHTTPAPIs { fsAPI = base.CreateHTTPFederationSenderAPIs() @@ -103,7 +110,7 @@ func main() { clientapi.SetupClientAPIComponent( base, deviceDB, accountDB, - federation, &keyRing, rsAPI, + federation, keyRing, rsAPI, eduInputAPI, asAPI, transactions.New(), fsAPI, ) @@ -111,7 +118,7 @@ func main() { base, deviceDB, accountDB, ) eduProducer := producers.NewEDUServerProducer(eduInputAPI) - federationapi.SetupFederationAPIComponent(base, accountDB, deviceDB, federation, &keyRing, rsAPI, asAPI, fsAPI, eduProducer) + federationapi.SetupFederationAPIComponent(base, accountDB, deviceDB, federation, keyRing, rsAPI, asAPI, fsAPI, eduProducer) mediaapi.SetupMediaAPIComponent(base, deviceDB) publicRoomsDB, err := storage.NewPublicRoomsServerDatabase(string(base.Cfg.Database.PublicRoomsAPI), base.Cfg.DbProperties()) if err != nil { diff --git a/cmd/dendrite-room-server/main.go b/cmd/dendrite-room-server/main.go index 31cf4a042..b86b74972 100644 --- a/cmd/dendrite-room-server/main.go +++ b/cmd/dendrite-room-server/main.go @@ -16,7 +16,6 @@ package main import ( "github.com/matrix-org/dendrite/internal/basecomponent" - "github.com/matrix-org/dendrite/internal/keydb" "github.com/matrix-org/dendrite/roomserver" ) @@ -24,9 +23,10 @@ func main() { cfg := basecomponent.ParseFlags() base := basecomponent.NewBaseDendrite(cfg, "RoomServerAPI", true) defer base.Close() // nolint: errcheck - keyDB := base.CreateKeyDB() federation := base.CreateFederationClient() - keyRing := keydb.CreateKeyRing(federation.Client, keyDB, cfg.Matrix.KeyPerspectives) + + serverKeyAPI := base.CreateHTTPServerKeyAPIs() + keyRing := serverKeyAPI.KeyRing() fsAPI := base.CreateHTTPFederationSenderAPIs() rsAPI := roomserver.SetupRoomServerComponent(base, keyRing, federation) diff --git a/cmd/dendrite-server-key-api-server/main.go b/cmd/dendrite-server-key-api-server/main.go new file mode 100644 index 000000000..075734125 --- /dev/null +++ b/cmd/dendrite-server-key-api-server/main.go @@ -0,0 +1,32 @@ +// Copyright 2020 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/matrix-org/dendrite/internal/basecomponent" + "github.com/matrix-org/dendrite/serverkeyapi" +) + +func main() { + cfg := basecomponent.ParseFlags() + base := basecomponent.NewBaseDendrite(cfg, "ServerKeyAPI", true) + defer base.Close() // nolint: errcheck + + federation := base.CreateFederationClient() + + serverkeyapi.SetupServerKeyAPIComponent(base, federation) + + base.SetupAndServeHTTP(string(base.Cfg.Bind.ServerKeyAPI), string(base.Cfg.Listen.ServerKeyAPI)) +} diff --git a/cmd/dendritejs/main.go b/cmd/dendritejs/main.go index 73d381492..b8517bf9d 100644 --- a/cmd/dendritejs/main.go +++ b/cmd/dendritejs/main.go @@ -37,6 +37,7 @@ import ( "github.com/matrix-org/dendrite/publicroomsapi" "github.com/matrix-org/dendrite/publicroomsapi/storage" "github.com/matrix-org/dendrite/roomserver" + "github.com/matrix-org/dendrite/serverkeyapi" "github.com/matrix-org/dendrite/syncapi" go_http_js_libp2p "github.com/matrix-org/go-http-js-libp2p" "github.com/matrix-org/gomatrixserverlib" @@ -194,13 +195,16 @@ func main() { accountDB := base.CreateAccountsDB() deviceDB := base.CreateDeviceDB() - keyDB := base.CreateKeyDB() federation := createFederationClient(cfg, node) + + serverKeyAPI := serverkeyapi.SetupServerKeyAPIComponent( + base, federation, + ) keyRing := gomatrixserverlib.KeyRing{ KeyFetchers: []gomatrixserverlib.KeyFetcher{ &libp2pKeyFetcher{}, }, - KeyDatabase: keyDB, + KeyDatabase: serverKeyAPI, } p2pPublicRoomProvider := NewLibP2PPublicRoomsProvider(node) diff --git a/dendrite-config.yaml b/dendrite-config.yaml index 2616d74db..1802b8b73 100644 --- a/dendrite-config.yaml +++ b/dendrite-config.yaml @@ -137,7 +137,8 @@ listen: federation_sender: "localhost:7776" appservice_api: "localhost:7777" edu_server: "localhost:7778" - key_server: "localhost:7779" + key_server: "localhost:7779" + server_key_api: "localhost:7780" # The configuration for tracing the dendrite components. tracing: diff --git a/go.mod b/go.mod index 151fee27a..fe2cff768 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3 github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26 - github.com/matrix-org/gomatrixserverlib v0.0.0-20200511154227-5cc71d36632b + github.com/matrix-org/gomatrixserverlib v0.0.0-20200521102632-2a81324a04ae github.com/matrix-org/naffka v0.0.0-20200422140631-181f1ee7401f github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7 github.com/mattn/go-sqlite3 v2.0.2+incompatible diff --git a/go.sum b/go.sum index 15822b532..aa0c8dd57 100644 --- a/go.sum +++ b/go.sum @@ -358,8 +358,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3 h1:Yb+Wlf github.com/matrix-org/go-sqlite3-js v0.0.0-20200522092705-bc8506ccbcf3/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26 h1:Hr3zjRsq2bhrnp3Ky1qgx/fzCtCALOoGYylh2tpS9K4= github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0= -github.com/matrix-org/gomatrixserverlib v0.0.0-20200511154227-5cc71d36632b h1:nAmSc1KvQOumoRTz/LD68KyrB6Q5/6q7CmQ5Bswc2nM= -github.com/matrix-org/gomatrixserverlib v0.0.0-20200511154227-5cc71d36632b/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20200521102632-2a81324a04ae h1:kFMh2aU3pMCkVCUeH57rtgm05XImbxKOHFYeUp80RCk= +github.com/matrix-org/gomatrixserverlib v0.0.0-20200521102632-2a81324a04ae/go.mod h1:JsAzE1Ll3+gDWS9JSUHPJiiyAksvOOnGWF2nXdg4ZzU= github.com/matrix-org/naffka v0.0.0-20200422140631-181f1ee7401f h1:pRz4VTiRCO4zPlEMc3ESdUOcW4PXHH4Kj+YDz1XyE+Y= github.com/matrix-org/naffka v0.0.0-20200422140631-181f1ee7401f/go.mod h1:y0oDTjZDv5SM9a2rp3bl+CU+bvTRINQsdb7YlDql5Go= github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7 h1:ntrLa/8xVzeSs8vHFHK25k0C+NV74sYMJnNSg5NoSRo= diff --git a/internal/basecomponent/base.go b/internal/basecomponent/base.go index e86d91025..a48323726 100644 --- a/internal/basecomponent/base.go +++ b/internal/basecomponent/base.go @@ -21,12 +21,8 @@ import ( "net/url" "time" - "golang.org/x/crypto/ed25519" - "github.com/matrix-org/dendrite/internal/caching" "github.com/matrix-org/dendrite/internal/httpapis" - "github.com/matrix-org/dendrite/internal/keydb" - "github.com/matrix-org/dendrite/internal/keydb/cache" "github.com/matrix-org/dendrite/internal/sqlutil" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/naffka" @@ -43,6 +39,7 @@ import ( federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api" "github.com/matrix-org/dendrite/internal/config" roomserverAPI "github.com/matrix-org/dendrite/roomserver/api" + serverKeyAPI "github.com/matrix-org/dendrite/serverkeyapi/api" "github.com/sirupsen/logrus" _ "net/http/pprof" @@ -157,6 +154,20 @@ func (b *BaseDendrite) CreateHTTPFederationSenderAPIs() federationSenderAPI.Fede return f } +// CreateHTTPServerKeyAPIs returns ServerKeyInternalAPI for hitting the server key +// API over HTTP +func (b *BaseDendrite) CreateHTTPServerKeyAPIs() serverKeyAPI.ServerKeyInternalAPI { + f, err := serverKeyAPI.NewServerKeyInternalAPIHTTP( + b.Cfg.ServerKeyAPIURL(), + b.httpClient, + b.ImmutableCache, + ) + if err != nil { + logrus.WithError(err).Panic("NewServerKeyInternalAPIHTTP failed", b.httpClient) + } + return f +} + // CreateDeviceDB creates a new instance of the device database. Should only be // called once per component. func (b *BaseDendrite) CreateDeviceDB() devices.Database { @@ -179,27 +190,6 @@ func (b *BaseDendrite) CreateAccountsDB() accounts.Database { return db } -// CreateKeyDB creates a new instance of the key database. Should only be called -// once per component. -func (b *BaseDendrite) CreateKeyDB() keydb.Database { - db, err := keydb.NewDatabase( - string(b.Cfg.Database.ServerKey), - b.Cfg.DbProperties(), - b.Cfg.Matrix.ServerName, - b.Cfg.Matrix.PrivateKey.Public().(ed25519.PublicKey), - b.Cfg.Matrix.KeyID, - ) - if err != nil { - logrus.WithError(err).Panicf("failed to connect to keys db") - } - - cachedDB, err := cache.NewKeyDatabase(db, b.ImmutableCache) - if err != nil { - logrus.WithError(err).Panicf("failed to create key cache wrapper") - } - return cachedDB -} - // CreateFederationClient creates a new federation client. Should only be called // once per component. func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationClient { diff --git a/internal/config/config.go b/internal/config/config.go index e1e96f9d5..2a95069a4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -223,6 +223,7 @@ type Dendrite struct { MediaAPI Address `yaml:"media_api"` ClientAPI Address `yaml:"client_api"` FederationAPI Address `yaml:"federation_api"` + ServerKeyAPI Address `yaml:"server_key_api"` AppServiceAPI Address `yaml:"appservice_api"` SyncAPI Address `yaml:"sync_api"` RoomServer Address `yaml:"room_server"` @@ -237,6 +238,7 @@ type Dendrite struct { MediaAPI Address `yaml:"media_api"` ClientAPI Address `yaml:"client_api"` FederationAPI Address `yaml:"federation_api"` + ServerKeyAPI Address `yaml:"server_key_api"` AppServiceAPI Address `yaml:"appservice_api"` SyncAPI Address `yaml:"sync_api"` RoomServer Address `yaml:"room_server"` @@ -620,6 +622,7 @@ func (config *Dendrite) checkListen(configErrs *configErrors) { checkNotEmpty(configErrs, "listen.sync_api", string(config.Listen.SyncAPI)) checkNotEmpty(configErrs, "listen.room_server", string(config.Listen.RoomServer)) checkNotEmpty(configErrs, "listen.edu_server", string(config.Listen.EDUServer)) + checkNotEmpty(configErrs, "listen.server_key_api", string(config.Listen.EDUServer)) } // checkLogging verifies the parameters logging.* are valid. @@ -751,6 +754,15 @@ func (config *Dendrite) FederationSenderURL() string { return "http://" + string(config.Listen.FederationSender) } +// FederationSenderURL returns an HTTP URL for where the federation sender is listening. +func (config *Dendrite) ServerKeyAPIURL() string { + // Hard code the server key API server to talk HTTP for now. + // If we support HTTPS we need to think of a practical way to do certificate validation. + // People setting up servers shouldn't need to get a certificate valid for the public + // internet for an internal API. + return "http://" + string(config.Listen.ServerKeyAPI) +} + // SetupTracing configures the opentracing using the supplied configuration. func (config *Dendrite) SetupTracing(serviceName string) (closer io.Closer, err error) { if !config.Tracing.Enabled { diff --git a/internal/keydb/keyring.go b/internal/keydb/keyring.go deleted file mode 100644 index d0b1904ed..000000000 --- a/internal/keydb/keyring.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package keydb - -import ( - "encoding/base64" - - "github.com/matrix-org/dendrite/internal/config" - "github.com/matrix-org/gomatrixserverlib" - "github.com/sirupsen/logrus" - "golang.org/x/crypto/ed25519" -) - -// CreateKeyRing creates and configures a KeyRing object. -// -// It creates the necessary key fetchers and collects them into a KeyRing -// backed by the given KeyDatabase. -func CreateKeyRing(client gomatrixserverlib.Client, - keyDB gomatrixserverlib.KeyDatabase, - cfg config.KeyPerspectives) gomatrixserverlib.KeyRing { - - fetchers := gomatrixserverlib.KeyRing{ - KeyFetchers: []gomatrixserverlib.KeyFetcher{ - &gomatrixserverlib.DirectKeyFetcher{ - Client: client, - }, - }, - KeyDatabase: keyDB, - } - - logrus.Info("Enabled direct key fetcher") - - var b64e = base64.StdEncoding.WithPadding(base64.NoPadding) - for _, ps := range cfg { - perspective := &gomatrixserverlib.PerspectiveKeyFetcher{ - PerspectiveServerName: ps.ServerName, - PerspectiveServerKeys: map[gomatrixserverlib.KeyID]ed25519.PublicKey{}, - Client: client, - } - - for _, key := range ps.Keys { - rawkey, err := b64e.DecodeString(key.PublicKey) - if err != nil { - logrus.WithError(err).WithFields(logrus.Fields{ - "server_name": ps.ServerName, - "public_key": key.PublicKey, - }).Warn("Couldn't parse perspective key") - continue - } - perspective.PerspectiveServerKeys[key.KeyID] = rawkey - } - - fetchers.KeyFetchers = append(fetchers.KeyFetchers, perspective) - - logrus.WithFields(logrus.Fields{ - "server_name": ps.ServerName, - "num_public_keys": len(ps.Keys), - }).Info("Enabled perspective key fetcher") - } - - return fetchers -} diff --git a/serverkeyapi/api/api.go b/serverkeyapi/api/api.go new file mode 100644 index 000000000..f108d437b --- /dev/null +++ b/serverkeyapi/api/api.go @@ -0,0 +1,113 @@ +package api + +import ( + "context" + "errors" + "net/http" + + "github.com/matrix-org/dendrite/internal/caching" + "github.com/matrix-org/gomatrixserverlib" +) + +type ServerKeyInternalAPI interface { + gomatrixserverlib.KeyDatabase + + KeyRing() *gomatrixserverlib.KeyRing + + InputPublicKeys( + ctx context.Context, + request *InputPublicKeysRequest, + response *InputPublicKeysResponse, + ) error + + QueryPublicKeys( + ctx context.Context, + request *QueryPublicKeysRequest, + response *QueryPublicKeysResponse, + ) error +} + +// NewRoomserverInputAPIHTTP creates a RoomserverInputAPI implemented by talking to a HTTP POST API. +// If httpClient is nil an error is returned +func NewServerKeyInternalAPIHTTP( + serverKeyAPIURL string, + httpClient *http.Client, + immutableCache caching.ImmutableCache, +) (ServerKeyInternalAPI, error) { + if httpClient == nil { + return nil, errors.New("NewRoomserverInternalAPIHTTP: httpClient is ") + } + return &httpServerKeyInternalAPI{ + serverKeyAPIURL: serverKeyAPIURL, + httpClient: httpClient, + immutableCache: immutableCache, + }, nil +} + +type httpServerKeyInternalAPI struct { + ServerKeyInternalAPI + + serverKeyAPIURL string + httpClient *http.Client + immutableCache caching.ImmutableCache +} + +func (s *httpServerKeyInternalAPI) KeyRing() *gomatrixserverlib.KeyRing { + // This is a bit of a cheat - we tell gomatrixserverlib that this API is + // both the key database and the key fetcher. While this does have the + // rather unfortunate effect of preventing gomatrixserverlib from handling + // key fetchers directly, we can at least reimplement this behaviour on + // the other end of the API. + return &gomatrixserverlib.KeyRing{ + KeyDatabase: s, + KeyFetchers: []gomatrixserverlib.KeyFetcher{s}, + } +} + +func (s *httpServerKeyInternalAPI) FetcherName() string { + return "httpServerKeyInternalAPI" +} + +func (s *httpServerKeyInternalAPI) StoreKeys( + ctx context.Context, + results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, +) error { + request := InputPublicKeysRequest{ + Keys: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult), + } + response := InputPublicKeysResponse{} + for req, res := range results { + request.Keys[req] = res + s.immutableCache.StoreServerKey(req, res) + } + return s.InputPublicKeys(ctx, &request, &response) +} + +func (s *httpServerKeyInternalAPI) FetchKeys( + ctx context.Context, + requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp, +) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) { + result := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult) + request := QueryPublicKeysRequest{ + Requests: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp), + } + response := QueryPublicKeysResponse{ + Results: make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult), + } + for req, ts := range requests { + if res, ok := s.immutableCache.GetServerKey(req); ok { + result[req] = res + continue + } + request.Requests[req] = ts + } + err := s.QueryPublicKeys(ctx, &request, &response) + if err != nil { + return nil, err + } + for req, res := range response.Results { + result[req] = res + s.immutableCache.StoreServerKey(req, res) + } + return result, nil +} diff --git a/serverkeyapi/api/http.go b/serverkeyapi/api/http.go new file mode 100644 index 000000000..ab89f7bfc --- /dev/null +++ b/serverkeyapi/api/http.go @@ -0,0 +1,57 @@ +package api + +import ( + "context" + + commonHTTP "github.com/matrix-org/dendrite/internal/http" + "github.com/matrix-org/gomatrixserverlib" + + "github.com/opentracing/opentracing-go" +) + +const ( + // ServerKeyInputPublicKeyPath is the HTTP path for the InputPublicKeys API. + ServerKeyInputPublicKeyPath = "/serverkeyapi/inputPublicKey" + + // ServerKeyQueryPublicKeyPath is the HTTP path for the QueryPublicKeys API. + ServerKeyQueryPublicKeyPath = "/serverkeyapi/queryPublicKey" +) + +type InputPublicKeysRequest struct { + Keys map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult `json:"keys"` +} + +type InputPublicKeysResponse struct { +} + +func (h *httpServerKeyInternalAPI) InputPublicKeys( + ctx context.Context, + request *InputPublicKeysRequest, + response *InputPublicKeysResponse, +) error { + span, ctx := opentracing.StartSpanFromContext(ctx, "InputPublicKey") + defer span.Finish() + + apiURL := h.serverKeyAPIURL + ServerKeyInputPublicKeyPath + return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) +} + +type QueryPublicKeysRequest struct { + Requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp `json:"requests"` +} + +type QueryPublicKeysResponse struct { + Results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult `json:"results"` +} + +func (h *httpServerKeyInternalAPI) QueryPublicKeys( + ctx context.Context, + request *QueryPublicKeysRequest, + response *QueryPublicKeysResponse, +) error { + span, ctx := opentracing.StartSpanFromContext(ctx, "QueryPublicKey") + defer span.Finish() + + apiURL := h.serverKeyAPIURL + ServerKeyQueryPublicKeyPath + return commonHTTP.PostJSON(ctx, span, h.httpClient, apiURL, request, response) +} diff --git a/serverkeyapi/internal/api.go b/serverkeyapi/internal/api.go new file mode 100644 index 000000000..cbae59d9a --- /dev/null +++ b/serverkeyapi/internal/api.go @@ -0,0 +1,76 @@ +package internal + +import ( + "context" + "fmt" + + "github.com/matrix-org/dendrite/internal/caching" + "github.com/matrix-org/dendrite/serverkeyapi/api" + "github.com/matrix-org/gomatrixserverlib" +) + +type ServerKeyAPI struct { + api.ServerKeyInternalAPI + + ImmutableCache caching.ImmutableCache + OurKeyRing gomatrixserverlib.KeyRing + FedClient *gomatrixserverlib.FederationClient +} + +func (s *ServerKeyAPI) KeyRing() *gomatrixserverlib.KeyRing { + // Return a real keyring - one that has the real database and real + // fetchers. + return &s.OurKeyRing +} + +func (s *ServerKeyAPI) StoreKeys( + ctx context.Context, + results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, +) error { + // Store any keys that we were given in our database. + return s.OurKeyRing.KeyDatabase.StoreKeys(ctx, results) +} + +func (s *ServerKeyAPI) FetchKeys( + ctx context.Context, + requests map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp, +) (map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, error) { + results := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{} + // First consult our local database and see if we have the requested + // keys. These might come from a cache, depending on the database + // implementation used. + if dbResults, err := s.OurKeyRing.KeyDatabase.FetchKeys(ctx, requests); err == nil { + // We successfully got some keys. Add them to the results and + // remove them from the request list. + for req, res := range dbResults { + results[req] = res + delete(requests, req) + } + } + // For any key requests that we still have outstanding, next try to + // fetch them directly. We'll go through each of the key fetchers to + // ask for the remaining keys. + for _, fetcher := range s.OurKeyRing.KeyFetchers { + if len(requests) == 0 { + break + } + if fetcherResults, err := fetcher.FetchKeys(ctx, requests); err == nil { + // We successfully got some keys. Add them to the results and + // remove them from the request list. + for req, res := range fetcherResults { + results[req] = res + delete(requests, req) + } + } + } + // If we failed to fetch any keys then we should report an error. + if len(requests) > 0 { + return results, fmt.Errorf("server key API failed to fetch %d keys", len(requests)) + } + // Return the keys. + return results, nil +} + +func (s *ServerKeyAPI) FetcherName() string { + return s.OurKeyRing.KeyDatabase.FetcherName() +} diff --git a/serverkeyapi/internal/http.go b/serverkeyapi/internal/http.go new file mode 100644 index 000000000..303275712 --- /dev/null +++ b/serverkeyapi/internal/http.go @@ -0,0 +1,60 @@ +package internal + +import ( + "encoding/json" + "net/http" + + "github.com/gorilla/mux" + "github.com/matrix-org/dendrite/internal" + "github.com/matrix-org/dendrite/serverkeyapi/api" + "github.com/matrix-org/gomatrixserverlib" + "github.com/matrix-org/util" +) + +func (s *ServerKeyAPI) SetupHTTP(internalAPIMux *mux.Router) { + internalAPIMux.Handle(api.ServerKeyQueryPublicKeyPath, + internal.MakeInternalAPI("queryPublicKeys", func(req *http.Request) util.JSONResponse { + result := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{} + request := api.QueryPublicKeysRequest{} + response := api.QueryPublicKeysResponse{} + if err := json.NewDecoder(req.Body).Decode(&request); err != nil { + return util.MessageResponse(http.StatusBadRequest, err.Error()) + } + lookup := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) + for req, timestamp := range request.Requests { + if res, ok := s.ImmutableCache.GetServerKey(req); ok { + result[req] = res + continue + } + lookup[req] = timestamp + } + keys, err := s.FetchKeys(req.Context(), lookup) + if err != nil { + return util.ErrorResponse(err) + } + for req, res := range keys { + result[req] = res + } + response.Results = result + return util.JSONResponse{Code: http.StatusOK, JSON: &response} + }), + ) + internalAPIMux.Handle(api.ServerKeyInputPublicKeyPath, + internal.MakeInternalAPI("inputPublicKeys", func(req *http.Request) util.JSONResponse { + request := api.InputPublicKeysRequest{} + response := api.InputPublicKeysResponse{} + if err := json.NewDecoder(req.Body).Decode(&request); err != nil { + return util.MessageResponse(http.StatusBadRequest, err.Error()) + } + store := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult) + for req, res := range request.Keys { + store[req] = res + s.ImmutableCache.StoreServerKey(req, res) + } + if err := s.StoreKeys(req.Context(), store); err != nil { + return util.ErrorResponse(err) + } + return util.JSONResponse{Code: http.StatusOK, JSON: &response} + }), + ) +} diff --git a/serverkeyapi/serverkeyapi.go b/serverkeyapi/serverkeyapi.go new file mode 100644 index 000000000..61d807d64 --- /dev/null +++ b/serverkeyapi/serverkeyapi.go @@ -0,0 +1,83 @@ +package serverkeyapi + +import ( + "crypto/ed25519" + "encoding/base64" + + "github.com/matrix-org/dendrite/internal/basecomponent" + "github.com/matrix-org/dendrite/serverkeyapi/api" + "github.com/matrix-org/dendrite/serverkeyapi/internal" + "github.com/matrix-org/dendrite/serverkeyapi/storage" + "github.com/matrix-org/dendrite/serverkeyapi/storage/cache" + "github.com/matrix-org/gomatrixserverlib" + "github.com/sirupsen/logrus" +) + +func SetupServerKeyAPIComponent( + base *basecomponent.BaseDendrite, + fedClient *gomatrixserverlib.FederationClient, +) api.ServerKeyInternalAPI { + innerDB, err := storage.NewDatabase( + string(base.Cfg.Database.ServerKey), + base.Cfg.DbProperties(), + base.Cfg.Matrix.ServerName, + base.Cfg.Matrix.PrivateKey.Public().(ed25519.PublicKey), + base.Cfg.Matrix.KeyID, + ) + if err != nil { + logrus.WithError(err).Panicf("failed to connect to server key database") + } + + serverKeyDB, err := cache.NewKeyDatabase(innerDB, base.ImmutableCache) + if err != nil { + logrus.WithError(err).Panicf("failed to set up caching wrapper for server key database") + } + + internalAPI := internal.ServerKeyAPI{ + ImmutableCache: base.ImmutableCache, + FedClient: fedClient, + OurKeyRing: gomatrixserverlib.KeyRing{ + KeyFetchers: []gomatrixserverlib.KeyFetcher{ + &gomatrixserverlib.DirectKeyFetcher{ + Client: fedClient.Client, + }, + }, + KeyDatabase: serverKeyDB, + }, + } + + var b64e = base64.StdEncoding.WithPadding(base64.NoPadding) + for _, ps := range base.Cfg.Matrix.KeyPerspectives { + perspective := &gomatrixserverlib.PerspectiveKeyFetcher{ + PerspectiveServerName: ps.ServerName, + PerspectiveServerKeys: map[gomatrixserverlib.KeyID]ed25519.PublicKey{}, + Client: fedClient.Client, + } + + for _, key := range ps.Keys { + rawkey, err := b64e.DecodeString(key.PublicKey) + if err != nil { + logrus.WithError(err).WithFields(logrus.Fields{ + "server_name": ps.ServerName, + "public_key": key.PublicKey, + }).Warn("Couldn't parse perspective key") + continue + } + perspective.PerspectiveServerKeys[key.KeyID] = rawkey + } + + internalAPI.OurKeyRing.KeyFetchers = append( + internalAPI.OurKeyRing.KeyFetchers, + perspective, + ) + + logrus.WithFields(logrus.Fields{ + "server_name": ps.ServerName, + "num_public_keys": len(ps.Keys), + }).Info("Enabled perspective key fetcher") + } + + internalAPI.SetupHTTP(base.InternalAPIMux) + + return &internalAPI +} diff --git a/internal/keydb/cache/keydb.go b/serverkeyapi/storage/cache/keydb.go similarity index 91% rename from internal/keydb/cache/keydb.go rename to serverkeyapi/storage/cache/keydb.go index 87573ed2b..a0cdb9007 100644 --- a/internal/keydb/cache/keydb.go +++ b/serverkeyapi/storage/cache/keydb.go @@ -5,18 +5,17 @@ import ( "errors" "github.com/matrix-org/dendrite/internal/caching" - "github.com/matrix-org/dendrite/internal/keydb" "github.com/matrix-org/gomatrixserverlib" ) // A Database implements gomatrixserverlib.KeyDatabase and is used to store // the public keys for other matrix servers. type KeyDatabase struct { - inner keydb.Database + inner gomatrixserverlib.KeyDatabase cache caching.ImmutableCache } -func NewKeyDatabase(inner keydb.Database, cache caching.ImmutableCache) (*KeyDatabase, error) { +func NewKeyDatabase(inner gomatrixserverlib.KeyDatabase, cache caching.ImmutableCache) (*KeyDatabase, error) { if inner == nil { return nil, errors.New("inner database can't be nil") } diff --git a/internal/keydb/interface.go b/serverkeyapi/storage/interface.go similarity index 96% rename from internal/keydb/interface.go rename to serverkeyapi/storage/interface.go index c9a20fdd9..3a67ac55a 100644 --- a/internal/keydb/interface.go +++ b/serverkeyapi/storage/interface.go @@ -1,4 +1,4 @@ -package keydb +package storage import ( "context" diff --git a/internal/keydb/keydb.go b/serverkeyapi/storage/keydb.go similarity index 91% rename from internal/keydb/keydb.go rename to serverkeyapi/storage/keydb.go index ad6d56b86..b9389bd63 100644 --- a/internal/keydb/keydb.go +++ b/serverkeyapi/storage/keydb.go @@ -14,7 +14,7 @@ // +build !wasm -package keydb +package storage import ( "net/url" @@ -22,8 +22,8 @@ import ( "golang.org/x/crypto/ed25519" "github.com/matrix-org/dendrite/internal" - "github.com/matrix-org/dendrite/internal/keydb/postgres" - "github.com/matrix-org/dendrite/internal/keydb/sqlite3" + "github.com/matrix-org/dendrite/serverkeyapi/storage/postgres" + "github.com/matrix-org/dendrite/serverkeyapi/storage/sqlite3" "github.com/matrix-org/gomatrixserverlib" ) diff --git a/internal/keydb/keydb_wasm.go b/serverkeyapi/storage/keydb_wasm.go similarity index 88% rename from internal/keydb/keydb_wasm.go rename to serverkeyapi/storage/keydb_wasm.go index c80329027..3d2ca5505 100644 --- a/internal/keydb/keydb_wasm.go +++ b/serverkeyapi/storage/keydb_wasm.go @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -package keydb +// +build wasm + +package storage import ( "fmt" @@ -21,7 +23,7 @@ import ( "golang.org/x/crypto/ed25519" "github.com/matrix-org/dendrite/internal" - "github.com/matrix-org/dendrite/internal/keydb/sqlite3" + "github.com/matrix-org/dendrite/serverkeyapi/storage/sqlite3" "github.com/matrix-org/gomatrixserverlib" ) @@ -41,7 +43,7 @@ func NewDatabase( case "postgres": return nil, fmt.Errorf("Cannot use postgres implementation") case "file": - return sqlite3.NewDatabase(uri.Path, serverName, serverKey, serverKeyID) + return sqlite3.NewDatabase(dataSourceName, serverName, serverKey, serverKeyID) default: return nil, fmt.Errorf("Cannot use postgres implementation") } diff --git a/internal/keydb/postgres/keydb.go b/serverkeyapi/storage/postgres/keydb.go similarity index 100% rename from internal/keydb/postgres/keydb.go rename to serverkeyapi/storage/postgres/keydb.go diff --git a/internal/keydb/postgres/server_key_table.go b/serverkeyapi/storage/postgres/server_key_table.go similarity index 100% rename from internal/keydb/postgres/server_key_table.go rename to serverkeyapi/storage/postgres/server_key_table.go diff --git a/internal/keydb/sqlite3/keydb.go b/serverkeyapi/storage/sqlite3/keydb.go similarity index 100% rename from internal/keydb/sqlite3/keydb.go rename to serverkeyapi/storage/sqlite3/keydb.go diff --git a/internal/keydb/sqlite3/server_key_table.go b/serverkeyapi/storage/sqlite3/server_key_table.go similarity index 100% rename from internal/keydb/sqlite3/server_key_table.go rename to serverkeyapi/storage/sqlite3/server_key_table.go