From 2ba1605094158ec3ec1c47bf40eb51d0e6add4e9 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Sun, 10 Oct 2021 23:00:22 -0700 Subject: [PATCH] Allow `cosigned` to validate `Fulcio` signatures. (#867) This change makes it so that when `cosigned` is enabled on a namespace, and no public key is provided the webhook will verify things against the Fulcio root. The basic idea here is that this roughly matches the CLI where omitting the key will verify things against the Fulcio root instead. Related: https://github.com/sigstore/cosign/issues/866 Signed-off-by: Matt Moore --- .github/workflows/kind-e2e-cosigned.yaml | 3 -- pkg/cosign/kubernetes/webhook/validation.go | 29 ++++++++++---- .../kubernetes/webhook/validator_test.go | 7 +--- test/e2e_test_cosigned.sh | 38 +++++++++++++++++++ 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/.github/workflows/kind-e2e-cosigned.yaml b/.github/workflows/kind-e2e-cosigned.yaml index 98c50bc40e7..ebbec7310cc 100644 --- a/.github/workflows/kind-e2e-cosigned.yaml +++ b/.github/workflows/kind-e2e-cosigned.yaml @@ -175,9 +175,6 @@ jobs: run: | ko apply -Bf config/ - # Update the cosign verification-key secret with a proper key pair. - cosign generate-key-pair k8s://cosign-system/verification-key - # Wait for the webhook to come up and become Ready kubectl rollout status --timeout 5m --namespace cosign-system deployments/webhook diff --git a/pkg/cosign/kubernetes/webhook/validation.go b/pkg/cosign/kubernetes/webhook/validation.go index ab2c84871c4..f1ceb119dfe 100644 --- a/pkg/cosign/kubernetes/webhook/validation.go +++ b/pkg/cosign/kubernetes/webhook/validation.go @@ -34,8 +34,26 @@ import ( ) func valid(ctx context.Context, ref name.Reference, keys []*ecdsa.PublicKey) bool { + if len(keys) == 0 { + // If there are no keys, then verify against the fulcio root. + sps, err := validSignatures(ctx, ref, nil /* verifier */) + if err != nil { + logging.FromContext(ctx).Errorf("error validating signatures: %v", err) + return false + } + if len(sps) > 0 { + return true + } + return false + } for _, k := range keys { - sps, err := validSignatures(ctx, ref, k) + verifier, err := signature.LoadECDSAVerifier(k, crypto.SHA256) + if err != nil { + logging.FromContext(ctx).Errorf("error creating verifier: %v", err) + return false + } + + sps, err := validSignatures(ctx, ref, verifier) if err != nil { logging.FromContext(ctx).Errorf("error validating signatures: %v", err) return false @@ -51,15 +69,10 @@ func valid(ctx context.Context, ref name.Reference, keys []*ecdsa.PublicKey) boo // For testing var cosignVerifySignatures = cosign.VerifySignatures -func validSignatures(ctx context.Context, ref name.Reference, key *ecdsa.PublicKey) ([]oci.Signature, error) { - ecdsaVerifier, err := signature.LoadECDSAVerifier(key, crypto.SHA256) - if err != nil { - return nil, err - } - +func validSignatures(ctx context.Context, ref name.Reference, verifier signature.Verifier) ([]oci.Signature, error) { sigs, _, err := cosignVerifySignatures(ctx, ref, &cosign.CheckOpts{ RootCerts: fulcioroots.Get(), - SigVerifier: ecdsaVerifier, + SigVerifier: verifier, ClaimVerifier: cosign.SimpleClaimVerifier, }) return sigs, err diff --git a/pkg/cosign/kubernetes/webhook/validator_test.go b/pkg/cosign/kubernetes/webhook/validator_test.go index 38643f7b07f..2c4d46614aa 100644 --- a/pkg/cosign/kubernetes/webhook/validator_test.go +++ b/pkg/cosign/kubernetes/webhook/validator_test.go @@ -212,12 +212,7 @@ func TestValidateCronJob(t *testing.T) { Name: secretName, }, Data: map[string][]byte{ - // Random public key (cosign generate-key-pair) 2021-09-25 - "cosign.pub": []byte(`-----BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEapTW568kniCbL0OXBFIhuhOboeox -UoJou2P8sbDxpLiE/v3yLw1/jyOrCPWYHWFXnyyeGlkgSVefG54tNoK7Uw== ------END PUBLIC KEY----- -`), + // No data should make us verify against Fulcio. }, }) diff --git a/test/e2e_test_cosigned.sh b/test/e2e_test_cosigned.sh index 2b6e02e0f85..baee893142b 100755 --- a/test/e2e_test_cosigned.sh +++ b/test/e2e_test_cosigned.sh @@ -30,6 +30,21 @@ spec: - name: sample image: $KO_DOCKER_REPO/sample EOF +cat > distroless-pod.yaml < job.yaml <