mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
support list foreach (#2522)
* support list foreach * fix testcase for each * fix mutate issue * Fix mutate patch issue * fix yaml * fix e2e test foreach validate list * code indentation * fix comments * delete unwanted files
This commit is contained in:
parent
2089767c85
commit
2798287497
14 changed files with 2378 additions and 2145 deletions
|
@ -1440,156 +1440,164 @@ spec:
|
|||
foreach:
|
||||
description: ForEach applies policy rule changes to nested
|
||||
elements.
|
||||
properties:
|
||||
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.
|
||||
items:
|
||||
description: ForEach applies policy rule changes to nested
|
||||
elements.
|
||||
properties:
|
||||
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 defines an HTTP request
|
||||
to the Kubernetes API server. The JSON data
|
||||
retrieved is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server
|
||||
response to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
list:
|
||||
description: List specifies a JMESPath expression
|
||||
that results in one or more elements to which the
|
||||
validation logic is applied.
|
||||
type: string
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge
|
||||
patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
apiCall:
|
||||
description: APICall defines an HTTP request to
|
||||
the Kubernetes API server. The JSON data retrieved
|
||||
is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server response
|
||||
to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, all of the conditions need to
|
||||
pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, at least one of the conditions
|
||||
need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
list:
|
||||
description: List specifies a JMESPath expression that
|
||||
results in one or more elements to which the validation
|
||||
logic is applied.
|
||||
type: string
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge
|
||||
patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, all of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, at least one of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
overlay:
|
||||
description: Overlay specifies an overlay pattern to modify
|
||||
resources. DEPRECATED. Use PatchStrategicMerge instead.
|
||||
|
@ -1661,175 +1669,183 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
foreach:
|
||||
description: ForEach applies policy rule checks to nested
|
||||
description: ForEach applies policy rule changes to nested
|
||||
elements.
|
||||
properties:
|
||||
anyPattern:
|
||||
description: AnyPattern specifies list of validation
|
||||
patterns. At least one of the patterns must be satisfied
|
||||
for the validation rule to succeed.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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.
|
||||
items:
|
||||
description: ForEach applies policy rule checks to nested
|
||||
elements.
|
||||
properties:
|
||||
anyPattern:
|
||||
description: AnyPattern specifies list of validation
|
||||
patterns. At least one of the patterns must be satisfied
|
||||
for the validation rule to succeed.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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 defines an HTTP request
|
||||
to the Kubernetes API server. The JSON data
|
||||
retrieved is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server
|
||||
response to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
deny:
|
||||
description: Deny defines conditions used to pass
|
||||
or fail a validation rule.
|
||||
properties:
|
||||
apiCall:
|
||||
description: APICall defines an HTTP request to
|
||||
the Kubernetes API server. The JSON data retrieved
|
||||
is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server response
|
||||
to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
conditions:
|
||||
description: 'Multiple conditions can be declared
|
||||
under an `any` or `all` statement. A direct
|
||||
list of conditions (without `any` or `all` statements)
|
||||
is also supported for backwards compatibility
|
||||
but will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/validate/#deny-rules'
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
deny:
|
||||
description: Deny defines conditions used to pass or
|
||||
fail a validation rule.
|
||||
properties:
|
||||
conditions:
|
||||
description: 'Multiple conditions can be declared
|
||||
under an `any` or `all` statement. A direct list
|
||||
of conditions (without `any` or `all` statements)
|
||||
is also supported for backwards compatibility
|
||||
but will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/validate/#deny-rules'
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
list:
|
||||
description: List specifies a JMESPath expression that
|
||||
results in one or more elements to which the validation
|
||||
logic is applied.
|
||||
type: string
|
||||
pattern:
|
||||
description: Pattern specifies an overlay-style pattern
|
||||
used to check resources.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, all of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, at least one of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
list:
|
||||
description: List specifies a JMESPath expression
|
||||
that results in one or more elements to which the
|
||||
validation logic is applied.
|
||||
type: string
|
||||
pattern:
|
||||
description: Pattern specifies an overlay-style pattern
|
||||
used to check resources.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, all of the conditions need to
|
||||
pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, at least one of the conditions
|
||||
need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: Message specifies a custom message to be displayed
|
||||
on failure.
|
||||
|
|
|
@ -1441,156 +1441,164 @@ spec:
|
|||
foreach:
|
||||
description: ForEach applies policy rule changes to nested
|
||||
elements.
|
||||
properties:
|
||||
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.
|
||||
items:
|
||||
description: ForEach applies policy rule changes to nested
|
||||
elements.
|
||||
properties:
|
||||
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 defines an HTTP request
|
||||
to the Kubernetes API server. The JSON data
|
||||
retrieved is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server
|
||||
response to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
list:
|
||||
description: List specifies a JMESPath expression
|
||||
that results in one or more elements to which the
|
||||
validation logic is applied.
|
||||
type: string
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge
|
||||
patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
apiCall:
|
||||
description: APICall defines an HTTP request to
|
||||
the Kubernetes API server. The JSON data retrieved
|
||||
is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server response
|
||||
to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, all of the conditions need to
|
||||
pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, at least one of the conditions
|
||||
need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
list:
|
||||
description: List specifies a JMESPath expression that
|
||||
results in one or more elements to which the validation
|
||||
logic is applied.
|
||||
type: string
|
||||
patchStrategicMerge:
|
||||
description: PatchStrategicMerge is a strategic merge
|
||||
patch used to modify resources. See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/
|
||||
and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, all of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, at least one of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
overlay:
|
||||
description: Overlay specifies an overlay pattern to modify
|
||||
resources. DEPRECATED. Use PatchStrategicMerge instead.
|
||||
|
@ -1662,175 +1670,183 @@ spec:
|
|||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
foreach:
|
||||
description: ForEach applies policy rule checks to nested
|
||||
description: ForEach applies policy rule changes to nested
|
||||
elements.
|
||||
properties:
|
||||
anyPattern:
|
||||
description: AnyPattern specifies list of validation
|
||||
patterns. At least one of the patterns must be satisfied
|
||||
for the validation rule to succeed.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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.
|
||||
items:
|
||||
description: ForEach applies policy rule checks to nested
|
||||
elements.
|
||||
properties:
|
||||
anyPattern:
|
||||
description: AnyPattern specifies list of validation
|
||||
patterns. At least one of the patterns must be satisfied
|
||||
for the validation rule to succeed.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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 defines an HTTP request
|
||||
to the Kubernetes API server. The JSON data
|
||||
retrieved is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server
|
||||
response to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
deny:
|
||||
description: Deny defines conditions used to pass
|
||||
or fail a validation rule.
|
||||
properties:
|
||||
apiCall:
|
||||
description: APICall defines an HTTP request to
|
||||
the Kubernetes API server. The JSON data retrieved
|
||||
is stored in the context.
|
||||
properties:
|
||||
jmesPath:
|
||||
description: JMESPath is an optional JSON
|
||||
Match Expression that can be used to transform
|
||||
the JSON response returned from the API
|
||||
server. For example a JMESPath of "items
|
||||
| length(@)" applied to the API server response
|
||||
to the URLPath "/apis/apps/v1/deployments"
|
||||
will return the total count of deployments
|
||||
across all namespaces.
|
||||
type: string
|
||||
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
|
||||
required:
|
||||
- urlPath
|
||||
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
|
||||
name:
|
||||
description: Name is the variable name.
|
||||
type: string
|
||||
conditions:
|
||||
description: 'Multiple conditions can be declared
|
||||
under an `any` or `all` statement. A direct
|
||||
list of conditions (without `any` or `all` statements)
|
||||
is also supported for backwards compatibility
|
||||
but will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/validate/#deny-rules'
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
deny:
|
||||
description: Deny defines conditions used to pass or
|
||||
fail a validation rule.
|
||||
properties:
|
||||
conditions:
|
||||
description: 'Multiple conditions can be declared
|
||||
under an `any` or `all` statement. A direct list
|
||||
of conditions (without `any` or `all` statements)
|
||||
is also supported for backwards compatibility
|
||||
but will be deprecated in the next major release.
|
||||
See: https://kyverno.io/docs/writing-policies/validate/#deny-rules'
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
list:
|
||||
description: List specifies a JMESPath expression that
|
||||
results in one or more elements to which the validation
|
||||
logic is applied.
|
||||
type: string
|
||||
pattern:
|
||||
description: Pattern specifies an overlay-style pattern
|
||||
used to check resources.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, all of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A condition
|
||||
can reference object data using JMESPath notation.
|
||||
Here, at least one of the conditions need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using using
|
||||
JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
list:
|
||||
description: List specifies a JMESPath expression
|
||||
that results in one or more elements to which the
|
||||
validation logic is applied.
|
||||
type: string
|
||||
pattern:
|
||||
description: Pattern specifies an overlay-style pattern
|
||||
used to check resources.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
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. See: https://kyverno.io/docs/writing-policies/preconditions/'
|
||||
properties:
|
||||
all:
|
||||
description: AllConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, all of the conditions need to
|
||||
pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
any:
|
||||
description: AnyConditions enable variable-based
|
||||
conditional rule execution. This is useful for
|
||||
finer control of when an rule is applied. A
|
||||
condition can reference object data using JMESPath
|
||||
notation. Here, at least one of the conditions
|
||||
need to pass
|
||||
items:
|
||||
description: Condition defines variable-based
|
||||
conditional criteria for rule execution.
|
||||
properties:
|
||||
key:
|
||||
description: Key is the context entry (using
|
||||
JMESPath) for conditional rule evaluation.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
operator:
|
||||
description: Operator is the operation to
|
||||
perform. Valid operators are Equals, NotEquals,
|
||||
In and NotIn.
|
||||
enum:
|
||||
- Equals
|
||||
- NotEquals
|
||||
- In
|
||||
- NotIn
|
||||
- GreaterThanOrEquals
|
||||
- GreaterThan
|
||||
- LessThanOrEquals
|
||||
- LessThan
|
||||
- DurationGreaterThanOrEquals
|
||||
- DurationGreaterThan
|
||||
- DurationLessThanOrEquals
|
||||
- DurationLessThan
|
||||
type: string
|
||||
value:
|
||||
description: Value is the conditional value,
|
||||
or set of values. The values can be fixed
|
||||
set or can be variables declared using
|
||||
using JMESPath.
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: object
|
||||
type: array
|
||||
message:
|
||||
description: Message specifies a custom message to be displayed
|
||||
on failure.
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -405,7 +405,7 @@ type Mutation struct {
|
|||
|
||||
// ForEach applies policy rule changes to nested elements.
|
||||
// +optional
|
||||
ForEachMutation *ForEachMutation `json:"foreach,omitempty" yaml:"foreach,omitempty"`
|
||||
ForEachMutation []*ForEachMutation `json:"foreach,omitempty" yaml:"foreach,omitempty"`
|
||||
}
|
||||
|
||||
// ForEach applies policy rule changes to nested elements.
|
||||
|
@ -460,7 +460,9 @@ type Validation struct {
|
|||
// +optional
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
|
||||
ForEachValidation *ForEachValidation `json:"foreach,omitempty" yaml:"foreach,omitempty"`
|
||||
// ForEach applies policy rule changes to nested elements.
|
||||
// +optional
|
||||
ForEachValidation []*ForEachValidation `json:"foreach,omitempty" yaml:"foreach,omitempty"`
|
||||
|
||||
// Pattern specifies an overlay-style pattern used to check resources.
|
||||
// +kubebuilder:validation:XPreserveUnknownFields
|
||||
|
|
|
@ -134,14 +134,6 @@ func (in *Validation) DeserializeAnyPattern() ([]interface{}, error) {
|
|||
return res, nil
|
||||
}
|
||||
|
||||
func (in *Validation) DeserializeForEachAnyPattern() ([]interface{}, error) {
|
||||
if in.ForEachValidation.AnyPattern == nil {
|
||||
return nil, nil
|
||||
}
|
||||
res, nil := deserializePattern(in.ForEachValidation.AnyPattern)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func deserializePattern(pattern apiextensions.JSON) ([]interface{}, error) {
|
||||
anyPattern, err := json.Marshal(pattern)
|
||||
if err != nil {
|
||||
|
|
|
@ -15,7 +15,7 @@ type Handler interface {
|
|||
}
|
||||
|
||||
// CreateMutateHandler initilizes a new instance of mutation handler
|
||||
func CreateMutateHandler(ruleName string, mutate *kyverno.Mutation, patchedResource unstructured.Unstructured, context context.EvalInterface, logger logr.Logger) Handler {
|
||||
func CreateMutateHandler(ruleName string, mutate *kyverno.Mutation, patchedResource unstructured.Unstructured, context context.EvalInterface, logger logr.Logger, foreachIndex int) Handler {
|
||||
|
||||
switch {
|
||||
case isPatchStrategicMerge(mutate):
|
||||
|
@ -31,7 +31,7 @@ func CreateMutateHandler(ruleName string, mutate *kyverno.Mutation, patchedResou
|
|||
case isPatches(mutate):
|
||||
return newPatchesHandler(ruleName, mutate, patchedResource, context, logger)
|
||||
case isForEach(mutate):
|
||||
return newForEachHandler(ruleName, mutate, patchedResource, context, logger)
|
||||
return newForEachHandler(ruleName, mutate, patchedResource, context, logger, foreachIndex)
|
||||
default:
|
||||
return newEmptyHandler(patchedResource)
|
||||
}
|
||||
|
@ -66,20 +66,22 @@ type forEachHandler struct {
|
|||
patchedResource unstructured.Unstructured
|
||||
evalCtx context.EvalInterface
|
||||
logger logr.Logger
|
||||
foreachIndex int
|
||||
}
|
||||
|
||||
func newForEachHandler(ruleName string, mutate *kyverno.Mutation, patchedResource unstructured.Unstructured, context context.EvalInterface, logger logr.Logger) Handler {
|
||||
func newForEachHandler(ruleName string, mutate *kyverno.Mutation, patchedResource unstructured.Unstructured, context context.EvalInterface, logger logr.Logger, foreachIndex int) Handler {
|
||||
return forEachHandler{
|
||||
ruleName: ruleName,
|
||||
mutation: mutate,
|
||||
patchedResource: patchedResource,
|
||||
evalCtx: context,
|
||||
logger: logger,
|
||||
foreachIndex: foreachIndex,
|
||||
}
|
||||
}
|
||||
|
||||
func (h forEachHandler) Handle() (response.RuleResponse, unstructured.Unstructured) {
|
||||
return ProcessStrategicMergePatch(h.ruleName, h.mutation.ForEachMutation.PatchStrategicMerge, h.patchedResource, h.logger)
|
||||
return ProcessStrategicMergePatch(h.ruleName, h.mutation.ForEachMutation[h.foreachIndex].PatchStrategicMerge, h.patchedResource, h.logger)
|
||||
}
|
||||
|
||||
// patchesJSON6902Handler
|
||||
|
|
|
@ -99,7 +99,7 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
if rule.Mutation.ForEachMutation != nil {
|
||||
ruleResp, patchedResource = mutateForEachResource(ruleCopy, policyContext, patchedResource, logger)
|
||||
} else {
|
||||
err, mutateResp := mutateResource(ruleCopy, policyContext.JSONContext, patchedResource, logger)
|
||||
err, mutateResp := mutateResource(ruleCopy, policyContext.JSONContext, patchedResource, logger, 0)
|
||||
if err != nil {
|
||||
if mutateResp.skip {
|
||||
ruleResp = ruleResponse(&policy.Spec.Rules[i], utils.Mutation, err.Error(), response.RuleStatusSkip)
|
||||
|
@ -132,56 +132,60 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
|
|||
}
|
||||
|
||||
func mutateForEachResource(rule *kyverno.Rule, ctx *PolicyContext, resource unstructured.Unstructured, logger logr.Logger) (*response.RuleResponse, unstructured.Unstructured) {
|
||||
foreach := rule.Mutation.ForEachMutation
|
||||
if foreach == nil {
|
||||
foreachList := rule.Mutation.ForEachMutation
|
||||
if foreachList == nil {
|
||||
return nil, resource
|
||||
}
|
||||
|
||||
if err := LoadContext(logger, foreach.Context, ctx.ResourceCache, ctx, rule.Name); err != nil {
|
||||
logger.Error(err, "failed to load context")
|
||||
return ruleError(rule, utils.Mutation, "failed to load context", err), resource
|
||||
}
|
||||
|
||||
preconditionsPassed, err := checkPreconditions(logger, ctx, foreach.AnyAllConditions)
|
||||
if err != nil {
|
||||
return ruleError(rule, utils.Mutation, "failed to evaluate preconditions", err), resource
|
||||
} else if !preconditionsPassed {
|
||||
return ruleResponse(rule, utils.Mutation, "preconditions not met", response.RuleStatusSkip), resource
|
||||
}
|
||||
|
||||
elements, err := evaluateList(foreach.List, ctx.JSONContext)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to evaluate list %s", foreach.List)
|
||||
return ruleError(rule, utils.Mutation, msg, err), resource
|
||||
}
|
||||
|
||||
ctx.JSONContext.Checkpoint()
|
||||
defer ctx.JSONContext.Restore()
|
||||
|
||||
applyCount := 0
|
||||
patchedResource := resource
|
||||
allPatches := make([][]byte, 0)
|
||||
for _, e := range elements {
|
||||
ctx.JSONContext.Reset()
|
||||
|
||||
ctx := ctx.Copy()
|
||||
if err := addElementToContext(ctx, e); err != nil {
|
||||
logger.Error(err, "failed to add element to context")
|
||||
return ruleError(rule, utils.Mutation, "failed to process foreach", err), resource
|
||||
for foreachIndex, foreach := range foreachList {
|
||||
|
||||
if err := LoadContext(logger, foreach.Context, ctx.ResourceCache, ctx, rule.Name); err != nil {
|
||||
logger.Error(err, "failed to load context")
|
||||
return ruleError(rule, utils.Mutation, "failed to load context", err), resource
|
||||
}
|
||||
|
||||
var skip = false
|
||||
err, mutateResp := mutateResource(rule, ctx.JSONContext, patchedResource, logger)
|
||||
if err != nil && !skip {
|
||||
return ruleResponse(rule, utils.Mutation, err.Error(), response.RuleStatusError), resource
|
||||
preconditionsPassed, err := checkPreconditions(logger, ctx, foreach.AnyAllConditions)
|
||||
if err != nil {
|
||||
return ruleError(rule, utils.Mutation, "failed to evaluate preconditions", err), resource
|
||||
} else if !preconditionsPassed {
|
||||
return ruleResponse(rule, utils.Mutation, "preconditions not met", response.RuleStatusSkip), resource
|
||||
}
|
||||
|
||||
patchedResource = mutateResp.patchedResource
|
||||
if len(mutateResp.patches) > 0 {
|
||||
allPatches = append(allPatches, mutateResp.patches...)
|
||||
elements, err := evaluateList(foreach.List, ctx.JSONContext)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to evaluate list %s", foreach.List)
|
||||
return ruleError(rule, utils.Mutation, msg, err), resource
|
||||
}
|
||||
|
||||
applyCount++
|
||||
ctx.JSONContext.Checkpoint()
|
||||
defer ctx.JSONContext.Restore()
|
||||
|
||||
for _, e := range elements {
|
||||
ctx.JSONContext.Reset()
|
||||
|
||||
ctx := ctx.Copy()
|
||||
if err := addElementToContext(ctx, e); err != nil {
|
||||
logger.Error(err, "failed to add element to context")
|
||||
return ruleError(rule, utils.Mutation, "failed to process foreach", err), resource
|
||||
}
|
||||
|
||||
var skip = false
|
||||
err, mutateResp := mutateResource(rule, ctx.JSONContext, patchedResource, logger, foreachIndex)
|
||||
if err != nil && !skip {
|
||||
return ruleResponse(rule, utils.Mutation, err.Error(), response.RuleStatusError), resource
|
||||
}
|
||||
|
||||
patchedResource = mutateResp.patchedResource
|
||||
if len(mutateResp.patches) > 0 {
|
||||
allPatches = append(allPatches, mutateResp.patches...)
|
||||
}
|
||||
|
||||
applyCount++
|
||||
}
|
||||
}
|
||||
|
||||
if applyCount == 0 {
|
||||
|
@ -200,8 +204,12 @@ type mutateResponse struct {
|
|||
message string
|
||||
}
|
||||
|
||||
func mutateResource(rule *kyverno.Rule, ctx *context.Context, resource unstructured.Unstructured, logger logr.Logger) (error, *mutateResponse) {
|
||||
func mutateResource(rule *kyverno.Rule, ctx *context.Context, resource unstructured.Unstructured, logger logr.Logger, foreachIndex int) (error, *mutateResponse) {
|
||||
mutateResp := &mutateResponse{false, unstructured.Unstructured{}, nil, ""}
|
||||
|
||||
// Pre-conditions checks for the list of foreach rules should ideally be performed once.
|
||||
// Currently they are performed for each entry in the foreach list.
|
||||
// Also, the foreach index parameter should be removed and a set of patches should be passed in.
|
||||
anyAllConditions, err := variables.SubstituteAllInPreconditions(logger, ctx, rule.AnyAllConditions)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to substitute vars in preconditions"), mutateResp
|
||||
|
@ -222,8 +230,9 @@ func mutateResource(rule *kyverno.Rule, ctx *context.Context, resource unstructu
|
|||
}
|
||||
|
||||
mutation := updatedRule.Mutation.DeepCopy()
|
||||
mutateHandler := mutate.CreateMutateHandler(updatedRule.Name, mutation, resource, ctx, logger)
|
||||
mutateHandler := mutate.CreateMutateHandler(updatedRule.Name, mutation, resource, ctx, logger, foreachIndex)
|
||||
resp, patchedResource := mutateHandler.Handle()
|
||||
|
||||
if resp.Status == response.RuleStatusPass {
|
||||
// - overlay pattern does not match the resource conditions
|
||||
if resp.Patches == nil {
|
||||
|
|
|
@ -2,10 +2,11 @@ package engine
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
|
@ -561,42 +562,44 @@ func Test_nonZeroIndexNumberPatchesJson6902(t *testing.T) {
|
|||
|
||||
func Test_foreach(t *testing.T) {
|
||||
policyRaw := []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {
|
||||
"name": "replace-image-registry"
|
||||
},
|
||||
"spec": {
|
||||
"background": false,
|
||||
"rules": [
|
||||
{
|
||||
"name": "replace-image-registry",
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Pod"
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {
|
||||
"name": "replace-image-registry"
|
||||
},
|
||||
"spec": {
|
||||
"background": false,
|
||||
"rules": [
|
||||
{
|
||||
"name": "replace-image-registry",
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Pod"
|
||||
]
|
||||
}
|
||||
},
|
||||
"mutate": {
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.containers",
|
||||
"patchStrategicMerge": {
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "{{ element.name }}",
|
||||
"image": "registry.io/{{images.containers.{{element.name}}.path}}:{{images.containers.{{element.name}}.tag}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"mutate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.containers",
|
||||
"patchStrategicMerge": {
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "{{ element.name }}",
|
||||
"image": "registry.io/{{images.containers.{{element.name}}.path}}:{{images.containers.{{element.name}}.tag}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
]
|
||||
}
|
||||
}`)
|
||||
resourceRaw := []byte(`{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
|
|
|
@ -157,25 +157,28 @@ func newValidator(log logr.Logger, ctx *PolicyContext, rule *kyverno.Rule) *vali
|
|||
}
|
||||
}
|
||||
|
||||
func newForeachValidator(log logr.Logger, ctx *PolicyContext, rule *kyverno.Rule) *validator {
|
||||
func newForeachValidator(log logr.Logger, ctx *PolicyContext, rule *kyverno.Rule) []*validator {
|
||||
ruleCopy := rule.DeepCopy()
|
||||
|
||||
val := []*validator{}
|
||||
for _, foreach := range ruleCopy.Validation.ForEachValidation {
|
||||
anyAllConditions, err := common.ToMap(foreach.AnyAllConditions)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to convert ruleCopy.Validation.ForEachValidation.AnyAllConditions")
|
||||
}
|
||||
temp := validator{
|
||||
log: log,
|
||||
ctx: ctx,
|
||||
rule: ruleCopy,
|
||||
contextEntries: foreach.Context,
|
||||
anyAllConditions: anyAllConditions,
|
||||
pattern: foreach.Pattern,
|
||||
anyPattern: foreach.AnyPattern,
|
||||
deny: foreach.Deny,
|
||||
}
|
||||
val = append(val, &temp)
|
||||
}
|
||||
// Variable substitution expects JSON data, so we convert to a map
|
||||
anyAllConditions, err := common.ToMap(ruleCopy.Validation.ForEachValidation.AnyAllConditions)
|
||||
if err != nil {
|
||||
log.Error(err, "failed to convert ruleCopy.Validation.ForEachValidation.AnyAllConditions")
|
||||
}
|
||||
|
||||
return &validator{
|
||||
log: log,
|
||||
ctx: ctx,
|
||||
rule: ruleCopy,
|
||||
contextEntries: ruleCopy.Validation.ForEachValidation.Context,
|
||||
anyAllConditions: anyAllConditions,
|
||||
pattern: ruleCopy.Validation.ForEachValidation.Pattern,
|
||||
anyPattern: ruleCopy.Validation.ForEachValidation.AnyPattern,
|
||||
deny: ruleCopy.Validation.ForEachValidation.Deny,
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (v *validator) validate() *response.RuleResponse {
|
||||
|
@ -219,44 +222,48 @@ func (v *validator) validateForEach() *response.RuleResponse {
|
|||
return ruleResponse(v.rule, utils.Validation, "preconditions not met", response.RuleStatusSkip)
|
||||
}
|
||||
|
||||
foreach := v.rule.Validation.ForEachValidation
|
||||
if foreach == nil {
|
||||
foreachList := v.rule.Validation.ForEachValidation
|
||||
applyCount := 0
|
||||
if foreachList == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
elements, err := evaluateList(foreach.List, v.ctx.JSONContext)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to evaluate list %s", foreach.List)
|
||||
return ruleError(v.rule, utils.Validation, msg, err)
|
||||
}
|
||||
|
||||
v.ctx.JSONContext.Checkpoint()
|
||||
defer v.ctx.JSONContext.Restore()
|
||||
|
||||
applyCount := 0
|
||||
for _, e := range elements {
|
||||
v.ctx.JSONContext.Reset()
|
||||
|
||||
ctx := v.ctx.Copy()
|
||||
if err := addElementToContext(ctx, e); err != nil {
|
||||
v.log.Error(err, "failed to add element to context")
|
||||
return ruleError(v.rule, utils.Validation, "failed to process foreach", err)
|
||||
for _, foreach := range foreachList {
|
||||
elements, err := evaluateList(foreach.List, v.ctx.JSONContext)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("failed to evaluate list %s", foreach.List)
|
||||
return ruleError(v.rule, utils.Validation, msg, err)
|
||||
}
|
||||
|
||||
foreachValidator := newForeachValidator(v.log, ctx, v.rule)
|
||||
r := foreachValidator.validate()
|
||||
if r == nil {
|
||||
v.log.Info("skipping rule due to empty result")
|
||||
continue
|
||||
} else if r.Status == response.RuleStatusSkip {
|
||||
v.log.Info("skipping rule as preconditions were not met")
|
||||
continue
|
||||
} else if r.Status != response.RuleStatusPass {
|
||||
msg := fmt.Sprintf("validation failed in foreach rule for %v", r.Message)
|
||||
return ruleResponse(v.rule, utils.Validation, msg, r.Status)
|
||||
}
|
||||
v.ctx.JSONContext.Checkpoint()
|
||||
defer v.ctx.JSONContext.Restore()
|
||||
|
||||
applyCount++
|
||||
for _, e := range elements {
|
||||
v.ctx.JSONContext.Reset()
|
||||
|
||||
ctx := v.ctx.Copy()
|
||||
if err := addElementToContext(ctx, e); err != nil {
|
||||
v.log.Error(err, "failed to add element to context")
|
||||
return ruleError(v.rule, utils.Validation, "failed to process foreach", err)
|
||||
}
|
||||
|
||||
foreachValidatorList := newForeachValidator(v.log, ctx, v.rule)
|
||||
for _, foreachValidator := range foreachValidatorList {
|
||||
r := foreachValidator.validate()
|
||||
if r == nil {
|
||||
v.log.Info("skipping rule due to empty result")
|
||||
continue
|
||||
} else if r.Status == response.RuleStatusSkip {
|
||||
v.log.Info("skipping rule as preconditions were not met")
|
||||
continue
|
||||
} else if r.Status != response.RuleStatusPass {
|
||||
msg := fmt.Sprintf("validation failed in foreach rule for %v", r.Message)
|
||||
return ruleResponse(v.rule, utils.Validation, msg, r.Status)
|
||||
}
|
||||
applyCount++
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if applyCount == 0 {
|
||||
|
|
|
@ -2,9 +2,10 @@ package engine
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
"testing"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/engine/response"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/utils"
|
||||
|
@ -2435,20 +2436,34 @@ func Test_foreach_container_pass(t *testing.T) {
|
|||
policyraw := []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {"name": "test"},
|
||||
"metadata": {
|
||||
"name": "test"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "test-path-not-exist",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"pattern": {
|
||||
"name": "*-valid"
|
||||
}
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Deployment"
|
||||
]
|
||||
}
|
||||
}}]}}`)
|
||||
},
|
||||
"validate": {
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"pattern": {
|
||||
"name": "*-valid"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
testForEach(t, policyraw, resourceRaw, "", response.RuleStatusPass)
|
||||
}
|
||||
|
@ -2476,12 +2491,14 @@ func Test_foreach_container_fail(t *testing.T) {
|
|||
"name": "test",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"pattern": {
|
||||
"name": "*-valid"
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"pattern": {
|
||||
"name": "*-valid"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}}]}}`)
|
||||
|
||||
testForEach(t, policyraw, resourceRaw, "", response.RuleStatusFail)
|
||||
|
@ -2503,22 +2520,40 @@ func Test_foreach_container_deny_fail(t *testing.T) {
|
|||
policyraw := []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {"name": "test"},
|
||||
"metadata": {
|
||||
"name": "test"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "test",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{"key": "{{ regex_match('{{element.image}}', 'docker.io') }}", "operator": "Equals", "value": false}
|
||||
]
|
||||
}
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Deployment"
|
||||
]
|
||||
}
|
||||
}}]}}`)
|
||||
},
|
||||
"validate": {
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{
|
||||
"key": "{{ regex_match('{{element.image}}', 'docker.io') }}",
|
||||
"operator": "Equals",
|
||||
"value": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
testForEach(t, policyraw, resourceRaw, "", response.RuleStatusFail)
|
||||
}
|
||||
|
@ -2546,14 +2581,20 @@ func Test_foreach_container_deny_success(t *testing.T) {
|
|||
"name": "test",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{"key": "{{ regex_match('{{element.image}}', 'docker.io') }}", "operator": "Equals", "value": false}
|
||||
]
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{
|
||||
"key": "{{ regex_match('{{element.image}}', 'docker.io') }}",
|
||||
"operator": "Equals",
|
||||
"value": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}}]}}`)
|
||||
|
||||
testForEach(t, policyraw, resourceRaw, "", response.RuleStatusFail)
|
||||
|
@ -2575,22 +2616,40 @@ func Test_foreach_container_deny_error(t *testing.T) {
|
|||
policyraw := []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {"name": "test"},
|
||||
"metadata": {
|
||||
"name": "test"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "test",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{"key": "{{ regex_match_INVALID('{{request.object.image}}', 'docker.io') }}", "operator": "Equals", "value": false}
|
||||
]
|
||||
}
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Deployment"
|
||||
]
|
||||
}
|
||||
}}]}}`)
|
||||
},
|
||||
"validate": {
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{
|
||||
"key": "{{ regex_match_INVALID('{{request.object.image}}', 'docker.io') }}",
|
||||
"operator": "Equals",
|
||||
"value": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
testForEach(t, policyraw, resourceRaw, "", response.RuleStatusError)
|
||||
}
|
||||
|
@ -2611,30 +2670,60 @@ func Test_foreach_context_preconditions(t *testing.T) {
|
|||
policyraw := []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {"name": "test"},
|
||||
"metadata": {
|
||||
"name": "test"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "test",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"context": [{"name": "img", "configMap": {"name": "mycmap", "namespace": "default"}}],
|
||||
"preconditions": { "all": [
|
||||
{
|
||||
"key": "{{element.name}}",
|
||||
"operator": "In",
|
||||
"value": ["podvalid"]
|
||||
}
|
||||
]},
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{"key": "{{ element.image }}", "operator": "NotEquals", "value": "{{ img.data.{{ element.name }} }}"}
|
||||
]
|
||||
}
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Deployment"
|
||||
]
|
||||
}
|
||||
}}]}}`)
|
||||
},
|
||||
"validate": {
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"context": [
|
||||
{
|
||||
"name": "img",
|
||||
"configMap": {
|
||||
"name": "mycmap",
|
||||
"namespace": "default"
|
||||
}
|
||||
}
|
||||
],
|
||||
"preconditions": {
|
||||
"all": [
|
||||
{
|
||||
"key": "{{element.name}}",
|
||||
"operator": "In",
|
||||
"value": [
|
||||
"podvalid"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{
|
||||
"key": "{{ element.image }}",
|
||||
"operator": "NotEquals",
|
||||
"value": "{{ img.data.{{ element.name }} }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
configMapVariableContext := store.Context{
|
||||
Policies: []store.Policy{
|
||||
|
@ -2675,30 +2764,61 @@ func Test_foreach_context_preconditions_fail(t *testing.T) {
|
|||
policyraw := []byte(`{
|
||||
"apiVersion": "kyverno.io/v1",
|
||||
"kind": "ClusterPolicy",
|
||||
"metadata": {"name": "test"},
|
||||
"metadata": {
|
||||
"name": "test"
|
||||
},
|
||||
"spec": {
|
||||
"rules": [
|
||||
{
|
||||
"name": "test",
|
||||
"match": {"resources": { "kinds": [ "Deployment" ] } },
|
||||
"validate": {
|
||||
"foreach": {
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"context": [{"name": "img", "configMap": {"name": "mycmap", "namespace": "default"}}],
|
||||
"preconditions": { "all": [
|
||||
{
|
||||
"key": "{{element.name}}",
|
||||
"operator": "In",
|
||||
"value": ["podvalid", "podinvalid"]
|
||||
}
|
||||
]},
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{"key": "{{ element.image }}", "operator": "NotEquals", "value": "{{ img.data.{{ element.name }} }}"}
|
||||
]
|
||||
}
|
||||
"match": {
|
||||
"resources": {
|
||||
"kinds": [
|
||||
"Deployment"
|
||||
]
|
||||
}
|
||||
}}]}}`)
|
||||
},
|
||||
"validate": {
|
||||
"foreach": [
|
||||
{
|
||||
"list": "request.object.spec.template.spec.containers",
|
||||
"context": [
|
||||
{
|
||||
"name": "img",
|
||||
"configMap": {
|
||||
"name": "mycmap",
|
||||
"namespace": "default"
|
||||
}
|
||||
}
|
||||
],
|
||||
"preconditions": {
|
||||
"all": [
|
||||
{
|
||||
"key": "{{element.name}}",
|
||||
"operator": "In",
|
||||
"value": [
|
||||
"podvalid",
|
||||
"podinvalid"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"deny": {
|
||||
"conditions": [
|
||||
{
|
||||
"key": "{{ element.image }}",
|
||||
"operator": "NotEquals",
|
||||
"value": "{{ img.data.{{ element.name }} }}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}`)
|
||||
|
||||
configMapVariableContext := store.Context{
|
||||
Policies: []store.Policy{
|
||||
|
|
|
@ -50,8 +50,10 @@ func (v *Validate) Validate() (string, error) {
|
|||
}
|
||||
|
||||
if v.rule.ForEachValidation != nil {
|
||||
if err := v.validateForEach(v.rule.ForEachValidation); err != nil {
|
||||
return "", err
|
||||
for _, foreach := range v.rule.ForEachValidation {
|
||||
if err := v.validateForEach(foreach); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,15 +95,6 @@ func generateCronJobRule(rule kyverno.Rule, controllers string, log logr.Logger)
|
|||
return *cronJobRule
|
||||
}
|
||||
|
||||
if (jobRule.Validation != nil) && (jobRule.Validation.ForEachValidation != nil) && (jobRule.Validation.ForEachValidation.Pattern != nil) {
|
||||
newValidate := &kyverno.Validation{
|
||||
Message: variables.FindAndShiftReferences(log, rule.Validation.Message, "spec/jobTemplate/spec/template", "pattern"),
|
||||
ForEachValidation: jobRule.Validation.ForEachValidation,
|
||||
}
|
||||
cronJobRule.Validation = newValidate.DeepCopy()
|
||||
return *cronJobRule
|
||||
}
|
||||
|
||||
if (jobRule.Validation != nil) && (jobRule.Validation.AnyPattern != nil) {
|
||||
var patterns []interface{}
|
||||
anyPatterns, err := jobRule.Validation.DeserializeAnyPattern()
|
||||
|
@ -128,25 +119,36 @@ func generateCronJobRule(rule kyverno.Rule, controllers string, log logr.Logger)
|
|||
return *cronJobRule
|
||||
}
|
||||
|
||||
if (jobRule.Validation != nil) && (jobRule.Validation.ForEachValidation != nil) && (jobRule.Validation.ForEachValidation.AnyPattern != nil) {
|
||||
if (jobRule.Validation != nil) && len(jobRule.Validation.ForEachValidation) > 0 && jobRule.Validation.ForEachValidation != nil {
|
||||
newForeachValidate := make([]*kyverno.ForEachValidation, len(jobRule.Validation.ForEachValidation))
|
||||
for i, foreach := range rule.Validation.ForEachValidation {
|
||||
newForeachValidate[i] = foreach
|
||||
}
|
||||
cronJobRule.Validation = &kyverno.Validation{
|
||||
Message: variables.FindAndShiftReferences(log, rule.Validation.Message, "spec/jobTemplate/spec/template", "anyPattern"),
|
||||
ForEachValidation: jobRule.Validation.ForEachValidation,
|
||||
Message: variables.FindAndShiftReferences(log, rule.Validation.Message, "spec/template", "pattern"),
|
||||
ForEachValidation: newForeachValidate,
|
||||
}
|
||||
return *cronJobRule
|
||||
}
|
||||
|
||||
if (jobRule.Validation != nil) && (jobRule.Validation.ForEachValidation != nil) && (jobRule.Validation.ForEachValidation.Deny != nil) {
|
||||
cronJobRule.Validation = &kyverno.Validation{
|
||||
Message: variables.FindAndShiftReferences(log, rule.Validation.Message, "spec/jobTemplate/spec/template", "anyPattern"),
|
||||
ForEachValidation: jobRule.Validation.ForEachValidation,
|
||||
}
|
||||
return *cronJobRule
|
||||
}
|
||||
if (jobRule.Mutation != nil) && len(jobRule.Mutation.ForEachMutation) > 0 && jobRule.Mutation.ForEachMutation != nil {
|
||||
|
||||
if (jobRule.Mutation != nil) && (jobRule.Mutation.ForEachMutation != nil) && (jobRule.Mutation.ForEachMutation.PatchStrategicMerge != nil) {
|
||||
var newForeachMutation []*kyverno.ForEachMutation
|
||||
|
||||
for _, foreach := range rule.Mutation.ForEachMutation {
|
||||
newForeachMutation = append(newForeachMutation, &kyverno.ForEachMutation{
|
||||
List: foreach.List,
|
||||
Context: foreach.Context,
|
||||
AnyAllConditions: foreach.AnyAllConditions,
|
||||
PatchStrategicMerge: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"jobTemplate": foreach.PatchStrategicMerge,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
cronJobRule.Mutation = &kyverno.Mutation{
|
||||
ForEachMutation: jobRule.Mutation.ForEachMutation,
|
||||
ForEachMutation: newForeachMutation,
|
||||
}
|
||||
return *cronJobRule
|
||||
}
|
||||
|
|
|
@ -567,6 +567,7 @@ func generateRulePatches(policy kyverno.ClusterPolicy, controllers string, log l
|
|||
|
||||
// handle CronJob, it appends an additional rule
|
||||
genRule = generateCronJobRule(rule, controllers, log)
|
||||
|
||||
if !reflect.DeepEqual(genRule, kyvernoRule{}) {
|
||||
pbytes := convertToPatches(genRule, patchPostion)
|
||||
pbytes = updateGenRuleByte(pbytes, "Cronjob", genRule)
|
||||
|
@ -724,20 +725,22 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.
|
|||
return *controllerRule
|
||||
}
|
||||
|
||||
if rule.Mutation.ForEachMutation != nil && rule.Mutation.ForEachMutation.PatchStrategicMerge != nil {
|
||||
newForeachMutation := &kyverno.Mutation{
|
||||
ForEachMutation: &kyverno.ForEachMutation{
|
||||
List: rule.Mutation.ForEachMutation.List,
|
||||
Context: rule.Mutation.ForEachMutation.Context,
|
||||
AnyAllConditions: rule.Mutation.ForEachMutation.AnyAllConditions,
|
||||
if len(rule.Mutation.ForEachMutation) > 0 && rule.Mutation.ForEachMutation != nil {
|
||||
var newForeachMutation []*kyverno.ForEachMutation
|
||||
for _, foreach := range rule.Mutation.ForEachMutation {
|
||||
newForeachMutation = append(newForeachMutation, &kyverno.ForEachMutation{
|
||||
List: foreach.List,
|
||||
AnyAllConditions: foreach.AnyAllConditions,
|
||||
PatchStrategicMerge: map[string]interface{}{
|
||||
"spec": map[string]interface{}{
|
||||
"template": rule.Mutation.ForEachMutation.PatchStrategicMerge,
|
||||
"template": foreach.PatchStrategicMerge,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
controllerRule.Mutation = &kyverno.Mutation{
|
||||
ForEachMutation: newForeachMutation,
|
||||
}
|
||||
controllerRule.Mutation = newForeachMutation.DeepCopy()
|
||||
return *controllerRule
|
||||
}
|
||||
|
||||
|
@ -769,19 +772,14 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.
|
|||
return *controllerRule
|
||||
}
|
||||
|
||||
if rule.Validation.ForEachValidation != nil && rule.Validation.ForEachValidation.Pattern != nil {
|
||||
newForeachValidate := &kyverno.Validation{
|
||||
Message: variables.FindAndShiftReferences(log, rule.Validation.Message, "spec/template", "pattern"),
|
||||
ForEachValidation: rule.Validation.ForEachValidation,
|
||||
if len(rule.Validation.ForEachValidation) > 0 && rule.Validation.ForEachValidation != nil {
|
||||
newForeachValidate := make([]*kyverno.ForEachValidation, len(rule.Validation.ForEachValidation))
|
||||
for i, foreach := range rule.Validation.ForEachValidation {
|
||||
newForeachValidate[i] = foreach
|
||||
}
|
||||
controllerRule.Validation = newForeachValidate.DeepCopy()
|
||||
return *controllerRule
|
||||
}
|
||||
|
||||
if rule.Validation.ForEachValidation != nil && rule.Validation.ForEachValidation.AnyPattern != nil {
|
||||
controllerRule.Validation = &kyverno.Validation{
|
||||
Message: variables.FindAndShiftReferences(log, rule.Validation.Message, "spec/template", "pattern"),
|
||||
ForEachValidation: rule.Validation.ForEachValidation,
|
||||
ForEachValidation: newForeachValidate,
|
||||
}
|
||||
return *controllerRule
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue