Skip to content

Commit

Permalink
feat: support keyless verification for verify-blob-attestation
Browse files Browse the repository at this point in the history
Signed-off-by: Asra Ali <asraa@google.com>

fix

Signed-off-by: Asra Ali <asraa@google.com>

fix failure

Signed-off-by: Asra Ali <asraa@google.com>

fix windows

Signed-off-by: Asra Ali <asraa@google.com>

update cli options

Signed-off-by: Asra Ali <asraa@google.com>

docgen

Signed-off-by: Asra Ali <asraa@google.com>
  • Loading branch information
asraa committed Dec 8, 2022
1 parent 09f023f commit e0bd392
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 274 deletions.
25 changes: 23 additions & 2 deletions cmd/cosign/cli/options/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ type VerifyBlobOptions struct {
SecurityKey SecurityKeyOptions
CertVerify CertVerifyOptions
Rekor RekorOptions
Registry RegistryOptions
CommonVerifyOptions CommonVerifyOptions

RFC3161TimestampPath string
Expand All @@ -152,7 +151,6 @@ func (o *VerifyBlobOptions) AddFlags(cmd *cobra.Command) {
o.SecurityKey.AddFlags(cmd)
o.Rekor.AddFlags(cmd)
o.CertVerify.AddFlags(cmd)
o.Registry.AddFlags(cmd)
o.CommonVerifyOptions.AddFlags(cmd)

cmd.Flags().StringVar(&o.Key, "key", "",
Expand Down Expand Up @@ -188,18 +186,41 @@ func (o *VerifyDockerfileOptions) AddFlags(cmd *cobra.Command) {
type VerifyBlobAttestationOptions struct {
Key string
SignaturePath string
BundlePath string

PredicateOptions
CheckClaims bool

SecurityKey SecurityKeyOptions
CertVerify CertVerifyOptions
Rekor RekorOptions
CommonVerifyOptions CommonVerifyOptions

RFC3161TimestampPath string
}

var _ Interface = (*VerifyBlobOptions)(nil)

// AddFlags implements Interface
func (o *VerifyBlobAttestationOptions) AddFlags(cmd *cobra.Command) {
o.PredicateOptions.AddFlags(cmd)
o.SecurityKey.AddFlags(cmd)
o.Rekor.AddFlags(cmd)
o.CertVerify.AddFlags(cmd)
o.CommonVerifyOptions.AddFlags(cmd)

cmd.Flags().StringVar(&o.Key, "key", "",
"path to the public key file, KMS URI or Kubernetes Secret")

cmd.Flags().StringVar(&o.SignaturePath, "signature", "",
"path to base64-encoded signature over attestation in DSSE format")

cmd.Flags().StringVar(&o.BundlePath, "bundle", "",
"path to bundle FILE")

cmd.Flags().BoolVar(&o.CheckClaims, "check-claims", true,
"whether to check the claims found")

cmd.Flags().StringVar(&o.RFC3161TimestampPath, "rfc3161-timestamp", "",
"path to RFC3161 timestamp FILE")
}
30 changes: 27 additions & 3 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,34 @@ The blob may be specified as a path to a file.`,
Args: cobra.ExactArgs(1),
PersistentPreRun: options.BindViper,
RunE: func(cmd *cobra.Command, args []string) error {
ko := options.KeyOpts{
KeyRef: o.Key,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
RekorURL: o.Rekor.URL,
BundlePath: o.BundlePath,
RFC3161TimestampPath: o.RFC3161TimestampPath,
TSACertChainPath: o.CommonVerifyOptions.TSACertChainPath,
}
v := verify.VerifyBlobAttestationCommand{
KeyRef: o.Key,
PredicateType: o.PredicateOptions.Type,
SignaturePath: o.SignaturePath,
KeyOpts: ko,
PredicateType: o.PredicateOptions.Type,
CheckClaims: o.CheckClaims,
SignaturePath: o.SignaturePath,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertIdentity: o.CertVerify.CertIdentity,
CertOIDCIssuer: o.CertVerify.CertOidcIssuer,
CertChain: o.CertVerify.CertChain,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSHA: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
CertGithubWorkflowRepository: o.CertVerify.CertGithubWorkflowRepository,
CertGithubWorkflowRef: o.CertVerify.CertGithubWorkflowRef,
IgnoreSCT: o.CertVerify.IgnoreSCT,
SCTRef: o.CertVerify.SCT,
Offline: o.CommonVerifyOptions.Offline,
SkipTlogVerify: o.CommonVerifyOptions.SkipTlogVerify,
}
if len(args) != 1 {
return fmt.Errorf("no path to blob passed in, run `cosign verify-blob-attestation -h` for more help")
Expand Down
46 changes: 6 additions & 40 deletions cmd/cosign/cli/verify/verify_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"os"
"path/filepath"

ssldsse "github.com/secure-systems-lab/go-securesystemslib/dsse"
"github.com/sigstore/cosign/cmd/cosign/cli/fulcio"
"github.com/sigstore/cosign/cmd/cosign/cli/options"
"github.com/sigstore/cosign/cmd/cosign/cli/rekor"
Expand All @@ -39,7 +38,6 @@ import (
"github.com/sigstore/cosign/pkg/oci/static"
sigs "github.com/sigstore/cosign/pkg/signature"

ctypes "github.com/sigstore/cosign/pkg/types"
"github.com/sigstore/sigstore/pkg/cryptoutils"
)

Expand Down Expand Up @@ -269,31 +267,12 @@ func (c *VerifyBlobCmd) Exec(ctx context.Context, blobRef string) error {
}
opts = append(opts, static.WithCertChain(certPEM, chainPEM))
}

// Use the DSSE verifier if the payload is a DSSE with the In-Toto format.
// TODO: This verifier only supports verification of a single signer/signature on
// the envelope. Either have the verifier validate that only one signature exists,
// or use a multi-signature verifier.
if isIntotoDSSE(blobBytes) {
// co.SigVerifier = dsse.WrapVerifier(co.SigVerifier)
signature, err := static.NewAttestation(blobBytes, opts...)
if err != nil {
return err
}
// We have no artifact the attestation is tied to, so we can't do any claim
// verification.
// TODO: Add an option to support this to populate the v1.Hash for a claim.
if _, err = cosign.VerifyBlobAttestation(ctx, signature, co); err != nil {
return err
}
} else {
signature, err := static.NewSignature(blobBytes, sig, opts...)
if err != nil {
return err
}
if _, err = cosign.VerifyBlobSignature(ctx, signature, co); err != nil {
return err
}
signature, err := static.NewSignature(blobBytes, sig, opts...)
if err != nil {
return err
}
if _, err = cosign.VerifyBlobSignature(ctx, signature, co); err != nil {
return err
}

fmt.Fprintln(os.Stderr, "Verified OK")
Expand Down Expand Up @@ -343,16 +322,3 @@ func payloadBytes(blobRef string) ([]byte, error) {
}
return blobBytes, nil
}

// isIntotoDSSE checks whether a payload is a Dead Simple Signing Envelope with the In-Toto format.
func isIntotoDSSE(blobBytes []byte) bool {
DSSEenvelope := ssldsse.Envelope{}
if err := json.Unmarshal(blobBytes, &DSSEenvelope); err != nil {
return false
}
if DSSEenvelope.PayloadType != ctypes.IntotoPayloadType {
return false
}

return true
}
Loading

0 comments on commit e0bd392

Please sign in to comment.