Skip to content

Commit

Permalink
Search through all shards when searching by hash (#1082)
Browse files Browse the repository at this point in the history
* Search through all shards when searching by hash

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

* Add cosign sign-blob and verify-blob to sharding e2e test

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

* Search hashes through all shards

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

* Fix searching by hash

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

* Use rekor-cli instead of cosign for testing upload and verify

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>

Signed-off-by: Priya Wadhwa <priya@chainguard.dev>
  • Loading branch information
priyawadhwa committed Sep 28, 2022
1 parent ca2dce6 commit 838f40b
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -17,3 +17,6 @@ rekorServerImagerefs
rekorCliImagerefs
trillianServerImagerefs
trillianSignerImagerefs
cosign.*
signature
rekor.pub
45 changes: 29 additions & 16 deletions pkg/api/entries.go
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
})
}
Expand All @@ -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)
}
}
Expand Down
9 changes: 9 additions & 0 deletions pkg/sharding/ranges.go
Expand Up @@ -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 {
Expand Down
7 changes: 6 additions & 1 deletion tests/sharding-e2e-test.sh
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 838f40b

Please sign in to comment.