diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index d1055db2d5..473a3b4dee 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -36,6 +36,12 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { defer endMutateResultResponse(logger, &resp, startTime) patchedResource := policyContext.NewResource + + if autoGenAnnotationApplied(patchedResource) && autoGenPolicy(&policy) { + resp.PatchedResource = patchedResource + return + } + for _, rule := range policy.Spec.Rules { var ruleResponse response.RuleResponse logger := logger.WithValues("rule", rule.Name) diff --git a/pkg/engine/utils.go b/pkg/engine/utils.go index 2c544331a4..79c252e823 100644 --- a/pkg/engine/utils.go +++ b/pkg/engine/utils.go @@ -200,3 +200,15 @@ func copyConditions(original []kyverno.Condition) []kyverno.Condition { } return copy } + +// autoGenAnnotationApplied checks if a Pod has annotation "pod-policies.kyverno.io/autogen-applied" +func autoGenAnnotationApplied(resource unstructured.Unstructured) bool { + if resource.GetKind() == "Pod" { + ann := resource.GetAnnotations() + if _, ok := ann[PodTemplateAnnotation]; ok { + return true + } + } + + return false +} diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index 6b20426999..ce553ae000 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -62,10 +62,10 @@ func Validate(policyContext PolicyContext) (resp response.EngineResponse) { // If request is delete, newR will be empty if reflect.DeepEqual(newR, unstructured.Unstructured{}) { return *isRequestDenied(logger, ctx, policy, oldR, admissionInfo) - } else { - if denyResp := isRequestDenied(logger, ctx, policy, newR, admissionInfo); !denyResp.IsSuccesful() { - return *denyResp - } + } + + if denyResp := isRequestDenied(logger, ctx, policy, newR, admissionInfo); !denyResp.IsSuccesful() { + return *denyResp } if reflect.DeepEqual(oldR, unstructured.Unstructured{}) { @@ -141,6 +141,11 @@ 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) { + return resp + } + for _, rule := range policy.Spec.Rules { if !rule.HasValidate() { continue diff --git a/pkg/engine/variables/common.go b/pkg/engine/variables/common.go index 292b82d988..febc1ccb6a 100644 --- a/pkg/engine/variables/common.go +++ b/pkg/engine/variables/common.go @@ -1,6 +1,8 @@ package variables -import "regexp" +import ( + "regexp" +) //IsVariable returns true if the element contains a 'valid' variable {{}} func IsVariable(element string) bool { diff --git a/pkg/webhooks/annotations.go b/pkg/webhooks/annotations.go index c44e03017d..e02ba00c96 100644 --- a/pkg/webhooks/annotations.go +++ b/pkg/webhooks/annotations.go @@ -8,9 +8,7 @@ import ( jsonpatch "github.com/evanphx/json-patch" "github.com/go-logr/logr" - "github.com/nirmata/kyverno/pkg/engine" "github.com/nirmata/kyverno/pkg/engine/response" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) const ( @@ -150,15 +148,3 @@ func annotationFromPolicyResponse(policyResponse response.PolicyResponse, log lo } return rulePatches } - -// checkPodTemplateAnn checks if a Pod has annotation "pod-policies.kyverno.io/autogen-applied" -func checkPodTemplateAnnotation(resource unstructured.Unstructured) bool { - if resource.GetKind() == "Pod" { - ann := resource.GetAnnotations() - if _, ok := ann[engine.PodTemplateAnnotation]; ok { - return true - } - } - - return false -} diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go index e216eae068..cde1283156 100644 --- a/pkg/webhooks/server.go +++ b/pkg/webhooks/server.go @@ -267,15 +267,6 @@ func (ws *WebhookServer) resourceMutation(request *v1beta1.AdmissionRequest) *v1 } } - if checkPodTemplateAnnotation(resource) { - return &v1beta1.AdmissionResponse{ - Allowed: true, - Result: &metav1.Status{ - Status: "Success", - }, - } - } - userRequestInfo := v1.RequestInfo{ Roles: roles, ClusterRoles: clusterRoles, @@ -334,7 +325,7 @@ func (ws *WebhookServer) resourceMutation(request *v1beta1.AdmissionRequest) *v1 // Only applied during resource creation and update // Success -> Generate Request CR created successsfully // Failed -> Failed to create Generate Request CR - if request.Operation == v1beta1.Create || request.Operation == v1beta1.Update { + if request.Operation == v1beta1.Create || request.Operation == v1beta1.Update { ok, msg := ws.HandleGenerate(request, policies, ctx, userRequestInfo) if !ok { logger.Info("admission request denied") @@ -422,33 +413,6 @@ func (ws *WebhookServer) resourceValidation(request *v1beta1.AdmissionRequest) * logger.Error(err, "failed to load service account in context") } - raw := request.Object.Raw - if request.Operation == v1beta1.Delete { - raw = request.OldObject.Raw - } - - resource, err := convertResource(raw, request.Kind.Group, request.Kind.Version, request.Kind.Kind, request.Namespace) - if err != nil { - logger.Error(err, "failed to convert RAW resource to unstructured format") - - return &v1beta1.AdmissionResponse{ - Allowed: false, - Result: &metav1.Status{ - Status: "Failure", - Message: err.Error(), - }, - } - } - - if checkPodTemplateAnnotation(resource) { - return &v1beta1.AdmissionResponse{ - Allowed: true, - Result: &metav1.Status{ - Status: "Success", - }, - } - } - ok, msg := ws.HandleValidation(request, policies, nil, ctx, userRequestInfo) if !ok { logger.Info("admission request denied")