From 44b5bf0b57e67d59eff848c8aa76e6878462c2df Mon Sep 17 00:00:00 2001 From: Sambhav Kothari Date: Mon, 25 Apr 2022 12:06:07 +0100 Subject: [PATCH] Allow definition of inline variables in context (#3658) Signed-off-by: Sambhav Kothari --- api/kyverno/v1/common_types.go | 20 ++ api/kyverno/v1/zz_generated.deepcopy.go | 30 +++ charts/kyverno/templates/crds.yaml | 156 ++++++++++++ config/crds/kyverno.io_clusterpolicies.yaml | 116 +++++++++ config/crds/kyverno.io_policies.yaml | 116 +++++++++ config/install.yaml | 232 ++++++++++++++++++ config/install_debug.yaml | 232 ++++++++++++++++++ docs/crd/v1/index.html | 101 ++++++-- pkg/engine/context/context.go | 17 ++ pkg/engine/jsonContext.go | 71 +++++- pkg/policy/validate.go | 72 +++--- .../test/context-entries/kyverno-test.yaml | 46 ++++ test/cli/test/context-entries/policies.yaml | 148 +++++++++++ test/cli/test/context-entries/resources.yaml | 6 + 14 files changed, 1301 insertions(+), 62 deletions(-) create mode 100644 test/cli/test/context-entries/kyverno-test.yaml create mode 100644 test/cli/test/context-entries/policies.yaml create mode 100644 test/cli/test/context-entries/resources.yaml diff --git a/api/kyverno/v1/common_types.go b/api/kyverno/v1/common_types.go index f36394b7b5..5e31ec1130 100755 --- a/api/kyverno/v1/common_types.go +++ b/api/kyverno/v1/common_types.go @@ -56,6 +56,26 @@ type ContextEntry struct { // ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image // details. ImageRegistry *ImageRegistry `json:"imageRegistry,omitempty" yaml:"imageRegistry,omitempty"` + + // Variable defines an arbitrary JMESPath context variable that can be defined inline. + Variable *Variable `json:"variable,omitempty" yaml:"variable,omitempty"` +} + +// Variable defines an arbitrary JMESPath context variable that can be defined inline. +type Variable struct { + // Value is any arbitrary JSON object representable in YAML or JSON form. + // +optional + Value *apiextv1.JSON `json:"value,omitempty" yaml:"value,omitempty"` + + // JMESPath is an optional JMESPath Expression that can be used to + // transform the variable. + // +optional + JMESPath string `json:"jmesPath,omitempty" yaml:"jmesPath,omitempty"` + + // Default is an optional arbitrary JSON object that the variable may take if the JMESPath + // expression evaluates to nil + // +optional + Default *apiextv1.JSON `json:"default,omitempty" yaml:"default,omitempty"` } // ImageRegistry defines requests to an OCI/Docker V2 registry to fetch image diff --git a/api/kyverno/v1/zz_generated.deepcopy.go b/api/kyverno/v1/zz_generated.deepcopy.go index e7a9f70164..abc739f855 100755 --- a/api/kyverno/v1/zz_generated.deepcopy.go +++ b/api/kyverno/v1/zz_generated.deepcopy.go @@ -357,6 +357,11 @@ func (in *ContextEntry) DeepCopyInto(out *ContextEntry) { *out = new(ImageRegistry) **out = **in } + if in.Variable != nil { + in, out := &in.Variable, &out.Variable + *out = new(Variable) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContextEntry. @@ -1196,6 +1201,31 @@ func (in *ValidationFailureActionOverride) DeepCopy() *ValidationFailureActionOv return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Variable) DeepCopyInto(out *Variable) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(apiextensionsv1.JSON) + (*in).DeepCopyInto(*out) + } + if in.Default != nil { + in, out := &in.Default, &out.Default + *out = new(apiextensionsv1.JSON) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Variable. +func (in *Variable) DeepCopy() *Variable { + if in == nil { + return nil + } + out := new(Variable) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ViolatedRule) DeepCopyInto(out *ViolatedRule) { *out = *in diff --git a/charts/kyverno/templates/crds.yaml b/charts/kyverno/templates/crds.yaml index 65d305bffe..af40189b88 100644 --- a/charts/kyverno/templates/crds.yaml +++ b/charts/kyverno/templates/crds.yaml @@ -113,6 +113,19 @@ spec: 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 exclude: @@ -972,6 +985,19 @@ spec: 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 list: @@ -1135,6 +1161,19 @@ spec: 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 deny: @@ -1580,6 +1619,19 @@ spec: 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 exclude: @@ -2439,6 +2491,19 @@ spec: 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 list: @@ -2602,6 +2667,19 @@ spec: 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 deny: @@ -3758,6 +3836,19 @@ spec: 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 exclude: @@ -4617,6 +4708,19 @@ spec: 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 list: @@ -4780,6 +4884,19 @@ spec: 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 deny: @@ -5225,6 +5342,19 @@ spec: 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 exclude: @@ -6084,6 +6214,19 @@ spec: 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 list: @@ -6247,6 +6390,19 @@ spec: 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 deny: diff --git a/config/crds/kyverno.io_clusterpolicies.yaml b/config/crds/kyverno.io_clusterpolicies.yaml index 8bd831b98c..a66d449f61 100644 --- a/config/crds/kyverno.io_clusterpolicies.yaml +++ b/config/crds/kyverno.io_clusterpolicies.yaml @@ -140,6 +140,24 @@ spec: 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 exclude: @@ -1567,6 +1585,26 @@ spec: 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 list: @@ -1820,6 +1858,26 @@ spec: 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 deny: @@ -2520,6 +2578,24 @@ spec: 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 exclude: @@ -3947,6 +4023,26 @@ spec: 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 list: @@ -4200,6 +4296,26 @@ spec: 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 deny: diff --git a/config/crds/kyverno.io_policies.yaml b/config/crds/kyverno.io_policies.yaml index 9165c6f5a4..979424a889 100644 --- a/config/crds/kyverno.io_policies.yaml +++ b/config/crds/kyverno.io_policies.yaml @@ -141,6 +141,24 @@ spec: 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 exclude: @@ -1568,6 +1586,26 @@ spec: 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 list: @@ -1821,6 +1859,26 @@ spec: 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 deny: @@ -2522,6 +2580,24 @@ spec: 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 exclude: @@ -3949,6 +4025,26 @@ spec: 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 list: @@ -4202,6 +4298,26 @@ spec: 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 deny: diff --git a/config/install.yaml b/config/install.yaml index fc18086c6e..5727912e4a 100644 --- a/config/install.yaml +++ b/config/install.yaml @@ -157,6 +157,24 @@ spec: 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 exclude: @@ -1584,6 +1602,26 @@ spec: 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 list: @@ -1837,6 +1875,26 @@ spec: 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 deny: @@ -2537,6 +2595,24 @@ spec: 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 exclude: @@ -3964,6 +4040,26 @@ spec: 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 list: @@ -4217,6 +4313,26 @@ spec: 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 deny: @@ -5807,6 +5923,24 @@ spec: 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 exclude: @@ -7234,6 +7368,26 @@ spec: 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 list: @@ -7487,6 +7641,26 @@ spec: 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 deny: @@ -8188,6 +8362,24 @@ spec: 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 exclude: @@ -9615,6 +9807,26 @@ spec: 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 list: @@ -9868,6 +10080,26 @@ spec: 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 deny: diff --git a/config/install_debug.yaml b/config/install_debug.yaml index d377392aaf..f7bdded60e 100755 --- a/config/install_debug.yaml +++ b/config/install_debug.yaml @@ -146,6 +146,24 @@ spec: 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 exclude: @@ -1573,6 +1591,26 @@ spec: 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 list: @@ -1826,6 +1864,26 @@ spec: 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 deny: @@ -2526,6 +2584,24 @@ spec: 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 exclude: @@ -3953,6 +4029,26 @@ spec: 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 list: @@ -4206,6 +4302,26 @@ spec: 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 deny: @@ -5772,6 +5888,24 @@ spec: 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 exclude: @@ -7199,6 +7333,26 @@ spec: 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 list: @@ -7452,6 +7606,26 @@ spec: 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 deny: @@ -8153,6 +8327,24 @@ spec: 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 exclude: @@ -9580,6 +9772,26 @@ spec: 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 list: @@ -9833,6 +10045,26 @@ spec: 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 deny: diff --git a/docs/crd/v1/index.html b/docs/crd/v1/index.html index 1c94df8bb1..52e1df85c7 100644 --- a/docs/crd/v1/index.html +++ b/docs/crd/v1/index.html @@ -209,8 +209,8 @@ string conditions
- -[]*github.com/kyverno/kyverno/api/kyverno/v1.AnyAllConditions + +[]*./api/kyverno/v1.AnyAllConditions @@ -330,8 +330,8 @@ value N, then N must be less than or equal to the size of entries, and at least entries
- -[]*github.com/kyverno/kyverno/api/kyverno/v1.Attestor + +[]*./api/kyverno/v1.Attestor @@ -817,6 +817,19 @@ ImageRegistry details.

+ + +variable
+ + +Variable + + + + +

Variable defines an arbitrary JMESPath context variable that can be defined inline.

+ +
@@ -1560,8 +1573,8 @@ Deprecated.

attestors
- -[]*github.com/kyverno/kyverno/api/kyverno/v1.AttestorSet + +[]*./api/kyverno/v1.AttestorSet @@ -1573,8 +1586,8 @@ Deprecated.

attestations
- -[]*github.com/kyverno/kyverno/api/kyverno/v1.Attestation + +[]*./api/kyverno/v1.Attestation @@ -1848,8 +1861,8 @@ See https://tools.ietf.org/html/rf foreach
-
-[]*github.com/kyverno/kyverno/api/kyverno/v1.ForEachMutation + +[]*./api/kyverno/v1.ForEachMutation @@ -2331,7 +2344,7 @@ ResourceDescription

ResourceFilters -([]github.com/kyverno/kyverno/api/kyverno/v1.ResourceFilter alias)

+([]./api/kyverno/v1.ResourceFilter alias)

(Appears on: MatchResources) @@ -2559,8 +2572,8 @@ Generation verifyImages
- -[]*github.com/kyverno/kyverno/api/kyverno/v1.ImageVerification + +[]*./api/kyverno/v1.ImageVerification @@ -2845,8 +2858,8 @@ string foreach
- -[]*github.com/kyverno/kyverno/api/kyverno/v1.ForEachValidation + +[]*./api/kyverno/v1.ForEachValidation @@ -2948,6 +2961,64 @@ ValidationFailureAction


+

Variable +

+

+(Appears on: +ContextEntry) +

+

+

Variable defines an arbitrary JMESPath context variable that can be defined inline.

+

+ + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+value
+ +k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.JSON + +
+(Optional) +

Value is any arbitrary JSON object representable in YAML or JSON form.

+
+jmesPath
+ +string + +
+(Optional) +

JMESPath is an optional JMESPath Expression that can be used to +transform the variable.

+
+default
+ +k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.JSON + +
+(Optional) +

Default is an optional arbitrary JSON object that the variable may take if the JMESPath +expression evaluates to nil

+
+

ViolatedRule

diff --git a/pkg/engine/context/context.go b/pkg/engine/context/context.go index 2003f79037..4f1dfe5fba 100644 --- a/pkg/engine/context/context.go +++ b/pkg/engine/context/context.go @@ -40,6 +40,9 @@ type Interface interface { // AddContextEntry adds a context entry to the context AddContextEntry(name string, dataRaw []byte) error + // ReplaceContextEntry replaces a context entry to the context + ReplaceContextEntry(name string, dataRaw []byte) error + // AddResource merges resource json under request.object AddResource(data map[string]interface{}) error @@ -138,6 +141,20 @@ func (ctx *context) AddContextEntry(name string, dataRaw []byte) error { return addToContext(ctx, data, name) } +func (ctx *context) ReplaceContextEntry(name string, dataRaw []byte) error { + var data interface{} + if err := json.Unmarshal(dataRaw, &data); err != nil { + logger.Error(err, "failed to unmarshal the resource") + return err + } + // Adding a nil entry to clean out any existing data in the context with the entry name + if err := addToContext(ctx, nil, name); err != nil { + logger.Error(err, "unable to replace context entry", "context entry name", name) + return err + } + return addToContext(ctx, data, name) +} + // AddResource data at path: request.object func (ctx *context) AddResource(data map[string]interface{}) error { return addToContext(ctx, data, "request", "object") diff --git a/pkg/engine/jsonContext.go b/pkg/engine/jsonContext.go index eb5cbd7bd7..961cedf958 100644 --- a/pkg/engine/jsonContext.go +++ b/pkg/engine/jsonContext.go @@ -23,12 +23,15 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, ctx policyName := ctx.Policy.GetName() if store.GetMock() { - if store.GetRegistryAccess() { - for _, entry := range contextEntries { - if entry.ImageRegistry != nil { - if err := loadImageData(logger, entry, ctx); err != nil { - return err - } + hasRegistryAccess := store.GetRegistryAccess() + for _, entry := range contextEntries { + if entry.ImageRegistry != nil && hasRegistryAccess { + if err := loadImageData(logger, entry, ctx); err != nil { + return err + } + } else if entry.Variable != nil { + if err := loadVariable(logger, entry, ctx); err != nil { + return err } } } @@ -62,12 +65,68 @@ func LoadContext(logger logr.Logger, contextEntries []kyverno.ContextEntry, ctx if err := loadImageData(logger, entry, ctx); err != nil { return err } + } else if entry.Variable != nil { + if err := loadVariable(logger, entry, ctx); err != nil { + return err + } } } } return nil } +func loadVariable(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) (err error) { + path := "" + if entry.Variable.JMESPath != "" { + jp, err := variables.SubstituteAll(logger, ctx.JSONContext, entry.Variable.JMESPath) + if err != nil { + return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.JMESPath, err) + } + path = jp.(string) + } + var defaultValue interface{} = nil + if entry.Variable.Default != nil { + value, err := variables.DocumentToUntyped(entry.Variable.Default) + if err != nil { + return fmt.Errorf("invalid default for variable %s", entry.Name) + } + defaultValue, err = variables.SubstituteAll(logger, ctx.JSONContext, value) + if err != nil { + return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Default, err) + } + } + var output interface{} = defaultValue + if entry.Variable.Value != nil { + value, _ := variables.DocumentToUntyped(entry.Variable.Value) + variable, err := variables.SubstituteAll(logger, ctx.JSONContext, value) + if err != nil { + return fmt.Errorf("failed to substitute variables in context entry %s %s: %v", entry.Name, entry.Variable.Value, err) + } + if path != "" { + variable, err := applyJMESPath(path, variable) + if err == nil { + output = variable + } + } else { + output = variable + } + } else { + if path != "" { + if variable, err := ctx.JSONContext.Query(path); err == nil { + output = variable + } + } + } + if output == nil { + return fmt.Errorf("unable to add context entry for variable %s since it evaluated to nil", entry.Name) + } + if outputBytes, err := json.Marshal(output); err == nil { + return ctx.JSONContext.ReplaceContextEntry(entry.Name, outputBytes) + } else { + return fmt.Errorf("unable to add context entry for variable %s: %w", entry.Name, err) + } +} + func loadImageData(logger logr.Logger, entry kyverno.ContextEntry, ctx *PolicyContext) error { if len(registryclient.Secrets) > 0 { if err := registryclient.UpdateKeychain(); err != nil { diff --git a/pkg/policy/validate.go b/pkg/policy/validate.go index 69dc4a1fc4..c9c650d8f2 100644 --- a/pkg/policy/validate.go +++ b/pkg/policy/validate.go @@ -489,7 +489,7 @@ func getAllowedVariables(background bool) *regexp.Regexp { func addContextVariables(entries []kyverno.ContextEntry, ctx *context.MockContext) { for _, contextEntry := range entries { - if contextEntry.APICall != nil || contextEntry.ImageRegistry != nil { + if contextEntry.APICall != nil || contextEntry.ImageRegistry != nil || contextEntry.Variable != nil { ctx.AddVariable(contextEntry.Name + "*") } @@ -819,17 +819,24 @@ func validateRuleContext(rule kyverno.Rule) error { if entry.Name == "" { return fmt.Errorf("a name is required for context entries") } + for _, v := range []string{"images", "request", "serviceAccountName", "serviceAccountNamespace", "element", "elementIndex"} { + if entry.Name == v || strings.HasPrefix(entry.Name, v+".") { + return fmt.Errorf("entry name %s is invalid as it conflicts with a pre-defined variable %s", entry.Name, v) + } + } contextNames = append(contextNames, entry.Name) var err error - if entry.ConfigMap != nil { + if entry.ConfigMap != nil && entry.APICall == nil && entry.ImageRegistry == nil && entry.Variable == nil { err = validateConfigMap(entry) - } else if entry.APICall != nil { + } else if entry.ConfigMap == nil && entry.APICall != nil && entry.ImageRegistry == nil && entry.Variable == nil { err = validateAPICall(entry) - } else if entry.ImageRegistry != nil { + } else if entry.ConfigMap == nil && entry.APICall == nil && entry.ImageRegistry != nil && entry.Variable == nil { err = validateImageRegistry(entry) + } else if entry.ConfigMap == nil && entry.APICall == nil && entry.ImageRegistry == nil && entry.Variable != nil { + err = validateVariable(entry) } else { - return fmt.Errorf("a configMap or apiCall or imageRegistry is required for context entries") + return fmt.Errorf("exactly one of configMap or apiCall or imageRegistry or variable is required for context entries") } if err != nil { @@ -851,19 +858,26 @@ func validateRuleContext(rule kyverno.Rule) error { return nil } +func validateVariable(entry kyverno.ContextEntry) error { + // If JMESPath contains variables, the validation will fail because it's not possible to infer which value + // will be inserted by the variable + // Skip validation if a variable is detected + jmesPath := variables.ReplaceAllVars(entry.Variable.JMESPath, func(s string) string { return "kyvernojmespathvariable" }) + if !strings.Contains(jmesPath, "kyvernojmespathvariable") && entry.Variable.JMESPath != "" { + if _, err := jmespath.NewParser().Parse(entry.Variable.JMESPath); err != nil { + return fmt.Errorf("failed to parse JMESPath %s: %v", entry.Variable.JMESPath, err) + } + } + if entry.Variable.Value == nil && jmesPath == "" { + return fmt.Errorf("a variable must define a value or a jmesPath expression") + } + if entry.Variable.Default != nil && jmesPath == "" { + return fmt.Errorf("a variable must define a default value only when a jmesPath expression is defined") + } + return nil +} + func validateConfigMap(entry kyverno.ContextEntry) error { - if entry.ConfigMap == nil { - return fmt.Errorf("configMap is empty") - } - - if entry.APICall != nil { - return fmt.Errorf("both configMap and apiCall are not allowed in a context entry") - } - - if entry.ImageRegistry != nil { - return fmt.Errorf("both imageRegistry and configMap are not allowed in a context entry") - } - if entry.ConfigMap.Name == "" { return fmt.Errorf("a name is required for configMap context entry") } @@ -876,18 +890,6 @@ func validateConfigMap(entry kyverno.ContextEntry) error { } func validateAPICall(entry kyverno.ContextEntry) error { - if entry.APICall == nil { - return fmt.Errorf("apiCall is empty") - } - - if entry.ConfigMap != nil { - return fmt.Errorf("both configMap and apiCall are not allowed in a context entry") - } - - if entry.ImageRegistry != nil { - return fmt.Errorf("both imageRegistry and apiCall are not allowed in a context entry") - } - // Replace all variables to prevent validation failing on variable keys. urlPath := variables.ReplaceAllVars(entry.APICall.URLPath, func(s string) string { return "kyvernoapicallvariable" }) @@ -911,18 +913,6 @@ func validateAPICall(entry kyverno.ContextEntry) error { } func validateImageRegistry(entry kyverno.ContextEntry) error { - if entry.ImageRegistry == nil { - return fmt.Errorf("imageRegistry is empty") - } - - if entry.ConfigMap != nil { - return fmt.Errorf("both configMap and imageRegistry are not allowed in a context entry") - } - - if entry.APICall != nil { - return fmt.Errorf("both configMap and apiCall are not allowed in a context entry") - } - if entry.ImageRegistry.Reference == "" { return fmt.Errorf("a ref is required for imageRegistry context entry") } diff --git a/test/cli/test/context-entries/kyverno-test.yaml b/test/cli/test/context-entries/kyverno-test.yaml new file mode 100644 index 0000000000..1df2ecd642 --- /dev/null +++ b/test/cli/test/context-entries/kyverno-test.yaml @@ -0,0 +1,46 @@ +name: test-variables +policies: + - policies.yaml +resources: + - resources.yaml +results: + - policy: example + rule: defined-value + resource: example + kind: Pod + result: pass + - policy: example + rule: defined-jmespath + resource: example + kind: Pod + result: pass + - policy: example + rule: defined-jmespath-with-default + resource: example + kind: Pod + result: pass + - policy: example + rule: defined-value-with-variable + resource: example + kind: Pod + result: pass + - policy: example + rule: defined-jmespath-with-default-variable + resource: example + kind: Pod + result: pass + - policy: example + rule: defined-value-jmespath + resource: example + kind: Pod + result: pass + - policy: example + rule: defined-value-jmespath-variable + resource: example + kind: Pod + result: pass + - policy: example + rule: value-override + resource: example + kind: Pod + result: pass diff --git a/test/cli/test/context-entries/policies.yaml b/test/cli/test/context-entries/policies.yaml new file mode 100644 index 0000000000..77062e3c85 --- /dev/null +++ b/test/cli/test/context-entries/policies.yaml @@ -0,0 +1,148 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: example +spec: + rules: + - name: defined-value + context: + - name: example + variable: + value: + test: + nested: + value: 1 + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ example.test.nested.value }}" + operator: NotEquals + value: 1 + - name: defined-jmespath + context: + - name: objName + variable: + jmesPath: request.object.metadata.name + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ objName }}" + operator: NotEquals + value: "example" + - name: defined-jmespath-with-default + context: + - name: objName + variable: + jmesPath: request.object.metadata.generateName + default: example + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ objName }}" + operator: NotEquals + value: "example" + - name: defined-value-with-variable + context: + - name: obj + variable: + value: + name: "{{ request.object.metadata.name }}" + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ obj.name }}" + operator: NotEquals + value: "example" + - name: defined-jmespath-with-default-variable + context: + - name: objName + variable: + jmesPath: request.object.metadata.generateName + default: "{{ request.object.metadata.name }}" + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ objName }}" + operator: NotEquals + value: "example" + - name: defined-value-jmespath + context: + - name: objName + variable: + value: + name: "{{ request.object.metadata.name }}" + jmesPath: name + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ objName }}" + operator: NotEquals + value: "example" + - name: defined-value-jmespath-variable + context: + - name: jpExpression + variable: + value: name + - name: objName + variable: + value: + name: "{{ request.object.metadata.name }}" + jmesPath: "{{ jpExpression }}" + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + - key: "{{ objName }}" + operator: NotEquals + value: "example" + - name: value-override + context: + - name: obj + variable: + value: + notName: not-example + - name: obj + variable: + value: + name: example + match: + resources: + kinds: + - Pod + validate: + deny: + conditions: + any: + - key: "{{ obj.name }}" + operator: NotEquals + value: "example" + - key: "{{ to_string(obj.notName) }}" + operator: NotEquals + value: 'null' diff --git a/test/cli/test/context-entries/resources.yaml b/test/cli/test/context-entries/resources.yaml new file mode 100644 index 0000000000..d9e857eb21 --- /dev/null +++ b/test/cli/test/context-entries/resources.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Pod +metadata: + name: example +spec: + containers: [] \ No newline at end of file