From 2f645cb6dafd96b6e67051698021feac1c9f3ae7 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 20 May 2020 11:01:32 +0100 Subject: [PATCH] Hopefully implement HTTP for server key API --- cmd/dendrite-server-key-api-server/main.go | 32 ++++++++++++++ common/config/config.go | 2 + serverkeyapi/api/http.go | 4 ++ serverkeyapi/api/satisfy.go | 34 ++++++++++++++- serverkeyapi/internal/http.go | 50 ++++++++++++++++------ 5 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 cmd/dendrite-server-key-api-server/main.go 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..9388a5d45 --- /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/common/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/common/config/config.go b/common/config/config.go index e1e96f9d5..7eeb67886 100644 --- a/common/config/config.go +++ b/common/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"` diff --git a/serverkeyapi/api/http.go b/serverkeyapi/api/http.go index af0bafe54..b35d858f8 100644 --- a/serverkeyapi/api/http.go +++ b/serverkeyapi/api/http.go @@ -4,6 +4,7 @@ import ( "context" commonHTTP "github.com/matrix-org/dendrite/common/http" + "github.com/matrix-org/gomatrixserverlib" "github.com/opentracing/opentracing-go" ) @@ -17,6 +18,7 @@ const ( ) type InputPublicKeysRequest struct { + Keys map[gomatrixserverlib.ServerName]map[gomatrixserverlib.KeyID]gomatrixserverlib.PublicKeyLookupResult `json:"keys"` } type InputPublicKeysResponse struct { @@ -35,9 +37,11 @@ func (h *httpServerKeyInternalAPI) InputPublicKeys( } type QueryPublicKeysRequest struct { + Requests map[gomatrixserverlib.ServerName]map[gomatrixserverlib.KeyID]gomatrixserverlib.Timestamp `json:"requests"` } type QueryPublicKeysResponse struct { + Results map[gomatrixserverlib.ServerName]map[gomatrixserverlib.KeyID]gomatrixserverlib.PublicKeyLookupResult `json:"results"` } func (h *httpServerKeyInternalAPI) QueryPublicKeys( diff --git a/serverkeyapi/api/satisfy.go b/serverkeyapi/api/satisfy.go index e43c011d8..32f8aeab9 100644 --- a/serverkeyapi/api/satisfy.go +++ b/serverkeyapi/api/satisfy.go @@ -14,12 +14,42 @@ func (s *httpServerKeyInternalAPI) StoreKeys( ctx context.Context, results map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult, ) error { - return nil + request := InputPublicKeysRequest{} + response := InputPublicKeysResponse{} + for req, res := range results { + if _, ok := request.Keys[req.ServerName]; !ok { + request.Keys[req.ServerName] = map[gomatrixserverlib.KeyID]gomatrixserverlib.PublicKeyLookupResult{} + } + request.Keys[req.ServerName][req.KeyID] = 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) { - return nil, nil + request := QueryPublicKeysRequest{} + response := QueryPublicKeysResponse{} + for req, ts := range requests { + if _, ok := request.Requests[req.ServerName]; !ok { + request.Requests[req.ServerName] = map[gomatrixserverlib.KeyID]gomatrixserverlib.Timestamp{} + } + request.Requests[req.ServerName][req.KeyID] = ts + } + err := s.QueryPublicKeys(ctx, &request, &response) + if err != nil { + return nil, err + } + result := map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult{} + for serverName, byServerName := range response.Results { + for keyID, res := range byServerName { + key := gomatrixserverlib.PublicKeyLookupRequest{ + ServerName: serverName, + KeyID: keyID, + } + result[key] = res + } + } + return result, nil } diff --git a/serverkeyapi/internal/http.go b/serverkeyapi/internal/http.go index a13a62fef..1e857b372 100644 --- a/serverkeyapi/internal/http.go +++ b/serverkeyapi/internal/http.go @@ -6,37 +6,63 @@ import ( "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/serverkeyapi/api" + "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/util" ) func (s *ServerKeyAPI) SetupHTTP(servMux *http.ServeMux) { servMux.Handle(api.ServerKeyQueryPublicKeyPath, common.MakeInternalAPI("queryPublicKeys", func(req *http.Request) util.JSONResponse { - var request api.QueryPublicKeysRequest - var response api.QueryPublicKeysResponse + request := api.QueryPublicKeysRequest{} + response := api.QueryPublicKeysResponse{ + Results: map[gomatrixserverlib.ServerName]map[gomatrixserverlib.KeyID]gomatrixserverlib.PublicKeyLookupResult{}, + } if err := json.NewDecoder(req.Body).Decode(&request); err != nil { return util.MessageResponse(http.StatusBadRequest, err.Error()) } - /* - if err := s.DB.FetchKeys(); err != nil { - return util.ErrorResponse(err) + lookup := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.Timestamp) + for serverName, byServerName := range request.Requests { + for keyID, timestamp := range byServerName { + key := gomatrixserverlib.PublicKeyLookupRequest{ + ServerName: serverName, + KeyID: keyID, + } + lookup[key] = timestamp } - */ + } + keys, err := s.DB.FetchKeys(req.Context(), lookup) + if err != nil { + return util.ErrorResponse(err) + } + for req, res := range keys { + if _, ok := response.Results[req.ServerName]; !ok { + response.Results[req.ServerName] = map[gomatrixserverlib.KeyID]gomatrixserverlib.PublicKeyLookupResult{} + } + response.Results[req.ServerName][req.KeyID] = res + } return util.JSONResponse{Code: http.StatusOK, JSON: &response} }), ) servMux.Handle(api.ServerKeyInputPublicKeyPath, common.MakeInternalAPI("inputPublicKeys", func(req *http.Request) util.JSONResponse { - var request api.InputPublicKeysRequest - var response api.InputPublicKeysResponse + request := api.InputPublicKeysRequest{} + response := api.InputPublicKeysResponse{} if err := json.NewDecoder(req.Body).Decode(&request); err != nil { return util.MessageResponse(http.StatusBadRequest, err.Error()) } - /* - if err := s.DB.FetchKeys(); err != nil { - return util.ErrorResponse(err) + store := make(map[gomatrixserverlib.PublicKeyLookupRequest]gomatrixserverlib.PublicKeyLookupResult) + for serverName, byServerName := range request.Keys { + for keyID, keyResult := range byServerName { + key := gomatrixserverlib.PublicKeyLookupRequest{ + ServerName: serverName, + KeyID: keyID, + } + store[key] = keyResult } - */ + } + if err := s.DB.StoreKeys(req.Context(), store); err != nil { + return util.ErrorResponse(err) + } return util.JSONResponse{Code: http.StatusOK, JSON: &response} }), )