1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-29 02:45:06 +00:00

feat: [preconditions, conditions] added backwards-compatible support for logical operators (#1604)

Signed-off-by: Yashvardhan Kukreja <yash.kukreja.98@gmail.com>
This commit is contained in:
Yashvardhan Kukreja 2021-03-02 10:01:06 +05:30 committed by GitHub
parent 6f15432a21
commit 10c714d5ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 449 additions and 525 deletions

View file

@ -385,26 +385,8 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -415,26 +397,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.
@ -1565,26 +1529,8 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -1595,26 +1541,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.

View file

@ -583,34 +583,15 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner
where in some situation all the conditions need to pass and
in some other situation, atleast one condition is enough to
pass. For the sake of backwards compatibility, it can be populated
with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -624,32 +605,10 @@ spec:
rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny
in a logical manner For the sake of backwards compatibility,
it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed

View file

@ -584,34 +584,15 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner
where in some situation all the conditions need to pass and
in some other situation, atleast one condition is enough to
pass. For the sake of backwards compatibility, it can be populated
with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -625,32 +606,10 @@ spec:
rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny
in a logical manner For the sake of backwards compatibility,
it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed

View file

@ -390,26 +390,8 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -420,26 +402,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.
@ -1570,26 +1534,8 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -1600,26 +1546,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.

View file

@ -390,26 +390,8 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -420,26 +402,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.
@ -1570,26 +1534,8 @@ spec:
maxLength: 63
type: string
preconditions:
description: Conditions 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.
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
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -1600,26 +1546,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.

View file

@ -111,7 +111,7 @@ spec:
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
type: string
namespaceSelector:
description: 'NamespaceSelector is a label selector for namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character). Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
description: 'NamespaceSelector is a label selector for the resource namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character).Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
@ -261,7 +261,7 @@ spec:
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
type: string
namespaceSelector:
description: 'NamespaceSelector is a label selector for namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character). Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
description: 'NamespaceSelector is a label selector for the resource namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character).Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
@ -389,26 +389,8 @@ spec:
description: Name is a label to identify the rule, It must be unique within the policy.
type: string
preconditions:
description: Conditions 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.
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.
enum:
- Equals
- NotEquals
- In
- NotIn
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -419,26 +401,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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.
enum:
- Equals
- NotEquals
- In
- NotIn
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.
@ -1290,7 +1254,7 @@ spec:
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
type: string
namespaceSelector:
description: 'NamespaceSelector is a label selector for namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character). Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
description: 'NamespaceSelector is a label selector for the resource namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character).Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
@ -1440,7 +1404,7 @@ spec:
description: Name is the name of the resource. The name supports wildcard characters "*" (matches zero or many characters) and "?" (at least one character).
type: string
namespaceSelector:
description: 'NamespaceSelector is a label selector for namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character). Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
description: 'NamespaceSelector is a label selector for the resource namespace. Label keys and values in `matchLabels` support the wildcard characters `*` (matches zero or many characters) and `?` (matches one character).Wildcards allows writing label selectors like ["storage.k8s.io/*": "*"]. Note that using ["*" : "*"] matches any key and value but does not match an empty label set.'
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements. The requirements are ANDed.
@ -1568,26 +1532,8 @@ spec:
description: Name is a label to identify the rule, It must be unique within the policy.
type: string
preconditions:
description: Conditions 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.
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.
enum:
- Equals
- NotEquals
- In
- NotIn
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
description: AnyAllConditions 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. This too can be made to happen in a logical-manner where in some situation all the conditions need to pass and in some other situation, atleast one condition is enough to pass. For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
validate:
description: Validation is used to validate matching resources.
properties:
@ -1598,26 +1544,8 @@ spec:
description: Deny defines conditions to fail the validation rule.
properties:
conditions:
description: Specifies set of condition to deny.
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.
enum:
- Equals
- NotEquals
- In
- NotIn
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
description: specifies the set of conditions to deny in a logical manner For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
x-kubernetes-preserve-unknown-fields: true
type: object
message:
description: Message specifies a custom message to be displayed on failure.

View file

@ -80,11 +80,15 @@ type Rule struct {
// +optional
ExcludeResources ExcludeResources `json:"exclude,omitempty" yaml:"exclude,omitempty"`
// Conditions enable variable-based conditional rule execution. This is useful for
// AnyAllConditions 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.
// This too can be made to happen in a logical-manner where in some situation all the conditions need to pass
// and in some other situation, atleast one condition is enough to pass.
// For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
// +kubebuilder:validation:XPreserveUnknownFields
// +optional
Conditions []Condition `json:"preconditions,omitempty" yaml:"preconditions,omitempty"`
AnyAllConditions apiextensions.JSON `json:"preconditions,omitempty" yaml:"preconditions,omitempty"`
// Mutation is used to modify matching resources.
// +optional
@ -99,6 +103,25 @@ type Rule struct {
Generation Generation `json:"generate,omitempty" yaml:"generate,omitempty"`
}
// AnyAllCondition consists of conditions wrapped denoting a logical criteria to be fulfilled.
// AnyConditions get fulfilled when at least one of its sub-conditions passes.
// AllConditions get fulfilled only when all of its sub-conditions pass.
type AnyAllConditions struct {
// 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, atleast one of the conditions need to pass
// +optional
AnyConditions []Condition `json:"any,omitempty" yaml:"any,omitempty"`
// 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
// +optional
AllConditions []Condition `json:"all,omitempty" yaml:"all,omitempty"`
}
// ContextEntry adds variables and data sources to a rule Context. Either a
// ConfigMap reference or a APILookup must be provided.
type ContextEntry struct {
@ -341,8 +364,10 @@ type Validation struct {
// Deny specifies a list of conditions. The validation rule fails, if any Condition
// evaluates to "false".
type Deny struct {
// Specifies set of condition to deny.
Conditions []Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
// specifies the set of conditions to deny in a logical manner
// For the sake of backwards compatibility, it can be populated with []kyverno.Condition.
// +kubebuilder:validation:XPreserveUnknownFields
AnyAllConditions apiextensions.JSON `json:"conditions,omitempty" yaml:"conditions,omitempty"`
}
// Generation defines how new resources should be created and managed.

View file

@ -39,6 +39,35 @@ func (in *APICall) DeepCopy() *APICall {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AnyAllConditions) DeepCopyInto(out *AnyAllConditions) {
*out = *in
if in.AnyConditions != nil {
in, out := &in.AnyConditions, &out.AnyConditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.AllConditions != nil {
in, out := &in.AllConditions, &out.AllConditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnyAllConditions.
func (in *AnyAllConditions) DeepCopy() *AnyAllConditions {
if in == nil {
return nil
}
out := new(AnyAllConditions)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CloneFrom) DeepCopyInto(out *CloneFrom) {
*out = *in
@ -166,13 +195,6 @@ func (in *ContextEntry) DeepCopy() *ContextEntry {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Deny) DeepCopyInto(out *Deny) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Deny.
@ -525,16 +547,6 @@ func (in *Rule) DeepCopyInto(out *Rule) {
}
in.MatchResources.DeepCopyInto(&out.MatchResources)
in.ExcludeResources.DeepCopyInto(&out.ExcludeResources)
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
in.Mutation.DeepCopyInto(&out.Mutation)
in.Validation.DeepCopyInto(&out.Validation)
in.Generation.DeepCopyInto(&out.Generation)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rule.

View file

@ -92,7 +92,11 @@ func filterRule(rule kyverno.Rule, policyContext *PolicyContext) *response.RuleR
}
// operate on the copy of the conditions, as we perform variable substitution
copyConditions := copyConditions(rule.Conditions)
copyConditions, err := copyConditions(rule.AnyAllConditions)
if err != nil {
logger.V(4).Info("cannot copy AnyAllConditions", "reason", err.Error())
return nil
}
// evaluate pre-conditions
if !variables.EvaluateConditions(logger, ctx, copyConditions) {

View file

@ -76,7 +76,11 @@ func Mutate(policyContext *PolicyContext) (resp *response.EngineResponse) {
}
// operate on the copy of the conditions, as we perform variable substitution
copyConditions := copyConditions(rule.Conditions)
copyConditions, err := copyConditions(rule.AnyAllConditions)
if err != nil {
logger.V(2).Info("failed to load context", "reason", err.Error())
continue
}
// evaluate pre-conditions
// - handle variable substitutions
if !variables.EvaluateConditions(logger, ctx, copyConditions) {

View file

@ -2,13 +2,13 @@ package engine
import (
"encoding/json"
"reflect"
"testing"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/utils"
"gotest.tools/assert"
"reflect"
"testing"
)
func Test_VariableSubstitutionOverlay(t *testing.T) {

View file

@ -13,6 +13,7 @@ import (
"github.com/minio/minio/pkg/wildcard"
authenticationv1 "k8s.io/api/authentication/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
@ -276,7 +277,15 @@ func MatchesResourceDescription(resourceRef unstructured.Unstructured, ruleRef k
return nil
}
func copyConditions(original []kyverno.Condition) []kyverno.Condition {
func copyAnyAllConditions(original kyverno.AnyAllConditions) kyverno.AnyAllConditions {
if reflect.DeepEqual(original, kyverno.AnyAllConditions{}) {
return kyverno.AnyAllConditions{}
}
return *original.DeepCopy()
}
// backwards compatibility
func copyOldConditions(original []kyverno.Condition) []kyverno.Condition {
if original == nil || len(original) == 0 {
return []kyverno.Condition{}
}
@ -289,6 +298,21 @@ func copyConditions(original []kyverno.Condition) []kyverno.Condition {
return copies
}
func copyConditions(original apiextensions.JSON) (interface{}, error) {
// conditions are currently in the form of []interface{}
kyvernoOriginalConditions, err := utils.ApiextensionsJsonToKyvernoConditions(original)
if err != nil {
return nil, err
}
switch typedValue := kyvernoOriginalConditions.(type) {
case kyverno.AnyAllConditions:
return copyAnyAllConditions(typedValue), nil
case []kyverno.Condition: // backwards compatibility
return copyOldConditions(typedValue), nil
}
return nil, fmt.Errorf("wrongfully configured data")
}
// excludeResource checks if the resource has ownerRef set
func excludeResource(resource unstructured.Unstructured) bool {
kind := resource.GetKind()

View file

@ -113,8 +113,11 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
log.V(3).Info("matched validate rule")
// operate on the copy of the conditions, as we perform variable substitution
preconditionsCopy := copyConditions(rule.Conditions)
preconditionsCopy, err := copyConditions(rule.AnyAllConditions)
if err != nil {
log.V(2).Info("wrongfully configured data", "reason", err.Error())
continue
}
// evaluate pre-conditions
// - handle variable substitutions
if !variables.EvaluateConditions(log, ctx.JSONContext, preconditionsCopy) {
@ -131,7 +134,11 @@ func validateResource(log logr.Logger, ctx *PolicyContext) *response.EngineRespo
}
}
} else if rule.Validation.Deny != nil {
denyConditionsCopy := copyConditions(rule.Validation.Deny.Conditions)
denyConditionsCopy, err := copyConditions(rule.Validation.Deny.AnyAllConditions)
if err != nil {
log.V(2).Info("wrongfully configured data", "reason", err.Error())
continue
}
deny := variables.EvaluateConditions(log, ctx.JSONContext, denyConditionsCopy)
ruleResp := response.RuleResponse{
Name: rule.Name,

File diff suppressed because one or more lines are too long

View file

@ -17,8 +17,49 @@ func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyverno.Cond
return handle.Evaluate(condition.Key, condition.Value)
}
//EvaluateConditions evaluates multiple conditions as a logical AND operation
func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition) bool {
//EvaluateConditions evalues all the conditions present in a slice, in a backwards compatible way
func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions interface{}) bool {
switch typedConditions := conditions.(type) {
case kyverno.AnyAllConditions:
return evaluateAnyAllConditions(log, ctx, typedConditions)
case []kyverno.Condition: // backwards compatibility
return evaluateOldConditions(log, ctx, typedConditions)
}
return false
}
//evaluateAnyAllConditions evaluates multiple conditions as a logical AND (all) or OR (any) operation depending on the conditions
func evaluateAnyAllConditions(log logr.Logger, ctx context.EvalInterface, conditions kyverno.AnyAllConditions) bool {
anyConditions, allConditions := conditions.AnyConditions, conditions.AllConditions
anyConditionsResult, allConditionsResult := true, true
// update the anyConditionsResult if they are present
if anyConditions != nil {
anyConditionsResult = false
for _, condition := range anyConditions {
if Evaluate(log, ctx, condition) {
anyConditionsResult = true
break
}
}
}
// update the allConditionsResult if they are present
if allConditions != nil {
for _, condition := range allConditions {
if !Evaluate(log, ctx, condition) {
allConditionsResult = false
break
}
}
}
finalResult := anyConditionsResult && allConditionsResult
return finalResult
}
//evaluateOldConditions evaluates multiple conditions when those conditions are provided in the old manner i.e. without 'any' or 'all'
func evaluateOldConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition) bool {
for _, condition := range conditions {
if !Evaluate(log, ctx, condition) {
return false

View file

@ -2,10 +2,13 @@ package policy
import (
"fmt"
"reflect"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/utils"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"sigs.k8s.io/controller-runtime/pkg/log"
)
@ -50,13 +53,9 @@ func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error {
}
}
for condIdx, condition := range rule.Conditions {
if condition.Key, err = variables.SubstituteVars(log.Log, ctx, condition.Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %v used at spec/rules[%d]/condition[%d]/key: %s", condition.Key, idx, condIdx, err.Error())
}
if condition.Value, err = variables.SubstituteVars(log.Log, ctx, condition.Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid %v variable used at spec/rules[%d]/condition[%d]/value: %s", condition.Value, idx, condIdx, err.Error())
if rule.AnyAllConditions != nil {
if err = validatePreConditions(idx, ctx, rule.AnyAllConditions); err != nil {
return err
}
}
@ -94,15 +93,8 @@ func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error {
}
if rule.Validation.Deny != nil {
for i := range rule.Validation.Deny.Conditions {
if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Deny.Conditions[i].Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/conditions[%d]/key: %v",
rule.Validation.Deny.Conditions[i].Key, idx, i, err)
}
if _, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Deny.Conditions[i].Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/conditions[%d]/value: %v",
rule.Validation.Deny.Conditions[i].Value, idx, i, err)
}
if err = validateDenyConditions(idx, ctx, rule.Validation.Deny.AnyAllConditions); err != nil {
return err
}
}
@ -130,6 +122,103 @@ func ContainsVariablesOtherThanObject(policy kyverno.ClusterPolicy) error {
return nil
}
func validatePreConditions(idx int, ctx context.EvalInterface, anyAllConditions apiextensions.JSON) error {
var err error
// conditions are currently in the form of []interface{}
kyvernoAnyAllConditions, err := utils.ApiextensionsJsonToKyvernoConditions(anyAllConditions)
if err != nil {
return err
}
switch typedPreConditions := kyvernoAnyAllConditions.(type) {
case kyverno.AnyAllConditions:
if !reflect.DeepEqual(typedPreConditions, kyverno.AnyAllConditions{}) && typedPreConditions.AnyConditions != nil {
for condIdx, condition := range typedPreConditions.AnyConditions {
if condition.Key, err = variables.SubstituteVars(log.Log, ctx, condition.Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/any/condition[%d]/key", condition.Key, idx, condIdx)
}
if condition.Value, err = variables.SubstituteVars(log.Log, ctx, condition.Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid %s variable used at spec/rules[%d]/any/condition[%d]/value", condition.Value, idx, condIdx)
}
}
}
if !reflect.DeepEqual(typedPreConditions, kyverno.AnyAllConditions{}) && typedPreConditions.AllConditions != nil {
for condIdx, condition := range typedPreConditions.AllConditions {
if condition.Key, err = variables.SubstituteVars(log.Log, ctx, condition.Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/all/condition[%d]/key", condition.Key, idx, condIdx)
}
if condition.Value, err = variables.SubstituteVars(log.Log, ctx, condition.Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid %s variable used at spec/rules[%d]/all/condition[%d]/value", condition.Value, idx, condIdx)
}
}
}
case []kyverno.Condition: //backwards compatibility
for condIdx, condition := range typedPreConditions {
if condition.Key, err = variables.SubstituteVars(log.Log, ctx, condition.Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/condition[%d]/key", condition.Key, idx, condIdx)
}
if condition.Value, err = variables.SubstituteVars(log.Log, ctx, condition.Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid %s variable used at spec/rules[%d]/condition[%d]/value", condition.Value, idx, condIdx)
}
}
}
return nil
}
func validateDenyConditions(idx int, ctx context.EvalInterface, denyConditions apiextensions.JSON) error {
// conditions are currently in the form of []interface{}
kyvernoDenyConditions, err := utils.ApiextensionsJsonToKyvernoConditions(denyConditions)
if err != nil {
return err
}
switch typedDenyConditions := kyvernoDenyConditions.(type) {
case kyverno.AnyAllConditions:
// validating validate.deny.any.conditions
if !reflect.DeepEqual(typedDenyConditions, kyverno.AnyAllConditions{}) && typedDenyConditions.AnyConditions != nil {
for i := range typedDenyConditions.AnyConditions {
if _, err := variables.SubstituteVars(log.Log, ctx, typedDenyConditions.AnyConditions[i].Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/any/conditions[%d]/key: %v",
typedDenyConditions.AnyConditions[i].Key, idx, i, err)
}
if _, err := variables.SubstituteVars(log.Log, ctx, typedDenyConditions.AnyConditions[i].Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/any/conditions[%d]/value: %v",
typedDenyConditions.AnyConditions[i].Value, idx, i, err)
}
}
}
// validating validate.deny.all.conditions
if !reflect.DeepEqual(typedDenyConditions, kyverno.AnyAllConditions{}) && typedDenyConditions.AllConditions != nil {
for i := range typedDenyConditions.AllConditions {
if _, err := variables.SubstituteVars(log.Log, ctx, typedDenyConditions.AllConditions[i].Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/all/conditions[%d]/key: %v",
typedDenyConditions.AllConditions[i].Key, idx, i, err)
}
if _, err := variables.SubstituteVars(log.Log, ctx, typedDenyConditions.AllConditions[i].Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/all/conditions[%d]/value: %v",
typedDenyConditions.AllConditions[i].Value, idx, i, err)
}
}
}
case []kyverno.Condition: // backwards compatibility
// validating validate.deny.conditions
for i := range typedDenyConditions {
if _, err := variables.SubstituteVars(log.Log, ctx, typedDenyConditions[i].Key); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/conditions[%d]/key: %v",
typedDenyConditions[i].Key, idx, i, err)
}
if _, err := variables.SubstituteVars(log.Log, ctx, typedDenyConditions[i].Value); !checkNotFoundErr(err) {
return fmt.Errorf("invalid variable %s used at spec/rules[%d]/validate/deny/conditions[%d]/value: %v",
typedDenyConditions[i].Value, idx, i, err)
}
}
}
return nil
}
func checkNotFoundErr(err error) bool {
if err != nil {
switch err.(type) {

View file

@ -17,6 +17,7 @@ import (
"github.com/kyverno/kyverno/pkg/utils"
"github.com/minio/minio/pkg/wildcard"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
log "sigs.k8s.io/controller-runtime/pkg/log"
)
@ -482,32 +483,63 @@ func validateResources(rule kyverno.Rule) (string, error) {
return fmt.Sprintf("exclude.resources.%s", path), err
}
//validating the values present under validation.preconditions, if they exist
if rule.Conditions != nil {
if path, err := validateConditions(rule.Conditions, "preconditions"); err != nil {
//validating the values present under validate.preconditions, if they exist
if rule.AnyAllConditions != nil {
if path, err := validateConditions(rule.AnyAllConditions, "preconditions"); err != nil {
return fmt.Sprintf("validate.%s", path), err
}
}
// validating the values present under validation.deny.conditions, if they exist
if rule.Validation.Deny != nil {
if path, err := validateConditions(rule.Validation.Deny.Conditions, "conditions"); err != nil {
//validating the values present under validate.conditions, if they exist
if rule.Validation.Deny != nil && rule.Validation.Deny.AnyAllConditions != nil {
if path, err := validateConditions(rule.Validation.Deny.AnyAllConditions, "conditions"); err != nil {
return fmt.Sprintf("validate.deny.%s", path), err
}
}
return "", nil
}
// validateConditions validates all the 'conditions' or 'preconditions' of a rule depending on the corresponding 'condition.key'.
// As of now, it is validating the 'value' field whether it contains the only allowed set of values or not when 'condition.key' is {{request.operation}}
func validateConditions(conditions []kyverno.Condition, schemaKey string) (string, error) {
// []kyverno.Condition can only exist under either 'conditions' or 'preconditions' key of the policy schema
if schemaKey != "conditions" && schemaKey != "preconditions" {
return fmt.Sprintf(schemaKey), fmt.Errorf("wrong schema key found for validating the conditions. Conditions can only occur under 'preconditions' or 'conditions' key in the policy schema")
// this is backwards compatible i.e. conditions can be provided in the old manner as well i.e. without 'any' or 'all'
func validateConditions(conditions apiextensions.JSON, schemaKey string) (string, error) {
// Conditions can only exist under some specific keys of the policy schema
allowedSchemaKeys := map[string]bool{
"preconditions": true,
"conditions": true,
}
for i, condition := range conditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s[%d].%s", schemaKey, i, path), err
if !allowedSchemaKeys[schemaKey] {
return fmt.Sprintf(schemaKey), fmt.Errorf("wrong schema key found for validating the conditions. Conditions can only occur under one of ['preconditions', 'conditions'] keys in the policy schema")
}
// conditions are currently in the form of []interface{}
kyvernoConditions, err := utils.ApiextensionsJsonToKyvernoConditions(conditions)
if err != nil {
return fmt.Sprintf("%s", schemaKey), err
}
switch typedConditions := kyvernoConditions.(type) {
case kyverno.AnyAllConditions:
// validating the conditions under 'any', if there are any
if !reflect.DeepEqual(typedConditions, kyverno.AnyAllConditions{}) && typedConditions.AnyConditions != nil {
for i, condition := range typedConditions.AnyConditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s.any[%d].%s", schemaKey, i, path), err
}
}
}
// validating the conditions under 'all', if there are any
if !reflect.DeepEqual(typedConditions, kyverno.AnyAllConditions{}) && typedConditions.AllConditions != nil {
for i, condition := range typedConditions.AllConditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s.all[%d].%s", schemaKey, i, path), err
}
}
}
case []kyverno.Condition: // backwards compatibility
for i, condition := range typedConditions {
if path, err := validateConditionValues(condition); err != nil {
return fmt.Sprintf("%s[%d].%s", schemaKey, i, path), err
}
}
}
return "", nil

View file

@ -4,8 +4,10 @@ import (
"encoding/json"
"testing"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/openapi"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
"gotest.tools/assert"
)
@ -253,23 +255,29 @@ func Test_Validate_ResourceDescription_MatchedValid(t *testing.T) {
func Test_Validate_DenyConditions_KeyRequestOperation_Empty(t *testing.T) {
denyConditions := []byte(`[]`)
var dcs []kyverno.Condition
var dcs apiextensions.JSON
err := json.Unmarshal(denyConditions, &dcs)
assert.NilError(t, err)
_, err = validateConditions(dcs, "conditions")
assert.NilError(t, err)
_, err = validateConditions(dcs, "conditions")
assert.NilError(t, err)
}
func Test_Validate_Preconditions_KeyRequestOperation_Empty(t *testing.T) {
preConditions := []byte(`[]`)
var pcs []kyverno.Condition
var pcs apiextensions.JSON
err := json.Unmarshal(preConditions, &pcs)
assert.NilError(t, err)
_, err = validateConditions(pcs, "preconditions")
assert.NilError(t, err)
_, err = validateConditions(pcs, "preconditions")
assert.NilError(t, err)
}
func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_ExpectedValue(t *testing.T) {
@ -303,12 +311,15 @@ func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_ExpectedValue(
]
`)
var dcs []kyverno.Condition
var dcs apiextensions.JSON
err := json.Unmarshal(denyConditions, &dcs)
assert.NilError(t, err)
_, err = validateConditions(dcs, "conditions")
assert.NilError(t, err)
_, err = validateConditions(dcs, "conditions")
assert.NilError(t, err)
}
func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_RightfullyTemplatizedValue(t *testing.T) {
@ -327,12 +338,15 @@ func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_RightfullyTemp
]
`)
var dcs []kyverno.Condition
var dcs apiextensions.JSON
err := json.Unmarshal(denyConditions, &dcs)
assert.NilError(t, err)
_, err = validateConditions(dcs, "conditions")
assert.NilError(t, err)
_, err = validateConditions(dcs, "conditions")
assert.NilError(t, err)
}
func Test_Validate_DenyConditionsValuesString_KeyRequestOperation_WrongfullyTemplatizedValue(t *testing.T) {
@ -375,12 +389,15 @@ func Test_Validate_PreconditionsValuesString_KeyRequestOperation_UnknownValue(t
]
`)
var pcs []kyverno.Condition
var pcs apiextensions.JSON
err := json.Unmarshal(preConditions, &pcs)
assert.NilError(t, err)
_, err = validateConditions(pcs, "preconditions")
assert.Assert(t, err != nil)
_, err = validateConditions(pcs, "preconditions")
assert.Assert(t, err != nil)
}
func Test_Validate_DenyConditionsValuesList_KeyRequestOperation_ExpectedItem(t *testing.T) {
@ -439,12 +456,15 @@ func Test_Validate_PreconditionsValuesList_KeyRequestOperation_UnknownItem(t *te
]
`)
var pcs []kyverno.Condition
var pcs apiextensions.JSON
err := json.Unmarshal(preConditions, &pcs)
assert.NilError(t, err)
_, err = validateConditions(pcs, "preconditions")
assert.Assert(t, err != nil)
_, err = validateConditions(pcs, "preconditions")
assert.Assert(t, err != nil)
}
func Test_Validate_ResourceDescription_MissingKindsOnExclude(t *testing.T) {
@ -1203,7 +1223,7 @@ func Test_doesMatchExcludeConflict(t *testing.T) {
},
{
description: "empty case",
rule: []byte(`{"name":"check-allow-deletes","match":{"resources":{"selector":{"matchLabels":{"allow-deletes":"false"}}}},"exclude":{"clusterRoles":["random"]},"validate":{"message":"Deleting {{request.object.kind}}/{{request.object.metadata.name}} is not allowed","deny":{"conditions":[{"key":"{{request.operation}}","operator":"Equal","value":"DELETE"}]}}}`),
rule: []byte(`{"name":"check-allow-deletes","match":{"resources":{"selector":{"matchLabels":{"allow-deletes":"false"}}}},"exclude":{"clusterRoles":["random"]},"validate":{"message":"Deleting {{request.object.kind}}/{{request.object.metadata.name}} is not allowed","deny":{"conditions":{"all":[{"key":"{{request.operation}}","operator":"Equal","value":"DELETE"}]}}}}`),
expectedOutput: false,
},
}

View file

@ -121,13 +121,15 @@ func newPolicy(t *testing.T) *kyverno.ClusterPolicy {
},
"validate": {
"deny": {
"conditions": [
{
"key": "a",
"operator": "Equals",
"value": "a"
}
]
"conditions": {
"all": [
{
"key": "a",
"operator": "Equals",
"value": "a"
}
]
}
}
}
},
@ -226,13 +228,15 @@ func newNsPolicy(t *testing.T) *kyverno.ClusterPolicy {
},
"validate": {
"deny": {
"conditions": [
{
"key": "a",
"operator": "Equals",
"value": "a"
}
]
"conditions": {
"all": [
{
"key": "a",
"operator": "Equals",
"value": "a"
}
]
}
}
}
},

View file

@ -14,6 +14,7 @@ import (
"github.com/kyverno/kyverno/pkg/common"
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/utils"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
)
// GenerateJSONPatchesForDefaults generates default JSON patches for
@ -360,7 +361,7 @@ type kyvernoRule struct {
MatchResources *kyverno.MatchResources `json:"match"`
ExcludeResources *kyverno.ExcludeResources `json:"exclude,omitempty"`
Context *[]kyverno.ContextEntry `json:"context,omitempty"`
Conditions *[]kyverno.Condition `json:"preconditions,omitempty"`
AnyAllConditions *apiextensions.JSON `json:"preconditions,omitempty"`
Mutation *kyverno.Mutation `json:"mutate,omitempty"`
Validation *kyverno.Validation `json:"validate,omitempty"`
}
@ -429,8 +430,16 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.
controllerRule.Context = &rule.DeepCopy().Context
}
if len(rule.Conditions) > 0 {
controllerRule.Conditions = &rule.DeepCopy().Conditions
kyvernoAnyAllConditions, _ := utils.ApiextensionsJsonToKyvernoConditions(rule.AnyAllConditions)
switch typedAnyAllConditions := kyvernoAnyAllConditions.(type) {
case kyverno.AnyAllConditions:
if !reflect.DeepEqual(typedAnyAllConditions, kyverno.AnyAllConditions{}) {
controllerRule.AnyAllConditions = &rule.DeepCopy().AnyAllConditions
}
case []kyverno.Condition:
if len(typedAnyAllConditions) > 0 {
controllerRule.AnyAllConditions = &rule.DeepCopy().AnyAllConditions
}
}
if !reflect.DeepEqual(exclude, kyverno.ExcludeResources{}) {

View file

@ -1,6 +1,7 @@
package utils
import (
"encoding/json"
"fmt"
"regexp"
"strconv"
@ -8,10 +9,12 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log"
"github.com/go-logr/logr"
kyverno "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
client "github.com/kyverno/kyverno/pkg/dclient"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"github.com/minio/minio/pkg/wildcard"
"k8s.io/api/admission/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
@ -193,3 +196,23 @@ func SliceContains(slice []string, values ...string) bool {
return false
}
// ApiextensionsJsonTOKyvernoConditions takes in user-provided conditions in abstract apiextensions.JSON form
// and converts it into []kyverno.Condition or kyverno.AnyAllConditions according to its content.
// it also helps in validating the condtions as it returns an error when the conditions are provided wrongfully by the user.
func ApiextensionsJsonToKyvernoConditions(original apiextensions.JSON) (interface{}, error) {
// marshalling the abstract apiextensions.JSON back to JSON form
jsonByte, err := json.Marshal(original)
var kyvernoOldConditions []kyverno.Condition
if err = json.Unmarshal(jsonByte, &kyvernoOldConditions); err == nil {
return kyvernoOldConditions, nil
}
var kyvernoAnyAllConditions kyverno.AnyAllConditions
if err = json.Unmarshal(jsonByte, &kyvernoAnyAllConditions); err == nil {
return kyvernoAnyAllConditions, nil
}
return nil, fmt.Errorf("conditions filled wrongfully")
}