diff --git a/pkg/background/mutate/mutate.go b/pkg/background/mutate/mutate.go index bcdf38af2d..3fedc3f1d2 100644 --- a/pkg/background/mutate/mutate.go +++ b/pkg/background/mutate/mutate.go @@ -18,10 +18,12 @@ import ( "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/registryclient" "github.com/kyverno/kyverno/pkg/utils" + engineutils "github.com/kyverno/kyverno/pkg/utils/engine" "go.uber.org/multierr" yamlv2 "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" + corev1listers "k8s.io/client-go/listers/core/v1" "k8s.io/client-go/tools/cache" ) @@ -35,6 +37,7 @@ type MutateExistingController struct { // listers policyLister kyvernov1listers.ClusterPolicyLister npolicyLister kyvernov1listers.PolicyLister + nsLister corev1listers.NamespaceLister configuration config.Configuration informerCacheResolvers resolvers.ConfigmapResolver @@ -50,6 +53,7 @@ func NewMutateExistingController( rclient registryclient.Client, policyLister kyvernov1listers.ClusterPolicyLister, npolicyLister kyvernov1listers.PolicyLister, + nsLister corev1listers.NamespaceLister, dynamicConfig config.Configuration, informerCacheResolvers resolvers.ConfigmapResolver, eventGen event.Interface, @@ -61,6 +65,7 @@ func NewMutateExistingController( rclient: rclient, policyLister: policyLister, npolicyLister: npolicyLister, + nsLister: nsLister, configuration: dynamicConfig, informerCacheResolvers: informerCacheResolvers, eventGen: eventGen, @@ -85,13 +90,14 @@ func (c *MutateExistingController) ProcessUR(ur *kyvernov1beta1.UpdateRequest) e } trigger, err := common.GetResource(c.client, ur.Spec, c.log) - if err != nil { + if err != nil || trigger == nil { logger.WithName(rule.Name).Error(err, "failed to get trigger resource") errs = append(errs, err) continue } - policyContext, _, err := common.NewBackgroundContext(c.client, ur, policy, trigger, c.configuration, c.informerCacheResolvers, nil, logger) + namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(trigger.GetKind(), trigger.GetNamespace(), c.nsLister, logger) + policyContext, _, err := common.NewBackgroundContext(c.client, ur, policy, trigger, c.configuration, c.informerCacheResolvers, namespaceLabels, logger) if err != nil { logger.WithName(rule.Name).Error(err, "failed to build policy context") errs = append(errs, err) diff --git a/pkg/background/update_request_controller.go b/pkg/background/update_request_controller.go index 92acd5f6ce..2edeb8a53a 100644 --- a/pkg/background/update_request_controller.go +++ b/pkg/background/update_request_controller.go @@ -420,7 +420,7 @@ func (c *controller) processUR(ur *kyvernov1beta1.UpdateRequest) error { statusControl := common.NewStatusControl(c.kyvernoClient, c.urLister) switch ur.Spec.Type { case kyvernov1beta1.Mutate: - ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.rclient, c.cpolLister, c.polLister, c.configuration, c.informerCacheResolvers, c.eventGen, logger) + ctrl := mutate.NewMutateExistingController(c.client, statusControl, c.rclient, c.cpolLister, c.polLister, c.nsLister, c.configuration, c.informerCacheResolvers, c.eventGen, logger) return ctrl.ProcessUR(ur) case kyvernov1beta1.Generate: ctrl := generate.NewGenerateController(c.client, c.kyvernoClient, statusControl, c.rclient, c.cpolLister, c.polLister, c.urLister, c.nsLister, c.configuration, c.informerCacheResolvers, c.eventGen, logger) diff --git a/pkg/policy/policy_controller.go b/pkg/policy/policy_controller.go index e85841d691..356853653b 100644 --- a/pkg/policy/policy_controller.go +++ b/pkg/policy/policy_controller.go @@ -28,6 +28,7 @@ import ( "github.com/kyverno/kyverno/pkg/event" "github.com/kyverno/kyverno/pkg/metrics" "github.com/kyverno/kyverno/pkg/registryclient" + engineutils "github.com/kyverno/kyverno/pkg/utils/engine" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" "github.com/pkg/errors" "go.uber.org/multierr" @@ -512,7 +513,8 @@ func (pc *PolicyController) updateUR(policyKey string, policy kyvernov1.PolicyIn } func (pc *PolicyController) handleUpdateRequest(ur *kyvernov1beta1.UpdateRequest, triggerResource *unstructured.Unstructured, rule kyvernov1.Rule, policy kyvernov1.PolicyInterface) (skip bool, err error) { - policyContext, _, err := backgroundcommon.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, pc.informerCacheResolvers, nil, pc.log) + namespaceLabels := engineutils.GetNamespaceSelectorsFromNamespaceLister(triggerResource.GetKind(), triggerResource.GetNamespace(), pc.nsLister, pc.log) + policyContext, _, err := backgroundcommon.NewBackgroundContext(pc.client, ur, policy, triggerResource, pc.configHandler, pc.informerCacheResolvers, namespaceLabels, pc.log) if err != nil { return false, errors.Wrapf(err, "failed to build policy context for rule %s", rule.Name) } diff --git a/pkg/webhooks/resource/handlers.go b/pkg/webhooks/resource/handlers.go index 421cd1d2de..252de3c0f9 100644 --- a/pkg/webhooks/resource/handlers.go +++ b/pkg/webhooks/resource/handlers.go @@ -137,9 +137,9 @@ func (h *handlers) Validate(ctx context.Context, logger logr.Logger, request *ad namespaceLabels = engineutils.GetNamespaceSelectorsFromNamespaceLister(request.Kind.Kind, request.Namespace, h.nsLister, logger) } + policyContext = policyContext.WithNamespaceLabels(namespaceLabels) vh := validation.NewValidationHandler(logger, h.kyvernoClient, h.rclient, h.pCache, h.pcBuilder, h.eventGen, h.admissionReports, h.metricsConfig) - - ok, msg, warnings := vh.HandleValidation(ctx, request, policies, policyContext, namespaceLabels, startTime) + ok, msg, warnings := vh.HandleValidation(ctx, request, policies, policyContext, startTime) if !ok { logger.Info("admission request denied") return admissionutils.Response(request.UID, errors.New(msg), warnings...) diff --git a/pkg/webhooks/resource/validation/validation.go b/pkg/webhooks/resource/validation/validation.go index 7a9275f9f5..5c764a2e75 100644 --- a/pkg/webhooks/resource/validation/validation.go +++ b/pkg/webhooks/resource/validation/validation.go @@ -31,7 +31,7 @@ type ValidationHandler interface { // HandleValidation handles validating webhook admission request // If there are no errors in validating rule we apply generation rules // patchedResource is the (resource + patches) after applying mutation rules - HandleValidation(context.Context, *admissionv1.AdmissionRequest, []kyvernov1.PolicyInterface, *engine.PolicyContext, map[string]string, time.Time) (bool, string, []string) + HandleValidation(context.Context, *admissionv1.AdmissionRequest, []kyvernov1.PolicyInterface, *engine.PolicyContext, time.Time) (bool, string, []string) } func NewValidationHandler( @@ -72,15 +72,8 @@ func (v *validationHandler) HandleValidation( request *admissionv1.AdmissionRequest, policies []kyvernov1.PolicyInterface, policyContext *engine.PolicyContext, - namespaceLabels map[string]string, admissionRequestTimestamp time.Time, ) (bool, string, []string) { - if len(policies) == 0 { - // invoke handleAudit as we may have some policies in audit mode to consider - go v.handleAudit(ctx, policyContext.NewResource(), request, namespaceLabels) - return true, "", nil - } - resourceName := admissionutils.GetResourceName(request) logger := v.log.WithValues("action", "validate", "resource", resourceName, "operation", request.Operation, "gvk", request.Kind) @@ -105,7 +98,7 @@ func (v *validationHandler) HandleValidation( "pkg/webhooks/resource/validate", fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()), func(ctx context.Context, span trace.Span) { - policyContext := policyContext.WithPolicy(policy).WithNamespaceLabels(namespaceLabels) + policyContext := policyContext.WithPolicy(policy) if policy.GetSpec().GetFailurePolicy() == kyvernov1.Fail { failurePolicy = kyvernov1.Fail } @@ -144,7 +137,7 @@ func (v *validationHandler) HandleValidation( return false, webhookutils.GetBlockedMessages(engineResponses), nil } - go v.handleAudit(ctx, policyContext.NewResource(), request, namespaceLabels, engineResponses...) + go v.handleAudit(ctx, policyContext.NewResource(), request, engineResponses...) warnings := webhookutils.GetWarningMessages(engineResponses) return true, "", warnings @@ -154,7 +147,6 @@ func (v *validationHandler) buildAuditResponses( ctx context.Context, resource unstructured.Unstructured, request *admissionv1.AdmissionRequest, - namespaceLabels map[string]string, ) ([]*response.EngineResponse, error) { policies := v.pCache.GetPolicies(policycache.ValidateAudit, request.Kind.Kind, request.Namespace) policyContext, err := v.pcBuilder.Build(request) @@ -168,7 +160,7 @@ func (v *validationHandler) buildAuditResponses( "pkg/webhooks/resource/validate", fmt.Sprintf("POLICY %s/%s", policy.GetNamespace(), policy.GetName()), func(ctx context.Context, span trace.Span) { - policyContext := policyContext.WithPolicy(policy).WithNamespaceLabels(namespaceLabels) + policyContext := policyContext.WithPolicy(policy) responses = append(responses, engine.Validate(ctx, v.rclient, policyContext)) }, ) @@ -180,7 +172,6 @@ func (v *validationHandler) handleAudit( ctx context.Context, resource unstructured.Unstructured, request *admissionv1.AdmissionRequest, - namespaceLabels map[string]string, engineResponses ...*response.EngineResponse, ) { if !v.admissionReports { @@ -202,7 +193,7 @@ func (v *validationHandler) handleAudit( "", fmt.Sprintf("AUDIT %s %s", request.Operation, request.Kind), func(ctx context.Context, span trace.Span) { - responses, err := v.buildAuditResponses(ctx, resource, request, namespaceLabels) + responses, err := v.buildAuditResponses(ctx, resource, request) if err != nil { v.log.Error(err, "failed to build audit responses") } diff --git a/scripts/config/standard/kyverno.yaml b/scripts/config/standard/kyverno.yaml index b9c670c4f3..e424b363f8 100644 --- a/scripts/config/standard/kyverno.yaml +++ b/scripts/config/standard/kyverno.yaml @@ -6,6 +6,9 @@ extraArgs: - --loggingFormat=json - --enablePolicyException +generatecontrollerExtraResources: + - pods + cleanupController: rbac: clusterRole: diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/01-manifests.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/01-manifests.yaml deleted file mode 100644 index 706fb39f53..0000000000 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/01-manifests.yaml +++ /dev/null @@ -1,58 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: staging-2 - labels: - app-type: corp - annotations: - cloud.platformzero.com/serviceClass: "xl2" ---- -apiVersion: v1 -data: - foo: bar -kind: ConfigMap -metadata: - name: dictionary-2 - namespace: staging-2 ---- -apiVersion: v1 -data: - foo: YmFy -kind: Secret -metadata: - name: test-secret-2 - namespace: staging-2 -type: Opaque ---- -apiVersion: kyverno.io/v1 -kind: ClusterPolicy -metadata: - name: test-post-mutation-delete-trigger -spec: - mutateExistingOnPolicyUpdate: false - rules: - - name: mutate-secret-on-configmap-delete - match: - any: - - resources: - kinds: - - ConfigMap - names: - - dictionary-2 - namespaces: - - staging-2 - preconditions: - any: - - key: "{{ request.operation }}" - operator: Equals - value: DELETE - mutate: - targets: - - apiVersion: v1 - kind: Secret - name: test-secret-2 - namespace: "{{ request.object.metadata.namespace }}" - patchStrategicMerge: - metadata: - labels: - foo: "{{ request.object.metadata.name }}" \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/02-delete-cm.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/02-delete-cm.yaml deleted file mode 100644 index 82f33a28bc..0000000000 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/02-delete-cm.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -delete: -- apiVersion: v1 - kind: ConfigMap - name: dictionary-2 - namespace: staging-2 \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/03-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/03-assert.yaml deleted file mode 100644 index fc44140bd6..0000000000 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/03-assert.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: test-secret-2 - namespace: staging-2 - labels: - foo: dictionary-2 \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/README.md b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/README.md deleted file mode 100644 index 9abd9c3007..0000000000 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Description - -This is a basic test for the mutate existing capability which ensures that specifically deleting a triggering resource, via a precondition, results in the correct mutation of a different resource. - -## Expected Behavior - -When the `dictionary-2` ConfigMap is deleted, this should result in the mutation of the Secret named `test-secret-2` within the same Namespace to add the label `foo` with value set to the name or `dictionary-2` in this case. If the Secret is mutated so that the label `foo: dictionary-2` is present, the test passes. If not, the test fails. - -## Reference Issue(s) - -N/A \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/cleanup.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/cleanup.yaml deleted file mode 100644 index 15c3c49051..0000000000 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/cleanup.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - command: kubectl delete -f 01-manifests.yaml --force --wait=true --ignore-not-found=true \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/01-policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/01-policy.yaml new file mode 100644 index 0000000000..b088ed7601 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/01-policy.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- policy.yaml +assert: +- policy-assert.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/02-pod.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/02-pod.yaml new file mode 100644 index 0000000000..b7d7b9997f --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/02-pod.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- file: pod.yaml +assert: +- pod.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/03-configmap.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/03-configmap.yaml new file mode 100644 index 0000000000..9a4f3b3c14 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/03-configmap.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- file: configmap.yaml +assert: +- configmap.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/04-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/04-assert.yaml new file mode 100644 index 0000000000..030f798740 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/04-assert.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + org: kyverno-test + name: test-org + namespace: test diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/README.md b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/README.md new file mode 100644 index 0000000000..a2935c8bfe --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/README.md @@ -0,0 +1,19 @@ +## Description + +The `namespaceSelector` should applies to mutateExisting policies upon admission reviews. + +## Expected Behavior +The pod is mutated with annotation `org: kyverno-test`. + +## Steps + +### Test Steps + +1. Create a `ClusterPolicy` that mutates existing pod upon configmap operations in namespaces with label `org`. +2. Create a pod in `test` namespace labeled by `org: kyverno-test`. +3. Create a configmap in `test` namespace. +4. The pod should be mutated with the annotation `org: kyverno-test`. + +## Reference Issue(s) + +https://github.com/kyverno/kyverno/issues/6176 diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/configmap.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/configmap.yaml new file mode 100644 index 0000000000..1656a39674 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/configmap.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-org + namespace: test diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/pod.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/pod.yaml new file mode 100644 index 0000000000..cb7280f482 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-org + namespace: test +spec: + containers: + - image: nginx:latest + name: test-org diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/01-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/policy-assert.yaml similarity index 76% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/01-assert.yaml rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/policy-assert.yaml index 0ac1ea7dcc..11ec9368ec 100644 --- a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-delete/01-assert.yaml +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/policy-assert.yaml @@ -1,7 +1,7 @@ apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: - name: test-post-mutation-delete-trigger + name: org-label-inheritance-existing status: conditions: - reason: Succeeded diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/policy.yaml new file mode 100644 index 0000000000..58ccd6fb4a --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/namespaceselector/policy.yaml @@ -0,0 +1,42 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: org-label-inheritance-existing + annotations: + pod-policies.kyverno.io/autogen-controllers: none +spec: + mutateExistingOnPolicyUpdate: false + validationFailureAction: enforce + rules: + - name: propagate org label from namespace + match: + any: + - resources: + kinds: + - ConfigMap + namespaceSelector: + matchExpressions: + - key: org + operator: Exists + context: + - name: org + apiCall: + urlPath: /api/v1/namespaces/{{ request.object.metadata.namespace }} + jmesPath: metadata.labels.org + mutate: + targets: + - apiVersion: v1 + kind: Pod + namespace: "{{ request.object.metadata.namespace }}" + name: "{{ request.object.metadata.name }}" + patchStrategicMerge: + metadata: + annotations: + org: "{{ org }}" +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + org: kyverno-test + name: test diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/01-manifests.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/01-manifests.yaml similarity index 100% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/01-manifests.yaml rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/01-manifests.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/02-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/02-assert.yaml similarity index 100% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/02-assert.yaml rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/02-assert.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/02-create-clusterpolicy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/02-create-clusterpolicy.yaml similarity index 100% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/02-create-clusterpolicy.yaml rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/02-create-clusterpolicy.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/03-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/03-assert.yaml similarity index 100% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/03-assert.yaml rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/03-assert.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/README.md b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/README.md similarity index 100% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/README.md rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/README.md diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/cleanup.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/cleanup.yaml similarity index 100% rename from test/conformance/kuttl/mutate/clusterpolicy/standard/existing/basic-create-policy/cleanup.yaml rename to test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/basic-create-policy/cleanup.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/01-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/01-assert.yaml new file mode 100644 index 0000000000..945c00b098 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/01-assert.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + org: kyverno-test + name: test +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-org + namespace: test +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-org + namespace: test +spec: + containers: + - image: nginx:latest + name: test-org \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/01-manifests.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/01-manifests.yaml new file mode 100644 index 0000000000..945c00b098 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/01-manifests.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + org: kyverno-test + name: test +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: test-org + namespace: test +--- +apiVersion: v1 +kind: Pod +metadata: + name: test-org + namespace: test +spec: + containers: + - image: nginx:latest + name: test-org \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/02-policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/02-policy.yaml new file mode 100644 index 0000000000..b088ed7601 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/02-policy.yaml @@ -0,0 +1,6 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- policy.yaml +assert: +- policy-assert.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/03-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/03-assert.yaml new file mode 100644 index 0000000000..030f798740 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/03-assert.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Pod +metadata: + annotations: + org: kyverno-test + name: test-org + namespace: test diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/README.md b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/README.md new file mode 100644 index 0000000000..13f2ed58e1 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/README.md @@ -0,0 +1,18 @@ +## Description + +The `namespaceSelector` should applies to mutateExisting policies upon policy events. + +## Expected Behavior +The pod is mutated with annotation `org: kyverno-test`. + +## Steps + +### Test Steps + +1. Create a pod and a configmap in `test` namespace labeled by `org: kyverno-test`. +2. Create a `ClusterPolicy` that mutates existing pod. +4. The pod should be mutated with the annotation `org: kyverno-test`. + +## Reference Issue(s) + +https://github.com/kyverno/kyverno/issues/6176 diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/policy-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/policy-assert.yaml new file mode 100644 index 0000000000..11ec9368ec --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/policy-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: org-label-inheritance-existing +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/policy.yaml new file mode 100644 index 0000000000..7156633e4d --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/onpolicyupdate/namespaceselector/policy.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: org-label-inheritance-existing + annotations: + pod-policies.kyverno.io/autogen-controllers: none +spec: + mutateExistingOnPolicyUpdate: true + validationFailureAction: enforce + rules: + - name: propagate org label from namespace + match: + any: + - resources: + kinds: + - ConfigMap + namespaceSelector: + matchExpressions: + - key: org + operator: Exists + context: + - name: org + apiCall: + urlPath: /api/v1/namespaces/{{ request.object.metadata.namespace }} + jmesPath: metadata.labels.org + mutate: + targets: + - apiVersion: v1 + kind: Pod + namespace: "{{ request.object.metadata.namespace }}" + name: "{{ request.object.metadata.name }}" + patchStrategicMerge: + metadata: + annotations: + org: "{{ org }}"