1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

feat: support conditions in PolicyException (#8577)

* feat: support conditions in PolicyException

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* fix matchesException func

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* add codegen-all files

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* fix after review

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* remove variable validation from PolicyException

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* fix after review

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* add kuttl tests

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* remove ValidateVariables() from tests

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* fix errors

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* remove check-variables kuttl test

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* fix after review

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>

* add sleep step to kuttl

Signed-off-by: Rakshit Gondwal <98955085+rakshitgondwal@users.noreply.github.com>

* miinor fix

Signed-off-by: Rakshit Gondwal <98955085+rakshitgondwal@users.noreply.github.com>

* add readme for kuttl test

Signed-off-by: Rakshit Gondwal <98955085+rakshitgondwal@users.noreply.github.com>

---------

Signed-off-by: Rakshit Gondwal <rakshitgondwal3@gmail.com>
Signed-off-by: Rakshit Gondwal <98955085+rakshitgondwal@users.noreply.github.com>
Signed-off-by: Jim Bugwadia <jim@nirmata.com>
Co-authored-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
Co-authored-by: Jim Bugwadia <jim@nirmata.com>
This commit is contained in:
Rakshit Gondwal 2023-10-24 16:15:52 +05:30 committed by GitHub
parent 3af6862f51
commit b574802c12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 995 additions and 116 deletions

View file

@ -16,10 +16,7 @@ limitations under the License.
package v2alpha1
import (
"fmt"
kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1"
"github.com/kyverno/kyverno/pkg/engine/variables/regex"
"k8s.io/apimachinery/pkg/util/validation/field"
)
@ -34,17 +31,10 @@ type PolicyException kyvernov2beta1.PolicyException
// Validate implements programmatic validation
func (p *PolicyException) Validate() (errs field.ErrorList) {
if err := ValidateVariables(p); err != nil {
errs = append(errs, field.Forbidden(field.NewPath(""), fmt.Sprintf("Policy Exception \"%s\" should not have variables", p.Name)))
}
errs = append(errs, p.Spec.Validate(field.NewPath("spec"))...)
return errs
}
func ValidateVariables(polex *PolicyException) error {
return regex.ObjectHasVariables(polex)
}
// Contains returns true if it contains an exception for the given policy/rule pair
func (p *PolicyException) Contains(policy string, rule string) bool {
return p.Spec.Contains(policy, rule)

View file

@ -16,9 +16,6 @@ limitations under the License.
package v2beta1
import (
"fmt"
"github.com/kyverno/kyverno/pkg/engine/variables/regex"
"github.com/kyverno/kyverno/pkg/utils/wildcard"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
@ -41,17 +38,10 @@ type PolicyException struct {
// Validate implements programmatic validation
func (p *PolicyException) Validate() (errs field.ErrorList) {
if err := ValidateVariables(p); err != nil {
errs = append(errs, field.Forbidden(field.NewPath(""), fmt.Sprintf("Policy Exception \"%s\" should not have variables", p.Name)))
}
errs = append(errs, p.Spec.Validate(field.NewPath("spec"))...)
return errs
}
func ValidateVariables(polex *PolicyException) error {
return regex.ObjectHasVariables(polex)
}
// Contains returns true if it contains an exception for the given policy/rule pair
func (p *PolicyException) Contains(policy string, rule string) bool {
return p.Spec.Contains(policy, rule)
@ -67,6 +57,11 @@ type PolicyExceptionSpec struct {
// Match defines match clause used to check if a resource applies to the exception
Match MatchResources `json:"match" yaml:"match"`
// Conditions are used to determine if a resource applies to the exception by evaluating a
// set of conditions. The declaration can contain nested `any` or `all` statements.
// +optional
Conditions *AnyAllConditions `json:"conditions,omitempty"`
// Exceptions is a list policy/rules to be excluded
Exceptions []Exception `json:"exceptions" yaml:"exceptions"`
}

View file

@ -535,6 +535,11 @@ func (in *PolicyExceptionSpec) DeepCopyInto(out *PolicyExceptionSpec) {
**out = **in
}
in.Match.DeepCopyInto(&out.Match)
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = new(AnyAllConditions)
(*in).DeepCopyInto(*out)
}
if in.Exceptions != nil {
in, out := &in.Exceptions, &out.Exceptions
*out = make([]Exception, len(*in))

View file

@ -41310,6 +41310,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:
@ -41809,6 +41901,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:

View file

@ -47,6 +47,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:
@ -546,6 +638,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:

View file

@ -47,6 +47,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:
@ -546,6 +638,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:

View file

@ -41533,6 +41533,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:
@ -42032,6 +42124,98 @@ spec:
that are only available in the admission review request (e.g. user
name).
type: boolean
conditions:
description: Conditions are used to determine if a resource applies
to the exception by evaluating a set of conditions. The declaration
can contain nested `any` or `all` statements.
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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 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:
properties:
key:
description: Key is the context entry (using JMESPath) for
conditional rule evaluation.
x-kubernetes-preserve-unknown-fields: true
message:
description: Message is an optional display message
type: string
operator:
description: 'Operator is the conditional operation to perform.
Valid operators are: Equals, NotEquals, In, AnyIn, AllIn,
NotIn, AnyNotIn, AllNotIn, GreaterThanOrEquals, GreaterThan,
LessThanOrEquals, LessThan, DurationGreaterThanOrEquals,
DurationGreaterThan, DurationLessThanOrEquals, DurationLessThan'
enum:
- Equals
- NotEquals
- AnyIn
- AllIn
- AnyNotIn
- AllNotIn
- 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 JMESPath.
x-kubernetes-preserve-unknown-fields: true
type: object
type: array
type: object
exceptions:
description: Exceptions is a list policy/rules to be excluded
items:

View file

@ -5795,6 +5795,21 @@ MatchResources
</tr>
<tr>
<td>
<code>conditions</code><br/>
<em>
<a href="#kyverno.io/v2beta1.AnyAllConditions">
AnyAllConditions
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Conditions are used to determine if a resource applies to the exception by evaluating a
set of conditions. The declaration can contain nested <code>any</code> or <code>all</code> statements.</p>
</td>
</tr>
<tr>
<td>
<code>exceptions</code><br/>
<em>
<a href="#kyverno.io/v2beta1.Exception">
@ -6742,6 +6757,21 @@ MatchResources
</tr>
<tr>
<td>
<code>conditions</code><br/>
<em>
<a href="#kyverno.io/v2beta1.AnyAllConditions">
AnyAllConditions
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Conditions are used to determine if a resource applies to the exception by evaluating a
set of conditions. The declaration can contain nested <code>any</code> or <code>all</code> statements.</p>
</td>
</tr>
<tr>
<td>
<code>exceptions</code><br/>
<em>
<a href="#kyverno.io/v2beta1.Exception">
@ -6765,6 +6795,7 @@ MatchResources
(<em>Appears on:</em>
<a href="#kyverno.io/v2beta1.CleanupPolicySpec">CleanupPolicySpec</a>,
<a href="#kyverno.io/v2beta1.Deny">Deny</a>,
<a href="#kyverno.io/v2beta1.PolicyExceptionSpec">PolicyExceptionSpec</a>,
<a href="#kyverno.io/v2beta1.Rule">Rule</a>)
</p>
<p>
@ -7363,6 +7394,21 @@ MatchResources
</tr>
<tr>
<td>
<code>conditions</code><br/>
<em>
<a href="#kyverno.io/v2beta1.AnyAllConditions">
AnyAllConditions
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Conditions are used to determine if a resource applies to the exception by evaluating a
set of conditions. The declaration can contain nested <code>any</code> or <code>all</code> statements.</p>
</td>
</tr>
<tr>
<td>
<code>exceptions</code><br/>
<em>
<a href="#kyverno.io/v2beta1.Exception">

View file

@ -21,9 +21,10 @@ package v2beta1
// PolicyExceptionSpecApplyConfiguration represents an declarative configuration of the PolicyExceptionSpec type for use
// with apply.
type PolicyExceptionSpecApplyConfiguration struct {
Background *bool `json:"background,omitempty"`
Match *MatchResourcesApplyConfiguration `json:"match,omitempty"`
Exceptions []ExceptionApplyConfiguration `json:"exceptions,omitempty"`
Background *bool `json:"background,omitempty"`
Match *MatchResourcesApplyConfiguration `json:"match,omitempty"`
Conditions *AnyAllConditionsApplyConfiguration `json:"conditions,omitempty"`
Exceptions []ExceptionApplyConfiguration `json:"exceptions,omitempty"`
}
// PolicyExceptionSpecApplyConfiguration constructs an declarative configuration of the PolicyExceptionSpec type for use with
@ -48,6 +49,14 @@ func (b *PolicyExceptionSpecApplyConfiguration) WithMatch(value *MatchResourcesA
return b
}
// WithConditions sets the Conditions field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Conditions field is set to the value of the last call.
func (b *PolicyExceptionSpecApplyConfiguration) WithConditions(value *AnyAllConditionsApplyConfiguration) *PolicyExceptionSpecApplyConfiguration {
b.Conditions = value
return b
}
// WithExceptions adds the given value to the Exceptions field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Exceptions field.

View file

@ -22,6 +22,7 @@ import (
"github.com/kyverno/kyverno/pkg/event"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/metrics"
"github.com/kyverno/kyverno/pkg/utils/conditions"
controllerutils "github.com/kyverno/kyverno/pkg/utils/controller"
"github.com/kyverno/kyverno/pkg/utils/match"
"go.opentelemetry.io/otel"
@ -280,7 +281,7 @@ func (c *controller) cleanup(ctx context.Context, logger logr.Logger, policy kyv
errs = append(errs, err)
continue
}
passed, err := checkAnyAllConditions(logger, enginectx, *spec.Conditions)
passed, err := conditions.CheckAnyAllConditions(logger, enginectx, *spec.Conditions)
if err != nil {
debug.Error(err, "failed to check condition")
errs = append(errs, err)

View file

@ -7,6 +7,7 @@ import (
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
"github.com/kyverno/kyverno/pkg/utils/conditions"
matched "github.com/kyverno/kyverno/pkg/utils/match"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
@ -42,6 +43,7 @@ func matchesException(
selector engineapi.PolicyExceptionSelector,
policyContext engineapi.PolicyContext,
rule kyvernov1.Rule,
logger logr.Logger,
) (*kyvernov2beta1.PolicyException, error) {
candidates, err := findExceptions(selector, policyContext.Policy(), rule.Name)
if err != nil {
@ -63,6 +65,15 @@ func matchesException(
)
// if there's no error it means a match
if err == nil {
if candidate.Spec.Conditions != nil {
passed, err := conditions.CheckAnyAllConditions(logger, policyContext.JSONContext(), *candidate.Spec.Conditions)
if err != nil {
return nil, err
}
if !passed {
return nil, fmt.Errorf("conditions did not pass")
}
}
return candidate, nil
}
}
@ -78,7 +89,7 @@ func (e *engine) hasPolicyExceptions(
rule kyvernov1.Rule,
) *engineapi.RuleResponse {
// if matches, check if there is a corresponding policy exception
exception, err := matchesException(e.exceptionSelector, ctx, rule)
exception, err := matchesException(e.exceptionSelector, ctx, rule, logger)
if err != nil {
logger.Error(err, "failed to match exceptions")
return nil

View file

@ -1,4 +1,4 @@
package cleanup
package conditions
import (
"fmt"
@ -11,7 +11,7 @@ import (
"github.com/kyverno/kyverno/pkg/engine/variables/operator"
)
func checkAnyAllConditions(logger logr.Logger, ctx enginecontext.Interface, condition kyvernov2beta1.AnyAllConditions) (bool, error) {
func CheckAnyAllConditions(logger logr.Logger, ctx enginecontext.Interface, condition kyvernov2beta1.AnyAllConditions) (bool, error) {
for _, condition := range condition.AllConditions {
if passed, err := checkCondition(logger, ctx, condition); err != nil {
return false, err

View file

@ -1,4 +1,4 @@
package cleanup
package conditions
import (
"testing"

View file

@ -4,7 +4,6 @@ import (
"context"
"testing"
"github.com/kyverno/kyverno/api/kyverno/v2beta1"
"github.com/kyverno/kyverno/pkg/logging"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
"gotest.tools/assert"
@ -75,34 +74,3 @@ func Test_Validate(t *testing.T) {
})
}
}
func Test_ValidateVariables(t *testing.T) {
tc := []struct {
name string
resource []byte
error bool
}{
{
name: "Variable used.",
resource: []byte(`{"apiVersion":"kyverno.io/v2beta1","kind":"PolicyException","metadata":{"name":"enforce-label-polex"},"spec":{"background":true,"exceptions":[{"policyName":"enforce-label","ruleNames":["enforce-label"]}],"match":{"any":[{"resources":{"kinds":["Pod"],"namespaces":["{{request.object.name}}"],"names":["{{request.userInfo.username}}"]}}]}}}`),
error: true,
},
{
name: "Variable not used.",
resource: []byte(`{"apiVersion":"kyverno.io/v2beta1","kind":"PolicyException","metadata":{"name":"enforce-label-polex"},"spec":{"background":true,"exceptions":[{"policyName":"enforce-label","ruleNames":["enforce-label"]}],"match":{"any":[{"resources":{"kinds":["Pod"]}}]}}}`),
error: false,
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
polex, err := admissionutils.UnmarshalPolicyException(c.resource)
assert.NilError(t, err)
err = v2beta1.ValidateVariables(polex)
if c.error {
assert.Assert(t, err != nil)
} else {
assert.Assert(t, err)
}
})
}
}

View file

@ -1,10 +0,0 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- file: exception-allowed.yaml
- file: exception-rejected.yaml
shouldFail: true
assert:
- exception-allowed.yaml
error:
- exception-rejected.yaml

View file

@ -1,11 +0,0 @@
## Description
This test creates policy exceptions with the `spec.background` field. It tests the usage of variables in exceptions.
## Expected Behavior
The polex-right is expected to be created but the polex-wrong should fail due to having variables.
## Reference Issue(s)
https://github.com/kyverno/kyverno/issues/5949

View file

@ -1,18 +0,0 @@
apiVersion: kyverno.io/v2beta1
kind: PolicyException
metadata:
name: polex-right
spec:
background: false
exceptions:
- policyName: test
ruleNames:
- test
match:
any:
- resources:
kinds:
- Pods
subjects:
- kind: User
name: chip

View file

@ -1,17 +0,0 @@
apiVersion: kyverno.io/v2beta1
kind: PolicyException
metadata:
name: polex-wrong
spec:
background: true
exceptions:
- policyName: test
ruleNames:
- test
match:
any:
- resources:
kinds:
- Pods
names:
- "{{ request.userInfo.username }}"

View file

@ -0,0 +1,4 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- policy.yaml

View file

@ -0,0 +1,4 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- exception.yaml

View file

@ -0,0 +1,7 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
apply:
- file: good-deployment.yaml
shouldFail: false
- file: bad-deployment.yaml
shouldFail: true

View file

@ -0,0 +1,4 @@
apiVersion: kuttl.dev/v1beta1
kind: TestStep
commands:
- command: sleep 4

View file

@ -0,0 +1,12 @@
## Description
This test creates a policy that only allows a maximum of 3 containers inside a pod. It then creates an exception with `conditions` field defined which tests out the functionality for the conditions support in `PolicyException`.
## Expected Behavior
If the exception is not applied, both the deployments `bad-deployment` and `good-deployment` should not be allowed but when the exception has been applied, `good-deployment` should be able to pass through the Policy as it satisfies the conditions mentioned in the `PolicyException`.
## Reference Issue(s)
https://github.com/kyverno/kyverno/issues/6223

View file

@ -0,0 +1,49 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: bad-deployment
labels:
app: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
resources:
limits:
cpu: "1"
memory: "256Mi"
requests:
cpu: "0.5"
memory: "128Mi"
- name: redis-container
image: redis:latest
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.5"
memory: "512Mi"
requests:
cpu: "0.25"
memory: "256Mi"
- name: busybox-container
image: busybox:latest
command: ["/bin/sh", "-c", "while true; do echo 'Hello from BusyBox'; sleep 10; done"]
resources:
limits:
cpu: "0.5"
memory: "128Mi"
requests:
cpu: "0.25"
memory: "64Mi"

View file

@ -0,0 +1,21 @@
apiVersion: kyverno.io/v2beta1
kind: PolicyException
metadata:
name: container-exception
spec:
exceptions:
- policyName: max-containers
ruleNames:
- max-two-containers
- autogen-max-two-containers
match:
any:
- resources:
kinds:
- Pod
- Deployment
conditions:
any:
- key: "{{ request.object.metadata.labels.color || '' }}"
operator: Equals
value: blue

View file

@ -0,0 +1,51 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: good-deployment
labels:
app: my-app
color: blue
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
color: blue
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
resources:
limits:
cpu: "1"
memory: "256Mi"
requests:
cpu: "0.5"
memory: "128Mi"
- name: redis-container
image: redis:latest
ports:
- containerPort: 6379
resources:
limits:
cpu: "0.5"
memory: "512Mi"
requests:
cpu: "0.25"
memory: "256Mi"
- name: busybox-container
image: busybox:latest
command: ["/bin/sh", "-c", "while true; do echo 'Hello from BusyBox'; sleep 10; done"]
resources:
limits:
cpu: "0.5"
memory: "128Mi"
requests:
cpu: "0.25"
memory: "64Mi"

View file

@ -0,0 +1,22 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: max-containers
spec:
validationFailureAction: Enforce
background: false
rules:
- name: max-two-containers
match:
any:
- resources:
kinds:
- Pod
validate:
message: "A maximum of 2 containers are allowed inside a Pod."
deny:
conditions:
any:
- key: "{{request.object.spec.containers[] | length(@)}}"
operator: GreaterThan
value: "2"