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

add handling of keyless verification for all verify commands #3761

Merged
merged 10 commits into from
Jul 11, 2024
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 != "":
dmitris marked this conversation as resolved.
Show resolved Hide resolved
// 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
Loading