1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

Fix PEM delimiter parse (#4331)

* update log levels

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* do not generate policy reports for blocked images

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

* fix PEM delimiter parsing and add test case

Signed-off-by: Jim Bugwadia <jim@nirmata.com>

Signed-off-by: Jim Bugwadia <jim@nirmata.com>
This commit is contained in:
Jim Bugwadia 2022-08-12 03:06:14 -07:00 committed by GitHub
parent b02da637b2
commit 22eb79a7f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 81 additions and 7 deletions

View file

@ -142,7 +142,7 @@ func buildCosignOptions(opts Options) (*cosign.CheckOpts, error) {
}
if opts.Key != "" {
if strings.HasPrefix(opts.Key, "-----BEGIN PUBLIC KEY-----") {
if strings.HasPrefix(strings.TrimSpace(opts.Key), "-----BEGIN PUBLIC KEY-----") {
cosignOpts.SigVerifier, err = decodePEM([]byte(opts.Key))
if err != nil {
return nil, errors.Wrap(err, "failed to load public key from PEM")
@ -426,14 +426,17 @@ func extractDigest(imgRef string, payload []payload.SimpleContainerImage) (strin
if digest := p.Critical.Image.DockerManifestDigest; digest != "" {
return digest, nil
} else {
logger.Info("failed to extract image digest from verification response", "image", imgRef, "payload", p)
return "", fmt.Errorf("unknown image response for " + imgRef)
return "", fmt.Errorf("failed to extract image digest from signature payload for " + imgRef)
}
}
return "", fmt.Errorf("digest not found for " + imgRef)
}
func matchCertificate(signatures []oci.Signature, subject, issuer string, extensions map[string]string) error {
if subject == "" && issuer == "" && len(extensions) == 0 {
return nil
}
for _, sig := range signatures {
cert, err := sig.Cert()
if err != nil {

View file

@ -132,15 +132,19 @@ var testResource = `{
}
}`
var payloads = [][]byte{
var attestationPayloads = [][]byte{
[]byte(`{"payloadType":"https://example.com/CodeReview/v1","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2V4YW1wbGUuY29tL0NvZGVSZXZpZXcvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiZ2hjci5pby9qaW1idWd3YWRpYS9wYXVzZTIiLCJkaWdlc3QiOnsic2hhMjU2IjoiYjMxYmZiNGQwMjEzZjI1NGQzNjFlMDA3OWRlYWFlYmVmYTRmODJiYTdhYTc2ZWY4MmU5MGI0OTM1YWQ1YjEwNSJ9fV0sInByZWRpY2F0ZSI6eyJhdXRob3IiOiJtYWlsdG86YWxpY2VAZXhhbXBsZS5jb20iLCJyZXBvIjp7ImJyYW5jaCI6Im1haW4iLCJ0eXBlIjoiZ2l0IiwidXJpIjoiaHR0cHM6Ly9naXRodWIuY29tL2V4YW1wbGUvbXktcHJvamVjdCJ9LCJyZXZpZXdlcnMiOlsibWFpbHRvOmJvYkBleGFtcGxlLmNvbSJdfX0=","signatures":[{"keyid":"","sig":"MEYCIQCrEr+vgPDmNCrqGDE/4z9iMLmCXMXcDlGKtSoiuMTSFgIhAN2riBaGk4accWzVl7ypi1XTRxyrPYHst8DesugPXgOf"}]}`),
[]byte(`{"payloadType":"cosign.sigstore.dev/attestation/v1","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJjb3NpZ24uc2lnc3RvcmUuZGV2L2F0dGVzdGF0aW9uL3YxIiwic3ViamVjdCI6W3sibmFtZSI6ImdoY3IuaW8vamltYnVnd2FkaWEvcGF1c2UyIiwiZGlnZXN0Ijp7InNoYTI1NiI6ImIzMWJmYjRkMDIxM2YyNTRkMzYxZTAwNzlkZWFhZWJlZmE0ZjgyYmE3YWE3NmVmODJlOTBiNDkzNWFkNWIxMDUifX1dLCJwcmVkaWNhdGUiOnsiRGF0YSI6ImhlbGxvIVxuIiwiVGltZXN0YW1wIjoiMjAyMS0xMC0wNVQwNToxODoxMVoifX0=","signatures":[{"keyid":"","sig":"MEQCIF5r9lf55rnYNPByZ9v6bortww694UEPvmyBIelIDYbIAiBNTGX4V64Oj6jZVRpkJQRxdzKUPYqC5GZTb4oS6eQ6aQ=="}]}`),
[]byte(`{"payloadType":"https://example.com/CodeReview/v1","payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjAuMSIsInByZWRpY2F0ZVR5cGUiOiJodHRwczovL2V4YW1wbGUuY29tL0NvZGVSZXZpZXcvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiZ2hjci5pby9qaW1idWd3YWRpYS9wYXVzZTIiLCJkaWdlc3QiOnsic2hhMjU2IjoiYjMxYmZiNGQwMjEzZjI1NGQzNjFlMDA3OWRlYWFlYmVmYTRmODJiYTdhYTc2ZWY4MmU5MGI0OTM1YWQ1YjEwNSJ9fV0sInByZWRpY2F0ZSI6eyJhdXRob3IiOiJtYWlsdG86YWxpY2VAZXhhbXBsZS5jb20iLCJyZXBvIjp7ImJyYW5jaCI6Im1haW4iLCJ0eXBlIjoiZ2l0IiwidXJpIjoiaHR0cHM6Ly9naXRodWIuY29tL2V4YW1wbGUvbXktcHJvamVjdCJ9LCJyZXZpZXdlcnMiOlsibWFpbHRvOmJvYkBleGFtcGxlLmNvbSJdfX0=","signatures":[{"keyid":"","sig":"MEUCIEeZbdBEFQzWqiMhB+SJgM6yFppUuQSKrpOIX1mxLDmRAiEA8pXqFq0GVc9LKhPzrnJRZhSruDNiKbiLHG5x7ETFyY8="}]}`),
}
var signaturePayloads = [][]byte{
[]byte(`{"critical":{"identity":{"docker-reference":"ghcr.io/kyverno/test-verify-image"},"image":{"docker-manifest-digest":"sha256:b31bfb4d0213f254d361e0079deaaebefa4f82ba7aa76ef82e90b4935ad5b105"},"type":"cosign container image signature"},"optional":null}`),
}
func Test_CosignMockAttest(t *testing.T) {
policyContext := buildContext(t, testPolicyGood, testResource, "")
err := cosign.SetMock("ghcr.io/jimbugwadia/pause2:latest", payloads)
err := cosign.SetMock("ghcr.io/jimbugwadia/pause2:latest", attestationPayloads)
assert.NilError(t, err)
er, ivm := VerifyAndPatchImages(policyContext)
@ -152,7 +156,7 @@ func Test_CosignMockAttest(t *testing.T) {
func Test_CosignMockAttest_fail(t *testing.T) {
policyContext := buildContext(t, testPolicyBad, testResource, "")
err := cosign.SetMock("ghcr.io/jimbugwadia/pause2:latest", payloads)
err := cosign.SetMock("ghcr.io/jimbugwadia/pause2:latest", attestationPayloads)
assert.NilError(t, err)
er, _ := VerifyAndPatchImages(policyContext)
@ -579,7 +583,7 @@ func Test_MarkImageVerified(t *testing.T) {
image := "ghcr.io/jimbugwadia/pause2:latest"
cosign.ClearMock()
policyContext := buildContext(t, testPolicyGood, testResource, "")
err := cosign.SetMock(image, payloads)
err := cosign.SetMock(image, attestationPayloads)
assert.NilError(t, err)
engineResponse, verifiedImages := VerifyAndPatchImages(policyContext)
@ -618,3 +622,70 @@ func applyPatches(t *testing.T, patches [][]byte) unstructured.Unstructured {
assert.NilError(t, err)
return u
}
func Test_ParsePEMDelimited(t *testing.T) {
testPEMPolicy := `{
"apiVersion": "kyverno.io/v1",
"kind": "Policy",
"metadata": {
"name": "check-image"
},
"spec": {
"validationFailureAction": "enforce",
"background": false,
"webhookTimeoutSeconds": 30,
"failurePolicy": "Fail",
"rules": [
{
"name": "check-image",
"match": {
"any": [
{
"resources": {
"kinds": [
"Pod"
]
}
}
]
},
"verifyImages": [
{
"imageReferences": [
"*"
],
"attestors": [
{
"count": 1,
"entries": [
{
"keys": {
"publicKeys": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfVMHGmFK4OgVqhy36KZ7a3r4R4/o\nCwaCVvXZV4ZULFbkFZ0IodGqKqcVmgycnoj7d8TpKpAUVNF8kKh90ewH3A==\n-----END PUBLIC KEY-----\n-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0f1W0XigyPFbX8Xq3QmkbL9gDFTf\nRfc8jF7UadBcwKxiyvPSOKZn+igQfXzpNjrwPSZ58JGvF4Fs8BB3fSRP2g==\n-----END PUBLIC KEY-----"
}
}
]
}
]
}
]
}
]
}
}`
image := "ghcr.io/jimbugwadia/pause2:latest"
cosign.ClearMock()
policyContext := buildContext(t, testPEMPolicy, testResource, "")
err := cosign.SetMock(image, signaturePayloads)
assert.NilError(t, err)
engineResponse, verifiedImages := VerifyAndPatchImages(policyContext)
assert.Assert(t, engineResponse != nil)
assert.Equal(t, len(engineResponse.PolicyResponse.Rules), 1)
assert.Equal(t, engineResponse.PolicyResponse.Rules[0].Status, response.RuleStatusPass)
assert.Assert(t, verifiedImages != nil)
assert.Assert(t, verifiedImages.Data != nil)
assert.Equal(t, len(verifiedImages.Data), 1)
assert.Equal(t, verifiedImages.isVerified(image), true)
}