diff options
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)), "/") -} |