diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index e1114d5fec..102335cb5a 100644 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -176,6 +176,7 @@ func createReportControllers( var ctrls []internal.Controller var warmups []func(context.Context) error kyvernoV1 := kyvernoInformer.Kyverno().V1() + kyvernoV2Alpha1 := kyvernoInformer.Kyverno().V2alpha1() if backgroundScan || admissionReports { resourceReportController := resourcereportcontroller.NewController( client, @@ -224,6 +225,7 @@ func createReportControllers( kyvernoV1.Policies(), kyvernoV1.ClusterPolicies(), kubeInformer.Core().V1().Namespaces(), + kyvernoV2Alpha1.PolicyExceptions(), resourceReportController, configMapResolver, backgroundScanInterval, diff --git a/pkg/controllers/report/background/controller.go b/pkg/controllers/report/background/controller.go index 4fc85f2e4e..55e23ec995 100644 --- a/pkg/controllers/report/background/controller.go +++ b/pkg/controllers/report/background/controller.go @@ -11,7 +11,9 @@ import ( policyreportv1alpha2 "github.com/kyverno/kyverno/api/policyreport/v1alpha2" "github.com/kyverno/kyverno/pkg/client/clientset/versioned" kyvernov1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v1" + kyvernov2alpha1informers "github.com/kyverno/kyverno/pkg/client/informers/externalversions/kyverno/v2alpha1" kyvernov1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v1" + kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1" "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/controllers" @@ -55,6 +57,7 @@ type controller struct { bgscanrLister cache.GenericLister cbgscanrLister cache.GenericLister nsLister corev1listers.NamespaceLister + polexLister kyvernov2alpha1listers.PolicyExceptionLister // queue queue workqueue.RateLimitingInterface @@ -77,6 +80,7 @@ func NewController( polInformer kyvernov1informers.PolicyInformer, cpolInformer kyvernov1informers.ClusterPolicyInformer, nsInformer corev1informers.NamespaceInformer, + polexInformer kyvernov2alpha1informers.PolicyExceptionInformer, metadataCache resource.MetadataCache, informerCacheResolvers resolvers.ConfigmapResolver, forceDelay time.Duration, @@ -95,6 +99,7 @@ func NewController( bgscanrLister: bgscanr.Lister(), cbgscanrLister: cbgscanr.Lister(), nsLister: nsInformer.Lister(), + polexLister: polexInformer.Lister(), queue: queue, metadataCache: metadataCache, informerCacheResolvers: informerCacheResolvers, @@ -305,7 +310,7 @@ func (c *controller) reconcileReport( // calculate necessary results for _, policy := range backgroundPolicies { if full || actual[reportutils.PolicyLabel(policy)] != policy.GetResourceVersion() { - scanner := utils.NewScanner(logger, c.client, c.rclient, c.informerCacheResolvers, c.config) + scanner := utils.NewScanner(logger, c.client, c.rclient, c.informerCacheResolvers, c.polexLister, c.config) for _, result := range scanner.ScanResource(ctx, *target, nsLabels, policy) { if result.Error != nil { return result.Error diff --git a/pkg/controllers/report/utils/scanner.go b/pkg/controllers/report/utils/scanner.go index b12a9f6ecc..7183a91b75 100644 --- a/pkg/controllers/report/utils/scanner.go +++ b/pkg/controllers/report/utils/scanner.go @@ -5,6 +5,7 @@ import ( "github.com/go-logr/logr" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" + kyvernov2alpha1listers "github.com/kyverno/kyverno/pkg/client/listers/kyverno/v2alpha1" "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" "github.com/kyverno/kyverno/pkg/engine" @@ -21,6 +22,7 @@ type scanner struct { client dclient.Interface rclient registryclient.Client informerCacheResolvers resolvers.ConfigmapResolver + polexLister kyvernov2alpha1listers.PolicyExceptionLister excludeGroupRole []string config config.Configuration } @@ -39,6 +41,7 @@ func NewScanner( client dclient.Interface, rclient registryclient.Client, informerCacheResolvers resolvers.ConfigmapResolver, + polexLister kyvernov2alpha1listers.PolicyExceptionLister, config config.Configuration, excludeGroupRole ...string, ) Scanner { @@ -47,6 +50,7 @@ func NewScanner( client: client, rclient: rclient, informerCacheResolvers: informerCacheResolvers, + polexLister: polexLister, config: config, excludeGroupRole: excludeGroupRole, } @@ -99,7 +103,8 @@ func (s *scanner) validateResource(ctx context.Context, resource unstructured.Un WithClient(s.client). WithNamespaceLabels(nsLabels). WithExcludeGroupRole(s.excludeGroupRole...). - WithInformerCacheResolver(s.informerCacheResolvers) + WithInformerCacheResolver(s.informerCacheResolvers). + WithExceptions(s.polexLister) return engine.Validate(ctx, s.rclient, policyCtx, s.config), nil } @@ -123,7 +128,8 @@ func (s *scanner) validateImages(ctx context.Context, resource unstructured.Unst WithClient(s.client). WithNamespaceLabels(nsLabels). WithExcludeGroupRole(s.excludeGroupRole...). - WithInformerCacheResolver(s.informerCacheResolvers) + WithInformerCacheResolver(s.informerCacheResolvers). + WithExceptions(s.polexLister) response, _ := engine.VerifyAndPatchImages(ctx, s.rclient, policyCtx, s.config) if len(response.PolicyResponse.Rules) > 0 { s.logger.Info("validateImages", "policy", policy, "response", response) diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index f3d1d70fb5..ded40cedf7 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -818,7 +818,6 @@ func hasPolicyExceptions(ctx *PolicyContext, rule *kyvernov1.Rule, subresourceGV Status: response.RuleStatusError, } } - log.V(3).Info("policy rule skipped due to policy exception", "exception", key) return &response.RuleResponse{ Name: rule.Name, diff --git a/test/conformance/kuttl/reports/admission/exception/01-policy.yaml b/test/conformance/kuttl/reports/admission/exception/01-policy.yaml new file mode 100644 index 0000000000..b088ed7601 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/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/reports/admission/exception/02-exception.yaml b/test/conformance/kuttl/reports/admission/exception/02-exception.yaml new file mode 100644 index 0000000000..dd6f12f500 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/02-exception.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- exception.yaml diff --git a/test/conformance/kuttl/reports/admission/exception/03-configmap.yaml b/test/conformance/kuttl/reports/admission/exception/03-configmap.yaml new file mode 100644 index 0000000000..9a4f3b3c14 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/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/reports/admission/exception/04-report.yaml b/test/conformance/kuttl/reports/admission/exception/04-report.yaml new file mode 100644 index 0000000000..db172beddc --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/04-report.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +assert: +- report-assert.yaml diff --git a/test/conformance/kuttl/reports/admission/exception/README.md b/test/conformance/kuttl/reports/admission/exception/README.md new file mode 100644 index 0000000000..8c66b3e7f4 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/README.md @@ -0,0 +1,12 @@ +## Description + +This test creates a policy, a policy exception and a configmap. +It makes sure the generated admission report contains a skipped result instead of a failed one. + +## Steps + +1. - Create a cluster policy + - Assert the policy becomes ready +1. - Create a policy exception for the cluster policy created above, configured to apply to configmap named `emergency` +1. - Try to create a confimap named `emergency` +1. - Assert that an admission report exists with a skipped result diff --git a/test/conformance/kuttl/reports/admission/exception/configmap.yaml b/test/conformance/kuttl/reports/admission/exception/configmap.yaml new file mode 100644 index 0000000000..c9323595fb --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/configmap.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: emergency diff --git a/test/conformance/kuttl/reports/admission/exception/exception.yaml b/test/conformance/kuttl/reports/admission/exception/exception.yaml new file mode 100644 index 0000000000..0144307401 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/exception.yaml @@ -0,0 +1,16 @@ +apiVersion: kyverno.io/v2alpha1 +kind: PolicyException +metadata: + name: mynewpolex +spec: + exceptions: + - policyName: require-labels + ruleNames: + - require-team + match: + any: + - resources: + kinds: + - ConfigMap + names: + - emergency diff --git a/test/conformance/kuttl/reports/admission/exception/policy-assert.yaml b/test/conformance/kuttl/reports/admission/exception/policy-assert.yaml new file mode 100644 index 0000000000..b0bd73c54e --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/policy-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-labels +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/kuttl/reports/admission/exception/policy.yaml b/test/conformance/kuttl/reports/admission/exception/policy.yaml new file mode 100644 index 0000000000..677e70d999 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/policy.yaml @@ -0,0 +1,20 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + name: require-labels +spec: + validationFailureAction: Enforce + background: true + rules: + - name: require-team + match: + any: + - resources: + kinds: + - ConfigMap + validate: + message: 'The label `team` is required.' + pattern: + metadata: + labels: + team: '?*' diff --git a/test/conformance/kuttl/reports/admission/exception/report-assert.yaml b/test/conformance/kuttl/reports/admission/exception/report-assert.yaml new file mode 100644 index 0000000000..6ab2c56b87 --- /dev/null +++ b/test/conformance/kuttl/reports/admission/exception/report-assert.yaml @@ -0,0 +1,28 @@ +apiVersion: kyverno.io/v1alpha2 +kind: AdmissionReport +metadata: + ownerReferences: + - apiVersion: v1 + kind: ConfigMap + name: emergency +spec: + owner: + apiVersion: v1 + kind: ConfigMap + name: emergency + results: + - policy: require-labels + resources: + - apiVersion: v1 + kind: ConfigMap + name: emergency + result: skip + rule: require-team + scored: true + source: kyverno + summary: + error: 0 + fail: 0 + pass: 0 + skip: 1 + warn: 0 diff --git a/test/conformance/kuttl/reports/background/exception/01-policy.yaml b/test/conformance/kuttl/reports/background/exception/01-policy.yaml new file mode 100644 index 0000000000..b088ed7601 --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/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/reports/background/exception/02-exception.yaml b/test/conformance/kuttl/reports/background/exception/02-exception.yaml new file mode 100644 index 0000000000..dd6f12f500 --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/02-exception.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- exception.yaml diff --git a/test/conformance/kuttl/reports/background/exception/03-configmap.yaml b/test/conformance/kuttl/reports/background/exception/03-configmap.yaml new file mode 100644 index 0000000000..9a4f3b3c14 --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/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/reports/background/exception/04-report.yaml b/test/conformance/kuttl/reports/background/exception/04-report.yaml new file mode 100644 index 0000000000..db172beddc --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/04-report.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +assert: +- report-assert.yaml diff --git a/test/conformance/kuttl/reports/background/exception/README.md b/test/conformance/kuttl/reports/background/exception/README.md new file mode 100644 index 0000000000..71f21c078d --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/README.md @@ -0,0 +1,12 @@ +## Description + +This test creates a policy, a policy exception and a configmap. +It makes sure the generated background scan report contains a skipped result instead of a failed one. + +## Steps + +1. - Create a cluster policy + - Assert the policy becomes ready +1. - Create a policy exception for the cluster policy created above, configured to apply to configmap named `emergency` +1. - Try to create a confimap named `emergency` +1. - Assert that an background scan report exists with a skipped result diff --git a/test/conformance/kuttl/reports/background/exception/configmap.yaml b/test/conformance/kuttl/reports/background/exception/configmap.yaml new file mode 100644 index 0000000000..c9323595fb --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/configmap.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: emergency diff --git a/test/conformance/kuttl/reports/background/exception/exception.yaml b/test/conformance/kuttl/reports/background/exception/exception.yaml new file mode 100644 index 0000000000..0144307401 --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/exception.yaml @@ -0,0 +1,16 @@ +apiVersion: kyverno.io/v2alpha1 +kind: PolicyException +metadata: + name: mynewpolex +spec: + exceptions: + - policyName: require-labels + ruleNames: + - require-team + match: + any: + - resources: + kinds: + - ConfigMap + names: + - emergency diff --git a/test/conformance/kuttl/reports/background/exception/policy-assert.yaml b/test/conformance/kuttl/reports/background/exception/policy-assert.yaml new file mode 100644 index 0000000000..b0bd73c54e --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/policy-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: require-labels +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/kuttl/reports/background/exception/policy.yaml b/test/conformance/kuttl/reports/background/exception/policy.yaml new file mode 100644 index 0000000000..677e70d999 --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/policy.yaml @@ -0,0 +1,20 @@ +apiVersion: kyverno.io/v2beta1 +kind: ClusterPolicy +metadata: + name: require-labels +spec: + validationFailureAction: Enforce + background: true + rules: + - name: require-team + match: + any: + - resources: + kinds: + - ConfigMap + validate: + message: 'The label `team` is required.' + pattern: + metadata: + labels: + team: '?*' diff --git a/test/conformance/kuttl/reports/background/exception/report-assert.yaml b/test/conformance/kuttl/reports/background/exception/report-assert.yaml new file mode 100644 index 0000000000..719e486788 --- /dev/null +++ b/test/conformance/kuttl/reports/background/exception/report-assert.yaml @@ -0,0 +1,20 @@ +apiVersion: kyverno.io/v1alpha2 +kind: BackgroundScanReport +metadata: + ownerReferences: + - apiVersion: v1 + kind: ConfigMap + name: emergency +spec: + results: + - policy: require-labels + result: skip + rule: require-team + scored: true + source: kyverno + summary: + error: 0 + fail: 0 + pass: 0 + skip: 1 + warn: 0