Skip to content

Commit

Permalink
Add name to attestations for easier referencing from cip policy.
Browse files Browse the repository at this point in the history
Signed-off-by: Ville Aikas <vaikas@chainguard.dev>
  • Loading branch information
vaikas committed Apr 19, 2022
1 parent 1318492 commit 00a5302
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 24 deletions.
3 changes: 3 additions & 0 deletions config/300-clusterimagepolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ spec:
items:
type: object
properties:
name:
description: Name of the attestation. These can then be referenced at the CIP level policy.
type: string
policy:
type: object
properties:
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/cosigned/v1alpha1/clusterimagepolicy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ type KeylessRef struct {
// specified attestation types, and if Policy is specified, then it's applied
// only after the validation of the Attestation signature has been verified.
type Attestation struct {
// Name of the attestation. These can then be referenced at the CIP level
// policy.
Name string `json:"name"`
// Which predicate type to verify. Matches cosign verify-attestation options.
PredicateType string `json:"predicateType"`
// +optional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ type KeylessRef struct {
}

type AttestationPolicy struct {
// Name of the Attestation
Name string `json:"name"`
// PredicateType to attest, one of the accepted in verify-attestation
PredicateType string `json:"predicateType"`
// Type specifies how to evaluate policy, only rego/cue are understood.
Expand Down Expand Up @@ -189,7 +191,10 @@ func convertAuthorityV1Alpha1ToWebhook(in v1alpha1.Authority) *Authority {
func convertAttestationsV1Alpha1ToWebhook(in []v1alpha1.Attestation) []AttestationPolicy {
ret := []AttestationPolicy{}
for _, inAtt := range in {
outAtt := AttestationPolicy{PredicateType: inAtt.PredicateType}
outAtt := AttestationPolicy{
Name: inAtt.Name,
PredicateType: inAtt.PredicateType,
}
if inAtt.Policy != nil {
outAtt.Type = inAtt.Policy.Type
outAtt.Data = inAtt.Policy.Data
Expand Down
4 changes: 2 additions & 2 deletions pkg/cosign/kubernetes/webhook/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ func ValidatePolicyAttestationsForAuthority(ctx context.Context, ref name.Refere
// If there's no type / policy to do more checking against,
// then we're done here. It matches all the attestations
if wantedAttestation.Type == "" {
ret[wantedAttestation.PredicateType] = ociSignatureToPolicySignature(ctx, verifiedAttestations)
ret[wantedAttestation.Name] = ociSignatureToPolicySignature(ctx, verifiedAttestations)
continue
}
// There's a particular type, so we need to go through all the verified
Expand All @@ -469,7 +469,7 @@ func ValidatePolicyAttestationsForAuthority(ctx context.Context, ref name.Refere
}
// Ok, so this passed aok, jot it down to our result set as
// verified attestation with the predicate type match
ret[wantedAttestation.PredicateType] = ociSignatureToPolicySignature(ctx, verifiedAttestations)
ret[wantedAttestation.Name] = ociSignatureToPolicySignature(ctx, verifiedAttestations)
}
}
return ret, nil
Expand Down
3 changes: 1 addition & 2 deletions pkg/cosign/kubernetes/webhook/validator_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ type AuthorityMatch struct {
// attestations name, aka, make this into a map.
Signatures []PolicySignature `json:"signatures"`

// Mapping from predicate type to all of the matching attestations’
// of that type’s signature
// Mapping from attestation name to all of verified attestations
Attestations map[string][]PolicySignature `json:"attestations"`
}

Expand Down
33 changes: 19 additions & 14 deletions test/e2e_test_cluster_image_policy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ echo '::endgroup::'
KUBECTL_OUT_FILE=./kubectl.output

echo '::group:: test job rejection'
# We signed this with key, but there are other things that will fail.
# This image has not been signed at all, so should get auto-reject
if kubectl create -n demo-key-signing job demo2 --image=${demoimage2} 2> ./${KUBECTL_OUT_FILE} ; then
echo Failed to block unsigned Job creation!
exit 1
Expand All @@ -320,9 +320,10 @@ echo '::group:: Verify demoimage2 with cosign key'
echo '::endgroup::'

echo '::group:: test job rejection'
# We signed this with key, but needs two signatures
# We signed this with key, but it needs two signatures, one from
# keyless and one with keyless
if kubectl create -n demo-key-signing job demo2 --image=${demoimage2} 2> ./${KUBECTL_OUT_FILE} ; then
echo Failed to block unsigned Job creation!
echo Failed to block signed Job creation that requires two signatures!
exit 1
else
echo Successfully blocked Job creation with only one signature on image
Expand All @@ -345,12 +346,13 @@ COSIGN_EXPERIMENTAL=1 ./cosign verify --rekor-url ${REKOR_URL} --allow-insecure-
echo '::endgroup::'

echo '::group:: test job rejection'
# We signed this with key and keyless, but there are other things that will fail.
# We signed this with key and keyless, but there are attestations that are
# required, which will fail now.
if kubectl create -n demo-key-signing job demo2 --image=${demoimage2} 2> ./${KUBECTL_OUT_FILE} ; then
echo Failed to block Job with no attestations creation!
exit 1
else
echo Successfully blocked Job creation with only one signature on image
echo Successfully blocked Job creation with two signatures but no attestations
if ! grep -q 'validate signatures with fulcio: no matching attestations' ${KUBECTL_OUT_FILE} ; then
echo Did not get expected failure message, wanted validate signatures with fulcio: no matching attestations got
cat ${KUBECTL_OUT_FILE}
Expand All @@ -367,12 +369,13 @@ COSIGN_EXPERIMENTAL=1 ./cosign verify-attestation --type=custom --rekor-url ${RE
echo '::endgroup::'

echo '::group:: test job rejection'
# We signed this with key and keyless and it has keyless attestation, but there are other things that will fail.
# We signed this with key and keyless and it has keyless attestation, but it
# requires two keyless and one key one.
if kubectl create -n demo-key-signing job demo2 --image=${demoimage2} 2> ./${KUBECTL_OUT_FILE} ; then
echo Failed to block unsigned Job creation!
echo Failed to block Job with missing attestations creation!
exit 1
else
echo Successfully blocked Job creation with only one signature on image
echo Successfully blocked Job creation with not enough attestations on it
if ! grep -q 'failed policy: image-policy-requires-two-signatures-two-attestations' ${KUBECTL_OUT_FILE} ; then
echo Did not get expected failure message, wanted failed policy: image-policy-requires-two-signatures-two-attestations got
cat ${KUBECTL_OUT_FILE}
Expand All @@ -382,20 +385,21 @@ fi
echo '::endgroup::'

# Then add the vuln attestation with key, we have then one attestation
# with key, one with keyless, but that's still not enough, so will fail.
# with key, one with keyless, but that's still not enough because we need
# two with keyless.
echo '::group:: Create one key attestation and verify it'
COSIGN_PASSWORD="" ./cosign attest --predicate ./test/testdata/attestations/vuln-predicate.json --rekor-url ${REKOR_URL} --type=vuln --key ./cosign.key --allow-insecure-registry --force ${demoimage2}

./cosign verify-attestation --type vuln --key ./cosign.pub --allow-insecure-registry --rekor-url ${REKOR_URL} ${demoimage2}
echo '::endgroup::'

echo '::group:: test job rejection'
# We signed this with key and keyless and it has one keyless attestation and one with key, but there are other things that will fail.
# We signed this with key and keyless and it has one keyless attestation and one with key, but it is still missing the second keyless attestation.
if kubectl create -n demo-key-signing job demo2 --image=${demoimage2} 2> ./${KUBECTL_OUT_FILE} ; then
echo Failed to block unsigned Job creation!
echo Failed to block Job creation with one missing keyless attestation
exit 1
else
echo Successfully blocked Job creation with only one signature on image
echo Successfully blocked Job creation with one missing keyless attestation
if ! grep -q 'failed policy: image-policy-requires-two-signatures-two-attestations' ${KUBECTL_OUT_FILE} ; then
echo Did not get expected failure message, wanted failed policy: image-policy-requires-two-signatures-two-attestations got
cat ${KUBECTL_OUT_FILE}
Expand All @@ -411,9 +415,10 @@ COSIGN_EXPERIMENTAL=1 ./cosign verify-attestation --type=vuln --rekor-url ${REKO
echo '::endgroup::'

echo '::group:: test job success'
# We signed this with key and keyless and it has keyless attestation, but there are other things that will fail.
# We signed this with key and keyless and it has two keyless attestations and
# it has one key attestation, so it should succeed.
if ! kubectl create -n demo-key-signing job demo2 --image=${demoimage2} 2> ./${KUBECTL_OUT_FILE} ; then
echo Failed to create job that should have been allowed through!
echo Failed to create job that has two signatures and 3 attestations
cat ${KUBECTL_OUT_FILE}
exit 1
fi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ spec:
url: http://rekor.rekor-system.svc
attestations:
- predicateType: custom
name: custom-keyless
policy:
type: cue
data: |
Expand All @@ -37,6 +38,7 @@ spec:
Timestamp: <before
}
- predicateType: vuln
name: vuln-keyless
policy:
type: cue
data: |
Expand Down Expand Up @@ -67,6 +69,7 @@ spec:
-----END PUBLIC KEY-----
attestations:
- predicateType: vuln
name: vuln-key
policy:
type: cue
data: |
Expand Down Expand Up @@ -124,18 +127,21 @@ spec:
keySignatureErr: "Did not get key signature"
}
authorityMatches: {
"custom-att": {
"key-att": {
attestations: {
custom: [
vuln-key: [
{subject: "PLACEHOLDER", issuer: "PLACEHOLDER"},
]
}
}
"vuln-att": {
"keyless-att": {
attestations: {
vuln: [
vuln-keyless: [
{subject: "PLACEHOLDER", issuer: "PLACEHOLDER"},
]
],
custom-keyless: [
{subject: "PLACEHOLDER", issuer: "PLACEHOLDER"},
],
}
}
"keyless-signature": {
Expand Down

0 comments on commit 00a5302

Please sign in to comment.