diff --git a/.gitignore b/.gitignore index f5ff5d8b8..55fce30e7 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ rekorServerImagerefs rekorCliImagerefs trillianServerImagerefs trillianSignerImagerefs +cosign.* +signature +rekor.pub diff --git a/pkg/api/entries.go b/pkg/api/entries.go index 64251a16a..378ca8f53 100644 --- a/pkg/api/entries.go +++ b/pkg/api/entries.go @@ -350,7 +350,6 @@ func GetLogEntryByUUIDHandler(params entries.GetLogEntryByUUIDParams) middleware func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Responder { httpReqCtx := params.HTTPRequest.Context() resultPayload := []models.LogEntry{} - tc := NewTrillianClient(httpReqCtx) totalQueries := len(params.Entry.EntryUUIDs) + len(params.Entry.Entries()) + len(params.Entry.LogIndexes) if totalQueries > maxSearchQueries { @@ -415,23 +414,34 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo searchHashes = append(searchHashes, hash) } - searchByHashResults := make([]*trillian.GetEntryAndProofResponse, len(searchHashes)) + searchByHashResults := make([]map[int64]*trillian.GetEntryAndProofResponse, len(searchHashes)) g, _ = errgroup.WithContext(httpReqCtx) for i, hash := range searchHashes { i, hash := i, hash // https://golang.org/doc/faq#closures_and_goroutines g.Go(func() error { - resp := tc.getLeafAndProofByHash(hash) - switch resp.status { - case codes.OK: - case codes.NotFound: - code = http.StatusNotFound - return resp.err - default: + var results map[int64]*trillian.GetEntryAndProofResponse + for _, shard := range api.logRanges.AllShards() { + tcs := NewTrillianClientFromTreeID(httpReqCtx, shard) + resp := tcs.getLeafAndProofByHash(hash) + if resp.status != codes.OK { + continue + } + if resp.err != nil { + continue + } + leafResult := resp.getLeafAndProofResult + if leafResult != nil && leafResult.Leaf != nil { + if results == nil { + results = map[int64]*trillian.GetEntryAndProofResponse{} + } + results[shard] = resp.getLeafAndProofResult + } } - leafResult := resp.getLeafAndProofResult - if leafResult != nil && leafResult.Leaf != nil { - searchByHashResults[i] = leafResult + if results == nil { + code = http.StatusNotFound + return fmt.Errorf("no responses found") } + searchByHashResults[i] = results return nil }) } @@ -440,14 +450,17 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo return handleRekorAPIError(params, code, err, err.Error()) } - for _, leafResp := range searchByHashResults { - if leafResp != nil { - logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tc, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof, api.logRanges.ActiveTreeID(), api.logRanges) + for _, hashMap := range searchByHashResults { + for shard, leafResp := range hashMap { + if leafResp == nil { + continue + } + tcs := NewTrillianClientFromTreeID(httpReqCtx, shard) + logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tcs, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof, shard, api.logRanges) if err != nil { code = http.StatusInternalServerError return handleRekorAPIError(params, code, err, err.Error()) } - resultPayload = append(resultPayload, logEntry) } } diff --git a/pkg/sharding/ranges.go b/pkg/sharding/ranges.go index 859f7e6e3..c5f62dc64 100644 --- a/pkg/sharding/ranges.go +++ b/pkg/sharding/ranges.go @@ -138,6 +138,15 @@ func (l *LogRanges) NoInactive() bool { return l.inactive == nil } +// AllShards returns all shards, starting with the active shard and then the inactive shards +func (l *LogRanges) AllShards() []int64 { + shards := []int64{l.ActiveTreeID()} + for _, in := range l.GetInactive() { + shards = append(shards, in.TreeID) + } + return shards +} + // TotalInactiveLength returns the total length across all inactive shards; // we don't know the length of the active shard. func (l *LogRanges) TotalInactiveLength() int64 { diff --git a/tests/sharding-e2e-test.sh b/tests/sharding-e2e-test.sh index b72b79f10..700f4ad2a 100755 --- a/tests/sharding-e2e-test.sh +++ b/tests/sharding-e2e-test.sh @@ -24,7 +24,6 @@ set -ex echo "Installing createtree..." go install github.com/google/trillian/cmd/createtree@latest - echo "starting services" docker-compose up -d rm ~/.rekor/state.json || true @@ -34,6 +33,7 @@ go build -o rekor-cli ./cmd/rekor-cli REKOR_CLI=$(pwd)/rekor-cli go build -o rekor-server ./cmd/rekor-server + function check_log_index () { logIndex=$1 # make sure we can get this log index from rekor @@ -251,6 +251,11 @@ ENTRY_ID_2=$($REKOR_CLI get --log-index 3 --rekor_server http://localhost:3000 - NUM_ELEMENTS=$(curl -f http://localhost:3000/api/v1/log/entries/retrieve -H "Content-Type: application/json" -H "Accept: application/json" -d "{ \"entryUUIDs\": [\"$ENTRY_ID_1\"]}" | jq '. | length') stringsMatch $NUM_ELEMENTS "1" +# Make sure we can verify the entry we entered into the now-inactive shard +pushd tests +$REKOR_CLI verify --artifact test_file.txt --signature test_file.sig --public-key test_public_key.key --rekor_server http://localhost:3000 +popd + # -f makes sure we exit on failure NUM_ELEMENTS=$(curl -f http://localhost:3000/api/v1/log/entries/retrieve -H "Content-Type: application/json" -H "Accept: application/json" -d "{ \"entryUUIDs\": [\"$ENTRY_ID_1\", \"$ENTRY_ID_2\"]}" | jq '. | length') stringsMatch $NUM_ELEMENTS "2"