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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cert-extensions verify #1626

Merged
merged 1 commit into from
Jun 29, 2022
Merged

Conversation

developer-guy
Copy link
Member

@developer-guy developer-guy commented Mar 17, 2022

Signed-off-by: Batuhan Apayd谋n batuhan.apaydin@trendyol.com
Co-authored-by: Christian Kotzbauer <@ckotzbauer1>

Summary

This PR will add support for verifying additional claims within the signature cert.

$ COSIGN_EXPERIMENTAL=1 cosign verify aquasec/trivy:0.24.3 --cert-extensions githubWorkflowRepository=aquasecurity/trivy

Ticket Link

Fixes #1625 and #1989

Release Note

feat: cert-extensions verify

馃毃 Include some breaking changes, I moved some logic into a different package which might cause breaking changes issues.

cc: @ckotzbauer1

@codecov-commenter
Copy link

codecov-commenter commented Mar 17, 2022

Codecov Report

Merging #1626 (fd446ed) into main (1832b4c) will decrease coverage by 0.31%.
The diff coverage is 0.00%.

@@            Coverage Diff             @@
##             main    #1626      +/-   ##
==========================================
- Coverage   27.97%   27.66%   -0.32%     
==========================================
  Files         137      140       +3     
  Lines        7820     7872      +52     
==========================================
- Hits         2188     2178      -10     
- Misses       5403     5465      +62     
  Partials      229      229              
Impacted Files Coverage 螖
cmd/cosign/cli/options/certextensions.go 0.00% <0.00%> (酶)
cmd/cosign/cli/options/verify.go 0.00% <0.00%> (酶)
cmd/cosign/cli/policy_init.go 1.43% <0.00%> (酶)
cmd/cosign/cli/verify.go 0.00% <0.00%> (酶)
cmd/cosign/cli/verify/verify.go 0.00% <0.00%> (酶)
pkg/cosign/certextensions.go 0.00% <0.00%> (酶)
pkg/cosign/verifiers.go 0.00% <0.00%> (酶)
pkg/cosign/verify.go 11.46% <0.00%> (-0.21%) 猬囷笍
pkg/signature/certextensions.go 0.00% <0.00%> (酶)
pkg/signature/keys.go 14.68% <酶> (-4.82%) 猬囷笍

Continue to review full report at Codecov.

Legend - Click here to learn more
螖 = absolute <relative> (impact), 酶 = not affected, ? = missing data
Powered by Codecov. Last update 1832b4c...fd446ed. Read the comment docs.

@developer-guy
Copy link
Member Author

PTAL @ckotzbauer

Copy link
Contributor

@ckotzbauer ckotzbauer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @developer-guy for adopting this logic! I think the code overall looks good and solid. It should not break the logic from Kyverno on the next update as the extensions-parameter is not used there (apart from the new location of some functions)

}
}
return true
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this function. Kyverno ignores empty-string values (same as the extension would not be required) and respects shortened values or wildcards. However, it is of course not mandatory that cosign will do the same here. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the function that makes the matching between the actual one and the expected one to decide whether claims are equal, I couldn't understand your comment :/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, correct. What I mean is, that this function checks for strict equality, wildcards and shortened values are not supported.
E.g. cosign verify aquasec/trivy:0.24.3 --cert-extensions githubWorkflowRepository=aquasecurity/* won't work (with or without asterisk). This is how Kyverno would validate: https://github.com/kyverno/kyverno/blob/main/pkg/cosign/cosign.go#L419-L421

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not required to make the validation equal to the Kyverno logic, just want to mention the difference 馃槈

Copy link
Contributor

@haydentherapper haydentherapper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to think more about the UX for this. How does the user discover the names of the supported custom OIDs? githubWorkflowTrigger is an internal name in code, I don't think it should become a flag name as-is.

@@ -34,6 +34,7 @@ type VerifyOptions struct {
Registry RegistryOptions
SignatureDigest SignatureDigestOptions
AnnotationOptions
CertExtensionOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is for verifying certificates, this should be under the existing CertVerifyOptions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping this comment, we should group this under CertVerifyOptions so it gets pulled into all of the verify commands automatically


var (
// Fulcio cert-extensions, documented here: https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md
CertExtensionOIDCIssuer = "1.3.6.1.4.1.57264.1.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already covered -

CertOidcIssuer string

See #1308 where it was added.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping this comment too - We shouldn't have two ways to verify the issuer

@haydentherapper
Copy link
Contributor

cc @asraa
There was related conversation on this topic in #1313, but focused on subject verification.

@developer-guy
Copy link
Member Author

I'd like to think more about the UX for this. How does the user discover the names of the supported custom OIDs? githubWorkflowTrigger is an internal name in code, I don't think it should become a flag name as-is.

We'll be creating documentation about this to help people to discover these certain extensions about what we are adding to certificates, does it make sense?

@haydentherapper
Copy link
Contributor

I'm wondering if this feature makes sense as flags or if policy should be a part of a file, since this is meant to be repeated for every command, and I'd assume users would want to check in their policy to audit.

@dlorenc
Copy link
Member

dlorenc commented Mar 18, 2022

I'm wondering if this feature makes sense as flags or if policy should be a part of a file, since this is meant to be repeated for every command, and I'd assume users would want to check in their policy to audit.

I don't see an issue with flags and a policy file. Both make sense to me.

@dlorenc
Copy link
Member

dlorenc commented Mar 18, 2022

We'll be creating documentation about this to help people to discover these certain extensions about what we are adding to certificates, does it make sense?

I think we should document the canonical strings/field names somewhere, probably near where the OIDs themselves live, then use those here. I agree the variable names themselves are probably not the best ux.

@developer-guy
Copy link
Member Author

kindly ping @dlorenc


var (
// Fulcio cert-extensions, documented here: https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md
CertExtensionOIDCIssuer = "1.3.6.1.4.1.57264.1.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping this comment too - We shouldn't have two ways to verify the issuer

@@ -34,6 +34,7 @@ type VerifyOptions struct {
Registry RegistryOptions
SignatureDigest SignatureDigestOptions
AnnotationOptions
CertExtensionOptions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping this comment, we should group this under CertVerifyOptions so it gets pulled into all of the verify commands automatically

@@ -51,11 +51,18 @@ func SimpleClaimVerifier(sig oci.Signature, imageDigest v1.Hash, annotations map
return errors.New("missing or incorrect annotation")
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the purpose of this function is, but I'd strongly prefer we continue to group certificate verification under this function -

func CheckCertificatePolicy(cert *x509.Certificate, co *CheckOpts) error {

This goes back to the earlier point too about the existing flag for OIDC issuer.


// AddFlags implements Interface
func (o *CertExtensionOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringSliceVarP(&o.CertExtensions, "cert-extensions", "", nil,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we discussed this on the comments, but it'd be preferrable to match the existing style of a flag per extension instead of have a map.

See https://github.com/sigstore/cosign/blob/aad7c5fcd6e5f854ae48a57e42919039e6d219c0/cmd/cosign/cli/options/certificate.go for existing flags. We should add flags like certificate-github-ref, etc

@@ -71,8 +71,10 @@ type CheckOpts struct {

// Annotations optionally specifies image signature annotations to verify.
Annotations map[string]interface{}
// CertExtensions optionally specifies image signature cert extensions to verify.
CertExtensions map[string]string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the same vein, moving away from a map, I think we should have a field per extension - CertGitHubSha, CertGitHubRef, etc - If this is used a library function, it's not as clean of an interface to take a map, because there's no way to know what is a valid string.

@developer-guy developer-guy changed the title feat: cert-extensions verify [W.I.P] feat: cert-extensions verify Jun 3, 2022
@developer-guy developer-guy force-pushed the feature/1625 branch 3 times, most recently from 0788d39 to fbb5437 Compare June 3, 2022 18:37
@developer-guy developer-guy changed the title [W.I.P] feat: cert-extensions verify feat: cert-extensions verify Jun 3, 2022
@developer-guy developer-guy force-pushed the feature/1625 branch 2 times, most recently from 7225580 to 802f0a2 Compare June 3, 2022 18:43
Copy link
Contributor

@haydentherapper haydentherapper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two high-level comments:

  • We need to make sure that the verify* commands do not diverge. This means that if we add a verify flag for cosign verify, it should work for verify, verify attestation, verify blob, verify manifest, and verify dockerfile.
  • Most of these changes lack tests. For all of the changes to pkg, please add tests.

@@ -90,6 +90,14 @@ type CheckOpts struct {
CertEmail string
// CertOidcIssuer is the OIDC issuer expected for a certificate to be valid. The empty string means any certificate can be valid.
CertOidcIssuer string

// CertGithubWorkflowTrigger is the GitHub Workflow Trigger name expected for a certificate to be valid. The empty string means any certificate can be valid.
CertGithubWorkflowTrigger string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Comments for all

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, thank you

sigs "github.com/sigstore/cosign/pkg/signature"
)

// CertExtensionOptions is the top level wrapper for the annotations.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this file is not used, delete?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, thank you good catch.

@@ -0,0 +1,84 @@
//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have tests in the keys_test.go file called TestCertExtensions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we copy over the tests to a new file? Otherwise, it's not clear that these are tested.

return errors.New("expected oidc issuer not found in certificate")
}

if err := validateCertExtensions(ce, co); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests? See

func TestValidateAndUnpackCertInvalidOidcIssuer(t *testing.T) {
for examples

GenerateLeafCert in the test utils will need to be updated to support adding all extensions

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

// See the License for the specific language governing permissions and
// limitations under the License.

package signature
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File unused, delete?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump, can this be deleted?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, deleted, thank you.

@@ -48,22 +48,27 @@ import (
// nolint
Copy link
Contributor

@haydentherapper haydentherapper Jun 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you, I missed those parts.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for updating these!

@developer-guy developer-guy force-pushed the feature/1625 branch 5 times, most recently from 1f1bbea to 777965f Compare June 12, 2022 19:59
@developer-guy developer-guy force-pushed the feature/1625 branch 2 times, most recently from 218ed2b to 6a25723 Compare June 12, 2022 21:42
// See the License for the specific language governing permissions and
// limitations under the License.

package signature
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bump, can this be deleted?

@@ -48,22 +48,27 @@ import (
// nolint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for updating these!

@@ -0,0 +1,84 @@
//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we copy over the tests to a new file? Otherwise, it's not clear that these are tested.

@@ -131,7 +132,12 @@ func GenerateLeafCert(subject string, oidcIssuer string, parentTemplate *x509.Ce
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 57264, 1, 1},
Critical: false,
Value: []byte(oidcIssuer),
}},
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: To avoid having to update all places where GenerateLeafCert is called, can we create a new function like GenerateLeafCertWithGitHubOIDs or something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that makes a lot of sense, thank you, updated.

Copy link
Contributor

@haydentherapper haydentherapper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one thing to update with verify-attestation, looks good otherwise!

Annotations: annotations,
HashAlgorithm: hashAlgorithm,
SignatureRef: o.SignatureRef,
LocalImage: o.LocalImage,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also need to update VerifyAttestation with the new verify options, on line 185

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch @haydentherapper as always

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>
Copy link
Contributor

@haydentherapper haydentherapper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the updates, this looks great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

verify additional certificate claims
5 participants