Skip to content

Commit

Permalink
fix: make tlog entry lookups for online verification shard-aware
Browse files Browse the repository at this point in the history
Signed-off-by: Asra Ali <asraa@google.com>

fix tests

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa committed Sep 30, 2022
1 parent 983c364 commit 193f041
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 18 deletions.
24 changes: 23 additions & 1 deletion cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,29 @@ func tlogFindCertificate(ctx context.Context, rekorClient *client.Rekor,
func tlogFindEntry(ctx context.Context, client *client.Rekor,
blobBytes []byte, sig string, pem []byte) (*models.LogEntryAnon, error) {
b64sig := base64.StdEncoding.EncodeToString([]byte(sig))
return cosign.FindTlogEntry(ctx, client, b64sig, blobBytes, pem)
tlogEntries, err := cosign.FindTlogEntry(ctx, client, b64sig, blobBytes, pem)
if err != nil {
return nil, err
}
if len(tlogEntries) == 0 {
return nil, fmt.Errorf("no valid tlog entries found with proposed entry")
}
// Always return the earliest integrated entry. That
// always suffices for verification of signature time.
var earliestLogEntry *models.LogEntryAnon
var earliestLogEntryTime *time.Time
// We'll always return a tlog entry because there's at least one entry in the log.
for _, entry := range tlogEntries {
entryTime := time.Unix(*entry.IntegratedTime, 0)
if earliestLogEntryTime == nil || entryTime.Before(*earliestLogEntryTime) {
earliestLogEntryTime = &entryTime
earliestLogEntry = &entry
}
}
if earliestLogEntry == nil {
return nil, fmt.Errorf("no valid tlog entries found with proposed entry")
}
return earliestLogEntry, nil
}

// signatures returns the raw signature
Expand Down
27 changes: 13 additions & 14 deletions pkg/cosign/tlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ func proposedEntry(b64Sig string, payload, pubKey []byte) ([]models.ProposedEntr
return proposedEntry, nil
}

func FindTlogEntry(ctx context.Context, rekorClient *client.Rekor, b64Sig string, payload, pubKey []byte) (entry *models.LogEntryAnon, err error) {
func FindTlogEntry(ctx context.Context, rekorClient *client.Rekor,
b64Sig string, payload, pubKey []byte) ([]models.LogEntryAnon, error) {
searchParams := entries.NewSearchLogQueryParamsWithContext(ctx)
searchLogQuery := models.SearchLogQuery{}
proposedEntry, err := proposedEntry(b64Sig, payload, pubKey)
Expand All @@ -406,23 +407,21 @@ func FindTlogEntry(ctx context.Context, rekorClient *client.Rekor, b64Sig string
}
if len(resp.Payload) == 0 {
return nil, errors.New("signature not found in transparency log")
} else if len(resp.Payload) > 1 {
return nil, errors.New("multiple entries returned; this should not happen")
}
logEntry := resp.Payload[0]
if len(logEntry) != 1 {
return nil, errors.New("UUID value can not be extracted")
}

var tlogEntry models.LogEntryAnon
for k, e := range logEntry {
// Check body hash matches uuid
if err := verifyUUID(k, e); err != nil {
return nil, err
// This may accumulate multiple entries on multiple tree IDs.
results := make([]models.LogEntryAnon, 0)
for _, logEntry := range resp.GetPayload() {
for k, e := range logEntry {
// Check body hash matches uuid
if err := verifyUUID(k, e); err != nil {
continue
}
results = append(results, e)
}
tlogEntry = e
}
return &tlogEntry, nil

return results, nil
}

func FindTLogEntriesByPayload(ctx context.Context, rekorClient *client.Rekor, payload []byte) (uuids []string, err error) {
Expand Down
26 changes: 24 additions & 2 deletions pkg/cosign/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,33 @@ func tlogValidateEntry(ctx context.Context, client *client.Rekor, sig oci.Signat
if err != nil {
return nil, err
}
e, err := FindTlogEntry(ctx, client, b64sig, payload, pem)
tlogEntries, err := FindTlogEntry(ctx, client, b64sig, payload, pem)
if err != nil {
return nil, err
}
return e, VerifyTLogEntry(ctx, client, e)
if len(tlogEntries) == 0 {
return nil, fmt.Errorf("no valid tlog entries found with proposed entry")
}
// Always return the earliest integrated entry. That
// always suffices for verification of signature time.
var earliestLogEntry *models.LogEntryAnon
earliestLogEntryTime := time.Now()
entryVerificationErrs := make([]string, 0)
for _, entry := range tlogEntries {
if err := VerifyTLogEntry(ctx, client, &entry); err != nil {
entryVerificationErrs = append(entryVerificationErrs, err.Error())
continue
}
entryTime := time.Unix(*entry.IntegratedTime, 0)
if entryTime.Before(earliestLogEntryTime) {
earliestLogEntryTime = entryTime
earliestLogEntry = &entry
}
}
if earliestLogEntry == nil {
return nil, fmt.Errorf("no valid tlog entries found %s", strings.Join(entryVerificationErrs, ", "))
}
return earliestLogEntry, nil
}

type fakeOCISignatures struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/cosign/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ func TestVerifyImageSignatureWithSigVerifierAndRekor(t *testing.T) {
// but we should look into improving this once there is an in-memory
// Rekor client that is capable of performing inclusion proof validation
// in unit tests.
t.Fatal("expected error while verifying signature")
t.Fatalf("expected error while verifying signature, got %s", err)
}
}

Expand Down

0 comments on commit 193f041

Please sign in to comment.