1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

feat: use pointer in rule (validate field) (#11095) (#11099)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
gcp-cherry-pick-bot[bot] 2024-09-11 09:38:20 +00:00 committed by GitHub
parent 632e3f5a4d
commit 0959cb68f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 206 additions and 201 deletions

View file

@ -93,7 +93,7 @@ type Rule struct {
// Validation is used to validate matching resources.
// +optional
Validation Validation `json:"validate,omitempty"`
Validation *Validation `json:"validate,omitempty"`
// Generation is used to create new resources.
// +optional
@ -164,35 +164,33 @@ func (r *Rule) HasVerifyImageChecks() bool {
// HasVerifyManifests checks for validate.manifests rule
func (r Rule) HasVerifyManifests() bool {
return r.Validation.Manifests != nil && len(r.Validation.Manifests.Attestors) != 0
return r.Validation != nil && r.Validation.Manifests != nil && len(r.Validation.Manifests.Attestors) != 0
}
// HasValidatePodSecurity checks for validate.podSecurity rule
func (r Rule) HasValidatePodSecurity() bool {
return r.Validation.PodSecurity != nil && !datautils.DeepEqual(r.Validation.PodSecurity, &PodSecurity{})
return r.Validation != nil && r.Validation.PodSecurity != nil && !datautils.DeepEqual(*r.Validation.PodSecurity, PodSecurity{})
}
// HasValidateCEL checks for validate.cel rule
func (r *Rule) HasValidateCEL() bool {
return r.Validation.CEL != nil && !datautils.DeepEqual(r.Validation.CEL, &CEL{})
return r.Validation != nil && r.Validation.CEL != nil && !datautils.DeepEqual(*r.Validation.CEL, CEL{})
}
// HasValidateAssert checks for validate.assert rule
func (r *Rule) HasValidateAssert() bool {
return !datautils.DeepEqual(r.Validation.Assert, AssertionTree{})
return r.Validation != nil && !datautils.DeepEqual(r.Validation.Assert, AssertionTree{})
}
// HasValidate checks for validate rule
func (r *Rule) HasValidate() bool {
return !datautils.DeepEqual(r.Validation, Validation{})
return r.Validation != nil && !datautils.DeepEqual(*r.Validation, Validation{})
}
// HasValidateAllowExistingViolations() checks for allowExisitingViolations under validate rule
func (r *Rule) HasValidateAllowExistingViolations() bool {
var allowExisitingViolations bool
if r.Validation.AllowExistingViolations == nil {
allowExisitingViolations = true
} else {
allowExisitingViolations := true
if r.Validation != nil && r.Validation.AllowExistingViolations != nil {
allowExisitingViolations = *r.Validation.AllowExistingViolations
}
return allowExisitingViolations
@ -204,7 +202,7 @@ func (r *Rule) HasGenerate() bool {
}
func (r *Rule) IsPodSecurity() bool {
return r.Validation.PodSecurity != nil
return r.Validation != nil && r.Validation.PodSecurity != nil
}
func (r *Rule) GetSyncAndOrphanDownstream() (sync bool, orphanDownstream bool) {
@ -243,7 +241,6 @@ func (r *Rule) ValidateRuleType(path *field.Path) (errs field.ErrorList) {
} else if count != 1 {
errs = append(errs, field.Invalid(path, r, fmt.Sprintf("Multiple operations defined in the rule '%s', only one operation (mutate,validate,generate,verifyImages) is allowed per rule", r.Name)))
}
if r.ImageExtractors != nil && !r.HasVerifyImages() {
errs = append(errs, field.Invalid(path.Child("imageExtractors"), r, fmt.Sprintf("Invalid rule spec for rule '%s', imageExtractors can only be defined for verifyImages rule", r.Name)))
}

View file

@ -19,7 +19,7 @@ func Test_Validate_UniqueRuleName(t *testing.T) {
},
},
},
Validation: Validation{
Validation: &Validation{
Message: "message",
RawAnyPattern: &apiextv1.JSON{
Raw: []byte("{"),
@ -34,7 +34,7 @@ func Test_Validate_UniqueRuleName(t *testing.T) {
},
},
},
Validation: Validation{
Validation: &Validation{
Message: "message",
RawAnyPattern: &apiextv1.JSON{
Raw: []byte("{"),

View file

@ -1430,7 +1430,11 @@ func (in *Rule) DeepCopyInto(out *Rule) {
*out = new(Mutation)
(*in).DeepCopyInto(*out)
}
in.Validation.DeepCopyInto(&out.Validation)
if in.Validation != nil {
in, out := &in.Validation, &out.Validation
*out = new(Validation)
(*in).DeepCopyInto(*out)
}
if in.Generation != nil {
in, out := &in.Generation, &out.Generation
*out = new(Generation)

View file

@ -56,7 +56,7 @@ type Rule struct {
// Validation is used to validate matching resources.
// +optional
Validation Validation `json:"validate,omitempty"`
Validation *Validation `json:"validate,omitempty"`
// Generation is used to create new resources.
// +optional
@ -114,22 +114,22 @@ func (r *Rule) HasVerifyImageChecks() bool {
// HasVerifyManifests checks for validate.manifests rule
func (r Rule) HasVerifyManifests() bool {
return r.Validation.Manifests != nil && len(r.Validation.Manifests.Attestors) != 0
return r.Validation != nil && r.Validation.Manifests != nil && len(r.Validation.Manifests.Attestors) != 0
}
// HasValidatePodSecurity checks for validate.podSecurity rule
func (r Rule) HasValidatePodSecurity() bool {
return r.Validation.PodSecurity != nil && !datautils.DeepEqual(r.Validation.PodSecurity, &kyvernov1.PodSecurity{})
return r.Validation != nil && r.Validation.PodSecurity != nil && !datautils.DeepEqual(*r.Validation.PodSecurity, kyvernov1.PodSecurity{})
}
// HasValidateCEL checks for validate.cel rule
func (r *Rule) HasValidateCEL() bool {
return r.Validation.CEL != nil && !datautils.DeepEqual(r.Validation.CEL, &kyvernov1.CEL{})
return r.Validation != nil && r.Validation.CEL != nil && !datautils.DeepEqual(*r.Validation.CEL, kyvernov1.CEL{})
}
// HasValidate checks for validate rule
func (r *Rule) HasValidate() bool {
return !datautils.DeepEqual(r.Validation, Validation{})
return r.Validation != nil && !datautils.DeepEqual(*r.Validation, Validation{})
}
// HasGenerate checks for generate rule
@ -151,7 +151,6 @@ func (r *Rule) ValidateRuleType(path *field.Path) (errs field.ErrorList) {
} else if count != 1 {
errs = append(errs, field.Invalid(path, r, fmt.Sprintf("Multiple operations defined in the rule '%s', only one operation (mutate,validate,generate,verifyImages) is allowed per rule", r.Name)))
}
if r.ImageExtractors != nil && !r.HasVerifyImages() {
errs = append(errs, field.Invalid(path.Child("imageExtractors"), r, fmt.Sprintf("Invalid rule spec for rule '%s', imageExtractors can only be defined for verifyImages rule", r.Name)))
}
@ -190,7 +189,6 @@ func (r *Rule) ValidateGenerate(path *field.Path, namespaced bool, policyNamespa
if !r.HasGenerate() {
return nil
}
return r.Generation.Validate(path, namespaced, policyNamespace, clusterResources)
}

View file

@ -22,7 +22,7 @@ func Test_Validate_UniqueRuleName(t *testing.T) {
},
}},
},
Validation: Validation{
Validation: &Validation{
Message: "message",
RawAnyPattern: kyverno.ToAny("{"),
},
@ -36,7 +36,7 @@ func Test_Validate_UniqueRuleName(t *testing.T) {
},
}},
}},
Validation: Validation{
Validation: &Validation{
Message: "message",
RawAnyPattern: kyverno.ToAny("{"),
},

View file

@ -747,7 +747,11 @@ func (in *Rule) DeepCopyInto(out *Rule) {
*out = new(v1.Mutation)
(*in).DeepCopyInto(*out)
}
in.Validation.DeepCopyInto(&out.Validation)
if in.Validation != nil {
in, out := &in.Validation, &out.Validation
*out = new(Validation)
(*in).DeepCopyInto(*out)
}
if in.Generation != nil {
in, out := &in.Generation, &out.Generation
*out = new(v1.Generation)

View file

@ -233,7 +233,7 @@ func convertRule(rule kyvernoRule, kind string) (*kyvernov1.Rule, error) {
out.Mutation = rule.Mutation
}
if rule.Validation != nil {
out.Validation = *rule.Validation
out.Validation = rule.Validation
}
return &out, nil
}

View file

@ -48,7 +48,7 @@ func createRule(rule *kyvernov1.Rule) *kyvernoRule {
if rule.Mutation != nil && !datautils.DeepEqual(*rule.Mutation, kyvernov1.Mutation{}) {
jsonFriendlyStruct.Mutation = rule.Mutation.DeepCopy()
}
if !datautils.DeepEqual(rule.Validation, kyvernov1.Validation{}) {
if rule.Validation != nil && !datautils.DeepEqual(*rule.Validation, kyvernov1.Validation{}) {
jsonFriendlyStruct.Validation = rule.Validation.DeepCopy()
}
kyvernoAnyAllConditions := rule.GetAnyAllConditions()
@ -131,84 +131,95 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
return rule
}
}
if target := rule.Validation.GetPattern(); target != nil {
newValidate := kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"),
FailureAction: rule.Validation.FailureAction,
FailureActionOverrides: rule.Validation.FailureActionOverrides,
}
newValidate.SetPattern(
map[string]interface{}{
"spec": map[string]interface{}{
tplKey: target,
},
},
)
rule.Validation = newValidate
return rule
}
if rule.Validation.Deny != nil {
deny := kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "deny"),
Deny: rule.Validation.Deny,
FailureAction: rule.Validation.FailureAction,
FailureActionOverrides: rule.Validation.FailureActionOverrides,
}
rule.Validation = deny
return rule
}
if rule.Validation.PodSecurity != nil {
newExclude := make([]kyvernov1.PodSecurityStandard, len(rule.Validation.PodSecurity.Exclude))
copy(newExclude, rule.Validation.PodSecurity.Exclude)
podSecurity := kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "podSecurity"),
PodSecurity: &kyvernov1.PodSecurity{
Level: rule.Validation.PodSecurity.Level,
Version: rule.Validation.PodSecurity.Version,
Exclude: newExclude,
},
FailureAction: rule.Validation.FailureAction,
FailureActionOverrides: rule.Validation.FailureActionOverrides,
}
rule.Validation = podSecurity
return rule
}
if rule.Validation.GetAnyPattern() != nil {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
logger.Error(err, "failed to deserialize anyPattern, expect type array")
}
var patterns []interface{}
for _, pattern := range anyPatterns {
newPattern := map[string]interface{}{
"spec": map[string]interface{}{
tplKey: pattern,
},
if rule.Validation != nil {
if target := rule.Validation.GetPattern(); target != nil {
newValidate := &kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"),
FailureAction: rule.Validation.FailureAction,
FailureActionOverrides: rule.Validation.FailureActionOverrides,
}
patterns = append(patterns, newPattern)
newValidate.SetPattern(
map[string]interface{}{
"spec": map[string]interface{}{
tplKey: target,
},
},
)
rule.Validation = newValidate
return rule
}
failureAction := rule.Validation.FailureAction
failureActionOverrides := rule.Validation.FailureActionOverrides
rule.Validation = kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "anyPattern"),
FailureAction: failureAction,
FailureActionOverrides: failureActionOverrides,
if rule.Validation.Deny != nil {
deny := &kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "deny"),
Deny: rule.Validation.Deny,
FailureAction: rule.Validation.FailureAction,
FailureActionOverrides: rule.Validation.FailureActionOverrides,
}
rule.Validation = deny
return rule
}
rule.Validation.SetAnyPattern(patterns)
return rule
}
if len(rule.Validation.ForEachValidation) > 0 && rule.Validation.ForEachValidation != nil {
newForeachValidate := make([]kyvernov1.ForEachValidation, len(rule.Validation.ForEachValidation))
copy(newForeachValidate, rule.Validation.ForEachValidation)
failureAction := rule.Validation.FailureAction
failureActionOverrides := rule.Validation.FailureActionOverrides
rule.Validation = kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"),
ForEachValidation: newForeachValidate,
FailureAction: failureAction,
FailureActionOverrides: failureActionOverrides,
if rule.Validation.PodSecurity != nil {
newExclude := make([]kyvernov1.PodSecurityStandard, len(rule.Validation.PodSecurity.Exclude))
copy(newExclude, rule.Validation.PodSecurity.Exclude)
podSecurity := &kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "podSecurity"),
PodSecurity: &kyvernov1.PodSecurity{
Level: rule.Validation.PodSecurity.Level,
Version: rule.Validation.PodSecurity.Version,
Exclude: newExclude,
},
FailureAction: rule.Validation.FailureAction,
FailureActionOverrides: rule.Validation.FailureActionOverrides,
}
rule.Validation = podSecurity
return rule
}
if rule.Validation.GetAnyPattern() != nil {
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
logger.Error(err, "failed to deserialize anyPattern, expect type array")
}
var patterns []interface{}
for _, pattern := range anyPatterns {
newPattern := map[string]interface{}{
"spec": map[string]interface{}{
tplKey: pattern,
},
}
patterns = append(patterns, newPattern)
}
failureAction := rule.Validation.FailureAction
failureActionOverrides := rule.Validation.FailureActionOverrides
rule.Validation = &kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "anyPattern"),
FailureAction: failureAction,
FailureActionOverrides: failureActionOverrides,
}
rule.Validation.SetAnyPattern(patterns)
return rule
}
if len(rule.Validation.ForEachValidation) > 0 && rule.Validation.ForEachValidation != nil {
newForeachValidate := make([]kyvernov1.ForEachValidation, len(rule.Validation.ForEachValidation))
copy(newForeachValidate, rule.Validation.ForEachValidation)
failureAction := rule.Validation.FailureAction
failureActionOverrides := rule.Validation.FailureActionOverrides
rule.Validation = &kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"),
ForEachValidation: newForeachValidate,
FailureAction: failureAction,
FailureActionOverrides: failureActionOverrides,
}
return rule
}
if rule.HasValidateCEL() {
cel := rule.Validation.CEL.DeepCopy()
rule.Validation.CEL = cel
return rule
}
if rule.HasValidateAssert() {
rule.Validation.Assert = createAutogenAssertion(*rule.Validation.Assert.DeepCopy(), tplKey)
return rule
}
return rule
}
if rule.VerifyImages != nil {
newVerifyImages := make([]kyvernov1.ImageVerification, len(rule.VerifyImages))
@ -218,16 +229,6 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
rule.VerifyImages = newVerifyImages
return rule
}
if rule.HasValidateCEL() {
cel := rule.Validation.CEL.DeepCopy()
rule.Validation.CEL = cel
return rule
}
if rule.HasValidateAssert() {
rule.Validation.Assert = createAutogenAssertion(*rule.Validation.Assert.DeepCopy(), tplKey)
return rule
}
return nil
}

View file

@ -716,7 +716,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &audit,
},
},
@ -731,7 +731,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
},
},
@ -772,7 +772,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -791,7 +791,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: "invalid",
@ -969,7 +969,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -989,7 +989,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -1012,7 +1012,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -1039,7 +1039,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -1066,7 +1066,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -1094,7 +1094,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -1122,7 +1122,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,
@ -1150,7 +1150,7 @@ func TestEngineResponse_GetValidationFailureAction(t *testing.T) {
Spec: kyvernov1.Spec{
Rules: []kyvernov1.Rule{
{
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
FailureActionOverrides: []kyvernov1.ValidationFailureActionOverride{{
Action: kyvernov1.Audit,

View file

@ -23,7 +23,7 @@ func ParsePolicyBackgroundMode(policy kyvernov1.PolicyInterface) PolicyBackgroun
}
func ParseRuleType(rule kyvernov1.Rule) RuleType {
if !datautils.DeepEqual(rule.Validation, kyvernov1.Validation{}) {
if rule.Validation != nil && !datautils.DeepEqual(*rule.Validation, kyvernov1.Validation{}) {
return Validate
}
if rule.Mutation != nil && !datautils.DeepEqual(*rule.Mutation, kyvernov1.Mutation{}) {

View file

@ -32,7 +32,7 @@ func NewValidateFactory(rule *kyvernov1.Rule, client dclient.Interface, mock boo
return &Validate{
rule: rule,
validationRule: &rule.Validation,
validationRule: rule.Validation,
authChecker: authChecker,
}
}
@ -40,7 +40,7 @@ func NewValidateFactory(rule *kyvernov1.Rule, client dclient.Interface, mock boo
func NewMockValidateFactory(rule *kyvernov1.Rule) *Validate {
return &Validate{
rule: rule,
validationRule: &rule.Validation,
validationRule: rule.Validation,
authChecker: fake.NewFakeAuth(),
}
}

View file

@ -31,7 +31,7 @@ func Test_Validate_OverlayPattern_Nil_PatternAnypattern(t *testing.T) {
var validation kyverno.Validation
err := json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -69,7 +69,7 @@ func Test_Validate_OverlayPattern_Exist_PatternAnypattern(t *testing.T) {
var validation kyverno.Validation
err := json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -107,7 +107,7 @@ func Test_Validate_OverlayPattern_Valid(t *testing.T) {
var validation kyverno.Validation
err := json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.NilError(t, err)
}
@ -140,7 +140,7 @@ func Test_Validate_ExistingAnchor_AnchorOnMap(t *testing.T) {
var validation kyverno.Validation
err := json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -170,7 +170,7 @@ func Test_Validate_ExistingAnchor_AnchorOnString(t *testing.T) {
var validation kyverno.Validation
err := json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -203,7 +203,7 @@ func Test_Validate_ExistingAnchor_Valid(t *testing.T) {
err = json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -228,7 +228,7 @@ func Test_Validate_ExistingAnchor_Valid(t *testing.T) {
} `)
err = json.Unmarshal(rawValidation, &validation)
assert.NilError(t, err)
checker = NewMockValidateFactory(&kyverno.Rule{Validation: validation})
checker = NewMockValidateFactory(&kyverno.Rule{Validation: &validation})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -269,7 +269,7 @@ func Test_Validate_Validate_ValidAnchor(t *testing.T) {
err = json.Unmarshal(rawValidate, &validate)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validate})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validate})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.NilError(t, err)
}
@ -291,7 +291,7 @@ func Test_Validate_Validate_ValidAnchor(t *testing.T) {
err = json.Unmarshal(rawValidate, &validate)
assert.NilError(t, err)
checker = NewMockValidateFactory(&kyverno.Rule{Validation: validate})
checker = NewMockValidateFactory(&kyverno.Rule{Validation: &validate})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.NilError(t, err)
}
@ -318,7 +318,7 @@ func Test_Validate_Validate_Mismatched(t *testing.T) {
var validate kyverno.Validation
err := json.Unmarshal(rawValidate, &validate)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validate})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validate})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -348,7 +348,7 @@ func Test_Validate_Validate_Unsupported(t *testing.T) {
err = json.Unmarshal(rawValidate, &validate)
assert.NilError(t, err)
checker := NewMockValidateFactory(&kyverno.Rule{Validation: validate})
checker := NewMockValidateFactory(&kyverno.Rule{Validation: &validate})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}
@ -374,7 +374,7 @@ func Test_Validate_Validate_Unsupported(t *testing.T) {
err = json.Unmarshal(rawValidate, &validate)
assert.NilError(t, err)
checker = NewMockValidateFactory(&kyverno.Rule{Validation: validate})
checker = NewMockValidateFactory(&kyverno.Rule{Validation: &validate})
if _, _, err := checker.Validate(context.TODO(), nil); err != nil {
assert.Assert(t, err != nil)
}

View file

@ -233,7 +233,7 @@ func createRule(f *fuzz.ConsumeFuzzer) (*kyvernov1.Rule, error) {
if err != nil {
return rule, err
}
rule.Validation = *v
rule.Validation = v
}
setGeneration, err := f.GetBool()

View file

@ -738,8 +738,10 @@ func buildContext(rule *kyvernov1.Rule, background bool, target bool) *enginecon
addContextVariables(rule.Context, ctx)
addImageVerifyVariables(rule, ctx)
for _, fe := range rule.Validation.ForEachValidation {
addContextVariables(fe.Context, ctx)
if rule.Validation != nil {
for _, fe := range rule.Validation.ForEachValidation {
addContextVariables(fe.Context, ctx)
}
}
if rule.Mutation != nil {
for _, fe := range rule.Mutation.ForEachMutation {
@ -943,29 +945,27 @@ func ruleOnlyDealsWithResourceMetaData(rule kyvernov1.Rule) bool {
}
}
}
patternMap, _ := rule.Validation.GetPattern().(map[string]interface{})
for k := range patternMap {
if k != "metadata" {
return false
}
}
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
logging.Error(err, "failed to deserialize anyPattern, expect type array")
return false
}
for _, pattern := range anyPatterns {
patternMap, _ := pattern.(map[string]interface{})
if rule.Validation != nil {
patternMap, _ := rule.Validation.GetPattern().(map[string]interface{})
for k := range patternMap {
if k != "metadata" {
return false
}
}
anyPatterns, err := rule.Validation.DeserializeAnyPattern()
if err != nil {
logging.Error(err, "failed to deserialize anyPattern, expect type array")
return false
}
for _, pattern := range anyPatterns {
patternMap, _ := pattern.(map[string]interface{})
for k := range patternMap {
if k != "metadata" {
return false
}
}
}
}
return true
}
@ -1018,20 +1018,21 @@ func validateResources(path *field.Path, rule kyvernov1.Rule) (string, error) {
}
}
// validating the values present under validate.conditions, if they exist
if rule.Validation.Deny != nil {
if target := rule.Validation.Deny.GetAnyAllConditions(); target != nil {
if path, err := validateConditions(target, "conditions"); err != nil {
return fmt.Sprintf("validate.deny.%s", path), err
}
if path, err := validateRawJSONConditionOperator(target, "conditions"); err != nil {
return fmt.Sprintf("validate.deny.%s", path), err
if rule.Validation != nil {
if rule.Validation.Deny != nil {
if target := rule.Validation.Deny.GetAnyAllConditions(); target != nil {
if path, err := validateConditions(target, "conditions"); err != nil {
return fmt.Sprintf("validate.deny.%s", path), err
}
if path, err := validateRawJSONConditionOperator(target, "conditions"); err != nil {
return fmt.Sprintf("validate.deny.%s", path), err
}
}
}
}
if len(rule.Validation.ForEachValidation) != 0 {
if path, err := validateValidationForEach(rule.Validation.ForEachValidation, "validate.foreach"); err != nil {
return path, err
if len(rule.Validation.ForEachValidation) != 0 {
if path, err := validateValidationForEach(rule.Validation.ForEachValidation, "validate.foreach"); err != nil {
return path, err
}
}
}
@ -1292,7 +1293,7 @@ func validateRuleContext(rule kyvernov1.Rule) error {
}
// if it the rule uses kyverno-json we add some constraints on the name of context entries to make
// sure we can create the corresponding bindings
if rule.Validation.Assert.Value != nil {
if rule.Validation != nil && rule.Validation.Assert.Value != nil {
if !bindingIdentifier.MatchString(entry.Name) {
return fmt.Errorf("context entry name %s is invalid, it must be a single word when the validation rule uses `assert`", entry.Name)
}
@ -1534,7 +1535,7 @@ func validateWildcard(kinds []string, background bool, rule kyvernov1.Rule) erro
return fmt.Errorf("wildcard policy can not deal with more than one kind")
}
if slices.Contains(kinds, "*") {
if rule.HasGenerate() || rule.HasVerifyImages() || rule.Validation.ForEachValidation != nil {
if rule.HasGenerate() || rule.HasVerifyImages() || (rule.Validation != nil && rule.Validation.ForEachValidation != nil) {
return fmt.Errorf("wildcard policy does not support rule type")
}
@ -1737,25 +1738,25 @@ func checkDeprecatedRawJSONConditionOperator(c apiextensions.JSON, warnings *[]s
}
func checkForDeprecatedOperatorsInRule(rule kyvernov1.Rule, warnings *[]string) {
if rule.Validation.Deny != nil {
if target := rule.Validation.Deny.GetAnyAllConditions(); target != nil {
checkDeprecatedRawJSONConditionOperator(target, warnings)
}
}
if len(rule.Validation.ForEachValidation) != 0 {
for _, fe := range rule.Validation.ForEachValidation {
if fe.AnyAllConditions != nil {
checkDeprecatedAnyAllConditionOperator(*fe.AnyAllConditions, warnings)
if rule.Validation != nil {
if rule.Validation.Deny != nil {
if target := rule.Validation.Deny.GetAnyAllConditions(); target != nil {
checkDeprecatedRawJSONConditionOperator(target, warnings)
}
if fe.Deny != nil {
if target := fe.Deny.GetAnyAllConditions(); target != nil {
checkDeprecatedRawJSONConditionOperator(target, warnings)
}
if len(rule.Validation.ForEachValidation) != 0 {
for _, fe := range rule.Validation.ForEachValidation {
if fe.AnyAllConditions != nil {
checkDeprecatedAnyAllConditionOperator(*fe.AnyAllConditions, warnings)
}
if fe.Deny != nil {
if target := fe.Deny.GetAnyAllConditions(); target != nil {
checkDeprecatedRawJSONConditionOperator(target, warnings)
}
}
}
}
}
if len(rule.VerifyImages) != 0 {
for _, vi := range rule.VerifyImages {
for _, att := range vi.Attestations {

View file

@ -37,7 +37,7 @@ func Test_PolicyValidationWithInvalidVariable(t *testing.T) {
},
},
},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "{{ bar }} world!",
Deny: &kyverno.Deny{},
},
@ -1661,7 +1661,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1724,7 +1724,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1756,7 +1756,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1788,7 +1788,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1820,7 +1820,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1852,7 +1852,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1883,7 +1883,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1916,7 +1916,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1948,7 +1948,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -1980,7 +1980,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -2011,7 +2011,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},
@ -2041,7 +2041,7 @@ func Test_ValidateNamespace(t *testing.T) {
{
Name: "require-labels",
MatchResources: kyverno.MatchResources{ResourceDescription: kyverno.ResourceDescription{Kinds: []string{"Pod"}}},
Validation: kyverno.Validation{
Validation: &kyverno.Validation{
Message: "label 'app.kubernetes.io/name' is required",
RawPattern: &apiextv1.JSON{Raw: []byte(`"metadata": {"lables": {"app.kubernetes.io/name": "?*"}}`)},
},

View file

@ -71,7 +71,7 @@ func TestBlockRequest(t *testing.T) {
Rules: []kyvernov1.Rule{
{
Name: "rule-audit",
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &audit,
},
},
@ -87,7 +87,7 @@ func TestBlockRequest(t *testing.T) {
Rules: []kyvernov1.Rule{
{
Name: "rule-enforce",
Validation: kyvernov1.Validation{
Validation: &kyvernov1.Validation{
FailureAction: &enforce,
},
},