Skip to content

Commit

Permalink
feat: cert-extensions verify
Browse files Browse the repository at this point in the history
Signed-off-by: Batuhan Apaydın <batuhan.apaydin@trendyol.com>
Co-authored-by: Christian Kotzbauer <@ckotzbauer1>
Signed-off-by: Batuhan Apaydın <batuhan.apaydin@trendyol.com>
  • Loading branch information
developer-guy committed Jun 12, 2022
1 parent b01a173 commit 777965f
Show file tree
Hide file tree
Showing 23 changed files with 575 additions and 192 deletions.
33 changes: 19 additions & 14 deletions cmd/cosign/cli/dockerfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,25 @@ Shell-like variables in the Dockerfile's FROM lines will be substituted with val
}
v := &dockerfile.VerifyDockerfileCommand{
VerifyCommand: verify.VerifyCommand{
RegistryOptions: o.Registry,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertOidcIssuer: o.CertVerify.CertOidcIssuer,
CertChain: o.CertVerify.CertChain,
EnforceSCT: o.CertVerify.EnforceSCT,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Output: o.Output,
RekorURL: o.Rekor.URL,
Attachment: o.Attachment,
Annotations: annotations,
RegistryOptions: o.Registry,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertOidcIssuer: o.CertVerify.CertOidcIssuer,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
CertGithubWorkflowRepository: o.CertVerify.CertGithubWorkflowRepository,
CertGithubWorkflowRef: o.CertVerify.CertGithubWorkflowRef,
CertChain: o.CertVerify.CertChain,
EnforceSCT: o.CertVerify.EnforceSCT,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Output: o.Output,
RekorURL: o.Rekor.URL,
Attachment: o.Attachment,
Annotations: annotations,
},
BaseOnly: o.BaseImageOnly,
}
Expand Down
33 changes: 19 additions & 14 deletions cmd/cosign/cli/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,25 @@ against the transparency log.`,
}
v := &manifest.VerifyManifestCommand{
VerifyCommand: verify.VerifyCommand{
RegistryOptions: o.Registry,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertOidcIssuer: o.CertVerify.CertOidcIssuer,
CertChain: o.CertVerify.CertChain,
EnforceSCT: o.CertVerify.EnforceSCT,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Output: o.Output,
RekorURL: o.Rekor.URL,
Attachment: o.Attachment,
Annotations: annotations,
RegistryOptions: o.Registry,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertOidcIssuer: o.CertVerify.CertOidcIssuer,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
CertGithubWorkflowRepository: o.CertVerify.CertGithubWorkflowRepository,
CertGithubWorkflowRef: o.CertVerify.CertGithubWorkflowRef,
CertChain: o.CertVerify.CertChain,
EnforceSCT: o.CertVerify.EnforceSCT,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Output: o.Output,
RekorURL: o.Rekor.URL,
Attachment: o.Attachment,
Annotations: annotations,
},
}
return v.Exec(cmd.Context(), args)
Expand Down
32 changes: 27 additions & 5 deletions cmd/cosign/cli/options/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ import (

// CertVerifyOptions is the wrapper for certificate verification.
type CertVerifyOptions struct {
Cert string
CertEmail string
CertOidcIssuer string
CertChain string
EnforceSCT bool
Cert string
CertEmail string
CertOidcIssuer string
CertGithubWorkflowTrigger string
CertGithubWorkflowSha string
CertGithubWorkflowName string
CertGithubWorkflowRepository string
CertGithubWorkflowRef string
CertChain string
EnforceSCT bool
}

var _ Interface = (*RekorOptions)(nil)
Expand All @@ -40,6 +45,23 @@ func (o *CertVerifyOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVar(&o.CertOidcIssuer, "certificate-oidc-issuer", "",
"the OIDC issuer expected in a valid Fulcio certificate, e.g. https://token.actions.githubusercontent.com or https://oauth2.sigstore.dev/auth")

// -- Cert extensions begin --
// Source: https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md
cmd.Flags().StringVar(&o.CertGithubWorkflowTrigger, "certificate-github-workflow-trigger", "",
"contains the event_name claim from the GitHub OIDC Identity token that contains the name of the event that triggered the workflow run")

cmd.Flags().StringVar(&o.CertGithubWorkflowSha, "certificate-github-workflow-sha", "",
"contains the sha claim from the GitHub OIDC Identity token that contains the commit SHA that the workflow run was based upon.")

cmd.Flags().StringVar(&o.CertGithubWorkflowName, "certificate-github-workflow-name", "",
"contains the workflow claim from the GitHub OIDC Identity token that contains the name of the executed workflow.")

cmd.Flags().StringVar(&o.CertGithubWorkflowRepository, "certificate-github-workflow-repository", "",
"contains the repository claim from the GitHub OIDC Identity token that contains the repository that the workflow run was based upon")

cmd.Flags().StringVar(&o.CertGithubWorkflowRef, "certificate-github-workflow-ref", "",
"contains the ref claim from the GitHub OIDC Identity token that contains the git ref that the workflow run was based upon.")
// -- Cert extensions end --
cmd.Flags().StringVar(&o.CertChain, "certificate-chain", "",
"path to a list of CA certificates in PEM format which will be needed "+
"when building the certificate chain for the signing certificate. "+
Expand Down
3 changes: 2 additions & 1 deletion cmd/cosign/cli/policy_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ func signPolicy() *cobra.Command {
return errors.New("error decoding certificate")
}
signerEmail := sigs.CertSubject(certs[0])
signerIssuer := sigs.CertIssuerExtension(certs[0])
ce := cosign.CertExtensions{Cert: certs[0]}
signerIssuer := ce.GetIssuer()

// Retrieve root.json from registry.
imgName := rootPath(o.ImageRef)
Expand Down
2 changes: 1 addition & 1 deletion cmd/cosign/cli/sign/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func generateCertificateFiles(t *testing.T, tmpDir string, pf cosign.PassFunc) (

rootCert, rootKey, _ := test.GenerateRootCa()
subCert, subKey, _ := test.GenerateSubordinateCa(rootCert, rootKey)
leafCert, privKey, _ := test.GenerateLeafCert("subject", "oidc-issuer", subCert, subKey)
leafCert, privKey, _ := test.GenerateLeafCert("subject", "oidc-issuer", "", "", "", "", "", subCert, subKey)
pemRoot := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert.Raw})
pemSub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: subCert.Raw})
pemLeaf := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafCert.Raw})
Expand Down
43 changes: 25 additions & 18 deletions cmd/cosign/cli/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,23 +93,28 @@ against the transparency log.`,
}

v := verify.VerifyCommand{
RegistryOptions: o.Registry,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertOidcIssuer: o.CertVerify.CertOidcIssuer,
CertChain: o.CertVerify.CertChain,
EnforceSCT: o.CertVerify.EnforceSCT,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Output: o.Output,
RekorURL: o.Rekor.URL,
Attachment: o.Attachment,
Annotations: annotations,
HashAlgorithm: hashAlgorithm,
SignatureRef: o.SignatureRef,
LocalImage: o.LocalImage,
RegistryOptions: o.Registry,
CheckClaims: o.CheckClaims,
KeyRef: o.Key,
CertRef: o.CertVerify.Cert,
CertEmail: o.CertVerify.CertEmail,
CertOidcIssuer: o.CertVerify.CertOidcIssuer,
CertGithubWorkflowTrigger: o.CertVerify.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: o.CertVerify.CertGithubWorkflowSha,
CertGithubWorkflowName: o.CertVerify.CertGithubWorkflowName,
CertGithubWorkflowRepository: o.CertVerify.CertGithubWorkflowRepository,
CertGithubWorkflowRef: o.CertVerify.CertGithubWorkflowRef,
CertChain: o.CertVerify.CertChain,
EnforceSCT: o.CertVerify.EnforceSCT,
Sk: o.SecurityKey.Use,
Slot: o.SecurityKey.Slot,
Output: o.Output,
RekorURL: o.Rekor.URL,
Attachment: o.Attachment,
Annotations: annotations,
HashAlgorithm: hashAlgorithm,
SignatureRef: o.SignatureRef,
LocalImage: o.LocalImage,
}

return v.Exec(cmd.Context(), args)
Expand Down Expand Up @@ -258,7 +263,9 @@ The blob may be specified as a path to a file or - for stdin.`,
}
if err := verify.VerifyBlobCmd(cmd.Context(), ko, o.CertVerify.Cert,
o.CertVerify.CertEmail, o.CertVerify.CertOidcIssuer, o.CertVerify.CertChain,
o.Signature, args[0], o.CertVerify.EnforceSCT); err != nil {
o.Signature, args[0], o.CertVerify.CertGithubWorkflowTrigger, o.CertVerify.CertGithubWorkflowSha,
o.CertVerify.CertGithubWorkflowName, o.CertVerify.CertGithubWorkflowRepository, o.CertVerify.CertGithubWorkflowRef,
o.CertVerify.EnforceSCT); err != nil {
return fmt.Errorf("verifying blob %s: %w", args, err)
}
return nil
Expand Down
98 changes: 74 additions & 24 deletions cmd/cosign/cli/verify/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,27 @@ import (
// nolint
type VerifyCommand struct {
options.RegistryOptions
CheckClaims bool
KeyRef string
CertRef string
CertEmail string
CertOidcIssuer string
CertChain string
EnforceSCT bool
Sk bool
Slot string
Output string
RekorURL string
Attachment string
Annotations sigs.AnnotationsMap
SignatureRef string
HashAlgorithm crypto.Hash
LocalImage bool
CheckClaims bool
KeyRef string
CertRef string
CertEmail string
CertOidcIssuer string
CertGithubWorkflowTrigger string
CertGithubWorkflowSha string
CertGithubWorkflowName string
CertGithubWorkflowRepository string
CertGithubWorkflowRef string
CertChain string
EnforceSCT bool
Sk bool
Slot string
Output string
RekorURL string
Attachment string
Annotations sigs.AnnotationsMap
SignatureRef string
HashAlgorithm crypto.Hash
LocalImage bool
}

// Exec runs the verification command
Expand Down Expand Up @@ -92,12 +97,17 @@ func (c *VerifyCommand) Exec(ctx context.Context, images []string) (err error) {
return fmt.Errorf("constructing client options: %w", err)
}
co := &cosign.CheckOpts{
Annotations: c.Annotations.Annotations,
RegistryClientOpts: ociremoteOpts,
CertEmail: c.CertEmail,
CertOidcIssuer: c.CertOidcIssuer,
EnforceSCT: c.EnforceSCT,
SignatureRef: c.SignatureRef,
Annotations: c.Annotations.Annotations,
RegistryClientOpts: ociremoteOpts,
CertEmail: c.CertEmail,
CertOidcIssuer: c.CertOidcIssuer,
CertGithubWorkflowTrigger: c.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: c.CertGithubWorkflowSha,
CertGithubWorkflowName: c.CertGithubWorkflowName,
CertGithubWorkflowRepository: c.CertGithubWorkflowRepository,
CertGithubWorkflowRef: c.CertGithubWorkflowRef,
EnforceSCT: c.EnforceSCT,
SignatureRef: c.SignatureRef,
}
if c.CheckClaims {
co.ClaimVerifier = cosign.SimpleClaimVerifier
Expand Down Expand Up @@ -239,10 +249,31 @@ func PrintVerification(imgRef string, verified []oci.Signature, output string) {
case "text":
for _, sig := range verified {
if cert, err := sig.Cert(); err == nil && cert != nil {
ce := cosign.CertExtensions{Cert: cert}
fmt.Fprintln(os.Stderr, "Certificate subject: ", sigs.CertSubject(cert))
if issuerURL := sigs.CertIssuerExtension(cert); issuerURL != "" {
if issuerURL := ce.GetIssuer(); issuerURL != "" {
fmt.Fprintln(os.Stderr, "Certificate issuer URL: ", issuerURL)
}

if githubWorkflowTrigger := ce.GetCertExtensionGithubWorkflowTrigger(); githubWorkflowTrigger != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Trigger:", githubWorkflowTrigger)
}

if githubWorkflowSha := ce.GetExtensionGithubWorkflowSha(); githubWorkflowSha != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow SHA:", githubWorkflowSha)
}
if githubWorkflowName := ce.GetCertExtensionGithubWorkflowName(); githubWorkflowName != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Name:", githubWorkflowName)
}

if githubWorkflowRepository := ce.GetCertExtensionGithubWorkflowRepository(); githubWorkflowRepository != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Trigger", githubWorkflowRepository)
}

if githubWorkflowRef := ce.GetCertExtensionGithubWorkflowRef(); githubWorkflowRef != "" {
fmt.Fprintln(os.Stderr, "Certificate extension GitHub Workflow Ref:", githubWorkflowRef)
}

}

p, err := sig.Payload()
Expand All @@ -269,13 +300,32 @@ func PrintVerification(imgRef string, verified []oci.Signature, output string) {
}

if cert, err := sig.Cert(); err == nil && cert != nil {
ce := cosign.CertExtensions{Cert: cert}
if ss.Optional == nil {
ss.Optional = make(map[string]interface{})
}
ss.Optional["Subject"] = sigs.CertSubject(cert)
if issuerURL := sigs.CertIssuerExtension(cert); issuerURL != "" {
if issuerURL := ce.GetIssuer(); issuerURL != "" {
ss.Optional["Issuer"] = issuerURL
}
if githubWorkflowTrigger := ce.GetCertExtensionGithubWorkflowTrigger(); githubWorkflowTrigger != "" {
ss.Optional[cosign.CertExtensionGithubWorkflowTrigger] = githubWorkflowTrigger
}

if githubWorkflowSha := ce.GetExtensionGithubWorkflowSha(); githubWorkflowSha != "" {
ss.Optional[cosign.CertExtensionGithubWorkflowSha] = githubWorkflowSha
}
if githubWorkflowName := ce.GetCertExtensionGithubWorkflowName(); githubWorkflowName != "" {
ss.Optional[cosign.CertExtensionGithubWorkflowName] = githubWorkflowName
}

if githubWorkflowRepository := ce.GetCertExtensionGithubWorkflowRepository(); githubWorkflowRepository != "" {
ss.Optional[cosign.CertExtensionGithubWorkflowRepository] = githubWorkflowRepository
}

if githubWorkflowRef := ce.GetCertExtensionGithubWorkflowRef(); githubWorkflowRef != "" {
ss.Optional[cosign.CertExtensionGithubWorkflowRef] = githubWorkflowRef
}
}
if bundle, err := sig.Bundle(); err == nil && bundle != nil {
if ss.Optional == nil {
Expand Down
46 changes: 28 additions & 18 deletions cmd/cosign/cli/verify/verify_attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,25 @@ import (
// nolint
type VerifyAttestationCommand struct {
options.RegistryOptions
CheckClaims bool
KeyRef string
CertRef string
CertEmail string
CertOidcIssuer string
CertChain string
EnforceSCT bool
Sk bool
Slot string
Output string
RekorURL string
PredicateType string
Policies []string
LocalImage bool
CheckClaims bool
KeyRef string
CertRef string
CertEmail string
CertOidcIssuer string
CertGithubWorkflowTrigger string
CertGithubWorkflowSha string
CertGithubWorkflowName string
CertGithubWorkflowRepository string
CertGithubWorkflowRef string
CertChain string
EnforceSCT bool
Sk bool
Slot string
Output string
RekorURL string
PredicateType string
Policies []string
LocalImage bool
}

// Exec runs the verification command
Expand All @@ -75,10 +80,15 @@ func (c *VerifyAttestationCommand) Exec(ctx context.Context, images []string) (e
return fmt.Errorf("constructing client options: %w", err)
}
co := &cosign.CheckOpts{
RegistryClientOpts: ociremoteOpts,
CertEmail: c.CertEmail,
CertOidcIssuer: c.CertOidcIssuer,
EnforceSCT: c.EnforceSCT,
RegistryClientOpts: ociremoteOpts,
CertEmail: c.CertEmail,
CertOidcIssuer: c.CertOidcIssuer,
CertGithubWorkflowTrigger: c.CertGithubWorkflowTrigger,
CertGithubWorkflowSha: c.CertGithubWorkflowSha,
CertGithubWorkflowName: c.CertGithubWorkflowName,
CertGithubWorkflowRepository: c.CertGithubWorkflowRepository,
CertGithubWorkflowRef: c.CertGithubWorkflowRef,
EnforceSCT: c.EnforceSCT,
}
if c.CheckClaims {
co.ClaimVerifier = cosign.IntotoSubjectClaimVerifier
Expand Down
Loading

0 comments on commit 777965f

Please sign in to comment.