diff --git a/pkg/api/kyverno/v1/utils.go b/pkg/api/kyverno/v1/utils.go index 6a5bfe12b3..b76363b447 100644 --- a/pkg/api/kyverno/v1/utils.go +++ b/pkg/api/kyverno/v1/utils.go @@ -2,6 +2,12 @@ package v1 import "reflect" +func (p *ClusterPolicy) HasAutoGenAnnotation() bool { + annotations := p.GetAnnotations() + _, ok := annotations["pod-policies.kyverno.io/autogen-controllers"] + return ok +} + //HasMutateOrValidateOrGenerate checks for rule types func (p *ClusterPolicy) HasMutateOrValidateOrGenerate() bool { for _, rule := range p.Spec.Rules { diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index 473a3b4dee..5f8677d3f9 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -37,7 +37,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { patchedResource := policyContext.NewResource - if autoGenAnnotationApplied(patchedResource) && autoGenPolicy(&policy) { + if autoGenAnnotationApplied(patchedResource) && policy.HasAutoGenAnnotation() { resp.PatchedResource = patchedResource return } @@ -106,7 +106,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { // insert annotation to podtemplate if resource is pod controller // skip inserting on existing resource - if autoGenPolicy(&policy) && strings.Contains(PodControllers, resource.GetKind()) { + if policy.HasAutoGenAnnotation() && strings.Contains(PodControllers, resource.GetKind()) { if !patchedResourceHasPodControllerAnnotation(patchedResource) { var ruleResponse response.RuleResponse ruleResponse, patchedResource = mutate.ProcessOverlay(logger, PodControllerRuleName, podTemplateRule.Mutation.Overlay, patchedResource) @@ -126,12 +126,6 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { return resp } -func autoGenPolicy(policy *kyverno.ClusterPolicy) bool { - annotations := policy.GetObjectMeta().GetAnnotations() - _, ok := annotations[PodControllersAnnotation] - return ok -} - func patchedResourceHasPodControllerAnnotation(resource unstructured.Unstructured) bool { var podController struct { Spec struct { diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index ce553ae000..a6c2de1374 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -142,7 +142,7 @@ func isRequestDenied(log logr.Logger, ctx context.EvalInterface, policy kyverno. func validateResource(log logr.Logger, ctx context.EvalInterface, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo) *response.EngineResponse { resp := &response.EngineResponse{} - if autoGenAnnotationApplied(resource) && autoGenPolicy(&policy) { + if autoGenAnnotationApplied(resource) && policy.HasAutoGenAnnotation() { return resp } diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go index 1bff21df59..323e96a8b3 100644 --- a/pkg/policy/controller.go +++ b/pkg/policy/controller.go @@ -331,7 +331,7 @@ func (pc *PolicyController) syncPolicy(key string) error { pc.resourceWebhookWatcher.RegisterResourceWebhook() - engineResponses := pc.processExistingResources(*policy) + engineResponses := pc.processExistingResources(policy) pc.cleanupAndReport(engineResponses) return nil diff --git a/pkg/policy/existing.go b/pkg/policy/existing.go index e7534b83f9..2365ae1e8a 100644 --- a/pkg/policy/existing.go +++ b/pkg/policy/existing.go @@ -21,7 +21,7 @@ import ( "k8s.io/apimachinery/pkg/labels" ) -func (pc *PolicyController) processExistingResources(policy kyverno.ClusterPolicy) []response.EngineResponse { +func (pc *PolicyController) processExistingResources(policy *kyverno.ClusterPolicy) []response.EngineResponse { logger := pc.log.WithValues("policy", policy.Name) // Parse through all the resources // drops the cache after configured rebuild time @@ -47,7 +47,7 @@ func (pc *PolicyController) processExistingResources(policy kyverno.ClusterPolic } // apply the policy on each - engineResponse := applyPolicy(policy, resource, logger) + engineResponse := applyPolicy(*policy, resource, logger) // get engine response for mutation & validation independently engineResponses = append(engineResponses, engineResponse...) // post-processing, register the resource as processed @@ -56,7 +56,9 @@ func (pc *PolicyController) processExistingResources(policy kyverno.ClusterPolic return engineResponses } -func (pc *PolicyController) listResources(policy kyverno.ClusterPolicy) map[string]unstructured.Unstructured { +func (pc *PolicyController) listResources(policy *kyverno.ClusterPolicy) map[string]unstructured.Unstructured { + pc.log.V(4).Info("list resources to be processed") + // key uid resourceMap := map[string]unstructured.Unstructured{} @@ -82,6 +84,26 @@ func (pc *PolicyController) listResources(policy kyverno.ClusterPolicy) map[stri } } + if policy.HasAutoGenAnnotation() { + return excludePod(resourceMap, pc.log) + } + + return resourceMap +} + +// excludePod filter out the pods with ownerReference +func excludePod(resourceMap map[string]unstructured.Unstructured, log logr.Logger) map[string]unstructured.Unstructured { + for uid, r := range resourceMap { + if r.GetKind() != "Pod" { + continue + } + + if len(r.GetOwnerReferences()) > 0 { + log.V(4).Info("exclude Pod", "namespace", r.GetNamespace(), "name", r.GetName()) + delete(resourceMap, uid) + } + } + return resourceMap } @@ -151,11 +173,7 @@ func getAllNamespaces(nslister listerv1.NamespaceLister, log logr.Logger) []stri func getResourcesPerNamespace(kind string, client *client.Client, namespace string, rule kyverno.Rule, configHandler config.Interface, log logr.Logger) map[string]unstructured.Unstructured { resourceMap := map[string]unstructured.Unstructured{} - // merge include and exclude label selector values ls := rule.MatchResources.Selector - // ls := mergeLabelSectors(rule.MatchResources.Selector, rule.ExcludeResources.Selector) - // list resources - log.V(4).Info("list resources to be processed") if kind == "Namespace" { namespace = ""