1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 07:26:55 +00:00

feat: add kyverno json support to validation rule (#10763)

* feat: add kyverno json support to validation rule

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* v2beta1

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* validation

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* engine handler

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* bindings

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* context functions

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

* better bindings

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2024-08-02 10:24:30 +02:00 committed by GitHub
parent 5c04256a4a
commit fc694bc24c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 499 additions and 0 deletions

View file

@ -94,6 +94,7 @@ jobs:
- name: v1.30
version: v1.30.0
tests:
- ^assert$
- ^autogen$
- ^background-only$
- ^cleanup$

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
kjson "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
"github.com/kyverno/kyverno/api/kyverno"
"github.com/kyverno/kyverno/pkg/engine/variables/regex"
"github.com/kyverno/kyverno/pkg/pss/utils"
@ -19,6 +20,9 @@ import (
"k8s.io/pod-security-admission/api"
)
// AssertionTree defines a kyverno-json assertion tree.
type AssertionTree = kjson.Any
// FailurePolicyType specifies a failure policy that defines how unrecognized errors from the admission endpoint are handled.
// +kubebuilder:validation:Enum=Ignore;Fail
type FailurePolicyType string
@ -495,6 +499,10 @@ type Validation struct {
// CEL allows validation checks using the Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
// +optional
CEL *CEL `json:"cel,omitempty" yaml:"cel,omitempty"`
// Assert defines a kyverno-json assertion tree.
// +optional
Assert AssertionTree `json:"assert"`
}
// PodSecurity applies exemptions for Kubernetes Pod Security admission

View file

@ -1632,6 +1632,7 @@ func (in *Validation) DeepCopyInto(out *Validation) {
*out = new(CEL)
(*in).DeepCopyInto(*out)
}
in.Assert.DeepCopyInto(&out.Assert)
return
}

View file

@ -1,10 +1,14 @@
package v2beta1
import (
kjson "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
"github.com/kyverno/kyverno/api/kyverno"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
)
// AssertionTree defines a kyverno-json assertion tree.
type AssertionTree = kjson.Any
// Validation defines checks to be performed on matching resources.
type Validation struct {
// ValidationFailureAction defines if a validation policy rule violation should block
@ -55,6 +59,10 @@ type Validation struct {
// CEL allows validation checks using the Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
// +optional
CEL *kyvernov1.CEL `json:"cel,omitempty" yaml:"cel,omitempty"`
// Assert defines a kyverno-json assertion tree.
// +optional
Assert AssertionTree `json:"assert"`
}
// ConditionOperator is the operation performed on condition key and value.

View file

@ -875,6 +875,7 @@ func (in *Validation) DeepCopyInto(out *Validation) {
*out = new(v1.CEL)
(*in).DeepCopyInto(*out)
}
in.Assert.DeepCopyInto(&out.Assert)
return
}

View file

@ -2374,6 +2374,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -6720,6 +6724,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -10815,6 +10824,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -15219,6 +15232,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -2375,6 +2375,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -6722,6 +6726,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -10818,6 +10827,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -15222,6 +15235,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -2368,6 +2368,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -6714,6 +6718,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -10809,6 +10818,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -15213,6 +15226,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -2369,6 +2369,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -6716,6 +6720,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -10812,6 +10821,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -15216,6 +15229,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -2368,6 +2368,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -6714,6 +6718,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -10809,6 +10818,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -15213,6 +15226,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -2369,6 +2369,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -6716,6 +6720,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -10812,6 +10821,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -15216,6 +15229,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -7575,6 +7575,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -11921,6 +11925,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -16016,6 +16025,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -20420,6 +20433,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -25114,6 +25132,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -29461,6 +29483,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -33557,6 +33584,10 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the Common
Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).
@ -37961,6 +37992,11 @@ spec:
AnyPattern specifies list of validation patterns. At least one of the patterns
must be satisfied for the validation rule to succeed.
x-kubernetes-preserve-unknown-fields: true
assert:
description: Assert defines a kyverno-json assertion
tree.
type: object
x-kubernetes-preserve-unknown-fields: true
cel:
description: CEL allows validation checks using the
Common Expression Language (https://kubernetes.io/docs/reference/using-api/cel/).

View file

@ -4570,6 +4570,18 @@ CEL
<p>CEL allows validation checks using the Common Expression Language (<a href="https://kubernetes.io/docs/reference/using-api/cel/">https://kubernetes.io/docs/reference/using-api/cel/</a>).</p>
</td>
</tr>
<tr>
<td>
<code>assert</code><br/>
<em>
github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1.Any
</em>
</td>
<td>
<em>(Optional)</em>
<p>Assert defines a kyverno-json assertion tree.</p>
</td>
</tr>
</tbody>
</table>
<hr />
@ -9328,6 +9340,18 @@ CEL
<p>CEL allows validation checks using the Common Expression Language (<a href="https://kubernetes.io/docs/reference/using-api/cel/">https://kubernetes.io/docs/reference/using-api/cel/</a>).</p>
</td>
</tr>
<tr>
<td>
<code>assert</code><br/>
<em>
github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1.Any
</em>
</td>
<td>
<em>(Optional)</em>
<p>Assert defines a kyverno-json assertion tree.</p>
</td>
</tr>
</tbody>
</table>
<hr />

View file

@ -9164,6 +9164,33 @@ by specifying exclusions for Pod Security Standards controls.</p>
</tr>
<tr>
<td><code>assert</code>
</br>
<span style="font-family: monospace">github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1.Any</span>
</td>
<td>
<p>Assert defines a kyverno-json assertion tree.</p>
</td>
</tr>
</tbody>

View file

@ -4810,6 +4810,33 @@ by specifying exclusions for Pod Security Standards controls.</p>
</tr>
<tr>
<td><code>assert</code>
</br>
<span style="font-family: monospace">github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1.Any</span>
</td>
<td>
<p>Assert defines a kyverno-json assertion tree.</p>
</td>
</tr>
</tbody>

View file

@ -19,6 +19,7 @@ limitations under the License.
package v1
import (
v1alpha1 "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)
@ -36,6 +37,7 @@ type ValidationApplyConfiguration struct {
Deny *DenyApplyConfiguration `json:"deny,omitempty"`
PodSecurity *PodSecurityApplyConfiguration `json:"podSecurity,omitempty"`
CEL *CELApplyConfiguration `json:"cel,omitempty"`
Assert *v1alpha1.Any `json:"assert,omitempty"`
}
// ValidationApplyConfiguration constructs an declarative configuration of the Validation type for use with
@ -133,3 +135,11 @@ func (b *ValidationApplyConfiguration) WithCEL(value *CELApplyConfiguration) *Va
b.CEL = value
return b
}
// WithAssert sets the Assert 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 Assert field is set to the value of the last call.
func (b *ValidationApplyConfiguration) WithAssert(value v1alpha1.Any) *ValidationApplyConfiguration {
b.Assert = &value
return b
}

View file

@ -19,6 +19,7 @@ limitations under the License.
package v2beta1
import (
v1alpha1 "github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1"
kyverno "github.com/kyverno/kyverno/api/kyverno"
v1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov1 "github.com/kyverno/kyverno/pkg/client/applyconfigurations/kyverno/v1"
@ -37,6 +38,7 @@ type ValidationApplyConfiguration struct {
Deny *DenyApplyConfiguration `json:"deny,omitempty"`
PodSecurity *kyvernov1.PodSecurityApplyConfiguration `json:"podSecurity,omitempty"`
CEL *kyvernov1.CELApplyConfiguration `json:"cel,omitempty"`
Assert *v1alpha1.Any `json:"assert,omitempty"`
}
// ValidationApplyConfiguration constructs an declarative configuration of the Validation type for use with
@ -134,3 +136,11 @@ func (b *ValidationApplyConfiguration) WithCEL(value *kyvernov1.CELApplyConfigur
b.CEL = value
return b
}
// WithAssert sets the Assert 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 Assert field is set to the value of the last call.
func (b *ValidationApplyConfiguration) WithAssert(value v1alpha1.Any) *ValidationApplyConfiguration {
b.Assert = &value
return b
}

View file

@ -0,0 +1,124 @@
package validation
import (
"context"
"fmt"
"strings"
"sync"
"github.com/go-logr/logr"
"github.com/jmespath-community/go-jmespath/pkg/binding"
gojmespath "github.com/kyverno/go-jmespath"
"github.com/kyverno/kyverno-json/pkg/engine/assert"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
kyvernov2 "github.com/kyverno/kyverno/api/kyverno/v2"
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/engine/handlers"
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/tools/cache"
)
type lazyBinding struct {
resolver func() (any, error)
}
func (b *lazyBinding) Value() (any, error) {
return b.resolver()
}
func newLazyBinding(jsonContext enginectx.EvalInterface, name string) binding.Binding {
return &lazyBinding{
resolver: sync.OnceValues(func() (any, error) {
return jsonContext.Query(name)
}),
}
}
type validateAssertHandler struct{}
func NewValidateAssertHandler() (handlers.Handler, error) {
return validateAssertHandler{}, nil
}
func (h validateAssertHandler) Process(
ctx context.Context,
logger logr.Logger,
policyContext engineapi.PolicyContext,
resource unstructured.Unstructured,
rule kyvernov1.Rule,
contextLoader engineapi.EngineContextLoader,
exceptions []*kyvernov2.PolicyException,
) (unstructured.Unstructured, []engineapi.RuleResponse) {
// check if there are policy exceptions that match the incoming resource
matchedExceptions := engineutils.MatchesException(exceptions, policyContext, logger)
if len(matchedExceptions) > 0 {
var keys []string
for i, exception := range matchedExceptions {
key, err := cache.MetaNamespaceKeyFunc(&matchedExceptions[i])
if err != nil {
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
return resource, handlers.WithError(rule, engineapi.Validation, "failed to compute exception key", err)
}
keys = append(keys, key)
}
logger.V(3).Info("policy rule is skipped due to policy exceptions", "exceptions", keys)
return resource, handlers.WithResponses(
engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule is skipped due to policy exceptions"+strings.Join(keys, ", ")).WithExceptions(matchedExceptions),
)
}
// load context
jsonContext := policyContext.JSONContext()
jsonContext.Checkpoint()
defer jsonContext.Restore()
if err := contextLoader(ctx, rule.Context, jsonContext); err != nil {
if _, ok := err.(gojmespath.NotFoundError); ok {
logger.V(3).Info("failed to load context", "reason", err.Error())
} else {
logger.Error(err, "failed to load context")
}
return resource, handlers.WithResponses(
engineapi.RuleError(rule.Name, engineapi.Validation, "failed to load context", err),
)
}
// prepare bindings
bindings := binding.NewBindings()
for _, entry := range rule.Context {
bindings = bindings.Register("$"+entry.Name, newLazyBinding(jsonContext, entry.Name))
}
// execute assertion
gvk, subResource := policyContext.ResourceKind()
payload := map[string]any{
"object": policyContext.NewResource().Object,
"oldObject": policyContext.OldResource().Object,
"admissionInfo": policyContext.AdmissionInfo(),
"operation": policyContext.Operation(),
"namespaceLabels": policyContext.NamespaceLabels(),
"admissionOperation": policyContext.AdmissionOperation(),
"requestResource": policyContext.RequestResource(),
"resourceKind": map[string]any{
"group": gvk.Group,
"version": gvk.Version,
"kind": gvk.Kind,
"subResource": subResource,
},
}
asserttion := assert.Parse(ctx, rule.Validation.Assert.Value)
errs, err := assert.Assert(ctx, nil, asserttion, payload, bindings)
if err != nil {
return resource, handlers.WithError(rule, engineapi.Validation, "failed to apply assertion", err)
}
// compose a response
if len(errs) != 0 {
var responses []*engineapi.RuleResponse
for _, err := range errs {
responses = append(responses, engineapi.RuleFail(rule.Name, engineapi.Validation, err.Error()))
}
return resource, handlers.WithResponses(responses...)
}
msg := fmt.Sprintf("Validation rule '%s' passed.", rule.Name)
return resource, handlers.WithResponses(
engineapi.RulePass(rule.Name, engineapi.Validation, msg),
)
}

View file

@ -37,6 +37,9 @@ func (e *engine) validate(
return nil, nil
}
if hasValidate {
if rule.Validation.Assert.Value != nil {
return validation.NewValidateAssertHandler()
}
hasVerifyManifest := rule.HasVerifyManifests()
hasValidatePss := rule.HasValidatePodSecurity()
hasValidateCEL := rule.HasValidateCEL()

View file

@ -170,6 +170,10 @@ func validationElemCount(v *kyvernov1.Validation) int {
count++
}
if v.Assert.Value != nil {
count++
}
return count
}

View file

@ -0,0 +1,11 @@
## Description
This test ensures that request.oldObject is not null on UPDATE operations when there are multiple rules in a policy.
## Expected Behavior
The namespace update operation is allowed.
## Reference Issue(s)
https://github.com/kyverno/kyverno/issues/9885

View file

@ -0,0 +1,23 @@
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Test
metadata:
creationTimestamp: null
name: check-old-object
spec:
steps:
- name: step-01
try:
- create:
file: policy.yaml
- assert:
file: policy-ready.yaml
- name: step-02
try:
- create:
file: ns.yaml
- assert:
file: ns-ready.yaml
- name: step-03
try:
- update:
file: ns-update.yaml

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
kubernetes.io/metadata.name: test
size: large

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
kubernetes.io/metadata.name: test
size: small

View file

@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: test
labels:
kubernetes.io/metadata.name: test
size: large

View file

@ -0,0 +1,4 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-old-object

View file

@ -0,0 +1,48 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: check-old-object
spec:
background: false
rules:
- name: require-labels
match:
all:
- resources:
operations:
- CREATE
- UPDATE
kinds:
- Namespace
context:
- name: small
variable:
value: small
- name: medium
variable:
value: medium
- name: large
variable:
value: large
validate:
validationFailureAction: Enforce
message: "The label `size` is required"
assert:
object:
metadata:
labels:
size:
(@ == $small || @ == $medium || @ == $large): true
- name: check-old-object
match:
all:
- resources:
operations:
- UPDATE
kinds:
- Namespace
validate:
validationFailureAction: Enforce
message: "request.oldObject cannot be null for update requests"
assert:
oldObject: {}