Skip to content

Commit

Permalink
verify-blob-attestation: Loosen arg requirements if --check-claims=fa…
Browse files Browse the repository at this point in the history
…lse (#2746)

1. Update --check-claims documentation to better describe the behavior
   of the flag.
2. Modify verify-blob-attestation to not require a blob argument if
   --check-claims=false. This file is not used if we're not checking
   claims - it can be set to anything and still pass.

Signed-off-by: Billy Lynch <billy@chainguard.dev>
  • Loading branch information
wlynch committed Mar 8, 2023
1 parent 4591600 commit 2670ed3
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 23 deletions.
2 changes: 1 addition & 1 deletion cmd/cosign/cli/options/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func (o *VerifyBlobAttestationOptions) AddFlags(cmd *cobra.Command) {
"path to bundle FILE")

cmd.Flags().BoolVar(&o.CheckClaims, "check-claims", true,
"whether to check the claims found")
"if true, verifies the provided blob's sha256 digest exists as an in-toto subject within the attestation. If false, only the DSSE envelope is verified.")

cmd.Flags().StringVar(&o.RFC3161TimestampPath, "rfc3161-timestamp", "",
"path to RFC3161 timestamp FILE")
Expand Down
11 changes: 8 additions & 3 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ The blob may be specified as a path to a file.`,
`,

Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
PersistentPreRun: options.BindViper,
RunE: func(cmd *cobra.Command, args []string) error {
ko := options.KeyOpts{
Expand Down Expand Up @@ -356,10 +356,15 @@ The blob may be specified as a path to a file.`,
Offline: o.CommonVerifyOptions.Offline,
IgnoreTlog: o.CommonVerifyOptions.IgnoreTlog,
}
if len(args) != 1 {
// We only use the blob if we are checking claims.
if len(args) == 0 && o.CheckClaims {
return fmt.Errorf("no path to blob passed in, run `cosign verify-blob-attestation -h` for more help")
}
return v.Exec(cmd.Context(), args[0])
var path string
if len(args) > 0 {
path = args[0]
}
return v.Exec(cmd.Context(), path)
},
}

Expand Down
36 changes: 18 additions & 18 deletions cmd/cosign/cli/verify/verify_blob_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,26 +108,26 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
Offline: c.Offline,
IgnoreTlog: c.IgnoreTlog,
}
var h v1.Hash
if c.CheckClaims {
co.ClaimVerifier = cosign.IntotoSubjectClaimVerifier
}

// Get the actual digest of the blob
var payload internal.HashReader
f, err := os.Open(filepath.Clean(artifactPath))
if err != nil {
return err
}
defer f.Close()
// Get the actual digest of the blob
var payload internal.HashReader
f, err := os.Open(filepath.Clean(artifactPath))
if err != nil {
return err
}
defer f.Close()

payload = internal.NewHashReader(f, sha256.New())
if _, err := io.ReadAll(&payload); err != nil {
return err
}
digest := payload.Sum(nil)
h := v1.Hash{
Hex: hex.EncodeToString(digest),
Algorithm: "sha256",
payload = internal.NewHashReader(f, sha256.New())
if _, err := io.ReadAll(&payload); err != nil {
return err
}
digest := payload.Sum(nil)
h = v1.Hash{
Hex: hex.EncodeToString(digest),
Algorithm: "sha256",
}
co.ClaimVerifier = cosign.IntotoSubjectClaimVerifier
}

// Set up TSA, Fulcio roots and tlog public keys and clients.
Expand Down
55 changes: 55 additions & 0 deletions cmd/cosign/cli/verify/verify_blob_attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,58 @@ func TestVerifyBlobAttestation(t *testing.T) {
})
}
}

func TestVerifyBlobAttestationNoCheckClaims(t *testing.T) {
ctx := context.Background()
td := t.TempDir()
defer os.RemoveAll(td)

blobPath := writeBlobFile(t, td, blobContents, "blob")
anotherBlobPath := writeBlobFile(t, td, anotherBlobContents, "other-blob")
keyRef := writeBlobFile(t, td, pubkey, "cosign.pub")

tests := []struct {
description string
blobPath string
signature string
}{
{
description: "verify a predicate",
blobPath: blobPath,
signature: blobSLSAProvenanceSignature,
}, {
description: "verify a predicate no path",
signature: blobSLSAProvenanceSignature,
}, {
description: "verify a predicate with another blob path",
signature: blobSLSAProvenanceSignature,
// This works because we're not checking the claims. It doesn't matter what we put in here - it should pass so long as the DSSE signagure can be verified.
blobPath: anotherBlobPath,
}, {
description: "verify a predicate with /dev/null",
signature: blobSLSAProvenanceSignature,
blobPath: "/dev/null",
},
}

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
decodedSig, err := base64.StdEncoding.DecodeString(test.signature)
if err != nil {
t.Fatal(err)
}
sigRef := writeBlobFile(t, td, string(decodedSig), "signature")

cmd := VerifyBlobAttestationCommand{
KeyOpts: options.KeyOpts{KeyRef: keyRef},
SignaturePath: sigRef,
IgnoreTlog: true,
CheckClaims: false,
PredicateType: "slsaprovenance",
}
if err := cmd.Exec(ctx, test.blobPath); err != nil {
t.Fatalf("verifyBlobAttestation()= %v", err)
}
})
}
}
2 changes: 1 addition & 1 deletion doc/cosign_verify-blob-attestation.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2670ed3

Please sign in to comment.