Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: enable parsing of UUID-only rekor entry ID #2887

Merged
merged 4 commits into from Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions pkg/fanal/artifact/image/remote_sbom.go
@@ -1,6 +1,7 @@
package image

import (
"bytes"
"context"
"encoding/json"
"errors"
Expand Down Expand Up @@ -61,10 +62,10 @@ func (a Artifact) inspectSBOMAttestation(ctx context.Context) (ftypes.ArtifactRe
for _, id := range entryIDs {
log.Logger.Debugf("Inspecting Rekor entry: %s", id)
ref, err := a.inspectRekorRecord(ctx, client, id)
if errors.Is(err, rekor.ErrNoAttestation) {
if errors.Is(err, rekor.ErrNoAttestation) || errors.Is(err, errNoSBOMFound) {
continue
} else if err != nil {
return ftypes.ArtifactReference{}, xerrors.Errorf("rekor rekord inspection error: %w", err)
return ftypes.ArtifactReference{}, xerrors.Errorf("rekor record inspection error: %w", err)
}
return ref, nil
}
Expand Down Expand Up @@ -111,6 +112,11 @@ func (a Artifact) inspectRekorRecord(ctx context.Context, client *rekor.Client,
}

func (a Artifact) parseStatement(entry rekor.Entry) (json.RawMessage, error) {
// Skip base64-encoded attestation
if bytes.HasPrefix(entry.Statement, []byte(`eyJ`)) {
return nil, errNoSBOMFound
}

// Parse statement of in-toto attestation
var raw json.RawMessage
statement := &in_toto.Statement{
Expand Down
28 changes: 18 additions & 10 deletions pkg/rekor/client.go
Expand Up @@ -22,20 +22,28 @@ const (

var ErrNoAttestation = xerrors.Errorf("Rekor attestations not found")

// EntryID is a hex-format string. The length of the string is 80.
// It consists of two elements, the TreeID and the UUID.
// EntryID is a hex-format string. The length of the string is 80 or 64.
// If the length is 80, it consists of two elements, the TreeID and the UUID. If the length is 64,
// it consists only of the UUID.
// cf. https://github.com/sigstore/rekor/blob/4923f60f4ae55ccd4baf28d182e8f55c2d8097d3/pkg/sharding/sharding.go#L25-L36
type EntryID string
type EntryID struct {
TreeID string
UUID string
}

func NewEntryID(entryID string) (EntryID, error) {
if len(entryID) == treeIDLen+uuidLen {
return EntryID(entryID), nil
switch len(entryID) {
case treeIDLen + uuidLen:
return EntryID{TreeID: entryID[:treeIDLen], UUID: entryID[treeIDLen:]}, nil
case uuidLen:
return EntryID{TreeID: "", UUID: entryID}, nil
default:
return EntryID{}, xerrors.New("invalid Entry ID length")
}
return "", xerrors.Errorf("invalid Entry ID length")
}

func (e EntryID) UUID() string {
return string(e)[treeIDLen:]
func (e EntryID) String() string {
return e.TreeID + e.UUID
}

type Entry struct {
Expand Down Expand Up @@ -79,15 +87,15 @@ func (c *Client) Search(ctx context.Context, hash string) ([]EntryID, error) {
}

func (c *Client) GetEntry(ctx context.Context, entryID EntryID) (Entry, error) {
params := entries.NewGetLogEntryByUUIDParamsWithContext(ctx).WithEntryUUID(string(entryID))
params := entries.NewGetLogEntryByUUIDParamsWithContext(ctx).WithEntryUUID(entryID.String())

// TODO: bulk search
resp, err := c.Entries.GetLogEntryByUUID(params)
if err != nil {
return Entry{}, xerrors.Errorf("failed to get log entry by UUID: %w", err)
}

entry, found := resp.Payload[entryID.UUID()]
entry, found := resp.Payload[entryID.UUID]
if !found {
return Entry{}, ErrNoAttestation
}
Expand Down
24 changes: 20 additions & 4 deletions pkg/rekor/client_test.go
Expand Up @@ -30,8 +30,18 @@ func TestClient_Search(t *testing.T) {
hash: "92251458088c638061cda8fd8b403b76d661a4dc6b7ee71b6affcf1872557b2b",
},
want: []rekor.EntryID{
"392f8ecba72f4326eb624a7403756250b5f2ad58842a99d1653cd6f147f4ce9eda2da350bd908a55",
"392f8ecba72f4326414eaca77bd19bf5f378725d7fd79309605a81b69cc0101f5cd3119d0a216523",
{
TreeID: "392f8ecba72f4326",
UUID: "eb624a7403756250b5f2ad58842a99d1653cd6f147f4ce9eda2da350bd908a55",
},
{
TreeID: "392f8ecba72f4326",
UUID: "414eaca77bd19bf5f378725d7fd79309605a81b69cc0101f5cd3119d0a216523",
},
{
TreeID: "",
UUID: "414eaca77bd19bf5f378725d7fd79309605a81b69cc0101f5cd3119d0a012345",
},
},
},
{
Expand Down Expand Up @@ -80,7 +90,10 @@ func TestClient_GetEntry(t *testing.T) {
name: "happy path",
mockResponseFile: "testdata/log-entry.json",
args: args{
uuid: "392f8ecba72f43268b5b2debb565fd5cb05ae0d3935351fa3faabce558bede72e197b5722a742b1e",
uuid: rekor.EntryID{
TreeID: "392f8ecba72f4326",
UUID: "8b5b2debb565fd5cb05ae0d3935351fa3faabce558bede72e197b5722a742b1e",
},
},
want: rekor.Entry{
Statement: []byte(`{"_type":"https://in-toto.io/Statement/v0.1","predicateType":"cosign.sigstore.dev/attestation/v1","subject":[{"name":"ghcr.io/aquasecurity/trivy-test-images","digest":{"sha256":"20d3f693dcffa44d6b24eae88783324d25cc132c22089f70e4fbfb858625b062"}}],"predicate":{"Data":"\"foo\\n\"\n","Timestamp":"2022-08-26T01:17:17Z"}}`),
Expand All @@ -90,7 +103,10 @@ func TestClient_GetEntry(t *testing.T) {
name: "no attestation",
mockResponseFile: "testdata/log-entry-no-attestation.json",
args: args{
uuid: "392f8ecba72f43268b5b2debb565fd5cb05ae0d3935351fa3faabce558bede72e197b5722a742b1e",
uuid: rekor.EntryID{
TreeID: "392f8ecba72f4326",
UUID: "8b5b2debb565fd5cb05ae0d3935351fa3faabce558bede72e197b5722a742b1e",
},
},
wantErr: rekor.ErrNoAttestation,
},
Expand Down
3 changes: 2 additions & 1 deletion pkg/rekor/testdata/search-response.json
@@ -1,4 +1,5 @@
[
"392f8ecba72f4326eb624a7403756250b5f2ad58842a99d1653cd6f147f4ce9eda2da350bd908a55",
"392f8ecba72f4326414eaca77bd19bf5f378725d7fd79309605a81b69cc0101f5cd3119d0a216523"
"392f8ecba72f4326414eaca77bd19bf5f378725d7fd79309605a81b69cc0101f5cd3119d0a216523",
"414eaca77bd19bf5f378725d7fd79309605a81b69cc0101f5cd3119d0a012345"
]