Add function for making authed federation APIs (#208)

This commit is contained in:
Mark Haines 2017-09-04 13:14:01 +01:00 committed by GitHub
parent d4cce7369f
commit 643d05b157
4 changed files with 44 additions and 40 deletions

View file

@ -2,24 +2,26 @@ package common
import ( import (
"net/http" "net/http"
"time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/matrix-org/dendrite/clientapi/auth" "github.com/matrix-org/dendrite/clientapi/auth"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes" "github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
// MakeAuthAPI turns a util.JSONRequestHandler function into an http.Handler which checks the access token in the request. // MakeAuthAPI turns a util.JSONRequestHandler function into an http.Handler which checks the access token in the request.
func MakeAuthAPI(metricsName string, deviceDB auth.DeviceDatabase, f func(*http.Request, *authtypes.Device) util.JSONResponse) http.Handler { func MakeAuthAPI(metricsName string, deviceDB auth.DeviceDatabase, f func(*http.Request, *authtypes.Device) util.JSONResponse) http.Handler {
h := util.NewJSONRequestHandler(func(req *http.Request) util.JSONResponse { h := func(req *http.Request) util.JSONResponse {
device, resErr := auth.VerifyAccessToken(req, deviceDB) device, resErr := auth.VerifyAccessToken(req, deviceDB)
if resErr != nil { if resErr != nil {
return *resErr return *resErr
} }
return f(req, device) return f(req, device)
}) }
return prometheus.InstrumentHandler(metricsName, util.MakeJSONAPI(h)) return MakeAPI(metricsName, h)
} }
// MakeAPI turns a util.JSONRequestHandler function into an http.Handler. // MakeAPI turns a util.JSONRequestHandler function into an http.Handler.
@ -28,6 +30,25 @@ func MakeAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.H
return prometheus.InstrumentHandler(metricsName, util.MakeJSONAPI(h)) return prometheus.InstrumentHandler(metricsName, util.MakeJSONAPI(h))
} }
// MakeFedAPI makes an http.Handler that checks matrix federation authentication.
func MakeFedAPI(
metricsName string,
serverName gomatrixserverlib.ServerName,
keyRing gomatrixserverlib.KeyRing,
f func(*http.Request, *gomatrixserverlib.FederationRequest) util.JSONResponse,
) http.Handler {
h := func(req *http.Request) util.JSONResponse {
fedReq, errResp := gomatrixserverlib.VerifyHTTPRequest(
req, time.Now(), serverName, keyRing,
)
if fedReq == nil {
return errResp
}
return f(req, fedReq)
}
return MakeAPI(metricsName, h)
}
// SetupHTTPAPI registers an HTTP API mux under /api and sets up a metrics // SetupHTTPAPI registers an HTTP API mux under /api and sets up a metrics
// listener. // listener.
func SetupHTTPAPI(servMux *http.ServeMux, apiMux *mux.Router) { func SetupHTTPAPI(servMux *http.ServeMux, apiMux *mux.Router) {

View file

@ -16,17 +16,16 @@ package routing
import ( import (
"net/http" "net/http"
"time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/matrix-org/dendrite/clientapi/producers" "github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/dendrite/common"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
"github.com/matrix-org/dendrite/federationapi/readers" "github.com/matrix-org/dendrite/federationapi/readers"
"github.com/matrix-org/dendrite/federationapi/writers" "github.com/matrix-org/dendrite/federationapi/writers"
"github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util" "github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus"
) )
const ( const (
@ -46,7 +45,7 @@ func Setup(
v2keysmux := apiMux.PathPrefix(pathPrefixV2Keys).Subrouter() v2keysmux := apiMux.PathPrefix(pathPrefixV2Keys).Subrouter()
v1fedmux := apiMux.PathPrefix(pathPrefixV1Federation).Subrouter() v1fedmux := apiMux.PathPrefix(pathPrefixV1Federation).Subrouter()
localKeys := makeAPI("localkeys", func(req *http.Request) util.JSONResponse { localKeys := common.MakeAPI("localkeys", func(req *http.Request) util.JSONResponse {
return readers.LocalKeys(req, cfg) return readers.LocalKeys(req, cfg)
}) })
@ -57,30 +56,25 @@ func Setup(
v2keysmux.Handle("/server/{keyID}", localKeys) v2keysmux.Handle("/server/{keyID}", localKeys)
v2keysmux.Handle("/server/", localKeys) v2keysmux.Handle("/server/", localKeys)
v1fedmux.Handle("/send/{txnID}/", makeAPI("federation_send", v1fedmux.Handle("/send/{txnID}/", common.MakeFedAPI(
func(req *http.Request) util.JSONResponse { "federation_send", cfg.Matrix.ServerName, keys,
vars := mux.Vars(req) func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
vars := mux.Vars(httpReq)
return writers.Send( return writers.Send(
req, gomatrixserverlib.TransactionID(vars["txnID"]), httpReq, request, gomatrixserverlib.TransactionID(vars["txnID"]),
time.Now(),
cfg, query, producer, keys, federation, cfg, query, producer, keys, federation,
) )
}, },
)) ))
v1fedmux.Handle("/invite/{roomID}/{eventID}", makeAPI("federation_invite", v1fedmux.Handle("/invite/{roomID}/{eventID}", common.MakeFedAPI(
func(req *http.Request) util.JSONResponse { "federation_invite", cfg.Matrix.ServerName, keys,
vars := mux.Vars(req) func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest) util.JSONResponse {
vars := mux.Vars(httpReq)
return writers.Invite( return writers.Invite(
req, vars["roomID"], vars["eventID"], httpReq, request, vars["roomID"], vars["eventID"],
time.Now(),
cfg, producer, keys, cfg, producer, keys,
) )
}, },
)) ))
} }
func makeAPI(metricsName string, f func(*http.Request) util.JSONResponse) http.Handler {
h := util.NewJSONRequestHandler(f)
return prometheus.InstrumentHandler(metricsName, util.MakeJSONAPI(h))
}

View file

@ -3,31 +3,25 @@ package writers
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"time"
"github.com/matrix-org/util"
"github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/clientapi/producers" "github.com/matrix-org/dendrite/clientapi/producers"
"github.com/matrix-org/dendrite/common/config" "github.com/matrix-org/dendrite/common/config"
"github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
) )
// Invite implements /_matrix/federation/v1/invite/{roomID}/{eventID} // Invite implements /_matrix/federation/v1/invite/{roomID}/{eventID}
func Invite( func Invite(
req *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest,
roomID string, roomID string,
eventID string, eventID string,
now time.Time,
cfg config.Dendrite, cfg config.Dendrite,
producer *producers.RoomserverProducer, producer *producers.RoomserverProducer,
keys gomatrixserverlib.KeyRing, keys gomatrixserverlib.KeyRing,
) util.JSONResponse { ) util.JSONResponse {
request, errResp := gomatrixserverlib.VerifyHTTPRequest(req, now, cfg.Matrix.ServerName, keys)
if request == nil {
return errResp
}
// Decode the event JSON from the request. // Decode the event JSON from the request.
var event gomatrixserverlib.Event var event gomatrixserverlib.Event
@ -70,7 +64,7 @@ func Invite(
}} }}
verifyResults, err := keys.VerifyJSONs(verifyRequests) verifyResults, err := keys.VerifyJSONs(verifyRequests)
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(httpReq, err)
} }
if verifyResults[0].Error != nil { if verifyResults[0].Error != nil {
return util.JSONResponse{ return util.JSONResponse{
@ -86,7 +80,7 @@ func Invite(
// Add the invite event to the roomserver. // Add the invite event to the roomserver.
if err = producer.SendInvite(signedEvent); err != nil { if err = producer.SendInvite(signedEvent); err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(httpReq, err)
} }
// Return the signed event to the originating server, it should then tell // Return the signed event to the originating server, it should then tell

View file

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"time"
"github.com/matrix-org/dendrite/clientapi/httputil" "github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror" "github.com/matrix-org/dendrite/clientapi/jsonerror"
@ -17,19 +16,15 @@ import (
// Send implements /_matrix/federation/v1/send/{txnID} // Send implements /_matrix/federation/v1/send/{txnID}
func Send( func Send(
req *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest,
txnID gomatrixserverlib.TransactionID, txnID gomatrixserverlib.TransactionID,
now time.Time,
cfg config.Dendrite, cfg config.Dendrite,
query api.RoomserverQueryAPI, query api.RoomserverQueryAPI,
producer *producers.RoomserverProducer, producer *producers.RoomserverProducer,
keys gomatrixserverlib.KeyRing, keys gomatrixserverlib.KeyRing,
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
) util.JSONResponse { ) util.JSONResponse {
request, errResp := gomatrixserverlib.VerifyHTTPRequest(req, now, cfg.Matrix.ServerName, keys)
if request == nil {
return errResp
}
t := txnReq{ t := txnReq{
query: query, query: query,
@ -50,7 +45,7 @@ func Send(
resp, err := t.processTransaction() resp, err := t.processTransaction()
if err != nil { if err != nil {
return httputil.LogThenError(req, err) return httputil.LogThenError(httpReq, err)
} }
return util.JSONResponse{ return util.JSONResponse{