Skip to content

Commit

Permalink
add handling of keyless verification for all verify commands (#3761)
Browse files Browse the repository at this point in the history
Copy the handling of non-Fulcio keys from the verify
to all other verify commands (verify-attestation,
verify-blob, verify-blob-attestations).

Fix #3759.

Signed-off-by: Dmitry S <[email protected]>
  • Loading branch information
dmitris authored Jul 11, 2024
1 parent ca682f2 commit bdcbf44
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 66 deletions.
18 changes: 15 additions & 3 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,14 @@ against the transparency log.`,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertChain: o.CertVerify.CertChain,
CAIntermediates: o.CertVerify.CAIntermediates,
CARoots: o.CertVerify.CARoots,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
CertGithubWorkflowRepository: o.CertVerify.CertGithubWorkflowRepository,
CertGithubWorkflowRef: o.CertVerify.CertGithubWorkflowRef,
CAIntermediates: o.CertVerify.CAIntermediates,
CARoots: o.CertVerify.CARoots,
CertChain: o.CertVerify.CertChain,
IgnoreSCT: o.CertVerify.IgnoreSCT,
SCTRef: o.CertVerify.SCT,
Sk: o.SecurityKey.Use,
Expand Down Expand Up @@ -223,6 +223,8 @@ against the transparency log.`,
CertVerifyOptions: o.CertVerify,
CertRef: o.CertVerify.Cert,
CertChain: o.CertVerify.CertChain,
CAIntermediates: o.CertVerify.CAIntermediates,
CARoots: o.CertVerify.CARoots,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
Expand Down Expand Up @@ -281,6 +283,12 @@ The blob may be specified as a path to a file or - for stdin.`,
# Verify a simple blob and message
cosign verify-blob --key cosign.pub (--signature <sig path>|<sig url> msg)
# Verify a signature with certificate and CA certificate chain
cosign verify-blob --certificate cert.pem --certificate-chain certchain.pem --signature $sig <blob>
# Verify a signature with CA roots and optional intermediate certificates
cosign verify-blob --certificate cert.pem --ca-roots caroots.pem [--ca-intermediates caintermediates.pem] --signature $sig <blob>
# Verify a signature from an environment variable
cosign verify-blob --key cosign.pub --signature $sig msg
Expand Down Expand Up @@ -333,6 +341,8 @@ The blob may be specified as a path to a file or - for stdin.`,
CertVerifyOptions: o.CertVerify,
CertRef: o.CertVerify.Cert,
CertChain: o.CertVerify.CertChain,
CARoots: o.CertVerify.CARoots,
CAIntermediates: o.CertVerify.CAIntermediates,
SigRef: o.Signature,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSHA: o.CertVerify.CertGithubWorkflowSha,
Expand Down Expand Up @@ -402,6 +412,8 @@ The blob may be specified as a path to a file.`,
CertVerifyOptions: o.CertVerify,
CertRef: o.CertVerify.Cert,
CertChain: o.CertVerify.CertChain,
CARoots: o.CertVerify.CARoots,
CAIntermediates: o.CertVerify.CAIntermediates,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSHA: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
Expand Down
10 changes: 4 additions & 6 deletions cmd/cosign/cli/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
return err
}
}

keyRef := c.KeyRef
certRef := c.CertRef

Expand Down Expand Up @@ -511,15 +512,11 @@ func shouldVerifySCT(ignoreSCT bool, keyRef string, sk bool) bool {
return true
}

// loadCertsKeylessVerification loads certificates for the verification of keyless signatures
// for the verify command.
//
// TODO - mention additionally verify-attestation, verify-blob, verify-blob-attestation
// commands when they are extended to call this function.
// loadCertsKeylessVerification loads certificates provided as a certificate chain or CA roots + CA intermediate
// certificate files. If both certChain and caRootsFile are empty strings, the Fulcio roots are loaded.
//
// The co *cosign.CheckOpts is both input and output parameter - it gets updated
// with the root and intermediate certificates needed for verification.
// If both certChain and caRootsFile are empty strings, the Fulcio roots are loaded.
func loadCertsKeylessVerification(certChainFile string,
caRootsFile string,
caIntermediatesFile string,
Expand Down Expand Up @@ -574,5 +571,6 @@ func loadCertsKeylessVerification(certChainFile string,
return fmt.Errorf("getting Fulcio intermediates: %w", err)
}
}

return nil
}
16 changes: 7 additions & 9 deletions cmd/cosign/cli/verify/verify_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ type VerifyAttestationCommand struct {
CertGithubWorkflowName string
CertGithubWorkflowRepository string
CertGithubWorkflowRef string
CAIntermediates string
CARoots string
CertChain string
IgnoreSCT bool
SCTRef string
Expand Down Expand Up @@ -156,15 +158,8 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
}

if keylessVerification(c.KeyRef, c.Sk) {
// This performs an online fetch of the Fulcio roots. This is needed
// for verifying keyless certificates (both online and offline).
co.RootCerts, err = fulcio.GetRoots()
if err != nil {
return fmt.Errorf("getting Fulcio roots: %w", err)
}
co.IntermediateCerts, err = fulcio.GetIntermediates()
if err != nil {
return fmt.Errorf("getting Fulcio intermediates: %w", err)
if err := loadCertsKeylessVerification(c.CertChain, c.CARoots, c.CAIntermediates, co); err != nil {
return err
}
}

Expand Down Expand Up @@ -228,6 +223,9 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
}
co.SCT = sct
}
case c.CARoots != "":
// CA roots + possible intermediates are already loaded into co.RootCerts with the call to
// loadCertsKeylessVerification above.
}

// NB: There are only 2 kinds of verification right now:
Expand Down
24 changes: 10 additions & 14 deletions cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"os"
"path/filepath"

"github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/rekor"
"github.com/sigstore/cosign/v2/internal/ui"
Expand All @@ -53,6 +52,8 @@ type VerifyBlobCmd struct {
options.KeyOpts
options.CertVerifyOptions
CertRef string
CAIntermediates string
CARoots string
CertChain string
SigRef string
CertGithubWorkflowTrigger string
Expand Down Expand Up @@ -151,19 +152,10 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
return fmt.Errorf("getting Rekor public keys: %w", err)
}
}

if keylessVerification(c.KeyRef, c.Sk) {
// Use default TUF roots if a cert chain is not provided.
// This performs an online fetch of the Fulcio roots. This is needed
// for verifying keyless certificates (both online and offline).
if c.CertChain == "" {
co.RootCerts, err = fulcio.GetRoots()
if err != nil {
return fmt.Errorf("getting Fulcio roots: %w", err)
}
co.IntermediateCerts, err = fulcio.GetIntermediates()
if err != nil {
return fmt.Errorf("getting Fulcio intermediates: %w", err)
}
if err := loadCertsKeylessVerification(c.CertChain, c.CARoots, c.CAIntermediates, co); err != nil {
return err
}
}

Expand Down Expand Up @@ -249,7 +241,8 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
}
// Set a cert chain if provided.
var chainPEM []byte
if c.CertChain != "" {
switch {
case c.CertChain != "":
chain, err := loadCertChainFromFileOrURL(c.CertChain)
if err != nil {
return err
Expand All @@ -269,6 +262,9 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
if err != nil {
return err
}
case c.CARoots != "":
// CA roots + possible intermediates are already loaded into co.RootCerts with the call to
// loadCertsKeylessVerification above.
}

// Gather the cert for the signature and add the cert along with the
Expand Down
25 changes: 10 additions & 15 deletions cmd/cosign/cli/verify/verify_blob_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"path/filepath"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/fulcio"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
"github.com/sigstore/cosign/v2/cmd/cosign/cli/rekor"
internal "github.com/sigstore/cosign/v2/internal/pkg/cosign"
Expand All @@ -52,8 +51,10 @@ type VerifyBlobAttestationCommand struct {
options.KeyOpts
options.CertVerifyOptions

CertRef string
CertChain string
CertRef string
CertChain string
CAIntermediates string
CARoots string

CertGithubWorkflowTrigger string
CertGithubWorkflowSHA string
Expand Down Expand Up @@ -170,20 +171,11 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
}
}
if keylessVerification(c.KeyRef, c.Sk) {
// Use default TUF roots if a cert chain is not provided.
// This performs an online fetch of the Fulcio roots. This is needed
// for verifying keyless certificates (both online and offline).
if c.CertChain == "" {
co.RootCerts, err = fulcio.GetRoots()
if err != nil {
return fmt.Errorf("getting Fulcio roots: %w", err)
}
co.IntermediateCerts, err = fulcio.GetIntermediates()
if err != nil {
return fmt.Errorf("getting Fulcio intermediates: %w", err)
}
if err := loadCertsKeylessVerification(c.CertChain, c.CARoots, c.CAIntermediates, co); err != nil {
return err
}
}

// Ignore Signed Certificate Timestamp if the flag is set or a key is provided
if shouldVerifySCT(c.IgnoreSCT, c.KeyRef, c.Sk) {
co.CTLogPubKeys, err = cosign.GetCTLogPubs(ctx)
Expand Down Expand Up @@ -228,6 +220,9 @@ func (c *VerifyBlobAttestationCommand) Exec(ctx context.Context, artifactPath st
if err != nil {
return err
}
case c.CARoots != "":
// CA roots + possible intermediates are already loaded into co.RootCerts with the call to
// loadCertsKeylessVerification above.
}
if c.BundlePath != "" {
b, err := cosign.FetchLocalSignedPayloadFromPath(c.BundlePath)
Expand Down
6 changes: 6 additions & 0 deletions doc/cosign_verify-blob.md

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

Loading

0 comments on commit bdcbf44

Please sign in to comment.