From ee3e12f3228b876b9fff8466b6d9ad3b7ea81816 Mon Sep 17 00:00:00 2001 From: Rasmus Dahlberg Date: Thu, 22 Oct 2020 16:32:15 +0200 Subject: added start on get-entries code path If the provided range is (mostly) valid the corresponding log entries are fetched from the Trillian back-end and returned as a JSON object. --- handler.go | 39 +++++++++++++++++++++++++++++++++++++-- type.go | 28 +++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/handler.go b/handler.go index 6c81d3e..4d2ace8 100644 --- a/handler.go +++ b/handler.go @@ -120,9 +120,44 @@ func getEntries(ctx context.Context, i *instance, w http.ResponseWriter, r *http if err := request.Unpack(r); err != nil { return http.StatusBadRequest, err } - glog.Infof("valid request: %v", request) - return http.StatusOK, nil // TODO + trillianRequest := trillian.GetLeavesByRangeRequest{ + LogId: i.logID, + StartIndex: request.Start, + Count: request.End - request.Start + 1, + } + trillianResponse, err := i.client.GetLeavesByRange(ctx, &trillianRequest) + if err != nil { + return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange request failed: %v", err) + } + + // Santity check + if len(trillianResponse.Leaves) > int(request.End-request.Start+1) { + return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned too many leaves: %d for [%d,%d]", len(trillianResponse.Leaves), request.Start, request.End) + } + for i, leaf := range trillianResponse.Leaves { + if leaf.LeafIndex != request.Start+int64(i) { + return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned unexpected leaf index: wanted %d, got %d", request.Start+int64(i), leaf.LeafIndex) + } + + glog.Infof("Entry(%d) => %v", request.Start+int64(i), leaf.GetLeafValue()) + } + // TODO: use the returned root for tree_size santity checking against start? + + w.Header().Set("Content-Type", "application/json") + data, err := NewGetEntriesResponse(trillianResponse.Leaves) + if err != nil { + return http.StatusInternalServerError, fmt.Errorf("failed createing GetEntriesResponse: %v", err) + } + json, err := json.Marshal(&data) + if err != nil { + return http.StatusInternalServerError, fmt.Errorf("failed json-encoding GetEntriesResponse: %v", err) + } + _, err = w.Write(json) + if err != nil { + return http.StatusInternalServerError, fmt.Errorf("failed writing get-entries response: %v", err) + } + return http.StatusOK, nil } // getAnchors provides a list of configured trust anchors diff --git a/type.go b/type.go index dcb2a9a..11fafe1 100644 --- a/type.go +++ b/type.go @@ -8,6 +8,7 @@ import ( "net/http" "github.com/google/certificate-transparency-go/tls" + "github.com/google/trillian" ) // StFormat defines a particular StItem type that is versioned @@ -104,7 +105,7 @@ type AddEntryRequest struct { // GetEntriesRequest is a collection of get-entry input parameters type GetEntriesRequest struct { Start int64 - End int64 + End int64 } func (r *GetEntriesRequest) Unpack(httpRequest *http.Request) error { @@ -129,3 +130,28 @@ func (r *GetEntriesRequest) Unpack(httpRequest *http.Request) error { // TODO: check that end is not past the most recent STH. Yes -> truncate return nil } + +type GetEntryResponse struct { + Leaf string `json:"leaf"` + Signature string `json:"signature"` + Chain []string `json:chain` +} + +func NewGetEntryResponse(leaf []byte) GetEntryResponse { + return GetEntryResponse{ + Leaf: base64.StdEncoding.EncodeToString(leaf), + // TODO: add signature and chain + } +} + +type GetEntriesResponse struct { + Entries []GetEntryResponse `json:"entries"` +} + +func NewGetEntriesResponse(leaves []*trillian.LogLeaf) (GetEntriesResponse, error) { + entries := make([]GetEntryResponse, 0, len(leaves)) + for _, leaf := range leaves { + entries = append(entries, NewGetEntryResponse(leaf.GetLeafValue())) // TODO: add signature and chain + } + return GetEntriesResponse{entries}, nil +} -- cgit v1.2.3