mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
chore: move kyverno.io/verify-images constant (#7955)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
8f4ddeecab
commit
cd9a13e751
6 changed files with 44 additions and 40 deletions
|
@ -9,6 +9,7 @@ const (
|
||||||
LabelWebhookManagedBy = "webhook.kyverno.io/managed-by"
|
LabelWebhookManagedBy = "webhook.kyverno.io/managed-by"
|
||||||
// Well known annotations
|
// Well known annotations
|
||||||
AnnotationAutogenControllers = "pod-policies.kyverno.io/autogen-controllers"
|
AnnotationAutogenControllers = "pod-policies.kyverno.io/autogen-controllers"
|
||||||
|
AnnotationImageVerify = "kyverno.io/verify-images"
|
||||||
AnnotationPolicyCategory = "policies.kyverno.io/category"
|
AnnotationPolicyCategory = "policies.kyverno.io/category"
|
||||||
AnnotationPolicySeverity = "policies.kyverno.io/severity"
|
AnnotationPolicySeverity = "policies.kyverno.io/severity"
|
||||||
AnnotationPolicyScored = "policies.kyverno.io/scored"
|
AnnotationPolicyScored = "policies.kyverno.io/scored"
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/kyverno/kyverno/api/kyverno"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
"github.com/kyverno/kyverno/pkg/engine"
|
"github.com/kyverno/kyverno/pkg/engine"
|
||||||
|
@ -88,7 +89,7 @@ func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unst
|
||||||
annotations := resource.GetAnnotations()
|
annotations := resource.GetAnnotations()
|
||||||
if annotations != nil {
|
if annotations != nil {
|
||||||
resource = *resource.DeepCopy()
|
resource = *resource.DeepCopy()
|
||||||
delete(annotations, "kyverno.io/verify-images")
|
delete(annotations, kyverno.AnnotationImageVerify)
|
||||||
resource.SetAnnotations(annotations)
|
resource.SetAnnotations(annotations)
|
||||||
}
|
}
|
||||||
policyCtx, err := engine.NewPolicyContext(s.jp, resource, kyvernov1.Create, nil, s.config)
|
policyCtx, err := engine.NewPolicyContext(s.jp, resource, kyvernov1.Create, nil, s.config)
|
||||||
|
|
|
@ -6,11 +6,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/kyverno/kyverno/api/kyverno"
|
||||||
"gomodules.xyz/jsonpatch/v2"
|
"gomodules.xyz/jsonpatch/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ImageVerifyAnnotationKey = "kyverno.io/verify-images"
|
|
||||||
|
|
||||||
type ImageVerificationMetadata struct {
|
type ImageVerificationMetadata struct {
|
||||||
Data map[string]bool `json:"data"`
|
Data map[string]bool `json:"data"`
|
||||||
}
|
}
|
||||||
|
@ -79,5 +78,5 @@ func (ivm *ImageVerificationMetadata) IsEmpty() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeAnnotationKeyForJSONPatch() string {
|
func makeAnnotationKeyForJSONPatch() string {
|
||||||
return "/metadata/annotations/" + strings.ReplaceAll(ImageVerifyAnnotationKey, "/", "~1")
|
return "/metadata/annotations/" + strings.ReplaceAll(kyverno.AnnotationImageVerify, "/", "~1")
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
"github.com/kyverno/kyverno/api/kyverno"
|
||||||
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
"github.com/kyverno/kyverno/pkg/cosign"
|
"github.com/kyverno/kyverno/pkg/cosign"
|
||||||
"github.com/kyverno/kyverno/pkg/engine/adapters"
|
"github.com/kyverno/kyverno/pkg/engine/adapters"
|
||||||
|
@ -219,7 +220,7 @@ func Test_CosignMockAttest_fail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildContext(t *testing.T, policy, resource string, oldResource string) *PolicyContext {
|
func buildContext(t *testing.T, policy, resource string, oldResource string) *PolicyContext {
|
||||||
var cpol kyverno.ClusterPolicy
|
var cpol kyvernov1.ClusterPolicy
|
||||||
err := json.Unmarshal([]byte(policy), &cpol)
|
err := json.Unmarshal([]byte(policy), &cpol)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
@ -229,7 +230,7 @@ func buildContext(t *testing.T, policy, resource string, oldResource string) *Po
|
||||||
policyContext, err := policycontext.NewPolicyContext(
|
policyContext, err := policycontext.NewPolicyContext(
|
||||||
jp,
|
jp,
|
||||||
*resourceUnstructured,
|
*resourceUnstructured,
|
||||||
kyverno.Create,
|
kyvernov1.Create,
|
||||||
nil,
|
nil,
|
||||||
cfg,
|
cfg,
|
||||||
)
|
)
|
||||||
|
@ -560,7 +561,7 @@ func Test_RuleSelectorImageVerify(t *testing.T) {
|
||||||
spec := policyContext.Policy().GetSpec()
|
spec := policyContext.Policy().GetSpec()
|
||||||
spec.Rules = append(spec.Rules, *rule)
|
spec.Rules = append(spec.Rules, *rule)
|
||||||
|
|
||||||
applyAll := kyverno.ApplyAll
|
applyAll := kyvernov1.ApplyAll
|
||||||
spec.ApplyRules = &applyAll
|
spec.ApplyRules = &applyAll
|
||||||
|
|
||||||
resp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
resp, _ := testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||||
|
@ -568,33 +569,33 @@ func Test_RuleSelectorImageVerify(t *testing.T) {
|
||||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message())
|
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message())
|
||||||
assert.Equal(t, resp.PolicyResponse.Rules[1].Status(), engineapi.RuleStatusFail, resp.PolicyResponse.Rules[1].Message())
|
assert.Equal(t, resp.PolicyResponse.Rules[1].Status(), engineapi.RuleStatusFail, resp.PolicyResponse.Rules[1].Message())
|
||||||
|
|
||||||
applyOne := kyverno.ApplyOne
|
applyOne := kyvernov1.ApplyOne
|
||||||
spec.ApplyRules = &applyOne
|
spec.ApplyRules = &applyOne
|
||||||
resp, _ = testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
resp, _ = testVerifyAndPatchImages(context.TODO(), registryclient.NewOrDie(), nil, policyContext, cfg)
|
||||||
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
assert.Equal(t, len(resp.PolicyResponse.Rules), 1)
|
||||||
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message())
|
assert.Equal(t, resp.PolicyResponse.Rules[0].Status(), engineapi.RuleStatusPass, resp.PolicyResponse.Rules[0].Message())
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStaticKeyRule(name, imageReference, key string) *kyverno.Rule {
|
func newStaticKeyRule(name, imageReference, key string) *kyvernov1.Rule {
|
||||||
return &kyverno.Rule{
|
return &kyvernov1.Rule{
|
||||||
Name: name,
|
Name: name,
|
||||||
MatchResources: kyverno.MatchResources{
|
MatchResources: kyvernov1.MatchResources{
|
||||||
All: kyverno.ResourceFilters{
|
All: kyvernov1.ResourceFilters{
|
||||||
{
|
{
|
||||||
ResourceDescription: kyverno.ResourceDescription{
|
ResourceDescription: kyvernov1.ResourceDescription{
|
||||||
Kinds: []string{"Pod"},
|
Kinds: []string{"Pod"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
VerifyImages: []kyverno.ImageVerification{
|
VerifyImages: []kyvernov1.ImageVerification{
|
||||||
{
|
{
|
||||||
ImageReferences: []string{"*"},
|
ImageReferences: []string{"*"},
|
||||||
Attestors: []kyverno.AttestorSet{
|
Attestors: []kyvernov1.AttestorSet{
|
||||||
{
|
{
|
||||||
Entries: []kyverno.Attestor{
|
Entries: []kyvernov1.Attestor{
|
||||||
{
|
{
|
||||||
Keys: &kyverno.StaticKeyAttestor{
|
Keys: &kyvernov1.StaticKeyAttestor{
|
||||||
PublicKeys: key,
|
PublicKeys: key,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -707,7 +708,7 @@ func Test_ExpandKeys(t *testing.T) {
|
||||||
|
|
||||||
as = internal.ExpandStaticKeys(createStaticKeyAttestorSet("", false, true, false))
|
as = internal.ExpandStaticKeys(createStaticKeyAttestorSet("", false, true, false))
|
||||||
assert.Equal(t, 1, len(as.Entries))
|
assert.Equal(t, 1, len(as.Entries))
|
||||||
assert.DeepEqual(t, &kyverno.SecretReference{Name: "testsecret", Namespace: "default"},
|
assert.DeepEqual(t, &kyvernov1.SecretReference{Name: "testsecret", Namespace: "default"},
|
||||||
as.Entries[0].Keys.Secret)
|
as.Entries[0].Keys.Secret)
|
||||||
|
|
||||||
as = internal.ExpandStaticKeys(createStaticKeyAttestorSet("", false, false, true))
|
as = internal.ExpandStaticKeys(createStaticKeyAttestorSet("", false, false, true))
|
||||||
|
@ -717,23 +718,23 @@ func Test_ExpandKeys(t *testing.T) {
|
||||||
as = internal.ExpandStaticKeys((createStaticKeyAttestorSet(testOtherKey, true, true, false)))
|
as = internal.ExpandStaticKeys((createStaticKeyAttestorSet(testOtherKey, true, true, false)))
|
||||||
assert.Equal(t, 2, len(as.Entries))
|
assert.Equal(t, 2, len(as.Entries))
|
||||||
assert.DeepEqual(t, testOtherKey, as.Entries[0].Keys.PublicKeys)
|
assert.DeepEqual(t, testOtherKey, as.Entries[0].Keys.PublicKeys)
|
||||||
assert.DeepEqual(t, &kyverno.SecretReference{Name: "testsecret", Namespace: "default"}, as.Entries[1].Keys.Secret)
|
assert.DeepEqual(t, &kyvernov1.SecretReference{Name: "testsecret", Namespace: "default"}, as.Entries[1].Keys.Secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createStaticKeyAttestorSet(s string, withPublicKey, withSecret, withKMS bool) kyverno.AttestorSet {
|
func createStaticKeyAttestorSet(s string, withPublicKey, withSecret, withKMS bool) kyvernov1.AttestorSet {
|
||||||
var entries []kyverno.Attestor
|
var entries []kyvernov1.Attestor
|
||||||
if withPublicKey {
|
if withPublicKey {
|
||||||
attestor := kyverno.Attestor{
|
attestor := kyvernov1.Attestor{
|
||||||
Keys: &kyverno.StaticKeyAttestor{
|
Keys: &kyvernov1.StaticKeyAttestor{
|
||||||
PublicKeys: s,
|
PublicKeys: s,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
entries = append(entries, attestor)
|
entries = append(entries, attestor)
|
||||||
}
|
}
|
||||||
if withSecret {
|
if withSecret {
|
||||||
attestor := kyverno.Attestor{
|
attestor := kyvernov1.Attestor{
|
||||||
Keys: &kyverno.StaticKeyAttestor{
|
Keys: &kyvernov1.StaticKeyAttestor{
|
||||||
Secret: &kyverno.SecretReference{
|
Secret: &kyvernov1.SecretReference{
|
||||||
Name: "testsecret",
|
Name: "testsecret",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
},
|
},
|
||||||
|
@ -743,18 +744,18 @@ func createStaticKeyAttestorSet(s string, withPublicKey, withSecret, withKMS boo
|
||||||
}
|
}
|
||||||
if withKMS {
|
if withKMS {
|
||||||
kmsKey := "gcpkms://projects/test_project_id/locations/asia-south1/keyRings/test_key_ring_name/cryptoKeys/test_key_name/versions/1"
|
kmsKey := "gcpkms://projects/test_project_id/locations/asia-south1/keyRings/test_key_ring_name/cryptoKeys/test_key_name/versions/1"
|
||||||
attestor := kyverno.Attestor{
|
attestor := kyvernov1.Attestor{
|
||||||
Keys: &kyverno.StaticKeyAttestor{
|
Keys: &kyvernov1.StaticKeyAttestor{
|
||||||
KMS: kmsKey,
|
KMS: kmsKey,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
entries = append(entries, attestor)
|
entries = append(entries, attestor)
|
||||||
}
|
}
|
||||||
return kyverno.AttestorSet{Entries: entries}
|
return kyvernov1.AttestorSet{Entries: entries}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_ChangedAnnotation(t *testing.T) {
|
func Test_ChangedAnnotation(t *testing.T) {
|
||||||
annotationKey := engineapi.ImageVerifyAnnotationKey
|
annotationKey := kyverno.AnnotationImageVerify
|
||||||
annotationNew := fmt.Sprintf("\"annotations\": {\"%s\": \"%s\"}", annotationKey, "true")
|
annotationNew := fmt.Sprintf("\"annotations\": {\"%s\": \"%s\"}", annotationKey, "true")
|
||||||
newResource := strings.ReplaceAll(testResource, "\"annotations\": {}", annotationNew)
|
newResource := strings.ReplaceAll(testResource, "\"annotations\": {}", annotationNew)
|
||||||
|
|
||||||
|
@ -798,7 +799,7 @@ func Test_MarkImageVerified(t *testing.T) {
|
||||||
patchedAnnotations := resource.GetAnnotations()
|
patchedAnnotations := resource.GetAnnotations()
|
||||||
assert.Equal(t, len(patchedAnnotations), 1)
|
assert.Equal(t, len(patchedAnnotations), 1)
|
||||||
|
|
||||||
json := patchedAnnotations[engineapi.ImageVerifyAnnotationKey]
|
json := patchedAnnotations[kyverno.AnnotationImageVerify]
|
||||||
assert.Assert(t, json != "")
|
assert.Assert(t, json != "")
|
||||||
|
|
||||||
verified, err := engineutils.IsImageVerified(resource, image, logr.Discard())
|
verified, err := engineutils.IsImageVerified(resource, image, logr.Discard())
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/kyverno/kyverno/api/kyverno"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
"github.com/kyverno/kyverno/pkg/cosign"
|
"github.com/kyverno/kyverno/pkg/cosign"
|
||||||
|
@ -58,8 +59,8 @@ func HasImageVerifiedAnnotationChanged(ctx engineapi.PolicyContext, log logr.Log
|
||||||
if newResource.Object == nil || oldResource.Object == nil {
|
if newResource.Object == nil || oldResource.Object == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
newValue := newResource.GetAnnotations()[engineapi.ImageVerifyAnnotationKey]
|
newValue := newResource.GetAnnotations()[kyverno.AnnotationImageVerify]
|
||||||
oldValue := oldResource.GetAnnotations()[engineapi.ImageVerifyAnnotationKey]
|
oldValue := oldResource.GetAnnotations()[kyverno.AnnotationImageVerify]
|
||||||
if newValue == oldValue {
|
if newValue == oldValue {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ func HasImageVerifiedAnnotationChanged(ctx engineapi.PolicyContext, log logr.Log
|
||||||
if found {
|
if found {
|
||||||
result := newValueObj[img] != oldValueObj[img]
|
result := newValueObj[img] != oldValueObj[img]
|
||||||
if result {
|
if result {
|
||||||
log.V(2).Info("annotation mismatch", "oldValue", oldValue, "newValue", newValue, "key", engineapi.ImageVerifyAnnotationKey)
|
log.V(2).Info("annotation mismatch", "oldValue", oldValue, "newValue", newValue, "key", kyverno.AnnotationImageVerify)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,9 +105,9 @@ func isImageVerified(resource unstructured.Unstructured, image string, log logr.
|
||||||
if len(annotations) == 0 {
|
if len(annotations) == 0 {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
data, ok := annotations[engineapi.ImageVerifyAnnotationKey]
|
data, ok := annotations[kyverno.AnnotationImageVerify]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.V(2).Info("missing image metadata in annotation", "key", engineapi.ImageVerifyAnnotationKey)
|
log.V(2).Info("missing image metadata in annotation", "key", kyverno.AnnotationImageVerify)
|
||||||
return false, fmt.Errorf("image is not verified")
|
return false, fmt.Errorf("image is not verified")
|
||||||
}
|
}
|
||||||
ivm, err := engineapi.ParseImageMetadata(data)
|
ivm, err := engineapi.ParseImageMetadata(data)
|
||||||
|
@ -218,7 +219,7 @@ func (iv *ImageVerifier) Verify(
|
||||||
image := imageInfo.String()
|
image := imageInfo.String()
|
||||||
|
|
||||||
if HasImageVerifiedAnnotationChanged(iv.policyContext, iv.logger) {
|
if HasImageVerifiedAnnotationChanged(iv.policyContext, iv.logger) {
|
||||||
msg := engineapi.ImageVerifyAnnotationKey + " annotation cannot be changed"
|
msg := kyverno.AnnotationImageVerify + " annotation cannot be changed"
|
||||||
iv.logger.Info("image verification error", "reason", msg)
|
iv.logger.Info("image verification error", "reason", msg)
|
||||||
responses = append(responses, engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg))
|
responses = append(responses, engineapi.RuleFail(iv.rule.Name, engineapi.ImageVerify, msg))
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/kyverno/kyverno/api/kyverno"
|
||||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||||
"github.com/kyverno/kyverno/pkg/config"
|
"github.com/kyverno/kyverno/pkg/config"
|
||||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||||
|
@ -71,8 +72,8 @@ func IsImageVerified(resource unstructured.Unstructured, image string, log logr.
|
||||||
}
|
}
|
||||||
if annotations := resource.GetAnnotations(); len(annotations) == 0 {
|
if annotations := resource.GetAnnotations(); len(annotations) == 0 {
|
||||||
return false, nil
|
return false, nil
|
||||||
} else if data, ok := annotations[engineapi.ImageVerifyAnnotationKey]; !ok {
|
} else if data, ok := annotations[kyverno.AnnotationImageVerify]; !ok {
|
||||||
log.V(2).Info("missing image metadata in annotation", "key", engineapi.ImageVerifyAnnotationKey)
|
log.V(2).Info("missing image metadata in annotation", "key", kyverno.AnnotationImageVerify)
|
||||||
return false, fmt.Errorf("image is not verified")
|
return false, fmt.Errorf("image is not verified")
|
||||||
} else if ivm, err := engineapi.ParseImageMetadata(data); err != nil {
|
} else if ivm, err := engineapi.ParseImageMetadata(data); err != nil {
|
||||||
log.Error(err, "failed to parse image verification metadata", "data", data)
|
log.Error(err, "failed to parse image verification metadata", "data", data)
|
||||||
|
|
Loading…
Add table
Reference in a new issue