diff options
author | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2021-02-25 14:36:35 +0100 |
---|---|---|
committer | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2021-02-25 14:36:35 +0100 |
commit | c05c22ddbc771e7713849cae40f9d91bfafa0503 (patch) | |
tree | b97d11ab2a914806e6f671f9aff1cab9767b2eab /instance.go | |
parent | c9b4b43654f0ff26207cc63449f13298cd3c56e8 (diff) |
major refactor based on README.md and TODOs
Updated types, improved units tests, isolated most test data to have
it in one place, renamed and created new files to improve readability,
and fixed a bunch of minor TODOs.
Diffstat (limited to 'instance.go')
-rw-r--r-- | instance.go | 138 |
1 files changed, 42 insertions, 96 deletions
diff --git a/instance.go b/instance.go index c729bc8..6f1314b 100644 --- a/instance.go +++ b/instance.go @@ -1,123 +1,69 @@ package stfe import ( - "crypto" + "context" "fmt" - "strings" "time" "net/http" + "github.com/golang/glog" "github.com/google/trillian" - "github.com/system-transparency/stfe/namespace" ) -// Instance is an instance of a particular log front-end +// Instance is an instance of the system transparency front-end type Instance struct { Client trillian.TrillianLogClient - SthSource SthSource LogParameters *LogParameters + SthSource SthSource } -// LogParameters is a collection of log parameters -type LogParameters struct { - LogId []byte // used externally by everyone - TreeId int64 // used internally by Trillian - Prefix string // e.g., "test" for <base>/test - MaxRange int64 // max entries per get-entries request - Submitters *namespace.NamespacePool // trusted submitters - Witnesses *namespace.NamespacePool // trusted witnesses - Deadline time.Duration // gRPC deadline - Interval time.Duration // cosigning sth frequency - Signer crypto.Signer // interface to access private key - HashType crypto.Hash // hash function used by Trillian +// Handlers returns a list of STFE handlers +func (i *Instance) Handlers() []Handler { + return []Handler{ + Handler{Instance: i, Handler: addEntry, Endpoint: EndpointAddEntry, Method: http.MethodPost}, + Handler{Instance: i, Handler: addCosignature, Endpoint: EndpointAddCosignature, Method: http.MethodPost}, + Handler{Instance: i, Handler: getLatestSth, Endpoint: EndpointGetLatestSth, Method: http.MethodGet}, + Handler{Instance: i, Handler: getStableSth, Endpoint: EndpointGetStableSth, Method: http.MethodGet}, + Handler{Instance: i, Handler: getCosignedSth, Endpoint: EndpointGetCosignedSth, Method: http.MethodGet}, + Handler{Instance: i, Handler: getProofByHash, Endpoint: EndpointGetProofByHash, Method: http.MethodPost}, + Handler{Instance: i, Handler: getConsistencyProof, Endpoint: EndpointGetConsistencyProof, Method: http.MethodPost}, + Handler{Instance: i, Handler: getEntries, Endpoint: EndpointGetEntries, Method: http.MethodPost}, + } } -// Endpoint is a named HTTP API endpoint -type Endpoint string - -const ( - EndpointAddEntry = Endpoint("add-entry") - EndpointAddCosignature = Endpoint("add-cosignature") - EndpointGetEntries = Endpoint("get-entries") - EndpointGetAnchors = Endpoint("get-anchors") - EndpointGetProofByHash = Endpoint("get-proof-by-hash") - EndpointGetConsistencyProof = Endpoint("get-consistency-proof") - EndpointGetLatestSth = Endpoint("get-latest-sth") - EndpointGetStableSth = Endpoint("get-stable-sth") - EndpointGetCosignedSth = Endpoint("get-cosigned-sth") -) - -func (i Instance) String() string { - return fmt.Sprintf("%s\n", i.LogParameters) +// Handler implements the http.Handler interface, and contains a reference +// to an STFE server instance as well as a function that uses it. +type Handler struct { + Instance *Instance + Endpoint Endpoint + Method string + Handler func(context.Context, *Instance, http.ResponseWriter, *http.Request) (int, error) } -func (lp LogParameters) String() string { - return fmt.Sprintf("LogId(%s) TreeId(%d) Prefix(%s) MaxRange(%d) Submitters(%d) Witnesses(%d) Deadline(%v) Interval(%v)", lp.id(), lp.TreeId, lp.Prefix, lp.MaxRange, len(lp.Submitters.List()), len(lp.Witnesses.List()), lp.Deadline, lp.Interval) -} +// ServeHTTP is part of the http.Handler interface +func (a Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // export prometheus metrics + var now time.Time = time.Now() + var statusCode int + defer func() { + rspcnt.Inc(string(a.Instance.LogParameters.LogIdBytes), string(a.Endpoint), fmt.Sprintf("%d", statusCode)) + latency.Observe(time.Now().Sub(now).Seconds(), string(a.Instance.LogParameters.LogIdBytes), string(a.Endpoint), fmt.Sprintf("%d", statusCode)) + }() + reqcnt.Inc(string(a.Instance.LogParameters.LogIdBytes), string(a.Endpoint)) -func (e Endpoint) String() string { - return string(e) -} + ctx, cancel := context.WithDeadline(r.Context(), now.Add(a.Instance.LogParameters.Deadline)) + defer cancel() -// NewInstance creates a new STFE instance -func NewInstance(lp *LogParameters, client trillian.TrillianLogClient, source SthSource) *Instance { - return &Instance{ - LogParameters: lp, - Client: client, - SthSource: source, + if r.Method != a.Method { + glog.Warningf("%s/%s: got HTTP %s, wanted HTTP %s", a.Instance.LogParameters.Prefix, string(a.Endpoint), r.Method, a.Method) + http.Error(w, "", http.StatusMethodNotAllowed) + return } -} -// NewLogParameters creates new log parameters. Note that the signer is -// assumed to be an ed25519 signing key. Could be fixed at some point. -func NewLogParameters(signer crypto.Signer, logId *namespace.Namespace, treeId int64, prefix string, submitters, witnesses *namespace.NamespacePool, maxRange int64, interval, deadline time.Duration) (*LogParameters, error) { - if signer == nil { - return nil, fmt.Errorf("need a signer but got none") - } - if maxRange < 1 { - return nil, fmt.Errorf("max range must be at least one") - } - lid, err := logId.Marshal() + statusCode, err := a.Handler(ctx, a.Instance, w, r) if err != nil { - return nil, fmt.Errorf("failed encoding log identifier: %v", err) - } - return &LogParameters{ - LogId: lid, - TreeId: treeId, - Prefix: prefix, - MaxRange: maxRange, - Submitters: submitters, - Witnesses: witnesses, - Deadline: deadline, - Interval: interval, - Signer: signer, - HashType: crypto.SHA256, // STFE assumes RFC 6962 hashing - }, nil -} - -// Handlers returns a list of STFE handlers -func (i *Instance) Handlers() []Handler { - return []Handler{ - Handler{instance: i, handler: addEntry, endpoint: EndpointAddEntry, method: http.MethodPost}, - Handler{instance: i, handler: addCosi, endpoint: EndpointAddCosignature, method: http.MethodPost}, - Handler{instance: i, handler: getEntries, endpoint: EndpointGetEntries, method: http.MethodGet}, - Handler{instance: i, handler: getAnchors, endpoint: EndpointGetAnchors, method: http.MethodGet}, - Handler{instance: i, handler: getProofByHash, endpoint: EndpointGetProofByHash, method: http.MethodGet}, - Handler{instance: i, handler: getConsistencyProof, endpoint: EndpointGetConsistencyProof, method: http.MethodGet}, - Handler{instance: i, handler: getSth, endpoint: EndpointGetLatestSth, method: http.MethodGet}, - Handler{instance: i, handler: getStableSth, endpoint: EndpointGetStableSth, method: http.MethodGet}, - Handler{instance: i, handler: getCosi, endpoint: EndpointGetCosignedSth, method: http.MethodGet}, + glog.Warningf("handler error %s/%s: %v", a.Instance.LogParameters.Prefix, a.Endpoint, err) + http.Error(w, "", statusCode) } } - -// id formats the log's identifier as base64 -func (i *LogParameters) id() string { - return b64(i.LogId) -} - -// Path joins a number of components to form a full endpoint path, e.g., base -// ("example.com"), prefix ("st/v1"), and the endpoint itself ("get-sth"). -func (e Endpoint) Path(components ...string) string { - return strings.Join(append(components, string(e)), "/") -} |