From 40ac8eb863dd515d8e38783d76d0db763945fa12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Edouard=20Br=C3=A9t=C3=A9ch=C3=A9?= Date: Mon, 3 Apr 2023 21:58:58 +0200 Subject: [PATCH] feat: add context/preconditions support to mutate existing (#6754) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: engine handlers Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * feat: add context/preconditions support to mutate existing Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * kuttl Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * readme Signed-off-by: Charles-Edouard Brétéché * fix and context kuttl test Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * validation Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * fix Signed-off-by: Charles-Edouard Brétéché * final fix Signed-off-by: Charles-Edouard Brétéché --------- Signed-off-by: Charles-Edouard Brétéché Co-authored-by: shuting --- api/kyverno/v1/common_types.go | 2 +- api/kyverno/v1/resource_spec_types.go | 29 +- api/kyverno/v1/zz_generated.deepcopy.go | 34 +- charts/kyverno/templates/crds/crds.yaml | 1204 +++++++++++++++++ config/crds/kyverno.io_clusterpolicies.yaml | 602 +++++++++ config/crds/kyverno.io_policies.yaml | 602 +++++++++ config/install-latest-testing.yaml | 1204 +++++++++++++++++ docs/user/crd/index.html | 72 +- pkg/engine/engine.go | 97 +- pkg/engine/handlers/mutation/common.go | 52 +- pkg/engine/handlers/mutation/load_targets.go | 22 +- .../handlers/mutation/mutate_existing.go | 41 +- pkg/engine/handlers/mutation/mutate_image.go | 53 +- .../handlers/mutation/mutate_resource.go | 10 +- .../handlers/validation/validate_image.go | 57 +- .../handlers/validation/validate_manifest.go | 33 +- .../handlers/validation/validate_pss.go | 24 +- .../handlers/validation/validate_resource.go | 22 +- pkg/engine/image_verify.go | 24 +- pkg/engine/mutation.go | 18 +- pkg/engine/validation.go | 47 +- pkg/policy/mutate/validate.go | 2 +- pkg/policy/validate.go | 63 +- .../existing/target-context/01-resources.yaml | 4 + .../existing/target-context/02-policy.yaml | 6 + .../existing/target-context/03-trigger.yaml | 4 + .../existing/target-context/04-verify.yaml | 4 + .../existing/target-context/README.md | 21 + .../target-context/policy-assert.yaml | 9 + .../existing/target-context/policy.yaml | 36 + .../target-context/resources-assert.yaml | 7 + .../existing/target-context/resources.yaml | 6 + .../existing/target-context/trigger.yaml | 6 + .../target-preconditions/01-resources.yaml | 4 + .../target-preconditions/02-policy.yaml | 6 + .../target-preconditions/03-trigger.yaml | 4 + .../target-preconditions/04-verify.yaml | 4 + .../existing/target-preconditions/README.md | 18 + .../target-preconditions/policy-assert.yaml | 9 + .../existing/target-preconditions/policy.yaml | 31 + .../resources-assert.yaml | 20 + .../target-preconditions/resources.yaml | 24 + .../target-preconditions/trigger.yaml | 6 + .../target-context/01-policies.yaml | 7 + .../cluster-policy/target-context/README.md | 8 + .../target-context/policy-1.yaml | 35 + .../target-context/policy-2.yaml | 39 + 47 files changed, 4326 insertions(+), 306 deletions(-) create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/01-resources.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/02-policy.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/03-trigger.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/04-verify.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/README.md create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy-assert.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources-assert.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/trigger.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/01-resources.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/02-policy.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/03-trigger.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/04-verify.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/README.md create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy-assert.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources-assert.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources.yaml create mode 100644 test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/trigger.yaml create mode 100644 test/conformance/kuttl/policy-validation/cluster-policy/target-context/01-policies.yaml create mode 100644 test/conformance/kuttl/policy-validation/cluster-policy/target-context/README.md create mode 100644 test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-1.yaml create mode 100644 test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-2.yaml diff --git a/api/kyverno/v1/common_types.go b/api/kyverno/v1/common_types.go index 809dad32c7..b8637c70d8 100644 --- a/api/kyverno/v1/common_types.go +++ b/api/kyverno/v1/common_types.go @@ -266,7 +266,7 @@ func (r ResourceFilter) IsEmpty() bool { type Mutation struct { // Targets defines the target resources to be mutated. // +optional - Targets []ResourceSpec `json:"targets,omitempty" yaml:"targets,omitempty"` + Targets []TargetResourceSpec `json:"targets,omitempty" yaml:"targets,omitempty"` // PatchStrategicMerge is a strategic merge patch used to modify resources. // See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ diff --git a/api/kyverno/v1/resource_spec_types.go b/api/kyverno/v1/resource_spec_types.go index 88aada79c0..997b435b76 100644 --- a/api/kyverno/v1/resource_spec_types.go +++ b/api/kyverno/v1/resource_spec_types.go @@ -1,6 +1,11 @@ package v1 -import "strings" +import ( + "strings" + + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" + apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" +) type ResourceSpec struct { // APIVersion specifies resource apiVersion. @@ -24,3 +29,25 @@ func (s ResourceSpec) GetAPIVersion() string { return s.APIVersion } func (s ResourceSpec) String() string { return strings.Join([]string{s.APIVersion, s.Kind, s.Namespace, s.Name}, "/") } + +// TargetResourceSpec defines targets for mutating existing resources. +type TargetResourceSpec struct { + // ResourceSpec contains the target resources to load when mutating existing resources. + ResourceSpec `json:",omitempty" yaml:",omitempty"` + + // Context defines variables and data sources that can be used during rule execution. + // +optional + Context []ContextEntry `json:"context,omitempty" yaml:"context,omitempty"` + + // Preconditions are used to determine if a policy rule should be applied by evaluating a + // set of conditions. The declaration can contain nested `any` or `all` statements. A direct list + // of conditions (without `any` or `all` statements is supported for backwards compatibility but + // will be deprecated in the next major release. + // See: https://kyverno.io/docs/writing-policies/preconditions/ + // +optional + RawAnyAllConditions *apiextv1.JSON `json:"preconditions,omitempty" yaml:"preconditions,omitempty"` +} + +func (r *TargetResourceSpec) GetAnyAllConditions() apiextensions.JSON { + return FromJSON(r.RawAnyAllConditions) +} diff --git a/api/kyverno/v1/zz_generated.deepcopy.go b/api/kyverno/v1/zz_generated.deepcopy.go index 5fb37ec7ea..96142f8650 100755 --- a/api/kyverno/v1/zz_generated.deepcopy.go +++ b/api/kyverno/v1/zz_generated.deepcopy.go @@ -775,8 +775,10 @@ func (in *Mutation) DeepCopyInto(out *Mutation) { *out = *in if in.Targets != nil { in, out := &in.Targets, &out.Targets - *out = make([]ResourceSpec, len(*in)) - copy(*out, *in) + *out = make([]TargetResourceSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.RawPatchStrategicMerge != nil { in, out := &in.RawPatchStrategicMerge, &out.RawPatchStrategicMerge @@ -1267,6 +1269,34 @@ func (in *StaticKeyAttestor) DeepCopy() *StaticKeyAttestor { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetResourceSpec) DeepCopyInto(out *TargetResourceSpec) { + *out = *in + out.ResourceSpec = in.ResourceSpec + if in.Context != nil { + in, out := &in.Context, &out.Context + *out = make([]ContextEntry, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.RawAnyAllConditions != nil { + in, out := &in.RawAnyAllConditions, &out.RawAnyAllConditions + *out = new(apiextensionsv1.JSON) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetResourceSpec. +func (in *TargetResourceSpec) DeepCopy() *TargetResourceSpec { + if in == nil { + return nil + } + out := new(TargetResourceSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserInfo) DeepCopyInto(out *UserInfo) { *out = *in diff --git a/charts/kyverno/templates/crds/crds.yaml b/charts/kyverno/templates/crds/crds.yaml index 5aee176742..86889db5a6 100644 --- a/charts/kyverno/templates/crds/crds.yaml +++ b/charts/kyverno/templates/crds/crds.yaml @@ -5566,10 +5566,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -5579,6 +5716,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -8982,10 +9128,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -8995,6 +9286,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -12042,10 +12343,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -12055,6 +12493,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -15586,10 +16033,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -15599,6 +16191,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -19099,10 +19701,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -19112,6 +19851,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -22516,10 +23264,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -22529,6 +23422,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -25577,10 +26480,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -25590,6 +26630,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -29121,10 +30170,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -29134,6 +30328,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object diff --git a/config/crds/kyverno.io_clusterpolicies.yaml b/config/crds/kyverno.io_clusterpolicies.yaml index 9ca1b61351..0bef098a9b 100644 --- a/config/crds/kyverno.io_clusterpolicies.yaml +++ b/config/crds/kyverno.io_clusterpolicies.yaml @@ -2060,10 +2060,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -2073,6 +2210,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -5476,10 +5622,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -5489,6 +5780,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -8536,10 +8837,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -8549,6 +8987,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -12080,10 +12527,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -12093,6 +12685,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object diff --git a/config/crds/kyverno.io_policies.yaml b/config/crds/kyverno.io_policies.yaml index fbffa313ae..a4b3f2998a 100644 --- a/config/crds/kyverno.io_policies.yaml +++ b/config/crds/kyverno.io_policies.yaml @@ -2061,10 +2061,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -2074,6 +2211,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -5478,10 +5624,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -5491,6 +5782,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -8539,10 +8840,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -8552,6 +8990,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -12083,10 +12530,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -12096,6 +12688,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index b26585958c..b28c8a047a 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -5649,10 +5649,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -5662,6 +5799,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -9065,10 +9211,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -9078,6 +9369,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -12125,10 +12426,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -12138,6 +12576,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -15669,10 +16116,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -15682,6 +16274,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -19182,10 +19784,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -19195,6 +19934,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -22599,10 +23347,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -22612,6 +23505,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -25660,10 +26563,147 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for mutating + existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data sources + that can be used during rule execution. + items: + description: ContextEntry adds variables and data + sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request to the + Kubernetes API server, or other JSON web service. + The data returned is stored in the context + with the name for the context entry. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the JSON response returned from the server. + For example a JMESPath of "items | length(@)" + applied to the API server response for + the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call to a + JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to validate + the server certificate. + type: string + data: + description: Data specifies the POST + data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique identifier + for the data value + type: string + value: + description: Value is the data + value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP request + type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web service + URL. The typical format is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path to + be used in the HTTP GET request to the + Kubernetes API server (e.g. "/api/v1/namespaces" + or "/apis/apps/v1/deployments"). The + format required is the same format used + by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch image + details. + properties: + jmesPath: + description: JMESPath is an optional JSON + Match Expression that can be used to transform + the ImageData struct returned as a result + of processing the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary JMESPath + context variable that can be defined inline. + properties: + default: + description: Default is an optional arbitrary + JSON object that the variable may take + if the JMESPath expression evaluates to + nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional JMESPath + Expression that can be used to transform + the variable. + type: string + value: + description: Value is any arbitrary JSON + object representable in YAML or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -25673,6 +26713,15 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but will + be deprecated in the next major release. See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object @@ -29204,10 +30253,155 @@ spec: description: Targets defines the target resources to be mutated. items: + description: TargetResourceSpec defines targets for + mutating existing resources. properties: apiVersion: description: APIVersion specifies resource apiVersion. type: string + context: + description: Context defines variables and data + sources that can be used during rule execution. + items: + description: ContextEntry adds variables and + data sources to a rule Context. Either a ConfigMap + reference or a APILookup must be provided. + properties: + apiCall: + description: APICall is an HTTP request + to the Kubernetes API server, or other + JSON web service. The data returned is + stored in the context with the name for + the context entry. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the JSON response + returned from the server. For example + a JMESPath of "items | length(@)" + applied to the API server response + for the URLPath "/apis/apps/v1/deployments" + will return the total count of deployments + across all namespaces. + type: string + service: + description: Service is an API call + to a JSON web service + properties: + caBundle: + description: CABundle is a PEM encoded + CA bundle which will be used to + validate the server certificate. + type: string + data: + description: Data specifies the + POST data sent to the server. + items: + description: RequestData contains + the HTTP POST data + properties: + key: + description: Key is a unique + identifier for the data + value + type: string + value: + description: Value is the + data value + x-kubernetes-preserve-unknown-fields: true + required: + - key + - value + type: object + type: array + requestType: + default: GET + description: Method is the HTTP + request type (GET or POST). + enum: + - GET + - POST + type: string + urlPath: + description: URL is the JSON web + service URL. The typical format + is `https://{service}.{namespace}:{port}/{path}`. + type: string + required: + - requestType + - urlPath + type: object + urlPath: + description: URLPath is the URL path + to be used in the HTTP GET request + to the Kubernetes API server (e.g. + "/api/v1/namespaces" or "/apis/apps/v1/deployments"). + The format required is the same format + used by the `kubectl get --raw` command. + type: string + type: object + configMap: + description: ConfigMap is the ConfigMap + reference. + properties: + name: + description: Name is the ConfigMap name. + type: string + namespace: + description: Namespace is the ConfigMap + namespace. + type: string + required: + - name + type: object + imageRegistry: + description: ImageRegistry defines requests + to an OCI/Docker V2 registry to fetch + image details. + properties: + jmesPath: + description: JMESPath is an optional + JSON Match Expression that can be + used to transform the ImageData struct + returned as a result of processing + the image reference. + type: string + reference: + description: 'Reference is image reference + to a container image in the registry. + Example: ghcr.io/kyverno/kyverno:latest' + type: string + required: + - reference + type: object + name: + description: Name is the variable name. + type: string + variable: + description: Variable defines an arbitrary + JMESPath context variable that can be + defined inline. + properties: + default: + description: Default is an optional + arbitrary JSON object that the variable + may take if the JMESPath expression + evaluates to nil + x-kubernetes-preserve-unknown-fields: true + jmesPath: + description: JMESPath is an optional + JMESPath Expression that can be used + to transform the variable. + type: string + value: + description: Value is any arbitrary + JSON object representable in YAML + or JSON form. + x-kubernetes-preserve-unknown-fields: true + type: object + type: object + type: array kind: description: Kind specifies resource kind. type: string @@ -29217,6 +30411,16 @@ spec: namespace: description: Namespace specifies resource namespace. type: string + preconditions: + description: 'Preconditions are used to determine + if a policy rule should be applied by evaluating + a set of conditions. The declaration can contain + nested `any` or `all` statements. A direct list + of conditions (without `any` or `all` statements + is supported for backwards compatibility but + will be deprecated in the next major release. + See: https://kyverno.io/docs/writing-policies/preconditions/' + x-kubernetes-preserve-unknown-fields: true type: object type: array type: object diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 8c1f675952..5efdcf8c02 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -1153,6 +1153,7 @@ string ForEachMutation, ForEachValidation, Rule, +TargetResourceSpec, Rule)

@@ -2299,8 +2300,8 @@ Please specify under “any” or “all” instead.

targets
- -[]ResourceSpec + +[]TargetResourceSpec @@ -2819,7 +2820,7 @@ ResourceDescription

(Appears on: Generation, -Mutation, +TargetResourceSpec, UpdateRequestSpec, UpdateRequestStatus)

@@ -3495,6 +3496,71 @@ Rekor (https://rekor.sigstore.dev) is u
+

TargetResourceSpec +

+

+(Appears on: +Mutation) +

+

+

TargetResourceSpec defines targets for mutating existing resources.

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ResourceSpec
+ + +ResourceSpec + + +
+

ResourceSpec contains the target resources to load when mutating existing resources.

+
+context
+ + +[]ContextEntry + + +
+(Optional) +

Context defines variables and data sources that can be used during rule execution.

+
+preconditions
+ + +Kubernetes apiextensions/v1.JSON + + +
+(Optional) +

Preconditions are used to determine if a policy rule should be applied by evaluating a +set of conditions. The declaration can contain nested any or all statements. A direct list +of conditions (without any or all statements is supported for backwards compatibility but +will be deprecated in the next major release. +See: https://kyverno.io/docs/writing-policies/preconditions/

+
+

UserInfo

diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index d10578fcb1..e4d28c671a 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -6,14 +6,13 @@ import ( "time" "github.com/go-logr/logr" + gojmespath "github.com/jmespath/go-jmespath" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" enginecontext "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/handlers" - "github.com/kyverno/kyverno/pkg/engine/handlers/mutation" - "github.com/kyverno/kyverno/pkg/engine/handlers/validation" "github.com/kyverno/kyverno/pkg/engine/internal" engineutils "github.com/kyverno/kyverno/pkg/engine/utils" "github.com/kyverno/kyverno/pkg/logging" @@ -24,19 +23,15 @@ import ( ) type engine struct { - configuration config.Configuration - client dclient.Interface - rclient registryclient.Client - engineContextLoaderFactory engineapi.EngineContextLoaderFactory - exceptionSelector engineapi.PolicyExceptionSelector - validateResourceHandler handlers.Handler - validateManifestHandler handlers.Handler - validatePssHandler handlers.Handler - validateImageHandler handlers.Handler - mutateResourceHandler handlers.Handler - mutateExistingHandler handlers.Handler + configuration config.Configuration + client dclient.Interface + rclient registryclient.Client + contextLoader engineapi.ContextLoaderFactory + exceptionSelector engineapi.PolicyExceptionSelector } +type handlerFactory = func() (handlers.Handler, error) + func NewEngine( configuration config.Configuration, client dclient.Interface, @@ -44,30 +39,12 @@ func NewEngine( contextLoader engineapi.ContextLoaderFactory, exceptionSelector engineapi.PolicyExceptionSelector, ) engineapi.Engine { - engineContextLoaderFactory := func(policy kyvernov1.PolicyInterface, rule kyvernov1.Rule) engineapi.EngineContextLoader { - loader := contextLoader(policy, rule) - return func(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error { - return loader.Load( - ctx, - client, - rclient, - contextEntries, - jsonContext, - ) - } - } return &engine{ - configuration: configuration, - client: client, - rclient: rclient, - engineContextLoaderFactory: engineContextLoaderFactory, - exceptionSelector: exceptionSelector, - validateResourceHandler: validation.NewValidateResourceHandler(), - validateManifestHandler: validation.NewValidateManifestHandler(client), - validatePssHandler: validation.NewValidatePssHandler(), - validateImageHandler: validation.NewValidateImageHandler(configuration), - mutateResourceHandler: mutation.NewMutateResourceHandler(), - mutateExistingHandler: mutation.NewMutateExistingHandler(client), + configuration: configuration, + client: client, + rclient: rclient, + contextLoader: contextLoader, + exceptionSelector: exceptionSelector, } } @@ -143,7 +120,16 @@ func (e *engine) ContextLoader( policy kyvernov1.PolicyInterface, rule kyvernov1.Rule, ) engineapi.EngineContextLoader { - return e.engineContextLoaderFactory(policy, rule) + loader := e.contextLoader(policy, rule) + return func(ctx context.Context, contextEntries []kyvernov1.ContextEntry, jsonContext enginecontext.Interface) error { + return loader.Load( + ctx, + e.client, + e.rclient, + contextEntries, + jsonContext, + ) + } } // matches checks if either the new or old resource satisfies the filter conditions defined in the rule @@ -188,7 +174,7 @@ func matches( func (e *engine) invokeRuleHandler( ctx context.Context, logger logr.Logger, - handler handlers.Handler, + handlerFactory handlerFactory, policyContext engineapi.PolicyContext, resource unstructured.Unstructured, rule kyvernov1.Rule, @@ -204,12 +190,37 @@ func (e *engine) invokeRuleHandler( logger.V(4).Info("rule not matched", "reason", err.Error()) return resource, nil } - // check if there's an exception - if ruleResp := e.hasPolicyExceptions(logger, ruleType, policyContext, rule); ruleResp != nil { - return resource, handlers.RuleResponses(ruleResp) + if handlerFactory == nil { + return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to instantiate handler", nil)) + } else if handler, err := handlerFactory(); err != nil { + return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to instantiate handler", err)) + } else if handler != nil { + // check if there's an exception + if ruleResp := e.hasPolicyExceptions(logger, ruleType, policyContext, rule); ruleResp != nil { + return resource, handlers.RuleResponses(ruleResp) + } + // load rule context + contextLoader := e.ContextLoader(policyContext.Policy(), rule) + if err := contextLoader(ctx, rule.Context, policyContext.JSONContext()); err != nil { + if _, ok := err.(gojmespath.NotFoundError); ok { + logger.V(3).Info("failed to load context", "reason", err.Error()) + } else { + logger.Error(err, "failed to load context") + } + return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to load context", err)) + } + // check preconditions + preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) + if err != nil { + return resource, handlers.RuleResponses(internal.RuleError(rule, ruleType, "failed to evaluate preconditions", err)) + } + if !preconditionsPassed { + return resource, handlers.RuleResponses(internal.RuleSkip(rule, ruleType, "preconditions not met")) + } + // process handler + return handler.Process(ctx, logger, policyContext, resource, rule, contextLoader) } - // process handler - return handler.Process(ctx, logger, policyContext, resource, rule, e.ContextLoader(policyContext.Policy(), rule)) + return resource, nil }, ) } diff --git a/pkg/engine/handlers/mutation/common.go b/pkg/engine/handlers/mutation/common.go index 4dc51c4a1d..d4b71c105f 100644 --- a/pkg/engine/handlers/mutation/common.go +++ b/pkg/engine/handlers/mutation/common.go @@ -14,36 +14,14 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -func mutateResource( - ctx context.Context, - contextLoader engineapi.EngineContextLoader, - rule kyvernov1.Rule, - policyContext engineapi.PolicyContext, - resource unstructured.Unstructured, - logger logr.Logger, -) *mutate.Response { - if err := contextLoader(ctx, rule.Context, policyContext.JSONContext()); err != nil { - logger.Error(err, "failed to load context") - return mutate.NewErrorResponse("failed to load context", err) - } - preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) - if err != nil { - return mutate.NewErrorResponse("failed to evaluate preconditions", err) - } - if !preconditionsPassed { - return mutate.NewResponse(engineapi.RuleStatusSkip, resource, nil, "preconditions not met") - } - return mutate.Mutate(&rule, policyContext.JSONContext(), resource, logger) -} - type forEachMutator struct { - rule *kyvernov1.Rule + logger logr.Logger + rule kyvernov1.Rule policyContext engineapi.PolicyContext foreach []kyvernov1.ForEachMutation resource resourceInfo nesting int contextLoader engineapi.EngineContextLoader - log logr.Logger } func (f *forEachMutator) mutateForEach(ctx context.Context) *mutate.Response { @@ -51,20 +29,6 @@ func (f *forEachMutator) mutateForEach(ctx context.Context) *mutate.Response { allPatches := make([][]byte, 0) for _, foreach := range f.foreach { - if err := f.contextLoader(ctx, f.rule.Context, f.policyContext.JSONContext()); err != nil { - f.log.Error(err, "failed to load context") - return mutate.NewErrorResponse("failed to load context", err) - } - - preconditionsPassed, err := internal.CheckPreconditions(f.log, f.policyContext.JSONContext(), f.rule.GetAnyAllConditions()) - if err != nil { - return mutate.NewErrorResponse("failed to evaluate preconditions", err) - } - - if !preconditionsPassed { - return mutate.NewResponse(engineapi.RuleStatusSkip, f.resource.unstructured, nil, "preconditions not met") - } - elements, err := engineutils.EvaluateList(foreach.List, f.policyContext.JSONContext()) if err != nil { msg := fmt.Sprintf("failed to evaluate list %s: %v", foreach.List, err) @@ -82,9 +46,9 @@ func (f *forEachMutator) mutateForEach(ctx context.Context) *mutate.Response { f.resource.unstructured = mutateResp.PatchedResource allPatches = append(allPatches, mutateResp.Patches...) } - f.log.Info("mutateResp.PatchedResource", "resource", mutateResp.PatchedResource) + f.logger.Info("mutateResp.PatchedResource", "resource", mutateResp.PatchedResource) if err := f.policyContext.JSONContext().AddResource(mutateResp.PatchedResource.Object); err != nil { - f.log.Error(err, "failed to update resource in context") + f.logger.Error(err, "failed to update resource in context") } } } @@ -124,13 +88,13 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F return mutate.NewErrorResponse(fmt.Sprintf("failed to load to mutate.foreach[%d].context", index), err) } - preconditionsPassed, err := internal.CheckPreconditions(f.log, policyContext.JSONContext(), foreach.AnyAllConditions) + preconditionsPassed, err := internal.CheckPreconditions(f.logger, policyContext.JSONContext(), foreach.AnyAllConditions) if err != nil { return mutate.NewErrorResponse(fmt.Sprintf("failed to evaluate mutate.foreach[%d].preconditions", index), err) } if !preconditionsPassed { - f.log.Info("mutate.foreach.preconditions not met", "elementIndex", index) + f.logger.Info("mutate.foreach.preconditions not met", "elementIndex", index) continue } @@ -145,7 +109,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F rule: f.rule, policyContext: f.policyContext, resource: patchedResource, - log: f.log, + logger: f.logger, foreach: nestedForEach, nesting: f.nesting + 1, contextLoader: f.contextLoader, @@ -153,7 +117,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F mutateResp = m.mutateForEach(ctx) } else { - mutateResp = mutate.ForEach(f.rule.Name, foreach, policyContext, patchedResource.unstructured, element, f.log) + mutateResp = mutate.ForEach(f.rule.Name, foreach, policyContext, patchedResource.unstructured, element, f.logger) } if mutateResp.Status == engineapi.RuleStatusFail || mutateResp.Status == engineapi.RuleStatusError { diff --git a/pkg/engine/handlers/mutation/load_targets.go b/pkg/engine/handlers/mutation/load_targets.go index 90e3993a85..e9d43b39aa 100644 --- a/pkg/engine/handlers/mutation/load_targets.go +++ b/pkg/engine/handlers/mutation/load_targets.go @@ -12,6 +12,7 @@ import ( kubeutils "github.com/kyverno/kyverno/pkg/utils/kube" "github.com/kyverno/kyverno/pkg/utils/wildcard" "go.uber.org/multierr" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -24,10 +25,17 @@ type resourceInfo struct { parentResourceGVR metav1.GroupVersionResource } -func loadTargets(client dclient.Interface, targets []kyvernov1.ResourceSpec, ctx engineapi.PolicyContext, logger logr.Logger) ([]resourceInfo, error) { - var targetObjects []resourceInfo +type target struct { + resourceInfo + context []kyvernov1.ContextEntry + preconditions apiextensions.JSON +} + +func loadTargets(client dclient.Interface, targets []kyvernov1.TargetResourceSpec, ctx engineapi.PolicyContext, logger logr.Logger) ([]target, error) { + var targetObjects []target var errors []error for i := range targets { + preconditions := targets[i].GetAnyAllConditions() spec, err := resolveSpec(i, targets[i], ctx, logger) if err != nil { errors = append(errors, err) @@ -38,12 +46,18 @@ func loadTargets(client dclient.Interface, targets []kyvernov1.ResourceSpec, ctx errors = append(errors, err) continue } - targetObjects = append(targetObjects, objs...) + for _, obj := range objs { + targetObjects = append(targetObjects, target{ + resourceInfo: obj, + context: targets[i].Context, + preconditions: preconditions, + }) + } } return targetObjects, multierr.Combine(errors...) } -func resolveSpec(i int, target kyvernov1.ResourceSpec, ctx engineapi.PolicyContext, logger logr.Logger) (kyvernov1.ResourceSpec, error) { +func resolveSpec(i int, target kyvernov1.TargetResourceSpec, ctx engineapi.PolicyContext, logger logr.Logger) (kyvernov1.ResourceSpec, error) { kind, err := variables.SubstituteAll(logger, ctx.JSONContext(), target.Kind) if err != nil { return kyvernov1.ResourceSpec{}, fmt.Errorf("failed to substitute variables in target[%d].Kind %s: %v", i, target.Kind, err) diff --git a/pkg/engine/handlers/mutation/mutate_existing.go b/pkg/engine/handlers/mutation/mutate_existing.go index afcd4d2376..6bc321d6c5 100644 --- a/pkg/engine/handlers/mutation/mutate_existing.go +++ b/pkg/engine/handlers/mutation/mutate_existing.go @@ -19,10 +19,10 @@ type mutateExistingHandler struct { func NewMutateExistingHandler( client dclient.Interface, -) handlers.Handler { +) (handlers.Handler, error) { return mutateExistingHandler{ client: client, - } + }, nil } func (h mutateExistingHandler) Process( @@ -35,42 +35,57 @@ func (h mutateExistingHandler) Process( ) (unstructured.Unstructured, []engineapi.RuleResponse) { var responses []engineapi.RuleResponse logger.V(3).Info("processing mutate rule") - var patchedResources []resourceInfo targets, err := loadTargets(h.client, rule.Mutation.Targets, policyContext, logger) if err != nil { rr := internal.RuleError(rule, engineapi.Mutation, "", err) responses = append(responses, *rr) - } else { - patchedResources = append(patchedResources, targets...) } - for _, patchedResource := range patchedResources { - if patchedResource.unstructured.Object == nil { + for _, target := range targets { + if target.unstructured.Object == nil { continue } policyContext := policyContext.Copy() - if err := policyContext.JSONContext().AddTargetResource(patchedResource.unstructured.Object); err != nil { + if err := policyContext.JSONContext().AddTargetResource(target.unstructured.Object); err != nil { logger.Error(err, "failed to add target resource to the context") continue } + // load target specific context + if err := contextLoader(ctx, target.context, policyContext.JSONContext()); err != nil { + rr := internal.RuleError(rule, engineapi.Mutation, "failed to load context", err) + responses = append(responses, *rr) + continue + } + // load target specific preconditions + preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), target.preconditions) + if err != nil { + rr := internal.RuleError(rule, engineapi.Mutation, "failed to evaluate preconditions", err) + responses = append(responses, *rr) + continue + } + if !preconditionsPassed { + rr := internal.RuleSkip(rule, engineapi.Mutation, "preconditions not met") + responses = append(responses, *rr) + continue + } // logger.V(4).Info("apply rule to resource", "resource namespace", patchedResource.unstructured.GetNamespace(), "resource name", patchedResource.unstructured.GetName()) var mutateResp *mutate.Response if rule.Mutation.ForEachMutation != nil { m := &forEachMutator{ - rule: &rule, + rule: rule, foreach: rule.Mutation.ForEachMutation, policyContext: policyContext, - resource: patchedResource, - log: logger, + resource: target.resourceInfo, + logger: logger, contextLoader: contextLoader, nesting: 0, } mutateResp = m.mutateForEach(ctx) } else { - mutateResp = mutateResource(ctx, contextLoader, rule, policyContext, patchedResource.unstructured, logger) + mutateResp = mutate.Mutate(&rule, policyContext.JSONContext(), target.unstructured, logger) } - if ruleResponse := buildRuleResponse(&rule, mutateResp, patchedResource); ruleResponse != nil { + if ruleResponse := buildRuleResponse(&rule, mutateResp, target.resourceInfo); ruleResponse != nil { responses = append(responses, *ruleResponse) } } diff --git a/pkg/engine/handlers/mutation/mutate_image.go b/pkg/engine/handlers/mutation/mutate_image.go index 24e4664ffd..a28fe82e27 100644 --- a/pkg/engine/handlers/mutation/mutate_image.go +++ b/pkg/engine/handlers/mutation/mutate_image.go @@ -4,7 +4,6 @@ import ( "context" "github.com/go-logr/logr" - gojmespath "github.com/jmespath/go-jmespath" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" @@ -14,6 +13,7 @@ import ( engineutils "github.com/kyverno/kyverno/pkg/engine/utils" "github.com/kyverno/kyverno/pkg/engine/variables" "github.com/kyverno/kyverno/pkg/registryclient" + apiutils "github.com/kyverno/kyverno/pkg/utils/api" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -21,18 +21,33 @@ type mutateImageHandler struct { configuration config.Configuration rclient registryclient.Client ivm *engineapi.ImageVerificationMetadata + images []apiutils.ImageInfo } func NewMutateImageHandler( + policyContext engineapi.PolicyContext, + resource unstructured.Unstructured, + rule kyvernov1.Rule, configuration config.Configuration, rclient registryclient.Client, ivm *engineapi.ImageVerificationMetadata, -) handlers.Handler { +) (handlers.Handler, error) { + if len(rule.VerifyImages) == 0 { + return nil, nil + } + ruleImages, _, err := engineutils.ExtractMatchingImages(resource, policyContext.JSONContext(), rule, configuration) + if err != nil { + return nil, err + } + if len(ruleImages) == 0 { + return nil, nil + } return mutateImageHandler{ configuration: configuration, rclient: rclient, ivm: ivm, - } + images: ruleImages, + }, nil } func (h mutateImageHandler) Process( @@ -43,37 +58,7 @@ func (h mutateImageHandler) Process( rule kyvernov1.Rule, contextLoader engineapi.EngineContextLoader, ) (unstructured.Unstructured, []engineapi.RuleResponse) { - if engineutils.IsDeleteRequest(policyContext) { - return resource, nil - } - if len(rule.VerifyImages) == 0 { - return resource, nil - } - ruleImages, _, err := engineutils.ExtractMatchingImages(resource, policyContext.JSONContext(), rule, h.configuration) - if err != nil { - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.ImageVerify, "failed to extract images", err)) - } - if len(ruleImages) == 0 { - return resource, nil - } jsonContext := policyContext.JSONContext() - // load context - if err := contextLoader(ctx, rule.Context, jsonContext); err != nil { - if _, ok := err.(gojmespath.NotFoundError); ok { - logger.V(3).Info("failed to load context", "reason", err.Error()) - } else { - logger.Error(err, "failed to load context") - } - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.ImageVerify, "failed to load context", err)) - } - // check preconditions - preconditionsPassed, err := internal.CheckPreconditions(logger, jsonContext, rule.GetAnyAllConditions()) - if err != nil { - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.ImageVerify, "failed to evaluate preconditions", err)) - } - if !preconditionsPassed { - return resource, handlers.RuleResponses(internal.RuleSkip(rule, engineapi.ImageVerify, "preconditions not met")) - } ruleCopy, err := substituteVariables(rule, jsonContext, logger) if err != nil { return resource, handlers.RuleResponses( @@ -83,7 +68,7 @@ func (h mutateImageHandler) Process( iv := internal.NewImageVerifier(logger, h.rclient, policyContext, *ruleCopy, h.ivm) var engineResponses []*engineapi.RuleResponse for _, imageVerify := range ruleCopy.VerifyImages { - engineResponses = append(engineResponses, iv.Verify(ctx, imageVerify, ruleImages, h.configuration)...) + engineResponses = append(engineResponses, iv.Verify(ctx, imageVerify, h.images, h.configuration)...) } return resource, handlers.RuleResponses(engineResponses...) } diff --git a/pkg/engine/handlers/mutation/mutate_resource.go b/pkg/engine/handlers/mutation/mutate_resource.go index 11956673a6..9493bd5ec6 100644 --- a/pkg/engine/handlers/mutation/mutate_resource.go +++ b/pkg/engine/handlers/mutation/mutate_resource.go @@ -14,8 +14,8 @@ import ( type mutateResourceHandler struct{} -func NewMutateResourceHandler() handlers.Handler { - return mutateResourceHandler{} +func NewMutateResourceHandler() (handlers.Handler, error) { + return mutateResourceHandler{}, nil } func (h mutateResourceHandler) Process( @@ -41,17 +41,17 @@ func (h mutateResourceHandler) Process( var mutateResp *mutate.Response if rule.Mutation.ForEachMutation != nil { m := &forEachMutator{ - rule: &rule, + rule: rule, foreach: rule.Mutation.ForEachMutation, policyContext: policyContext, resource: resourceInfo, - log: logger, + logger: logger, contextLoader: contextLoader, nesting: 0, } mutateResp = m.mutateForEach(ctx) } else { - mutateResp = mutateResource(ctx, contextLoader, rule, policyContext, resourceInfo.unstructured, logger) + mutateResp = mutate.Mutate(&rule, policyContext.JSONContext(), resource, logger) } if mutateResp == nil { return resource, nil diff --git a/pkg/engine/handlers/validation/validate_image.go b/pkg/engine/handlers/validation/validate_image.go index 92ab5fdcb0..2e638e7d10 100644 --- a/pkg/engine/handlers/validation/validate_image.go +++ b/pkg/engine/handlers/validation/validate_image.go @@ -5,7 +5,6 @@ import ( "fmt" "github.com/go-logr/logr" - gojmespath "github.com/jmespath/go-jmespath" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" @@ -16,16 +15,25 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -type validateImageHandler struct { - configuration config.Configuration -} +type validateImageHandler struct{} func NewValidateImageHandler( + policyContext engineapi.PolicyContext, + resource unstructured.Unstructured, + rule kyvernov1.Rule, configuration config.Configuration, -) handlers.Handler { - return validateImageHandler{ - configuration: configuration, +) (handlers.Handler, error) { + if engineutils.IsDeleteRequest(policyContext) { + return nil, nil } + ruleImages, _, err := engineutils.ExtractMatchingImages(resource, policyContext.JSONContext(), rule, configuration) + if err != nil { + return nil, err + } + if len(ruleImages) == 0 { + return nil, nil + } + return validateImageHandler{}, nil } func (h validateImageHandler) Process( @@ -34,41 +42,8 @@ func (h validateImageHandler) Process( policyContext engineapi.PolicyContext, resource unstructured.Unstructured, rule kyvernov1.Rule, - contextLoader engineapi.EngineContextLoader, + _ engineapi.EngineContextLoader, ) (unstructured.Unstructured, []engineapi.RuleResponse) { - if engineutils.IsDeleteRequest(policyContext) { - return resource, nil - } - if len(rule.VerifyImages) == 0 { - return resource, nil - } - ruleImages, _, err := engineutils.ExtractMatchingImages(resource, policyContext.JSONContext(), rule, h.configuration) - if err != nil { - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to extract images", err)) - } - if len(ruleImages) == 0 { - return resource, nil - } - // load context - if err := contextLoader(ctx, rule.Context, policyContext.JSONContext()); err != nil { - if _, ok := err.(gojmespath.NotFoundError); ok { - logger.V(3).Info("failed to load context", "reason", err.Error()) - } else { - logger.Error(err, "failed to load context") - } - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to load context", err)) - } - // check preconditions - preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) - if err != nil { - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to evaluate preconditions", err)) - } - if !preconditionsPassed { - if policyContext.Policy().GetSpec().ValidationFailureAction.Audit() { - return resource, nil - } - return resource, handlers.RuleResponses(internal.RuleSkip(rule, engineapi.Validation, "preconditions not met")) - } for _, v := range rule.VerifyImages { imageVerify := v.Convert() for _, infoMap := range policyContext.JSONContext().ImageInfo() { diff --git a/pkg/engine/handlers/validation/validate_manifest.go b/pkg/engine/handlers/validation/validate_manifest.go index 02e7eb42f8..7bc679c481 100644 --- a/pkg/engine/handlers/validation/validate_manifest.go +++ b/pkg/engine/handlers/validation/validate_manifest.go @@ -14,7 +14,6 @@ import ( "github.com/ghodss/yaml" "github.com/go-logr/logr" - gojmespath "github.com/jmespath/go-jmespath" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/auth" "github.com/kyverno/kyverno/pkg/clients/dclient" @@ -39,10 +38,16 @@ type validateManifestHandler struct { client dclient.Interface } -func NewValidateManifestHandler(client dclient.Interface) handlers.Handler { +func NewValidateManifestHandler( + policyContext engineapi.PolicyContext, + client dclient.Interface, +) (handlers.Handler, error) { + if engineutils.IsDeleteRequest(policyContext) { + return nil, nil + } return validateManifestHandler{ client: client, - } + }, nil } func (h validateManifestHandler) Process( @@ -51,28 +56,8 @@ func (h validateManifestHandler) Process( policyContext engineapi.PolicyContext, resource unstructured.Unstructured, rule kyvernov1.Rule, - contextLoader engineapi.EngineContextLoader, + _ engineapi.EngineContextLoader, ) (unstructured.Unstructured, []engineapi.RuleResponse) { - if engineutils.IsDeleteRequest(policyContext) { - return resource, nil - } - // load context - if err := contextLoader(ctx, rule.Context, policyContext.JSONContext()); err != nil { - if _, ok := err.(gojmespath.NotFoundError); ok { - logger.V(3).Info("failed to load context", "reason", err.Error()) - } else { - logger.Error(err, "failed to load context") - } - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to load context", err)) - } - // check preconditions - preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) - if err != nil { - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to evaluate preconditions", err)) - } - if !preconditionsPassed { - return resource, handlers.RuleResponses(internal.RuleSkip(rule, engineapi.Validation, "preconditions not met")) - } // verify manifest verified, reason, err := h.verifyManifest(ctx, logger, policyContext, *rule.Validation.Manifests) if err != nil { diff --git a/pkg/engine/handlers/validation/validate_pss.go b/pkg/engine/handlers/validation/validate_pss.go index 55ab210b3c..06a63c5905 100644 --- a/pkg/engine/handlers/validation/validate_pss.go +++ b/pkg/engine/handlers/validation/validate_pss.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/go-logr/logr" - gojmespath "github.com/jmespath/go-jmespath" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/handlers" @@ -21,8 +20,8 @@ import ( type validatePssHandler struct{} -func NewValidatePssHandler() handlers.Handler { - return validatePssHandler{} +func NewValidatePssHandler() (handlers.Handler, error) { + return validatePssHandler{}, nil } func (h validatePssHandler) Process( @@ -31,25 +30,8 @@ func (h validatePssHandler) Process( policyContext engineapi.PolicyContext, resource unstructured.Unstructured, rule kyvernov1.Rule, - contextLoader engineapi.EngineContextLoader, + _ engineapi.EngineContextLoader, ) (unstructured.Unstructured, []engineapi.RuleResponse) { - // load context - if err := contextLoader(ctx, rule.Context, policyContext.JSONContext()); err != nil { - if _, ok := err.(gojmespath.NotFoundError); ok { - logger.V(3).Info("failed to load context", "reason", err.Error()) - } else { - logger.Error(err, "failed to load context") - } - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to load context", err)) - } - // check preconditions - preconditionsPassed, err := internal.CheckPreconditions(logger, policyContext.JSONContext(), rule.GetAnyAllConditions()) - if err != nil { - return resource, handlers.RuleResponses(internal.RuleError(rule, engineapi.Validation, "failed to evaluate preconditions", err)) - } - if !preconditionsPassed { - return resource, handlers.RuleResponses(internal.RuleSkip(rule, engineapi.Validation, "preconditions not met")) - } // Marshal pod metadata and spec podSecurity := rule.Validation.PodSecurity podSpec, metadata, err := getSpec(resource) diff --git a/pkg/engine/handlers/validation/validate_resource.go b/pkg/engine/handlers/validation/validate_resource.go index 20fca3e5b3..3a6ff7170b 100644 --- a/pkg/engine/handlers/validation/validate_resource.go +++ b/pkg/engine/handlers/validation/validate_resource.go @@ -23,8 +23,8 @@ import ( type validateResourceHandler struct{} -func NewValidateResourceHandler() handlers.Handler { - return validateResourceHandler{} +func NewValidateResourceHandler() (handlers.Handler, error) { + return validateResourceHandler{}, nil } func (h validateResourceHandler) Process( @@ -55,16 +55,14 @@ type validator struct { func newValidator(log logr.Logger, contextLoader engineapi.EngineContextLoader, ctx engineapi.PolicyContext, rule kyvernov1.Rule) *validator { return &validator{ - log: log, - rule: rule, - policyContext: ctx, - contextLoader: contextLoader, - contextEntries: rule.Context, - anyAllConditions: rule.GetAnyAllConditions(), - pattern: rule.Validation.GetPattern(), - anyPattern: rule.Validation.GetAnyPattern(), - deny: rule.Validation.Deny, - forEach: rule.Validation.ForEachValidation, + log: log, + rule: rule, + policyContext: ctx, + contextLoader: contextLoader, + pattern: rule.Validation.GetPattern(), + anyPattern: rule.Validation.GetAnyPattern(), + deny: rule.Validation.Deny, + forEach: rule.Validation.ForEachValidation, } } diff --git a/pkg/engine/image_verify.go b/pkg/engine/image_verify.go index 4cf6918558..8424f16e7b 100644 --- a/pkg/engine/image_verify.go +++ b/pkg/engine/image_verify.go @@ -8,6 +8,7 @@ import ( kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/autogen" engineapi "github.com/kyverno/kyverno/pkg/engine/api" + "github.com/kyverno/kyverno/pkg/engine/handlers" "github.com/kyverno/kyverno/pkg/engine/handlers/mutation" "github.com/kyverno/kyverno/pkg/engine/internal" ) @@ -29,18 +30,23 @@ func (e *engine) verifyAndPatchImages( for _, rule := range autogen.ComputeRules(policy) { startTime := time.Now() logger := internal.LoggerWithRule(logger, rule) - if !rule.HasVerifyImages() { - continue + handlerFactory := func() (handlers.Handler, error) { + if !rule.HasVerifyImages() { + return nil, nil + } + return mutation.NewMutateImageHandler( + policyContext, + matchedResource, + rule, + e.configuration, + e.rclient, + &ivm, + ) } - handler := mutation.NewMutateImageHandler( - e.configuration, - e.rclient, - &ivm, - ) resource, ruleResp := e.invokeRuleHandler( ctx, logger, - handler, + handlerFactory, policyContext, matchedResource, rule, @@ -56,6 +62,6 @@ func (e *engine) verifyAndPatchImages( break } } - // TODO: i doesn't make sense to not return the patched resource here + // TODO: it doesn't make sense to not return the patched resource here return resp, ivm } diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index 11f5078917..53ed1770a4 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -9,6 +9,7 @@ import ( "github.com/kyverno/kyverno/pkg/autogen" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/handlers" + "github.com/kyverno/kyverno/pkg/engine/handlers/mutation" "github.com/kyverno/kyverno/pkg/engine/internal" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -30,18 +31,19 @@ func (e *engine) mutate( for _, rule := range autogen.ComputeRules(policy) { startTime := time.Now() logger := internal.LoggerWithRule(logger, rule) - if !rule.HasMutate() { - continue - } - var handler handlers.Handler - handler = e.mutateResourceHandler - if !policyContext.AdmissionOperation() && rule.IsMutateExisting() { - handler = e.mutateExistingHandler + handlerFactory := func() (handlers.Handler, error) { + if !rule.HasMutate() { + return nil, nil + } + if !policyContext.AdmissionOperation() && rule.IsMutateExisting() { + return mutation.NewMutateExistingHandler(e.client) + } + return mutation.NewMutateResourceHandler() } resource, ruleResp := e.invokeRuleHandler( ctx, logger, - handler, + handlerFactory, policyContext, matchedResource, rule, diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index 3771329dcf..5d24afd024 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -9,6 +9,7 @@ import ( "github.com/kyverno/kyverno/pkg/autogen" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/handlers" + "github.com/kyverno/kyverno/pkg/engine/handlers/validation" "github.com/kyverno/kyverno/pkg/engine/internal" ) @@ -28,29 +29,39 @@ func (e *engine) validate( for _, rule := range autogen.ComputeRules(policy) { startTime := time.Now() logger := internal.LoggerWithRule(logger, rule) - hasValidate := rule.HasValidate() - hasVerifyImageChecks := rule.HasVerifyImageChecks() - if !hasValidate && !hasVerifyImageChecks { - continue - } - var handler handlers.Handler - if hasValidate { - hasVerifyManifest := rule.HasVerifyManifests() - hasValidatePss := rule.HasValidatePodSecurity() - if hasVerifyManifest { - handler = e.validateManifestHandler - } else if hasValidatePss { - handler = e.validatePssHandler - } else { - handler = e.validateResourceHandler + handlerFactory := func() (handlers.Handler, error) { + hasValidate := rule.HasValidate() + hasVerifyImageChecks := rule.HasVerifyImageChecks() + if !hasValidate && !hasVerifyImageChecks { + return nil, nil } - } else if hasVerifyImageChecks { - handler = e.validateImageHandler + if hasValidate { + hasVerifyManifest := rule.HasVerifyManifests() + hasValidatePss := rule.HasValidatePodSecurity() + if hasVerifyManifest { + return validation.NewValidateManifestHandler( + policyContext, + e.client, + ) + } else if hasValidatePss { + return validation.NewValidatePssHandler() + } else { + return validation.NewValidateResourceHandler() + } + } else if hasVerifyImageChecks { + return validation.NewValidateImageHandler( + policyContext, + policyContext.NewResource(), + rule, + e.configuration, + ) + } + return nil, nil } resource, ruleResp := e.invokeRuleHandler( ctx, logger, - handler, + handlerFactory, policyContext, matchedResource, rule, diff --git a/pkg/policy/mutate/validate.go b/pkg/policy/mutate/validate.go index fbf391b829..727889cb6d 100644 --- a/pkg/policy/mutate/validate.go +++ b/pkg/policy/mutate/validate.go @@ -90,7 +90,7 @@ func (m *Mutate) hasPatchesJSON6902() bool { return m.mutation.PatchesJSON6902 != "" } -func (m *Mutate) validateAuth(ctx context.Context, targets []kyvernov1.ResourceSpec) error { +func (m *Mutate) validateAuth(ctx context.Context, targets []kyvernov1.TargetResourceSpec) error { var errs []error for _, target := range targets { if !regex.IsVariable(target.Namespace) { diff --git a/pkg/policy/validate.go b/pkg/policy/validate.go index b64a0e3c7f..f785ee4748 100644 --- a/pkg/policy/validate.go +++ b/pkg/policy/validate.go @@ -39,14 +39,15 @@ import ( "k8s.io/client-go/discovery" ) -var allowedVariables = regexp.MustCompile(`request\.|serviceAccountName|serviceAccountNamespace|element|elementIndex|@|images\.|image\.|target\.|([a-z_0-9]+\()[^{}]`) - -var allowedVariablesBackground = regexp.MustCompile(`request\.|element|elementIndex|@|images\.|image\.|target\.|([a-z_0-9]+\()[^{}]`) - -// wildCardAllowedVariables represents regex for the allowed fields in wildcards -var wildCardAllowedVariables = regexp.MustCompile(`\{\{\s*(request\.|serviceAccountName|serviceAccountNamespace)[^{}]*\}\}`) - -var errOperationForbidden = errors.New("variables are forbidden in the path of a JSONPatch") +var ( + allowedVariables = regexp.MustCompile(`request\.|serviceAccountName|serviceAccountNamespace|element|elementIndex|@|images\.|image\.|([a-z_0-9]+\()[^{}]`) + allowedVariablesBackground = regexp.MustCompile(`request\.|element|elementIndex|@|images\.|image\.|([a-z_0-9]+\()[^{}]`) + allowedVariablesInTarget = regexp.MustCompile(`request\.|serviceAccountName|serviceAccountNamespace|element|elementIndex|@|images\.|image\.|target\.|([a-z_0-9]+\()[^{}]`) + allowedVariablesBackgroundInTarget = regexp.MustCompile(`request\.|element|elementIndex|@|images\.|image\.|target\.|([a-z_0-9]+\()[^{}]`) + // wildCardAllowedVariables represents regex for the allowed fields in wildcards + wildCardAllowedVariables = regexp.MustCompile(`\{\{\s*(request\.|serviceAccountName|serviceAccountNamespace)[^{}]*\}\}`) + errOperationForbidden = errors.New("variables are forbidden in the path of a JSONPatch") +) // validateJSONPatchPathForForwardSlash checks for forward slash func validateJSONPatchPathForForwardSlash(patch string) error { @@ -441,9 +442,22 @@ func hasInvalidVariables(policy kyvernov1.PolicyInterface, background bool) erro } } - ctx := buildContext(ruleCopy, background) - if _, err := variables.SubstituteAllInRule(logging.GlobalLogger(), ctx, *ruleCopy); !variables.CheckNotFoundErr(err) { - return fmt.Errorf("variable substitution failed for rule %s: %s", ruleCopy.Name, err.Error()) + // skip variable checks on mutate.targets, they will be validated separately + withoutTargets := ruleCopy.DeepCopy() + for i := range withoutTargets.Mutation.Targets { + withoutTargets.Mutation.Targets[i].RawAnyAllConditions = nil + } + ctx := buildContext(withoutTargets, background, false, nil) + if _, err := variables.SubstituteAllInRule(logging.GlobalLogger(), ctx, *withoutTargets); !variables.CheckNotFoundErr(err) { + return fmt.Errorf("variable substitution failed for rule %s: %s", withoutTargets.Name, err.Error()) + } + + // perform variable checks with mutate.targets + for _, target := range r.Mutation.Targets { + ctx := buildContext(ruleCopy, background, true, target.Context) + if _, err := variables.SubstituteAllInRule(logging.GlobalLogger(), ctx, *ruleCopy); !variables.CheckNotFoundErr(err) { + return fmt.Errorf("variable substitution failed for rule target %s: %s", ruleCopy.Name, err.Error()) + } } } @@ -554,29 +568,34 @@ func imageRefHasVariables(verifyImages []kyvernov1.ImageVerification) error { return nil } -func buildContext(rule *kyvernov1.Rule, background bool) *enginecontext.MockContext { - re := getAllowedVariables(background) +func buildContext(rule *kyvernov1.Rule, background bool, target bool, targetContext []kyvernov1.ContextEntry) *enginecontext.MockContext { + re := getAllowedVariables(background, target) ctx := enginecontext.NewMockContext(re) - addContextVariables(rule.Context, ctx) - for _, fe := range rule.Validation.ForEachValidation { addContextVariables(fe.Context, ctx) } - for _, fe := range rule.Mutation.ForEachMutation { addContextVariables(fe.Context, ctx) } - + for _, fe := range rule.Mutation.Targets { + addContextVariables(fe.Context, ctx) + } return ctx } -func getAllowedVariables(background bool) *regexp.Regexp { - if background { - return allowedVariablesBackground +func getAllowedVariables(background bool, target bool) *regexp.Regexp { + if target { + if background { + return allowedVariablesBackgroundInTarget + } + return allowedVariablesInTarget + } else { + if background { + return allowedVariablesBackground + } + return allowedVariables } - - return allowedVariables } func addContextVariables(entries []kyvernov1.ContextEntry, ctx *enginecontext.MockContext) { diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/01-resources.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/01-resources.yaml new file mode 100644 index 0000000000..463aa5f025 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/01-resources.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- file: resources.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/02-policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/02-policy.yaml new file mode 100644 index 0000000000..b088ed7601 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/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/target-context/03-trigger.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/03-trigger.yaml new file mode 100644 index 0000000000..5977a5ea37 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/03-trigger.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- file: trigger.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/04-verify.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/04-verify.yaml new file mode 100644 index 0000000000..65215a2507 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/04-verify.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +assert: +- resources-assert.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/README.md b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/README.md new file mode 100644 index 0000000000..c2706fe413 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/README.md @@ -0,0 +1,21 @@ +## Description + +This test creates one `ConfigMap` named `target`. + +It then creates a `ClusterPolicy` with a mutate existing rule targeting the previously created `ConfigMap`. + +The policy rule uses `context` on the trigger resource to create a variable containing the value of `data.content`. +The policy rule uses `context` on the target resource to create a variable containing the value of `data.content`. +The policy mutates target resource, setting `data.content` to the value of the trigger resource level variable and `data.targetContent` to the value of the target resource level variable. + +Finally, the test creates the trigger config map. + +## Expected Behavior + +The target config map should contain: + +```yaml +data: + content: trigger + targetContent: target +``` \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy-assert.yaml new file mode 100644 index 0000000000..36e4e29d43 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: update-targets +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy.yaml new file mode 100644 index 0000000000..faa83268c2 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/policy.yaml @@ -0,0 +1,36 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: update-targets +spec: + background: false + rules: + - name: update-targets + match: + any: + - resources: + kinds: + - ConfigMap + context: + - name: triggerContent + variable: + jmesPath: request.object.data.content + preconditions: + all: + - key: "{{ request.object.metadata.name }}" + operator: Equals + value: trigger + mutate: + targets: + - apiVersion: v1 + kind: ConfigMap + namespace: "{{ request.object.metadata.namespace }}" + name: target* + context: + - name: targetContent + variable: + jmesPath: target.data.content + patchStrategicMerge: + data: + content: "{{ triggerContent }}" + targetContent: "{{ targetContent }}" diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources-assert.yaml new file mode 100644 index 0000000000..b41ee4b3e5 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources-assert.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: target +data: + content: trigger + targetContent: target diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources.yaml new file mode 100644 index 0000000000..57164dc146 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/resources.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: target +data: + content: target diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/trigger.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/trigger.yaml new file mode 100644 index 0000000000..ec0e34dd5d --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-context/trigger.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: trigger +data: + content: trigger diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/01-resources.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/01-resources.yaml new file mode 100644 index 0000000000..463aa5f025 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/01-resources.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- file: resources.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/02-policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/02-policy.yaml new file mode 100644 index 0000000000..b088ed7601 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/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/target-preconditions/03-trigger.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/03-trigger.yaml new file mode 100644 index 0000000000..5977a5ea37 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/03-trigger.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +- file: trigger.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/04-verify.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/04-verify.yaml new file mode 100644 index 0000000000..65215a2507 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/04-verify.yaml @@ -0,0 +1,4 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +assert: +- resources-assert.yaml diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/README.md b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/README.md new file mode 100644 index 0000000000..2fce39203a --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/README.md @@ -0,0 +1,18 @@ +## Description + +This test creates three `ConfigMap`s: +- one without labels +- one with label `foo: bar` +- one with label `foo: not_bar` + +It then creates a `ClusterPolicy` with a mutate existing rule targeting the previously created `ConfigMap`s. + +The policy rule uses preconditions on the trigger resource to match only `ConfigMap`s with the `trigger` name. +The policy rule also uses preconditions on target resources to match only `ConfigMap`s with he label `foo: bar`. +The policy mutates target resources passing preconditions by copying the `data.content` from the trigger `ConfigMap` to the target `ConfigMap`. + +Finally, the test creates the trigger config map. + +## Expected Behavior + +Only the target config map with label `foo: bar` should have its content updated. \ No newline at end of file diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy-assert.yaml new file mode 100644 index 0000000000..36e4e29d43 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: update-targets +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy.yaml new file mode 100644 index 0000000000..dcc3001107 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/policy.yaml @@ -0,0 +1,31 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: update-targets +spec: + background: false + rules: + - name: update-targets + match: + any: + - resources: + kinds: + - ConfigMap + preconditions: + all: + - key: "{{ request.object.metadata.name }}" + operator: Equals + value: trigger + mutate: + targets: + - apiVersion: v1 + kind: ConfigMap + namespace: "{{ request.object.metadata.namespace }}" + preconditions: + all: + - key: "{{ target.metadata.labels.foo || '' }}" + operator: Equals + value: bar + patchStrategicMerge: + data: + content: "{{ request.object.data.content }}" diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources-assert.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources-assert.yaml new file mode 100644 index 0000000000..fc1f80b1f6 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources-assert.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: target-1 +data: + content: trigger +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: target-2 +data: + content: abc +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: target-3 +data: + content: abc diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources.yaml new file mode 100644 index 0000000000..cd00e45340 --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/resources.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: target-1 + labels: + foo: bar +data: + content: abc +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: target-2 + labels: + foo: not_bar +data: + content: abc +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: target-3 +data: + content: abc diff --git a/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/trigger.yaml b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/trigger.yaml new file mode 100644 index 0000000000..ec0e34dd5d --- /dev/null +++ b/test/conformance/kuttl/mutate/clusterpolicy/standard/existing/target-preconditions/trigger.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: trigger +data: + content: trigger diff --git a/test/conformance/kuttl/policy-validation/cluster-policy/target-context/01-policies.yaml b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/01-policies.yaml new file mode 100644 index 0000000000..22a4c123cf --- /dev/null +++ b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/01-policies.yaml @@ -0,0 +1,7 @@ +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +apply: +# - file: policy-1.yaml +# shouldFail: true +- file: policy-2.yaml + shouldFail: true diff --git a/test/conformance/kuttl/policy-validation/cluster-policy/target-context/README.md b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/README.md new file mode 100644 index 0000000000..d42f9132ec --- /dev/null +++ b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/README.md @@ -0,0 +1,8 @@ +## Description + +This test tries to create policies referencing `target` in the trigger preconditions or context of a mutate existing rule. + +## Expected Behavior + +Policies shoudl be rejected. +Referencing `target` is only allowed in the target section of a mutate existing rule. \ No newline at end of file diff --git a/test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-1.yaml b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-1.yaml new file mode 100644 index 0000000000..b0519c4b74 --- /dev/null +++ b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-1.yaml @@ -0,0 +1,35 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: update-targets +spec: + background: false + rules: + - name: update-targets + match: + any: + - resources: + kinds: + - ConfigMap + context: + - name: triggerContent + variable: + jmesPath: request.object.data.content + - name: targetContent + variable: + jmesPath: target.data.content + preconditions: + all: + - key: "{{ request.object.metadata.name }}" + operator: Equals + value: trigger + mutate: + targets: + - apiVersion: v1 + kind: ConfigMap + namespace: "{{ request.object.metadata.namespace }}" + name: target* + patchStrategicMerge: + data: + content: "{{ triggerContent }}" + targetContent: "{{ targetContent }}" diff --git a/test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-2.yaml b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-2.yaml new file mode 100644 index 0000000000..c68ebad920 --- /dev/null +++ b/test/conformance/kuttl/policy-validation/cluster-policy/target-context/policy-2.yaml @@ -0,0 +1,39 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: update-targets +spec: + background: false + rules: + - name: update-targets + match: + any: + - resources: + kinds: + - ConfigMap + context: + - name: triggerContent + variable: + jmesPath: request.object.data.content + preconditions: + all: + - key: "{{ request.object.metadata.name }}" + operator: Equals + value: trigger + - key: "{{ target.data.content }}" + operator: Equals + value: target + mutate: + targets: + - apiVersion: v1 + kind: ConfigMap + namespace: "{{ request.object.metadata.namespace }}" + name: target* + context: + - name: targetContent + variable: + jmesPath: target.data.content + patchStrategicMerge: + data: + content: "{{ triggerContent }}" + targetContent: "{{ targetContent }}"