2021-10-05 22:42:42 -07:00
package engine
import (
"encoding/json"
2022-04-27 08:09:52 -07:00
"fmt"
2022-04-19 08:35:12 -07:00
"strings"
2021-10-29 11:24:26 +01:00
"testing"
2022-04-27 08:09:52 -07:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/log"
2021-10-29 18:13:20 +02:00
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
2021-10-05 22:42:42 -07:00
"github.com/kyverno/kyverno/pkg/cosign"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/response"
"github.com/kyverno/kyverno/pkg/engine/utils"
"gotest.tools/assert"
)
2022-04-19 08:35:12 -07:00
var testPolicyGood = ` {
2021-10-05 22:42:42 -07:00
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "attest"
} ,
"spec" : {
"rules" : [
{
"name" : "attest" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"image" : "*" ,
"key" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHMmDjK65krAyDaGaeyWNzgvIu155JI50B2vezCw8+3CVeE0lJTL5dbL3OP98Za0oAEBJcOxky8Riy/XcmfKZbw==\n-----END PUBLIC KEY-----" ,
"attestations" : [
{
"predicateType" : "https://example.com/CodeReview/v1" ,
"conditions" : [
{
"all" : [
{
"key" : "{{ repo.uri }}" ,
"operator" : "Equals" ,
"value" : "https://github.com/example/my-project"
} ,
{
"key" : "{{ repo.branch }}" ,
"operator" : "Equals" ,
"value" : "main"
}
]
}
]
}
]
}
]
}
]
}
} `
2022-04-19 08:35:12 -07:00
var testPolicyBad = ` {
2021-10-05 22:42:42 -07:00
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "attest"
} ,
"spec" : {
"rules" : [
{
"name" : "attest" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"image" : "*" ,
"key" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHMmDjK65krAyDaGaeyWNzgvIu155JI50B2vezCw8+3CVeE0lJTL5dbL3OP98Za0oAEBJcOxky8Riy/XcmfKZbw==\n-----END PUBLIC KEY-----" ,
"attestations" : [
{
"predicateType" : "https://example.com/CodeReview/v1" ,
"conditions" : [
{
"all" : [
{
"key" : "{{ repo.uri }}" ,
"operator" : "Equals" ,
"value" : "https://github.com/example/my-project"
} ,
{
"key" : "{{ repo.branch }}" ,
"operator" : "Equals" ,
"value" : "prod"
}
]
}
]
}
]
}
]
}
]
}
} `
2022-04-19 08:35:12 -07:00
var testResource = ` {
2021-10-05 22:42:42 -07:00
"apiVersion" : "v1" ,
"kind" : "Pod" ,
2022-04-27 08:09:52 -07:00
"metadata" : {
"name" : "test" ,
"annotations" : { }
} ,
2021-10-05 22:42:42 -07:00
"spec" : {
"containers" : [
{
"name" : "pause2" ,
"image" : "ghcr.io/jimbugwadia/pause2"
}
]
}
} `
var payloads = [ ] [ ] 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="}]} ` ) ,
}
2022-04-19 08:35:12 -07:00
func Test_CosignMockAttest ( t * testing . T ) {
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , testPolicyGood , testResource , "" )
2021-10-05 22:42:42 -07:00
err := cosign . SetMock ( "ghcr.io/jimbugwadia/pause2:latest" , payloads )
assert . NilError ( t , err )
2022-05-05 14:06:18 -07:00
er , ivm := VerifyAndPatchImages ( policyContext )
2021-10-05 22:42:42 -07:00
assert . Equal ( t , len ( er . PolicyResponse . Rules ) , 1 )
assert . Equal ( t , er . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusPass )
2022-05-05 14:06:18 -07:00
assert . Equal ( t , ivm . IsEmpty ( ) , false )
assert . Equal ( t , ivm . isVerified ( "ghcr.io/jimbugwadia/pause2:latest" ) , true )
2021-10-05 22:42:42 -07:00
}
2022-04-19 08:35:12 -07:00
func Test_CosignMockAttest_fail ( t * testing . T ) {
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , testPolicyBad , testResource , "" )
2021-10-05 22:42:42 -07:00
err := cosign . SetMock ( "ghcr.io/jimbugwadia/pause2:latest" , payloads )
assert . NilError ( t , err )
2022-05-05 14:06:18 -07:00
er , _ := VerifyAndPatchImages ( policyContext )
2021-10-05 22:42:42 -07:00
assert . Equal ( t , len ( er . PolicyResponse . Rules ) , 1 )
assert . Equal ( t , er . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusFail )
}
2022-04-27 08:09:52 -07:00
func buildContext ( t * testing . T , policy , resource string , oldResource string ) * PolicyContext {
2021-10-05 22:42:42 -07:00
var cpol kyverno . ClusterPolicy
2022-04-27 08:09:52 -07:00
err := json . Unmarshal ( [ ] byte ( policy ) , & cpol )
assert . NilError ( t , err )
2021-10-05 22:42:42 -07:00
2022-04-27 08:09:52 -07:00
resourceUnstructured , err := utils . ConvertToUnstructured ( [ ] byte ( resource ) )
2021-10-05 22:42:42 -07:00
assert . NilError ( t , err )
2022-04-27 08:09:52 -07:00
2021-10-05 22:42:42 -07:00
ctx := context . NewContext ( )
2022-04-27 08:09:52 -07:00
err = context . AddResource ( ctx , [ ] byte ( resource ) )
assert . NilError ( t , err )
2021-10-05 22:42:42 -07:00
policyContext := & PolicyContext {
2022-03-30 15:04:30 +02:00
Policy : & cpol ,
2021-10-05 22:42:42 -07:00
JSONContext : ctx ,
2022-04-27 08:09:52 -07:00
NewResource : * resourceUnstructured ,
}
if oldResource != "" {
oldResourceUnstructured , err := utils . ConvertToUnstructured ( [ ] byte ( oldResource ) )
assert . NilError ( t , err )
err = context . AddOldResource ( ctx , [ ] byte ( oldResource ) )
assert . NilError ( t , err )
policyContext . OldResource = * oldResourceUnstructured
}
2021-10-05 22:42:42 -07:00
2022-04-09 13:52:50 +02:00
if err := ctx . AddImageInfos ( resourceUnstructured ) ; err != nil {
2021-10-05 22:42:42 -07:00
t . Errorf ( "unable to add image info to variables context: %v" , err )
t . Fail ( )
}
2022-04-27 08:09:52 -07:00
2021-10-05 22:42:42 -07:00
return policyContext
}
2022-04-19 08:35:12 -07:00
var testSampleSingleKeyPolicy = `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "check-image" ,
"annotations" : {
"pod-policies.kyverno.io/autogen-controllers" : "none"
}
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"webhookTimeoutSeconds" : 30 ,
"failurePolicy" : "Fail" ,
"rules" : [
{
"name" : "check-signature" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"imageReferences" : [
"ghcr.io/kyverno/test-verify-image:*"
] ,
"attestors" : [
{
"entries" : [
{
2022-05-05 21:57:20 -07:00
"keys" : {
"publicKeys" : "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM\n5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==\n-----END PUBLIC KEY-----"
2022-04-19 08:35:12 -07:00
}
}
]
}
]
}
]
}
]
}
}
`
var testSampleMultipleKeyPolicy = `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "check-image" ,
"annotations" : {
"pod-policies.kyverno.io/autogen-controllers" : "none"
}
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"webhookTimeoutSeconds" : 30 ,
"failurePolicy" : "Fail" ,
"rules" : [
{
"name" : "check-signature" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"imageReferences" : [
"ghcr.io/kyverno/test-verify-image:*"
] ,
"attestors" : [
{
"count" : COUNT ,
"entries" : [
{
2022-05-05 21:57:20 -07:00
"keys" : {
"publicKeys" : "KEY1"
2022-04-19 08:35:12 -07:00
}
} ,
{
2022-05-05 21:57:20 -07:00
"keys" : {
"publicKeys" : "KEY2"
2022-04-19 08:35:12 -07:00
}
}
]
}
]
}
]
}
]
}
}
`
var testSampleResource = ` {
"apiVersion" : "v1" ,
"kind" : "Pod" ,
"metadata" : { "name" : "test" } ,
"spec" : {
"containers" : [
{
"name" : "pause2" ,
"image" : "ghcr.io/kyverno/test-verify-image:signed"
}
]
}
} `
var testVerifyImageKey = ` -----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA==\n-----END PUBLIC KEY-----\n `
var testOtherKey = ` -----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyBg8yod24/wIcc5QqlVLtCfL+6Te+nwdPdTvMb1AiZn24zBToHJVZvQdYLgRWAbh0Jd+6JhEwsDmnXRrlV7rfw==\n-----END PUBLIC KEY-----\n `
func Test_SignatureGoodSigned ( t * testing . T ) {
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , testSampleSingleKeyPolicy , testSampleResource , "" )
2022-04-19 08:35:12 -07:00
cosign . ClearMock ( )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusPass , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
func Test_SignatureUnsigned ( t * testing . T ) {
cosign . ClearMock ( )
unsigned := strings . Replace ( testSampleResource , ":signed" , ":unsigned" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , testSampleSingleKeyPolicy , unsigned , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusFail , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
func Test_SignatureWrongKey ( t * testing . T ) {
cosign . ClearMock ( )
otherKey := strings . Replace ( testSampleResource , ":signed" , ":signed-by-someone-else" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , testSampleSingleKeyPolicy , otherKey , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusFail , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
func Test_SignaturesMultiKey ( t * testing . T ) {
cosign . ClearMock ( )
policy := strings . Replace ( testSampleMultipleKeyPolicy , "KEY1" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "KEY2" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "0" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusPass , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
func Test_SignaturesMultiKeyFail ( t * testing . T ) {
cosign . ClearMock ( )
policy := strings . Replace ( testSampleMultipleKeyPolicy , "KEY1" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "0" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusFail , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
func Test_SignaturesMultiKeyOneGoodKey ( t * testing . T ) {
cosign . ClearMock ( )
policy := strings . Replace ( testSampleMultipleKeyPolicy , "KEY1" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "KEY2" , testOtherKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "1" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusPass , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
func Test_SignaturesMultiKeyZeroGoodKey ( t * testing . T ) {
cosign . ClearMock ( )
policy := strings . Replace ( testSampleMultipleKeyPolicy , "KEY1" , testOtherKey , - 1 )
policy = strings . Replace ( policy , "KEY2" , testOtherKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "1" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusFail , err . PolicyResponse . Rules [ 0 ] . Message )
2022-04-19 08:35:12 -07:00
}
var testNestedAttestorPolicy = `
{
"apiVersion" : "kyverno.io/v1" ,
"kind" : "ClusterPolicy" ,
"metadata" : {
"name" : "check-image-keyless" ,
"annotations" : {
"pod-policies.kyverno.io/autogen-controllers" : "none"
}
} ,
"spec" : {
"validationFailureAction" : "enforce" ,
"background" : false ,
"webhookTimeoutSeconds" : 30 ,
"failurePolicy" : "Fail" ,
"rules" : [
{
"name" : "check-image-keyless" ,
"match" : {
"resources" : {
"kinds" : [
"Pod"
]
}
} ,
"verifyImages" : [
{
"imageReferences" : [
"ghcr.io/kyverno/test-verify-image:*"
] ,
"attestors" : [
{
"count" : COUNT ,
"entries" : [
{
2022-05-05 21:57:20 -07:00
"keys" : {
"publicKeys" : "KEY1"
2022-04-19 08:35:12 -07:00
}
} ,
{
"attestor" : {
"entries" : [
{
2022-05-05 21:57:20 -07:00
"keys" : {
"publicKeys" : "KEY2"
2022-04-19 08:35:12 -07:00
}
}
]
}
}
]
}
]
}
]
}
]
}
}
`
func Test_NestedAttestors ( t * testing . T ) {
cosign . ClearMock ( )
policy := strings . Replace ( testNestedAttestorPolicy , "KEY1" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "KEY2" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "0" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext := buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ := VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusPass )
policy = strings . Replace ( testNestedAttestorPolicy , "KEY1" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "KEY2" , testOtherKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "0" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext = buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ = VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusFail )
policy = strings . Replace ( testNestedAttestorPolicy , "KEY1" , testVerifyImageKey , - 1 )
policy = strings . Replace ( policy , "KEY2" , testOtherKey , - 1 )
policy = strings . Replace ( policy , "COUNT" , "1" , - 1 )
2022-04-27 08:09:52 -07:00
policyContext = buildContext ( t , policy , testSampleResource , "" )
2022-05-05 14:06:18 -07:00
err , _ = VerifyAndPatchImages ( policyContext )
2022-04-19 08:35:12 -07:00
assert . Equal ( t , len ( err . PolicyResponse . Rules ) , 1 )
assert . Equal ( t , err . PolicyResponse . Rules [ 0 ] . Status , response . RuleStatusPass )
}
2022-04-22 00:10:02 -07:00
func Test_ExpandKeys ( t * testing . T ) {
as := expandStaticKeys ( createStaticKeyAttestorSet ( "" ) )
assert . Equal ( t , 1 , len ( as . Entries ) )
as = expandStaticKeys ( createStaticKeyAttestorSet ( testOtherKey ) )
assert . Equal ( t , 1 , len ( as . Entries ) )
as = expandStaticKeys ( createStaticKeyAttestorSet ( testOtherKey + testOtherKey + testOtherKey ) )
assert . Equal ( t , 3 , len ( as . Entries ) )
}
2022-04-28 14:30:23 +02:00
func createStaticKeyAttestorSet ( s string ) kyverno . AttestorSet {
return kyverno . AttestorSet {
Entries : [ ] kyverno . Attestor {
2022-04-22 00:10:02 -07:00
{
2022-05-05 21:57:20 -07:00
Keys : & kyverno . StaticKeyAttestor {
PublicKeys : s ,
2022-04-22 00:10:02 -07:00
} ,
} ,
} ,
}
}
2022-04-27 08:09:52 -07:00
func Test_ChangedAnnotation ( t * testing . T ) {
2022-05-05 14:06:18 -07:00
annotationKey := imageVerifyAnnotationKey
2022-04-27 08:09:52 -07:00
annotationNew := fmt . Sprintf ( "\"annotations\": {\"%s\": \"%s\"}" , annotationKey , "true" )
newResource := strings . ReplaceAll ( testResource , "\"annotations\": {}" , annotationNew )
policyContext := buildContext ( t , testPolicyGood , testResource , testResource )
2022-05-05 14:06:18 -07:00
2022-05-08 00:45:02 -07:00
hasChanged := hasImageVerifiedAnnotationChanged ( policyContext , log . Log )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , hasChanged , false )
policyContext = buildContext ( t , testPolicyGood , newResource , testResource )
2022-05-08 00:45:02 -07:00
hasChanged = hasImageVerifiedAnnotationChanged ( policyContext , log . Log )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , hasChanged , true )
annotationOld := fmt . Sprintf ( "\"annotations\": {\"%s\": \"%s\"}" , annotationKey , "false" )
oldResource := strings . ReplaceAll ( testResource , "\"annotations\": {}" , annotationOld )
policyContext = buildContext ( t , testPolicyGood , newResource , oldResource )
2022-05-08 00:45:02 -07:00
hasChanged = hasImageVerifiedAnnotationChanged ( policyContext , log . Log )
2022-04-27 08:09:52 -07:00
assert . Equal ( t , hasChanged , true )
}
func Test_MarkImageVerified ( t * testing . T ) {
2022-05-05 14:06:18 -07:00
image := "ghcr.io/jimbugwadia/pause2:latest"
cosign . ClearMock ( )
policyContext := buildContext ( t , testPolicyGood , testResource , "" )
err := cosign . SetMock ( image , payloads )
assert . NilError ( t , err )
2022-04-27 08:09:52 -07:00
2022-05-05 14:06:18 -07:00
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 )
2022-04-27 08:09:52 -07:00
2022-05-05 14:06:18 -07:00
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 )
2022-05-01 16:02:49 -07:00
2022-05-05 14:06:18 -07:00
patches , err := verifiedImages . Patches ( false , log . Log )
2022-05-01 16:02:49 -07:00
assert . NilError ( t , err )
2022-05-05 14:06:18 -07:00
assert . Equal ( t , len ( patches ) , 2 )
2022-05-01 16:02:49 -07:00
2022-05-05 14:06:18 -07:00
resource := applyPatches ( t , patches )
patchedAnnotations := resource . GetAnnotations ( )
assert . Equal ( t , len ( patchedAnnotations ) , 1 )
2022-04-27 08:09:52 -07:00
2022-05-05 14:06:18 -07:00
json := patchedAnnotations [ imageVerifyAnnotationKey ]
assert . Assert ( t , json != "" )
verified , err := isImageVerified ( resource , image , log . Log )
assert . NilError ( t , err )
assert . Equal ( t , verified , true )
2022-04-27 08:09:52 -07:00
}
2022-05-05 14:06:18 -07:00
func applyPatches ( t * testing . T , patches [ ] [ ] byte ) unstructured . Unstructured {
patchedResource , err := utils . ApplyPatches ( [ ] byte ( testResource ) , patches )
2022-04-27 08:09:52 -07:00
assert . NilError ( t , err )
assert . Assert ( t , patchedResource != nil )
u := unstructured . Unstructured { }
err = u . UnmarshalJSON ( patchedResource )
assert . NilError ( t , err )
return u
}