From 646267b2294059d428db172ae28e0344251f0dac Mon Sep 17 00:00:00 2001 From: Mariam Fahmy Date: Thu, 31 Oct 2024 17:12:22 +0300 Subject: [PATCH] fix: add celPreconditions in autogen rules (#11503) --- pkg/autogen/v1/autogen.go | 3 + pkg/autogen/v1/rule.go | 23 ++++--- .../autogen/cel-preconditions/README.md | 11 ++++ .../cel-preconditions/chainsaw-test.yaml | 25 ++++++++ .../cel-preconditions/check-autogen.yaml | 63 +++++++++++++++++++ .../autogen/cel-preconditions/policy.yaml | 29 +++++++++ 6 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 test/conformance/chainsaw/autogen/cel-preconditions/README.md create mode 100755 test/conformance/chainsaw/autogen/cel-preconditions/chainsaw-test.yaml create mode 100644 test/conformance/chainsaw/autogen/cel-preconditions/check-autogen.yaml create mode 100644 test/conformance/chainsaw/autogen/cel-preconditions/policy.yaml diff --git a/pkg/autogen/v1/autogen.go b/pkg/autogen/v1/autogen.go index da010f3f2d..8754f0bece 100644 --- a/pkg/autogen/v1/autogen.go +++ b/pkg/autogen/v1/autogen.go @@ -227,6 +227,9 @@ func convertRule(rule kyvernoRule, kind string) (*kyvernov1.Rule, error) { if rule.Context != nil { out.Context = *rule.Context } + if rule.CELPreconditions != nil { + out.CELPreconditions = *rule.CELPreconditions + } if rule.AnyAllConditions != nil { out.SetAnyAllConditions(rule.AnyAllConditions.Conditions) } diff --git a/pkg/autogen/v1/rule.go b/pkg/autogen/v1/rule.go index 9799821a5a..30b0370ea6 100644 --- a/pkg/autogen/v1/rule.go +++ b/pkg/autogen/v1/rule.go @@ -9,6 +9,7 @@ import ( "github.com/kyverno/kyverno/pkg/engine/variables" datautils "github.com/kyverno/kyverno/pkg/utils/data" kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" + admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1" ) // the kyvernoRule holds the temporary kyverno rule struct @@ -21,15 +22,16 @@ import ( // https://github.com/kyverno/kyverno/issues/568 type kyvernoRule struct { - Name string `json:"name"` - MatchResources *kyvernov1.MatchResources `json:"match"` - ExcludeResources *kyvernov1.MatchResources `json:"exclude,omitempty"` - Context *[]kyvernov1.ContextEntry `json:"context,omitempty"` - AnyAllConditions *kyvernov1.ConditionsWrapper `json:"preconditions,omitempty"` - Mutation *kyvernov1.Mutation `json:"mutate,omitempty"` - Validation *kyvernov1.Validation `json:"validate,omitempty"` - VerifyImages []kyvernov1.ImageVerification `json:"verifyImages,omitempty"` - SkipBackgroundRequests *bool `json:"skipBackgroundRequests,omitempty"` + Name string `json:"name"` + MatchResources *kyvernov1.MatchResources `json:"match"` + ExcludeResources *kyvernov1.MatchResources `json:"exclude,omitempty"` + CELPreconditions *[]admissionregistrationv1beta1.MatchCondition `json:"celPreconditions,omitempty"` + Context *[]kyvernov1.ContextEntry `json:"context,omitempty"` + AnyAllConditions *kyvernov1.ConditionsWrapper `json:"preconditions,omitempty"` + Mutation *kyvernov1.Mutation `json:"mutate,omitempty"` + Validation *kyvernov1.Validation `json:"validate,omitempty"` + VerifyImages []kyvernov1.ImageVerification `json:"verifyImages,omitempty"` + SkipBackgroundRequests *bool `json:"skipBackgroundRequests,omitempty"` } func createRule(rule *kyvernov1.Rule) *kyvernoRule { @@ -67,6 +69,9 @@ func createRule(rule *kyvernov1.Rule) *kyvernoRule { if len(rule.Context) > 0 { jsonFriendlyStruct.Context = &rule.DeepCopy().Context } + if len(rule.CELPreconditions) > 0 { + jsonFriendlyStruct.CELPreconditions = &rule.DeepCopy().CELPreconditions + } return &jsonFriendlyStruct } diff --git a/test/conformance/chainsaw/autogen/cel-preconditions/README.md b/test/conformance/chainsaw/autogen/cel-preconditions/README.md new file mode 100644 index 0000000000..cd051f24e9 --- /dev/null +++ b/test/conformance/chainsaw/autogen/cel-preconditions/README.md @@ -0,0 +1,11 @@ +## Description + +The policy should contain autogen rules with cel preconditions correctly adjusted. + +## Expected Behavior + +The policy contains autogen rules with cel preconditions correctly adjusted. + +## Related Issue(s) + +- https://github.com/kyverno/kyverno/issues/11421 diff --git a/test/conformance/chainsaw/autogen/cel-preconditions/chainsaw-test.yaml b/test/conformance/chainsaw/autogen/cel-preconditions/chainsaw-test.yaml new file mode 100755 index 0000000000..5c0951c4a9 --- /dev/null +++ b/test/conformance/chainsaw/autogen/cel-preconditions/chainsaw-test.yaml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: cel-preconditions +spec: + steps: + - name: create policy + use: + template: ../../_step-templates/create-policy.yaml + with: + bindings: + - name: file + value: policy.yaml + - name: wait policy ready + use: + template: ../../_step-templates/cluster-policy-ready.yaml + with: + bindings: + - name: name + value: disallow-privilege-escalation + - name: check autogen + try: + - assert: + file: check-autogen.yaml diff --git a/test/conformance/chainsaw/autogen/cel-preconditions/check-autogen.yaml b/test/conformance/chainsaw/autogen/cel-preconditions/check-autogen.yaml new file mode 100644 index 0000000000..ac6097ea18 --- /dev/null +++ b/test/conformance/chainsaw/autogen/cel-preconditions/check-autogen.yaml @@ -0,0 +1,63 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-privilege-escalation +status: + autogen: + rules: + - celPreconditions: + - expression: has(object.spec.template.metadata.labels) && has(object.spec.template.metadata.labels.prod) + && object.spec.template.metadata.labels.prod == 'true' + name: Only for prod + match: + any: + - resources: + kinds: + - DaemonSet + - Deployment + - Job + - ReplicaSet + - ReplicationController + - StatefulSet + operations: + - CREATE + - UPDATE + resources: {} + name: autogen-privilege-escalation + skipBackgroundRequests: true + validate: + allowExistingViolations: true + cel: + expressions: + - expression: object.spec.template.spec.containers.all(container, has(container.securityContext) + && has(container.securityContext.allowPrivilegeEscalation) && container.securityContext.allowPrivilegeEscalation + == false) + message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation + must be set to `false`. + failureAction: Enforce + - celPreconditions: + - expression: has(object.spec.jobTemplate.spec.template.metadata.labels) && + has(object.spec.jobTemplate.spec.template.metadata.labels.prod) && object.spec.jobTemplate.spec.template.metadata.labels.prod + == 'true' + name: Only for prod + match: + any: + - resources: + kinds: + - CronJob + operations: + - CREATE + - UPDATE + resources: {} + name: autogen-cronjob-privilege-escalation + skipBackgroundRequests: true + validate: + allowExistingViolations: true + cel: + expressions: + - expression: object.spec.jobTemplate.spec.template.spec.containers.all(container, + has(container.securityContext) && has(container.securityContext.allowPrivilegeEscalation) + && container.securityContext.allowPrivilegeEscalation == false) + message: Privilege escalation is disallowed. The field spec.containers[*].securityContext.allowPrivilegeEscalation + must be set to `false`. + failureAction: Enforce diff --git a/test/conformance/chainsaw/autogen/cel-preconditions/policy.yaml b/test/conformance/chainsaw/autogen/cel-preconditions/policy.yaml new file mode 100644 index 0000000000..acf73e5e18 --- /dev/null +++ b/test/conformance/chainsaw/autogen/cel-preconditions/policy.yaml @@ -0,0 +1,29 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-privilege-escalation +spec: + rules: + - name: privilege-escalation + match: + any: + - resources: + kinds: + - Pod + operations: + - CREATE + - UPDATE + celPreconditions: + - name: "Only for prod" + expression: "has(object.metadata.labels) && has(object.metadata.labels.prod) && object.metadata.labels.prod == 'true'" + validate: + failureAction: Enforce + cel: + expressions: + - expression: >- + object.spec.containers.all(container, has(container.securityContext) && + has(container.securityContext.allowPrivilegeEscalation) && + container.securityContext.allowPrivilegeEscalation == false) + message: >- + Privilege escalation is disallowed. The field + spec.containers[*].securityContext.allowPrivilegeEscalation must be set to `false`.