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

fix: return policies with either audit or enforce rules from the cache (#10667)

* fix: return policies with either audit or enforce rules from the cache

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>

* feat: introduce validationFailureAction under verifyImage rules

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>

* feat: add chainsaw tests

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>

* fix

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>

---------

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
Co-authored-by: shuting <shuting@nirmata.com>
This commit is contained in:
Mariam Fahmy 2024-08-06 21:24:28 +03:00 committed by GitHub
parent a32bdf1ac1
commit c796bb765c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
513 changed files with 4473 additions and 718 deletions

View file

@ -17,7 +17,6 @@ import (
// +kubebuilder:resource:path=clusterpolicies,scope="Cluster",shortName=cpol,categories=kyverno // +kubebuilder:resource:path=clusterpolicies,scope="Cluster",shortName=cpol,categories=kyverno
// +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission" // +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission"
// +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background" // +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background"
// +kubebuilder:printcolumn:name="VALIDATE ACTION",type=string,JSONPath=".spec.validationFailureAction"
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status` // +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status`
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1 // +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1

View file

@ -454,11 +454,11 @@ func (m *ForEachMutation) SetPatchStrategicMerge(in apiextensions.JSON) {
// Validation defines checks to be performed on matching resources. // Validation defines checks to be performed on matching resources.
type Validation struct { type Validation struct {
// ValidationFailureAction defines if a validation policy rule violation should block // ValidationFailureAction defines if a validation policy rule violation should block
// the admission review request (enforce), or allow (audit) the admission review request // the admission review request (Enforce), or allow (Audit) the admission review request
// and report an error in a policy report. Optional. // and report an error in a policy report. Optional.
// Allowed values are audit or enforce. // Allowed values are Audit or Enforce.
// +optional // +optional
// +kubebuilder:validation:Enum=audit;enforce;Audit;Enforce // +kubebuilder:validation:Enum=Audit;Enforce
ValidationFailureAction *ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"` ValidationFailureAction *ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"`
// ValidationFailureActionOverrides is a Cluster Policy attribute that specifies ValidationFailureAction // ValidationFailureActionOverrides is a Cluster Policy attribute that specifies ValidationFailureAction

View file

@ -40,6 +40,11 @@ var signatureAlgorithmMap = map[string]bool{
// are signed with the supplied public key. Once the image is verified it is // are signed with the supplied public key. Once the image is verified it is
// mutated to include the SHA digest retrieved during the registration. // mutated to include the SHA digest retrieved during the registration.
type ImageVerification struct { type ImageVerification struct {
// Allowed values are Audit or Enforce.
// +optional
// +kubebuilder:validation:Enum=Audit;Enforce
ValidationFailureAction *ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"`
// Type specifies the method of signature validation. The allowed options // Type specifies the method of signature validation. The allowed options
// are Cosign and Notary. By default Cosign is used if a type is not specified. // are Cosign and Notary. By default Cosign is used if a type is not specified.
// +kubebuilder:validation:Optional // +kubebuilder:validation:Optional

View file

@ -15,7 +15,6 @@ import (
// +kubebuilder:subresource:status // +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission" // +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission"
// +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background" // +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background"
// +kubebuilder:printcolumn:name="VALIDATE ACTION",type=string,JSONPath=".spec.validationFailureAction"
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status` // +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status`
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1 // +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1

View file

@ -171,6 +171,19 @@ func (s *Spec) HasValidate() bool {
return false return false
} }
// HasValidateEnforce checks if the policy has any validate rules with enforce action
func (s *Spec) HasValidateEnforce() bool {
for _, rule := range s.Rules {
if rule.HasValidate() {
action := rule.Validation.ValidationFailureAction
if action != nil && action.Enforce() {
return true
}
}
}
return s.ValidationFailureAction.Enforce()
}
// HasGenerate checks for generate rule types // HasGenerate checks for generate rule types
func (s *Spec) HasGenerate() bool { func (s *Spec) HasGenerate() bool {
for _, rule := range s.Rules { for _, rule := range s.Rules {
@ -228,32 +241,6 @@ func (s *Spec) BackgroundProcessingEnabled() bool {
return *s.Background return *s.Background
} }
// GetValidationFailureAction returns the value of the validationFailureAction
func (s *Spec) GetValidationFailureAction() ValidationFailureAction {
for _, rule := range s.Rules {
if rule.HasValidate() {
validationFailureAction := rule.Validation.ValidationFailureAction
if validationFailureAction != nil {
return *validationFailureAction
}
}
}
return s.ValidationFailureAction
}
// GetValidationFailureActionOverrides returns the value of the validationFailureActionOverrides
func (s *Spec) GetValidationFailureActionOverrides() []ValidationFailureActionOverride {
for _, rule := range s.Rules {
if rule.HasValidate() {
validationFailureActionOverrides := rule.Validation.ValidationFailureActionOverrides
if len(validationFailureActionOverrides) != 0 {
return validationFailureActionOverrides
}
}
}
return s.ValidationFailureActionOverrides
}
// GetMutateExistingOnPolicyUpdate return MutateExistingOnPolicyUpdate set value // GetMutateExistingOnPolicyUpdate return MutateExistingOnPolicyUpdate set value
func (s *Spec) GetMutateExistingOnPolicyUpdate() bool { func (s *Spec) GetMutateExistingOnPolicyUpdate() bool {
for _, rule := range s.Rules { for _, rule := range s.Rules {

View file

@ -794,6 +794,11 @@ func (in *ImageRegistryCredentials) DeepCopy() *ImageRegistryCredentials {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageVerification) DeepCopyInto(out *ImageVerification) { func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
*out = *in *out = *in
if in.ValidationFailureAction != nil {
in, out := &in.ValidationFailureAction, &out.ValidationFailureAction
*out = new(ValidationFailureAction)
**out = **in
}
if in.ImageReferences != nil { if in.ImageReferences != nil {
in, out := &in.ImageReferences, &out.ImageReferences in, out := &in.ImageReferences, &out.ImageReferences
*out = make([]string, len(*in)) *out = make([]string, len(*in))

View file

@ -18,7 +18,6 @@ import (
// +kubebuilder:resource:path=clusterpolicies,scope="Cluster",shortName=cpol,categories=kyverno // +kubebuilder:resource:path=clusterpolicies,scope="Cluster",shortName=cpol,categories=kyverno
// +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission" // +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission"
// +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background" // +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background"
// +kubebuilder:printcolumn:name="VALIDATE ACTION",type=string,JSONPath=".spec.validationFailureAction"
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status` // +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status`
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1 // +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1

View file

@ -12,11 +12,11 @@ type AssertionTree = kjson.Any
// Validation defines checks to be performed on matching resources. // Validation defines checks to be performed on matching resources.
type Validation struct { type Validation struct {
// ValidationFailureAction defines if a validation policy rule violation should block // ValidationFailureAction defines if a validation policy rule violation should block
// the admission review request (enforce), or allow (audit) the admission review request // the admission review request (Enforce), or allow (Audit) the admission review request
// and report an error in a policy report. Optional. // and report an error in a policy report. Optional.
// Allowed values are audit or enforce. // Allowed values are Audit or Enforce.
// +optional // +optional
// +kubebuilder:validation:Enum=audit;enforce;Audit;Enforce // +kubebuilder:validation:Enum=Audit;Enforce
ValidationFailureAction *kyvernov1.ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"` ValidationFailureAction *kyvernov1.ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"`
// ValidationFailureActionOverrides is a Cluster Policy attribute that specifies ValidationFailureAction // ValidationFailureActionOverrides is a Cluster Policy attribute that specifies ValidationFailureAction

View file

@ -9,6 +9,11 @@ import (
// are signed with the supplied public key. Once the image is verified it is // are signed with the supplied public key. Once the image is verified it is
// mutated to include the SHA digest retrieved during the registration. // mutated to include the SHA digest retrieved during the registration.
type ImageVerification struct { type ImageVerification struct {
// Allowed values are Audit or Enforce.
// +optional
// +kubebuilder:validation:Enum=Audit;Enforce
ValidationFailureAction *kyvernov1.ValidationFailureAction `json:"validationFailureAction,omitempty" yaml:"validationFailureAction,omitempty"`
// Type specifies the method of signature validation. The allowed options // Type specifies the method of signature validation. The allowed options
// are Cosign and Notary. By default Cosign is used if a type is not specified. // are Cosign and Notary. By default Cosign is used if a type is not specified.
// +kubebuilder:validation:Optional // +kubebuilder:validation:Optional

View file

@ -16,7 +16,6 @@ import (
// +kubebuilder:subresource:status // +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission" // +kubebuilder:printcolumn:name="ADMISSION",type=boolean,JSONPath=".spec.admission"
// +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background" // +kubebuilder:printcolumn:name="BACKGROUND",type=boolean,JSONPath=".spec.background"
// +kubebuilder:printcolumn:name="VALIDATE ACTION",type=string,JSONPath=".spec.validationFailureAction"
// +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status` // +kubebuilder:printcolumn:name="READY",type=string,JSONPath=`.status.conditions[?(@.type == "Ready")].status`
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1 // +kubebuilder:printcolumn:name="FAILURE POLICY",type=string,JSONPath=".spec.failurePolicy",priority=1

View file

@ -135,6 +135,19 @@ func (s *Spec) HasValidate() bool {
return false return false
} }
// HasValidateEnforce checks if the policy has any validate rules with enforce action
func (s *Spec) HasValidateEnforce() bool {
for _, rule := range s.Rules {
if rule.HasValidate() {
action := rule.Validation.ValidationFailureAction
if action != nil && action.Enforce() {
return true
}
}
}
return s.ValidationFailureAction.Enforce()
}
// HasGenerate checks for generate rule types // HasGenerate checks for generate rule types
func (s *Spec) HasGenerate() bool { func (s *Spec) HasGenerate() bool {
for _, rule := range s.Rules { for _, rule := range s.Rules {
@ -197,32 +210,6 @@ func (s *Spec) BackgroundProcessingEnabled() bool {
return *s.Background return *s.Background
} }
// GetValidationFailureAction returns the value of the validationFailureAction
func (s *Spec) GetValidationFailureAction() kyvernov1.ValidationFailureAction {
for _, rule := range s.Rules {
if rule.HasValidate() {
validationFailureAction := rule.Validation.ValidationFailureAction
if validationFailureAction != nil {
return *validationFailureAction
}
}
}
return s.ValidationFailureAction
}
// GetValidationFailureActionOverrides returns the value of the validationFailureActionOverrides
func (s *Spec) GetValidationFailureActionOverrides() []kyvernov1.ValidationFailureActionOverride {
for _, rule := range s.Rules {
if rule.HasValidate() {
validationFailureActionOverrides := rule.Validation.ValidationFailureActionOverrides
if len(validationFailureActionOverrides) != 0 {
return validationFailureActionOverrides
}
}
}
return s.ValidationFailureActionOverrides
}
// GetMutateExistingOnPolicyUpdate return MutateExistingOnPolicyUpdate set value // GetMutateExistingOnPolicyUpdate return MutateExistingOnPolicyUpdate set value
func (s *Spec) GetMutateExistingOnPolicyUpdate() bool { func (s *Spec) GetMutateExistingOnPolicyUpdate() bool {
for _, rule := range s.Rules { for _, rule := range s.Rules {

View file

@ -368,6 +368,11 @@ func (in *Exception) DeepCopy() *Exception {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ImageVerification) DeepCopyInto(out *ImageVerification) { func (in *ImageVerification) DeepCopyInto(out *ImageVerification) {
*out = *in *out = *in
if in.ValidationFailureAction != nil {
in, out := &in.ValidationFailureAction, &out.ValidationFailureAction
*out = new(v1.ValidationFailureAction)
**out = **in
}
if in.ImageReferences != nil { if in.ImageReferences != nil {
in, out := &in.ImageReferences, &out.ImageReferences in, out := &in.ImageReferences, &out.ImageReferences
*out = make([]string, len(*in)) *out = make([]string, len(*in))

View file

@ -31,9 +31,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -3436,12 +3433,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -4277,6 +4272,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -7804,12 +7805,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -8658,6 +8657,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -8798,9 +8803,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -11975,12 +11977,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -12785,6 +12785,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -16312,12 +16318,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17166,6 +17170,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -31,9 +31,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -3437,12 +3434,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -4278,6 +4273,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -7806,12 +7807,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -8660,6 +8659,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -8800,9 +8805,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -11978,12 +11980,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -12788,6 +12788,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -16315,12 +16321,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17169,6 +17173,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -26,7 +26,6 @@ metadata:
name: require-ns-purpose-label name: require-ns-purpose-label
namespace: test namespace: test
spec: spec:
validationFailureAction: Enforce
rules: rules:
- name: require-ns-purpose-label - name: require-ns-purpose-label
match: match:
@ -35,6 +34,7 @@ spec:
kinds: kinds:
- Namespace - Namespace
validate: validate:
validationFailureAction: Enforce
message: "You must have label 'purpose' with value 'production' set on all new namespaces." message: "You must have label 'purpose' with value 'production' set on all new namespaces."
pattern: pattern:
metadata: metadata:

View file

@ -18,6 +18,7 @@ spec:
- Pod - Pod
name: pods-require-account name: pods-require-account
validate: validate:
validationFailureAction: Audit
message: User pods must include an account for charging message: User pods must include an account for charging
pattern: pattern:
metadata: metadata:
@ -30,6 +31,7 @@ spec:
- Pod - Pod
name: pods-require-limits name: pods-require-limits
validate: validate:
validationFailureAction: Audit
message: CPU and memory resource requests and limits are required for user pods message: CPU and memory resource requests and limits are required for user pods
pattern: pattern:
spec: spec:
@ -41,4 +43,3 @@ spec:
requests: requests:
cpu: ?* cpu: ?*
memory: ?* memory: ?*
validationFailureAction: Audit

View file

@ -18,6 +18,7 @@ spec:
- Pod - Pod
name: pods-require-account name: pods-require-account
validate: validate:
validationFailureAction: Audit
message: User pods must include an account for charging message: User pods must include an account for charging
pattern: pattern:
metadata: metadata:
@ -30,6 +31,7 @@ spec:
- Pod - Pod
name: pods-require-limits name: pods-require-limits
validate: validate:
validationFailureAction: Audit
message: CPU and memory resource requests and limits are required for user pods message: CPU and memory resource requests and limits are required for user pods
pattern: pattern:
spec: spec:
@ -41,4 +43,3 @@ spec:
requests: requests:
cpu: ?* cpu: ?*
memory: ?* memory: ?*
validationFailureAction: Audit

View file

@ -18,6 +18,7 @@ spec:
- Pod - Pod
name: pods-require-account name: pods-require-account
validate: validate:
validationFailureAction: Audit
message: User pods must include an account for charging message: User pods must include an account for charging
pattern: pattern:
metadata: metadata:

View file

@ -8,7 +8,6 @@ metadata:
policies.kyverno.io/category: Pod Security Standards (Restricted) policies.kyverno.io/category: Pod Security Standards (Restricted)
spec: spec:
background: false background: false
validationFailureAction: audit
rules: rules:
- name: pods-require-account - name: pods-require-account
match: match:
@ -19,6 +18,7 @@ spec:
matchLabels: matchLabels:
istio/rev: "default" istio/rev: "default"
validate: validate:
validationFailureAction: audit
message: User pods must include an account for charging message: User pods must include an account for charging
pattern: pattern:
metadata: metadata:
@ -30,6 +30,7 @@ spec:
kinds: kinds:
- Pod - Pod
validate: validate:
validationFailureAction: audit
message: CPU and memory resource requests and limits are required for user pods message: CPU and memory resource requests and limits are required for user pods
pattern: pattern:
spec: spec:

View file

@ -19,6 +19,7 @@ spec:
- Pod - Pod
name: pods-require-account name: pods-require-account
validate: validate:
validationFailureAction: Audit
message: User pods must include an account for charging message: User pods must include an account for charging
pattern: pattern:
metadata: metadata:
@ -31,6 +32,7 @@ spec:
- Pod - Pod
name: pods-require-limits name: pods-require-limits
validate: validate:
validationFailureAction: Audit
message: CPU and memory resource requests and limits are required for user pods message: CPU and memory resource requests and limits are required for user pods
pattern: pattern:
spec: spec:
@ -42,4 +44,3 @@ spec:
requests: requests:
cpu: ?* cpu: ?*
memory: ?* memory: ?*
validationFailureAction: Audit

View file

@ -25,9 +25,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -3430,12 +3427,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -4271,6 +4266,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -7798,12 +7799,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -8652,6 +8651,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -8792,9 +8797,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -11969,12 +11971,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -12779,6 +12779,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -16306,12 +16312,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17160,6 +17164,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -25,9 +25,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -3431,12 +3428,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -4272,6 +4267,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -7800,12 +7801,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -8654,6 +8653,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -8794,9 +8799,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -11972,12 +11974,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -12782,6 +12782,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -16309,12 +16315,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17163,6 +17167,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -110,7 +110,7 @@ func TestLoadWithKubectlValidate(t *testing.T) {
assert.NotNil(t, policy) assert.NotNil(t, policy)
spec := policy.GetSpec() spec := policy.GetSpec()
assert.NotNil(t, spec) assert.NotNil(t, spec)
assert.True(t, spec.GetValidationFailureAction().Audit()) assert.True(t, spec.ValidationFailureAction.Audit())
assert.NotNil(t, spec.Background) assert.NotNil(t, spec.Background)
assert.True(t, *spec.Background) assert.True(t, *spec.Background)
assert.NotNil(t, spec.Admission) assert.NotNil(t, spec.Admission)

View file

@ -205,7 +205,7 @@ func (p *PolicyProcessor) ApplyPoliciesOnResource() ([]engineapi.EngineResponse,
} }
responses = append(responses, generateResponse) responses = append(responses, generateResponse)
} }
p.Rc.addGenerateResponse(p.AuditWarn, generateResponse) p.Rc.addGenerateResponse(generateResponse)
} }
} }
p.Rc.addEngineResponses(p.AuditWarn, responses...) p.Rc.addEngineResponses(p.AuditWarn, responses...)

View file

@ -63,7 +63,7 @@ func (rc *ResultCounts) addEngineResponse(auditWarn bool, response engineapi.Eng
} }
} }
func (rc *ResultCounts) addGenerateResponse(auditWarn bool, response engineapi.EngineResponse) { func (rc *ResultCounts) addGenerateResponse(response engineapi.EngineResponse) {
genericPolicy := response.Policy() genericPolicy := response.Policy()
if polType := genericPolicy.GetType(); polType == engineapi.ValidatingAdmissionPolicyType { if polType := genericPolicy.GetType(); polType == engineapi.ValidatingAdmissionPolicyType {
return return
@ -74,13 +74,9 @@ func (rc *ResultCounts) addGenerateResponse(auditWarn bool, response engineapi.E
if policyRule.Name == ruleResponse.Name() { if policyRule.Name == ruleResponse.Name() {
if ruleResponse.Status() == engineapi.RuleStatusPass { if ruleResponse.Status() == engineapi.RuleStatusPass {
rc.Pass++ rc.Pass++
} else {
if auditWarn && response.GetValidationFailureAction().Audit() {
rc.Warn++
} else { } else {
rc.Fail++ rc.Fail++
} }
}
continue continue
} }
} }

View file

@ -25,9 +25,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -3430,12 +3427,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -4271,6 +4266,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -7798,12 +7799,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -8652,6 +8651,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -8792,9 +8797,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -11969,12 +11971,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -12779,6 +12779,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -16306,12 +16312,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17160,6 +17164,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -25,9 +25,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -3431,12 +3428,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -4272,6 +4267,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -7800,12 +7801,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -8654,6 +8653,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -8794,9 +8799,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -11972,12 +11974,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -12782,6 +12782,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -16309,12 +16315,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17163,6 +17167,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -5222,9 +5222,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -8627,12 +8624,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -9468,6 +9463,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -12995,12 +12996,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -13849,6 +13848,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -13989,9 +13994,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -17166,12 +17168,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -17976,6 +17976,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -21503,12 +21509,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -22357,6 +22361,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -22778,9 +22788,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -26184,12 +26191,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -27025,6 +27030,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -30553,12 +30564,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -31407,6 +31416,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have
@ -31547,9 +31562,6 @@ spec:
- jsonPath: .spec.background - jsonPath: .spec.background
name: BACKGROUND name: BACKGROUND
type: boolean type: boolean
- jsonPath: .spec.validationFailureAction
name: VALIDATE ACTION
type: string
- jsonPath: .status.conditions[?(@.type == "Ready")].status - jsonPath: .status.conditions[?(@.type == "Ready")].status
name: READY name: READY
type: string type: string
@ -34725,12 +34737,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -35535,6 +35545,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule responses for this rule
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have a description: VerifyDigest validates that images have a
@ -39062,12 +39078,10 @@ spec:
validationFailureAction: validationFailureAction:
description: |- description: |-
ValidationFailureAction defines if a validation policy rule violation should block ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce. Allowed values are Audit or Enforce.
enum: enum:
- audit
- enforce
- Audit - Audit
- Enforce - Enforce
type: string type: string
@ -39916,6 +39930,12 @@ spec:
description: UseCache enables caching of image verify description: UseCache enables caching of image verify
responses for this rule. responses for this rule.
type: boolean type: boolean
validationFailureAction:
description: Allowed values are Audit or Enforce.
enum:
- Audit
- Enforce
type: string
verifyDigest: verifyDigest:
default: true default: true
description: VerifyDigest validates that images have description: VerifyDigest validates that images have

View file

@ -2389,6 +2389,20 @@ mutated to include the SHA digest retrieved during the registration.</p>
<tbody> <tbody>
<tr> <tr>
<td> <td>
<code>validationFailureAction</code><br/>
<em>
<a href="#kyverno.io/v1.ValidationFailureAction">
ValidationFailureAction
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Allowed values are Audit or Enforce.</p>
</td>
</tr>
<tr>
<td>
<code>type</code><br/> <code>type</code><br/>
<em> <em>
<a href="#kyverno.io/v1.ImageVerificationType"> <a href="#kyverno.io/v1.ImageVerificationType">
@ -4472,9 +4486,9 @@ ValidationFailureAction
<td> <td>
<em>(Optional)</em> <em>(Optional)</em>
<p>ValidationFailureAction defines if a validation policy rule violation should block <p>ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce.</p> Allowed values are Audit or Enforce.</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -4623,9 +4637,11 @@ github.com/kyverno/kyverno-json/pkg/apis/policy/v1alpha1.Any
(<code>string</code> alias)</p></h3> (<code>string</code> alias)</p></h3>
<p> <p>
(<em>Appears on:</em> (<em>Appears on:</em>
<a href="#kyverno.io/v1.ImageVerification">ImageVerification</a>,
<a href="#kyverno.io/v1.Spec">Spec</a>, <a href="#kyverno.io/v1.Spec">Spec</a>,
<a href="#kyverno.io/v1.Validation">Validation</a>, <a href="#kyverno.io/v1.Validation">Validation</a>,
<a href="#kyverno.io/v1.ValidationFailureActionOverride">ValidationFailureActionOverride</a>, <a href="#kyverno.io/v1.ValidationFailureActionOverride">ValidationFailureActionOverride</a>,
<a href="#kyverno.io/v2beta1.ImageVerification">ImageVerification</a>,
<a href="#kyverno.io/v2beta1.Spec">Spec</a>, <a href="#kyverno.io/v2beta1.Spec">Spec</a>,
<a href="#kyverno.io/v2beta1.Validation">Validation</a>) <a href="#kyverno.io/v2beta1.Validation">Validation</a>)
</p> </p>
@ -8369,6 +8385,20 @@ mutated to include the SHA digest retrieved during the registration.</p>
<tbody> <tbody>
<tr> <tr>
<td> <td>
<code>validationFailureAction</code><br/>
<em>
<a href="#kyverno.io/v1.ValidationFailureAction">
ValidationFailureAction
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>Allowed values are Audit or Enforce.</p>
</td>
</tr>
<tr>
<td>
<code>type</code><br/> <code>type</code><br/>
<em> <em>
<a href="#kyverno.io/v1.ImageVerificationType"> <a href="#kyverno.io/v1.ImageVerificationType">
@ -9248,9 +9278,9 @@ ValidationFailureAction
<td> <td>
<em>(Optional)</em> <em>(Optional)</em>
<p>ValidationFailureAction defines if a validation policy rule violation should block <p>ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce.</p> Allowed values are Audit or Enforce.</p>
</td> </td>
</tr> </tr>
<tr> <tr>

View file

@ -4694,6 +4694,35 @@ mutated to include the SHA digest retrieved during the registration.</p>
<tr>
<td><code>validationFailureAction</code>
</br>
<a href="#kyverno-io-v1-ValidationFailureAction">
<span style="font-family: monospace">ValidationFailureAction</span>
</a>
</td>
<td>
<p>Allowed values are Audit or Enforce.</p>
</td>
</tr>
<tr> <tr>
<td><code>type</code> <td><code>type</code>
@ -8965,9 +8994,9 @@ It is an empty string when validating admission policy is successfully generated
<p>ValidationFailureAction defines if a validation policy rule violation should block <p>ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce.</p> Allowed values are Audit or Enforce.</p>
@ -9274,6 +9303,7 @@ by specifying exclusions for Pod Security Standards controls.</p>
<p> <p>
(<em>Appears in:</em> (<em>Appears in:</em>
<a href="#kyverno-io-v1-ImageVerification">ImageVerification</a>,
<a href="#kyverno-io-v1-Spec">Spec</a>, <a href="#kyverno-io-v1-Spec">Spec</a>,
<a href="#kyverno-io-v1-Validation">Validation</a>, <a href="#kyverno-io-v1-Validation">Validation</a>,
<a href="#kyverno-io-v1-ValidationFailureActionOverride">ValidationFailureActionOverride</a>) <a href="#kyverno-io-v1-ValidationFailureActionOverride">ValidationFailureActionOverride</a>)

View file

@ -2773,6 +2773,35 @@ mutated to include the SHA digest retrieved during the registration.</p>
<tr>
<td><code>validationFailureAction</code>
</br>
<a href="#kyverno-io-v1-ValidationFailureAction">
<span style="font-family: monospace">ValidationFailureAction</span>
</a>
</td>
<td>
<p>Allowed values are Audit or Enforce.</p>
</td>
</tr>
<tr> <tr>
<td><code>type</code> <td><code>type</code>
@ -4536,9 +4565,9 @@ Defaults to &quot;false&quot; if not specified.</p>
<p>ValidationFailureAction defines if a validation policy rule violation should block <p>ValidationFailureAction defines if a validation policy rule violation should block
the admission review request (enforce), or allow (audit) the admission review request the admission review request (Enforce), or allow (Audit) the admission review request
and report an error in a policy report. Optional. and report an error in a policy report. Optional.
Allowed values are audit or enforce.</p> Allowed values are Audit or Enforce.</p>

View file

@ -242,7 +242,7 @@ func Test_GetSupportedControllers(t *testing.T) {
}, },
{ {
name: "rule-with-validate-podsecurity", name: "rule-with-validate-podsecurity",
policy: []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"pod-security"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"restricted","match":{"all":[{"resources":{"kinds":["Pod"]}}]},"validate":{"podSecurity":{"level":"restricted","version":"v1.24"}}}]}}`), policy: []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"pod-security"},"spec":{"rules":[{"name":"restricted","match":{"all":[{"resources":{"kinds":["Pod"]}}]},"validate":{"validationFailureAction":"enforce","podSecurity":{"level":"restricted","version":"v1.24"}}}]}}`),
expectedControllers: PodControllers, expectedControllers: PodControllers,
}, },
} }
@ -406,7 +406,6 @@ kind: ClusterPolicy
metadata: metadata:
name: check-image name: check-image
spec: spec:
validationFailureAction: enforce
background: false background: false
webhookTimeoutSeconds: 30 webhookTimeoutSeconds: 30
failurePolicy: Fail failurePolicy: Fail
@ -540,7 +539,7 @@ kA==
} }
func Test_PodSecurityWithNoExceptions(t *testing.T) { func Test_PodSecurityWithNoExceptions(t *testing.T) {
policy := []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"pod-security"},"spec":{"validationFailureAction":"enforce","rules":[{"name":"restricted","match":{"all":[{"resources":{"kinds":["Pod"]}}]},"validate":{"podSecurity":{"level":"restricted","version":"v1.24"}}}]}}`) policy := []byte(`{"apiVersion":"kyverno.io/v1","kind":"ClusterPolicy","metadata":{"name":"pod-security"},"spec":{"rules":[{"name":"restricted","match":{"all":[{"resources":{"kinds":["Pod"]}}]},"validate":{"validationFailureAction":"enforce","podSecurity":{"level":"restricted","version":"v1.24"}}}]}}`)
policies, _, _, err := yamlutils.GetPolicy([]byte(policy)) policies, _, _, err := yamlutils.GetPolicy([]byte(policy))
assert.NilError(t, err) assert.NilError(t, err)
assert.Equal(t, 1, len(policies)) assert.Equal(t, 1, len(policies))
@ -558,7 +557,6 @@ func Test_ValidateWithCELExpressions(t *testing.T) {
"name": "disallow-host-path" "name": "disallow-host-path"
}, },
"spec": { "spec": {
"validationFailureAction": "Enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
@ -575,6 +573,7 @@ func Test_ValidateWithCELExpressions(t *testing.T) {
] ]
}, },
"validate": { "validate": {
"validationFailureAction": "Enforce",
"cel": { "cel": {
"expressions": [ "expressions": [
{ {

View file

@ -130,6 +130,8 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
if target := rule.Validation.GetPattern(); target != nil { if target := rule.Validation.GetPattern(); target != nil {
newValidate := kyvernov1.Validation{ newValidate := kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"), Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"),
ValidationFailureAction: rule.Validation.ValidationFailureAction,
ValidationFailureActionOverrides: rule.Validation.ValidationFailureActionOverrides,
} }
newValidate.SetPattern( newValidate.SetPattern(
map[string]interface{}{ map[string]interface{}{
@ -145,6 +147,8 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
deny := kyvernov1.Validation{ deny := kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "deny"), Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "deny"),
Deny: rule.Validation.Deny, Deny: rule.Validation.Deny,
ValidationFailureAction: rule.Validation.ValidationFailureAction,
ValidationFailureActionOverrides: rule.Validation.ValidationFailureActionOverrides,
} }
rule.Validation = deny rule.Validation = deny
return rule return rule
@ -159,6 +163,8 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
Version: rule.Validation.PodSecurity.Version, Version: rule.Validation.PodSecurity.Version,
Exclude: newExclude, Exclude: newExclude,
}, },
ValidationFailureAction: rule.Validation.ValidationFailureAction,
ValidationFailureActionOverrides: rule.Validation.ValidationFailureActionOverrides,
} }
rule.Validation = podSecurity rule.Validation = podSecurity
return rule return rule
@ -177,8 +183,12 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
} }
patterns = append(patterns, newPattern) patterns = append(patterns, newPattern)
} }
validationFailureAction := rule.Validation.ValidationFailureAction
validationFailureActionOverrides := rule.Validation.ValidationFailureActionOverrides
rule.Validation = kyvernov1.Validation{ rule.Validation = kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "anyPattern"), Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "anyPattern"),
ValidationFailureAction: validationFailureAction,
ValidationFailureActionOverrides: validationFailureActionOverrides,
} }
rule.Validation.SetAnyPattern(patterns) rule.Validation.SetAnyPattern(patterns)
return rule return rule
@ -186,9 +196,13 @@ func generateRule(name string, rule *kyvernov1.Rule, tplKey, shift string, kinds
if len(rule.Validation.ForEachValidation) > 0 && rule.Validation.ForEachValidation != nil { if len(rule.Validation.ForEachValidation) > 0 && rule.Validation.ForEachValidation != nil {
newForeachValidate := make([]kyvernov1.ForEachValidation, len(rule.Validation.ForEachValidation)) newForeachValidate := make([]kyvernov1.ForEachValidation, len(rule.Validation.ForEachValidation))
copy(newForeachValidate, rule.Validation.ForEachValidation) copy(newForeachValidate, rule.Validation.ForEachValidation)
validationFailureAction := rule.Validation.ValidationFailureAction
validationFailureActionOverrides := rule.Validation.ValidationFailureActionOverrides
rule.Validation = kyvernov1.Validation{ rule.Validation = kyvernov1.Validation{
Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"), Message: variables.FindAndShiftReferences(logger, rule.Validation.Message, shift, "pattern"),
ForEachValidation: newForeachValidate, ForEachValidation: newForeachValidate,
ValidationFailureAction: validationFailureAction,
ValidationFailureActionOverrides: validationFailureActionOverrides,
} }
return rule return rule
} }

View file

@ -25,6 +25,7 @@ import (
// ImageVerificationApplyConfiguration represents an declarative configuration of the ImageVerification type for use // ImageVerificationApplyConfiguration represents an declarative configuration of the ImageVerification type for use
// with apply. // with apply.
type ImageVerificationApplyConfiguration struct { type ImageVerificationApplyConfiguration struct {
ValidationFailureAction *v1.ValidationFailureAction `json:"validationFailureAction,omitempty"`
Type *v1.ImageVerificationType `json:"type,omitempty"` Type *v1.ImageVerificationType `json:"type,omitempty"`
Image *string `json:"image,omitempty"` Image *string `json:"image,omitempty"`
ImageReferences []string `json:"imageReferences,omitempty"` ImageReferences []string `json:"imageReferences,omitempty"`
@ -52,6 +53,14 @@ func ImageVerification() *ImageVerificationApplyConfiguration {
return &ImageVerificationApplyConfiguration{} return &ImageVerificationApplyConfiguration{}
} }
// WithValidationFailureAction sets the ValidationFailureAction 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 ValidationFailureAction field is set to the value of the last call.
func (b *ImageVerificationApplyConfiguration) WithValidationFailureAction(value v1.ValidationFailureAction) *ImageVerificationApplyConfiguration {
b.ValidationFailureAction = &value
return b
}
// WithType sets the Type field in the declarative configuration to the given value // WithType sets the Type field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations. // and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Type field is set to the value of the last call. // If called multiple times, the Type field is set to the value of the last call.

View file

@ -26,6 +26,7 @@ import (
// ImageVerificationApplyConfiguration represents an declarative configuration of the ImageVerification type for use // ImageVerificationApplyConfiguration represents an declarative configuration of the ImageVerification type for use
// with apply. // with apply.
type ImageVerificationApplyConfiguration struct { type ImageVerificationApplyConfiguration struct {
ValidationFailureAction *v1.ValidationFailureAction `json:"validationFailureAction,omitempty"`
Type *v1.ImageVerificationType `json:"type,omitempty"` Type *v1.ImageVerificationType `json:"type,omitempty"`
ImageReferences []string `json:"imageReferences,omitempty"` ImageReferences []string `json:"imageReferences,omitempty"`
SkipImageReferences []string `json:"skipImageReferences,omitempty"` SkipImageReferences []string `json:"skipImageReferences,omitempty"`
@ -45,6 +46,14 @@ func ImageVerification() *ImageVerificationApplyConfiguration {
return &ImageVerificationApplyConfiguration{} return &ImageVerificationApplyConfiguration{}
} }
// WithValidationFailureAction sets the ValidationFailureAction 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 ValidationFailureAction field is set to the value of the last call.
func (b *ImageVerificationApplyConfiguration) WithValidationFailureAction(value v1.ValidationFailureAction) *ImageVerificationApplyConfiguration {
b.ValidationFailureAction = &value
return b
}
// WithType sets the Type field in the declarative configuration to the given value // WithType sets the Type field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations. // and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Type field is set to the value of the last call. // If called multiple times, the Type field is set to the value of the last call.

View file

@ -27,7 +27,7 @@ func (pc *controller) registerPolicyChangesMetricUpdatePolicy(ctx context.Contex
logger.Error(err, "error occurred while registering kyverno_policy_changes_total metrics for the above policy's updation", "name", oldP.GetName()) logger.Error(err, "error occurred while registering kyverno_policy_changes_total metrics for the above policy's updation", "name", oldP.GetName())
} }
// curP will require a new kyverno_policy_changes_total metric if the above update involved change in the following fields: // curP will require a new kyverno_policy_changes_total metric if the above update involved change in the following fields:
if curSpec.BackgroundProcessingEnabled() != oldSpec.BackgroundProcessingEnabled() || curSpec.GetValidationFailureAction().Enforce() != oldSpec.GetValidationFailureAction().Enforce() { if curSpec.BackgroundProcessingEnabled() != oldSpec.BackgroundProcessingEnabled() || curSpec.ValidationFailureAction.Enforce() != oldSpec.ValidationFailureAction.Enforce() {
err = policyChangesMetric.RegisterPolicy(ctx, pc.metricsConfig, curP, policyChangesMetric.PolicyUpdated) err = policyChangesMetric.RegisterPolicy(ctx, pc.metricsConfig, curP, policyChangesMetric.PolicyUpdated)
if err != nil { if err != nil {
logger.Error(err, "error occurred while registering kyverno_policy_changes_total metrics for the above policy's updation", "name", curP.GetName()) logger.Error(err, "error occurred while registering kyverno_policy_changes_total metrics for the above policy's updation", "name", curP.GetName())

View file

@ -35,7 +35,6 @@ var policy = `
"name": "disallow-unsigned-images" "name": "disallow-unsigned-images"
}, },
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {

View file

@ -199,7 +199,9 @@ func (er EngineResponse) GetValidationFailureAction() kyvernov1.ValidationFailur
return "" return ""
} }
spec := pol.AsKyvernoPolicy().GetSpec() spec := pol.AsKyvernoPolicy().GetSpec()
for _, v := range spec.GetValidationFailureActionOverrides() { for _, r := range spec.Rules {
if r.HasValidate() {
for _, v := range r.Validation.ValidationFailureActionOverrides {
if !v.Action.IsValid() { if !v.Action.IsValid() {
continue continue
} }
@ -221,5 +223,37 @@ func (er EngineResponse) GetValidationFailureAction() kyvernov1.ValidationFailur
} }
} }
} }
return spec.GetValidationFailureAction()
if r.Validation.ValidationFailureAction != nil {
return *r.Validation.ValidationFailureAction
}
} else if r.HasVerifyImages() {
if r.VerifyImages[0].ValidationFailureAction != nil {
return *r.VerifyImages[0].ValidationFailureAction
}
}
}
for _, v := range spec.ValidationFailureActionOverrides {
if !v.Action.IsValid() {
continue
}
if v.Namespaces == nil {
hasPass, err := utils.CheckSelector(v.NamespaceSelector, er.namespaceLabels)
if err == nil && hasPass {
return v.Action
}
}
for _, ns := range v.Namespaces {
if wildcard.Match(ns, er.PatchedResource.GetNamespace()) {
if v.NamespaceSelector == nil {
return v.Action
}
hasPass, err := utils.CheckSelector(v.NamespaceSelector, er.namespaceLabels)
if err == nil && hasPass {
return v.Action
}
}
}
}
return spec.ValidationFailureAction
} }

View file

@ -40,7 +40,6 @@ func buildTestNamespaceLabelsContext(t *testing.T) api.PolicyContext {
"name": "block-label-changes" "name": "block-label-changes"
}, },
"spec": { "spec": {
"validationFailureAction": "Enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
@ -61,6 +60,7 @@ func buildTestNamespaceLabelsContext(t *testing.T) api.PolicyContext {
] ]
}, },
"validate": { "validate": {
"validationFailureAction": "Enforce",
"message": "The label size is required", "message": "The label size is required",
"pattern": { "pattern": {
"metadata": { "metadata": {
@ -88,6 +88,7 @@ func buildTestNamespaceLabelsContext(t *testing.T) api.PolicyContext {
] ]
}, },
"validate": { "validate": {
"validationFailureAction": "Enforce",
"message": "The label size cannot be changed for a namespace", "message": "The label size cannot be changed for a namespace",
"deny": { "deny": {
"conditions": { "conditions": {

View file

@ -180,7 +180,6 @@ func Test_PolicyDeserilize(t *testing.T) {
"name": "set-image-pull-policy" "name": "set-image-pull-policy"
}, },
"spec": { "spec": {
"validationFailureAction": "enforce",
"rules": [ "rules": [
{ {
"name": "set-image-pull-policy", "name": "set-image-pull-policy",

View file

@ -655,7 +655,6 @@ func Test_foreach_element_mutation(t *testing.T) {
"name": "mutate-privileged" "name": "mutate-privileged"
}, },
"spec": { "spec": {
"validationFailureAction": "audit",
"background": false, "background": false,
"webhookTimeoutSeconds": 10, "webhookTimeoutSeconds": 10,
"failurePolicy": "Fail", "failurePolicy": "Fail",

View file

@ -837,7 +837,7 @@ func TestMatchesResourceDescription(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`), Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`),
areErrorsExpected: false, areErrorsExpected: false,
}, },
{ {
@ -846,7 +846,7 @@ func TestMatchesResourceDescription(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`), Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "v1/Pod" ] } }, "validate": { "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": {"rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "v1/Pod" ] } }, "validate": { "validationFailureAction": "enforce", "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`),
areErrorsExpected: false, areErrorsExpected: false,
}, },
{ {
@ -864,7 +864,7 @@ func TestMatchesResourceDescription(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "apps/v1beta1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`), Resource: []byte(`{ "apiVersion": "apps/v1beta1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
{ {
@ -873,7 +873,7 @@ func TestMatchesResourceDescription(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "kind": "ClusterRole", "apiVersion": "rbac.authorization.k8s.io/v1", "metadata": { "name": "secret-reader-demo", "namespace": "default" }, "rules": [ { "apiGroups": [ "" ], "resources": [ "secrets" ], "verbs": [ "get", "watch", "list" ] } ] }`), Resource: []byte(`{ "kind": "ClusterRole", "apiVersion": "rbac.authorization.k8s.io/v1", "metadata": { "name": "secret-reader-demo", "namespace": "default" }, "rules": [ { "apiGroups": [ "" ], "resources": [ "secrets" ], "verbs": [ "get", "watch", "list" ] } ] }`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "check-host-path" }, "spec": { "validationFailureAction": "enforce", "background": true, "rules": [ { "name": "check-host-path", "match": { "resources": { "kinds": [ "rbac.authorization.k8s.io/v1beta1/ClusterRole" ] } }, "validate": { "message": "Host path is not allowed", "pattern": { "spec": { "volumes": [ { "name": "*", "hostPath": { "path": "" } } ] } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "check-host-path" }, "spec": { "background": true, "rules": [ { "name": "check-host-path", "match": { "resources": { "kinds": [ "rbac.authorization.k8s.io/v1beta1/ClusterRole" ] } }, "validate": { "validationFailureAction": "enforce", "message": "Host path is not allowed", "pattern": { "spec": { "volumes": [ { "name": "*", "hostPath": { "path": "" } } ] } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
{ {
@ -882,7 +882,7 @@ func TestMatchesResourceDescription(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`), Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "pod" ] } }, "validate": { "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "pod" ] } }, "validate": { "validationFailureAction": "enforce", "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
{ {
@ -891,7 +891,7 @@ func TestMatchesResourceDescription(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`), Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "name": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
} }
@ -1742,7 +1742,7 @@ func TestMatchesResourceDescription_GenerateName(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "generateName": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`), Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "generateName": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "validationFailureAction": "enforce", "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`),
areErrorsExpected: false, areErrorsExpected: false,
}, },
{ {
@ -1751,7 +1751,7 @@ func TestMatchesResourceDescription_GenerateName(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "generateName": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`), Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "generateName": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "v1/Pod" ] } }, "validate": { "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "v1/Pod" ] } }, "validate": { "validationFailureAction": "enforce", "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`),
areErrorsExpected: false, areErrorsExpected: false,
}, },
{ {
@ -1769,7 +1769,7 @@ func TestMatchesResourceDescription_GenerateName(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "apps/v1beta1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "generateName": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`), Resource: []byte(`{ "apiVersion": "apps/v1beta1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "generateName": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } }, { "name": "check-cpu-memory-limits", "match": { "resources": { "kinds": [ "apps/v1/Deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "validate": { "validationFailureAction": "enforce", "message": "Resource limits are required for CPU and memory", "pattern": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "memory": "?*", "cpu": "?*" } } } ] } } } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
{ {
@ -1778,7 +1778,7 @@ func TestMatchesResourceDescription_GenerateName(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "kind": "ClusterRole", "apiVersion": "rbac.authorization.k8s.io/v1", "metadata": { "generateName": "secret-reader-demo", "namespace": "default" }, "rules": [ { "apiGroups": [ "" ], "resources": [ "secrets" ], "verbs": [ "get", "watch", "list" ] } ] }`), Resource: []byte(`{ "kind": "ClusterRole", "apiVersion": "rbac.authorization.k8s.io/v1", "metadata": { "generateName": "secret-reader-demo", "namespace": "default" }, "rules": [ { "apiGroups": [ "" ], "resources": [ "secrets" ], "verbs": [ "get", "watch", "list" ] } ] }`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "check-host-path" }, "spec": { "validationFailureAction": "enforce", "background": true, "rules": [ { "name": "check-host-path", "match": { "resources": { "kinds": [ "rbac.authorization.k8s.io/v1beta1/ClusterRole" ] } }, "validate": { "message": "Host path is not allowed", "pattern": { "spec": { "volumes": [ { "name": "*", "hostPath": { "path": "" } } ] } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "check-host-path" }, "spec": { "background": true, "rules": [ { "name": "check-host-path", "match": { "resources": { "kinds": [ "rbac.authorization.k8s.io/v1beta1/ClusterRole" ] } }, "validate": { "validationFailureAction": "enforce", "message": "Host path is not allowed", "pattern": { "spec": { "volumes": [ { "name": "*", "hostPath": { "path": "" } } ] } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
{ {
@ -1787,7 +1787,7 @@ func TestMatchesResourceDescription_GenerateName(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "generateName": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`), Resource: []byte(`{ "apiVersion": "v1", "kind": "Pod", "metadata": { "generateName": "myapp-pod2", "labels": { "app": "myapp2" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx" } ] } }`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "pod" ] } }, "validate": { "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "disallow-latest-tag", "annotations": { "policies.kyverno.io/category": "Workload Isolation", "policies.kyverno.io/description": "The ':latest' tag is mutable and can lead to unexpected errors if the image changes. A best practice is to use an immutable tag that maps to a specific version of an application pod." } }, "spec": { "rules": [ { "name": "require-image-tag", "match": { "resources": { "kinds": [ "pod" ] } }, "validate": { "validationFailureAction": "enforce", "message": "An image tag is required", "pattern": { "spec": { "containers": [ { "image": "*:*" } ] } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
{ {
@ -1796,7 +1796,7 @@ func TestMatchesResourceDescription_GenerateName(t *testing.T) {
ClusterRoles: []string{"admin"}, ClusterRoles: []string{"admin"},
}, },
Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "generateName": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`), Resource: []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "generateName": "qos-demo", "labels": { "test": "qos" } }, "spec": { "replicas": 1, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "creationTimestamp": "2020-09-21T12:56:35Z", "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:latest", "resources": { "limits": { "cpu": "50m" } } } ]}}}}`),
Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "validationFailureAction": "enforce", "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } } ] } }`), Policy: []byte(`{ "apiVersion": "kyverno.io/v1", "kind": "ClusterPolicy", "metadata": { "name": "policy-qos" }, "spec": { "rules": [ { "name": "add-memory-limit", "match": { "resources": { "kinds": [ "apps/v1/deployment" ], "selector": { "matchLabels": { "test": "qos" } } } }, "mutate": { "overlay": { "spec": { "template": { "spec": { "containers": [ { "(name)": "*", "resources": { "limits": { "+(memory)": "300Mi", "+(cpu)": "100" } } } ] } } } } } } ] } }`),
areErrorsExpected: true, areErrorsExpected: true,
}, },
} }

View file

@ -679,7 +679,6 @@ func TestValidate_foreach_zero_reported_asskip(t *testing.T) {
} }
}, },
"spec": { "spec": {
"validationFailureAction": "Enforce",
"background": true, "background": true,
"rules": [ "rules": [
{ {
@ -690,6 +689,7 @@ func TestValidate_foreach_zero_reported_asskip(t *testing.T) {
} }
}, },
"validate": { "validate": {
"validationFailureAction": "Enforce",
"foreach": [ "foreach": [
{ {
"list": "request.object.spec.volumes[].projected.sources[].serviceAccountToken.expirationSeconds", "list": "request.object.spec.volumes[].projected.sources[].serviceAccountToken.expirationSeconds",
@ -1948,7 +1948,6 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
"name": "cm-array-example" "name": "cm-array-example"
}, },
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
@ -1961,6 +1960,7 @@ func Test_VariableSubstitutionValidate_VariablesInMessageAreResolved(t *testing.
} }
}, },
"validate": { "validate": {
"validationFailureAction": "enforce",
"message": "The animal {{ request.object.metadata.labels.animal }} is not in the allowed list of animals.", "message": "The animal {{ request.object.metadata.labels.animal }} is not in the allowed list of animals.",
"deny": { "deny": {
"conditions": [ "conditions": [
@ -2125,7 +2125,6 @@ func Test_BlockLabelRemove(t *testing.T) {
"name": "prevent-label-remove" "name": "prevent-label-remove"
}, },
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
@ -2152,6 +2151,7 @@ func Test_BlockLabelRemove(t *testing.T) {
] ]
}, },
"validate": { "validate": {
"validationFailureAction": "enforce",
"message": "not allowed", "message": "not allowed",
"deny": { "deny": {
"conditions": { "conditions": {
@ -2248,7 +2248,6 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
"name": "restrict-pod-count" "name": "restrict-pod-count"
}, },
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
@ -2270,6 +2269,7 @@ func TestValidate_context_variable_substitution_CLI(t *testing.T) {
} }
], ],
"validate": { "validate": {
"validationFailureAction": "enforce",
"message": "restrict pod counts to be no more than 10 on node minikube", "message": "restrict pod counts to be no more than 10 on node minikube",
"deny": { "deny": {
"conditions": [ "conditions": [
@ -2372,6 +2372,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
} }
], ],
"validate": { "validate": {
"validationFailureAction": "enforce",
"deny": { "deny": {
"conditions": [ "conditions": [
{ {
@ -2383,8 +2384,7 @@ func Test_EmptyStringInDenyCondition(t *testing.T) {
} }
} }
} }
], ]
"validationFailureAction": "enforce"
} }
}`) }`)
@ -2457,6 +2457,7 @@ func Test_StringInDenyCondition(t *testing.T) {
} }
], ],
"validate": { "validate": {
"validationFailureAction": "enforce",
"deny": { "deny": {
"conditions": [ "conditions": [
{ {
@ -2468,8 +2469,7 @@ func Test_StringInDenyCondition(t *testing.T) {
} }
} }
} }
], ]
"validationFailureAction": "enforce"
} }
}`) }`)
@ -3000,13 +3000,13 @@ func Test_outof_foreach_element_validation(t *testing.T) {
"kind": "ClusterPolicy", "kind": "ClusterPolicy",
"metadata": {"name": "check-container-names"}, "metadata": {"name": "check-container-names"},
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
"name": "test", "name": "test",
"match": {"resources": { "kinds": [ "Pod" ] } }, "match": {"resources": { "kinds": [ "Pod" ] } },
"validate": { "validate": {
"validationFailureAction": "enforce",
"message": "Invalid name", "message": "Invalid name",
"pattern": { "pattern": {
"name": "{{ element.name }}" "name": "{{ element.name }}"
@ -3033,7 +3033,6 @@ func Test_foreach_skip_initContainer_pass(t *testing.T) {
"name": "check-images" "name": "check-images"
}, },
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
@ -3046,6 +3045,7 @@ func Test_foreach_skip_initContainer_pass(t *testing.T) {
} }
}, },
"validate": { "validate": {
"validationFailureAction": "enforce",
"message": "unknown registry", "message": "unknown registry",
"foreach": [ "foreach": [
{ {
@ -3210,13 +3210,13 @@ func Test_delete_ignore_pattern(t *testing.T) {
"kind": "ClusterPolicy", "kind": "ClusterPolicy",
"metadata": {"name": "check-container-labels"}, "metadata": {"name": "check-container-labels"},
"spec": { "spec": {
"validationFailureAction": "enforce",
"background": false, "background": false,
"rules": [ "rules": [
{ {
"name": "test", "name": "test",
"match": {"resources": { "kinds": [ "Pod" ] } }, "match": {"resources": { "kinds": [ "Pod" ] } },
"validate": { "validate": {
"validationFailureAction": "enforce",
"message": "Invalid label", "message": "Invalid label",
"pattern": { "pattern": {
"metadata" : { "metadata" : {

View file

@ -77,6 +77,12 @@ func GetPolicyInfos(policy kyvernov1.PolicyInterface) (string, string, PolicyTyp
policyType = Namespaced policyType = Namespaced
} }
backgroundMode := ParsePolicyBackgroundMode(policy) backgroundMode := ParsePolicyBackgroundMode(policy)
validationMode, err := ParsePolicyValidationMode(policy.GetSpec().GetValidationFailureAction()) isEnforce := policy.GetSpec().HasValidateEnforce()
return name, namespace, policyType, backgroundMode, validationMode, err var validationMode PolicyValidationMode
if isEnforce {
validationMode = Enforce
} else {
validationMode = Audit
}
return name, namespace, policyType, backgroundMode, validationMode, nil
} }

View file

@ -3,6 +3,7 @@ package policycache
import ( import (
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/ext/wildcard" "github.com/kyverno/kyverno/ext/wildcard"
"github.com/kyverno/kyverno/pkg/autogen"
"github.com/kyverno/kyverno/pkg/clients/dclient" "github.com/kyverno/kyverno/pkg/clients/dclient"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -62,31 +63,56 @@ func (c *cache) GetPolicies(pkey PolicyType, gvr schema.GroupVersionResource, su
func filterPolicies(pkey PolicyType, result []kyvernov1.PolicyInterface, nspace string) []kyvernov1.PolicyInterface { func filterPolicies(pkey PolicyType, result []kyvernov1.PolicyInterface, nspace string) []kyvernov1.PolicyInterface {
var policies []kyvernov1.PolicyInterface var policies []kyvernov1.PolicyInterface
for _, policy := range result { for _, policy := range result {
var filteredPolicy kyvernov1.PolicyInterface
keepPolicy := true keepPolicy := true
switch pkey { switch pkey {
case ValidateAudit: case ValidateAudit:
keepPolicy = checkValidationFailureActionOverrides(false, nspace, policy) keepPolicy, filteredPolicy = checkValidationFailureActionOverrides(false, nspace, policy)
case ValidateEnforce: case ValidateEnforce:
keepPolicy = checkValidationFailureActionOverrides(true, nspace, policy) keepPolicy, filteredPolicy = checkValidationFailureActionOverrides(true, nspace, policy)
} }
// add policy to result // add policy to result
if keepPolicy { if keepPolicy {
policies = append(policies, policy) policies = append(policies, filteredPolicy)
} }
} }
return policies return policies
} }
func checkValidationFailureActionOverrides(enforce bool, ns string, policy kyvernov1.PolicyInterface) bool { func checkValidationFailureActionOverrides(enforce bool, ns string, policy kyvernov1.PolicyInterface) (bool, kyvernov1.PolicyInterface) {
validationFailureAction := policy.GetSpec().GetValidationFailureAction() var filteredRules []kyvernov1.Rule
validationFailureActionOverrides := policy.GetSpec().GetValidationFailureActionOverrides() for _, rule := range autogen.ComputeRules(policy, "") {
if validationFailureAction.Enforce() != enforce && (ns == "" || len(validationFailureActionOverrides) == 0) { if !rule.HasValidate() {
return false continue
}
// if the field isn't set, use the higher level policy setting
validationFailureAction := rule.Validation.ValidationFailureAction
if validationFailureAction == nil {
validationFailureAction = &policy.GetSpec().ValidationFailureAction
}
validationFailureActionOverrides := rule.Validation.ValidationFailureActionOverrides
if len(validationFailureActionOverrides) == 0 {
validationFailureActionOverrides = policy.GetSpec().ValidationFailureActionOverrides
}
if (ns == "" || len(validationFailureActionOverrides) == 0) && validationFailureAction.Enforce() == enforce {
filteredRules = append(filteredRules, rule)
continue
} }
for _, action := range validationFailureActionOverrides { for _, action := range validationFailureActionOverrides {
if action.Action.Enforce() != enforce && wildcard.CheckPatterns(action.Namespaces, ns) { if action.Action.Enforce() == enforce && wildcard.CheckPatterns(action.Namespaces, ns) {
return false filteredRules = append(filteredRules, rule)
continue
} }
} }
return true }
if len(filteredRules) > 0 {
filteredPolicy := policy.CreateDeepCopy()
filteredPolicy.GetSpec().Rules = filteredRules
return true, filteredPolicy
}
return false, nil
} }

View file

@ -80,10 +80,10 @@ func newPolicyMap() *policyMap {
} }
func computeEnforcePolicy(spec *kyvernov1.Spec) bool { func computeEnforcePolicy(spec *kyvernov1.Spec) bool {
if spec.GetValidationFailureAction().Enforce() { if spec.ValidationFailureAction.Enforce() {
return true return true
} }
for _, k := range spec.GetValidationFailureActionOverrides() { for _, k := range spec.ValidationFailureActionOverrides {
if k.Action.Enforce() { if k.Action.Enforce() {
return true return true
} }
@ -108,6 +108,17 @@ func (m *policyMap) set(key string, policy kyvernov1.PolicyInterface, client Res
} }
kindStates := map[policyKey]state{} kindStates := map[policyKey]state{}
for _, rule := range autogen.ComputeRules(policy, "") { for _, rule := range autogen.ComputeRules(policy, "") {
if rule.HasValidate() {
action := rule.Validation.ValidationFailureAction
if action != nil && action.Enforce() {
enforcePolicy = true
}
for _, k := range rule.Validation.ValidationFailureActionOverrides {
if k.Action.Enforce() {
enforcePolicy = true
}
}
}
entries := sets.New[policyKey]() entries := sets.New[policyKey]()
for _, gvk := range rule.MatchResources.GetKinds() { for _, gvk := range rule.MatchResources.GetKinds() {
group, version, kind, subresource := kubeutils.ParseKindSelector(gvk) group, version, kind, subresource := kubeutils.ParseKindSelector(gvk)

View file

@ -105,13 +105,23 @@ func BuildValidatingAdmissionPolicyBinding(
// set validation action for vap binding // set validation action for vap binding
var validationActions []admissionregistrationv1alpha1.ValidationAction var validationActions []admissionregistrationv1alpha1.ValidationAction
action := cpol.GetSpec().GetValidationFailureAction() validateAction := cpol.GetSpec().Rules[0].Validation.ValidationFailureAction
if action.Enforce() { if validateAction != nil {
if validateAction.Enforce() {
validationActions = append(validationActions, admissionregistrationv1alpha1.Deny) validationActions = append(validationActions, admissionregistrationv1alpha1.Deny)
} else if action.Audit() { } else if validateAction.Audit() {
validationActions = append(validationActions, admissionregistrationv1alpha1.Audit) validationActions = append(validationActions, admissionregistrationv1alpha1.Audit)
validationActions = append(validationActions, admissionregistrationv1alpha1.Warn) validationActions = append(validationActions, admissionregistrationv1alpha1.Warn)
} }
} else {
validateAction := cpol.GetSpec().ValidationFailureAction
if validateAction.Enforce() {
validationActions = append(validationActions, admissionregistrationv1alpha1.Deny)
} else if validateAction.Audit() {
validationActions = append(validationActions, admissionregistrationv1alpha1.Audit)
validationActions = append(validationActions, admissionregistrationv1alpha1.Warn)
}
}
// set validating admission policy binding spec // set validating admission policy binding spec
rule := cpol.GetSpec().Rules[0] rule := cpol.GetSpec().Rules[0]

View file

@ -17,14 +17,11 @@ func CanGenerateVAP(spec *kyvernov1.Spec) (bool, string) {
return false, msg return false, msg
} }
validationFailureActionOverrides := spec.GetValidationFailureActionOverrides() if ok, msg := checkValidationFailureActionOverrides(spec.ValidationFailureActionOverrides); !ok {
if len(validationFailureActionOverrides) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple validationFailureActionOverrides are not applicable."
return false, msg return false, msg
} }
if len(validationFailureActionOverrides) != 0 && len(validationFailureActionOverrides[0].Namespaces) != 0 { if ok, msg := checkValidationFailureActionOverrides(rule.Validation.ValidationFailureActionOverrides); !ok {
msg = "skip generating ValidatingAdmissionPolicy: Namespaces in validationFailureActionOverrides is not applicable."
return false, msg return false, msg
} }
@ -164,3 +161,17 @@ func checkResourceFilter(resFilters kyvernov1.ResourceFilters, isMatch bool) (bo
return true, msg return true, msg
} }
func checkValidationFailureActionOverrides(validationFailureActionOverrides []kyvernov1.ValidationFailureActionOverride) (bool, string) {
var msg string
if len(validationFailureActionOverrides) > 1 {
msg = "skip generating ValidatingAdmissionPolicy: multiple validationFailureActionOverrides are not applicable."
return false, msg
}
if len(validationFailureActionOverrides) != 0 && len(validationFailureActionOverrides[0].Namespaces) != 0 {
msg = "skip generating ValidatingAdmissionPolicy: Namespaces in validationFailureActionOverrides is not applicable."
return false, msg
}
return true, msg
}

View file

@ -114,12 +114,12 @@ func validateJSONPatch(patch string, ruleIdx int) error {
return nil return nil
} }
func checkValidationFailureAction(spec *kyvernov1.Spec) []string { func checkValidationFailureAction(validationFailureAction kyvernov1.ValidationFailureAction, validationFailureActionOverrides []kyvernov1.ValidationFailureActionOverride) []string {
msg := "Validation failure actions enforce/audit are deprecated, use Enforce/Audit instead." msg := "Validation failure actions enforce/audit are deprecated, use Enforce/Audit instead."
if spec.GetValidationFailureAction() == "enforce" || spec.GetValidationFailureAction() == "audit" { if validationFailureAction == "enforce" || validationFailureAction == "audit" {
return []string{msg} return []string{msg}
} }
for _, override := range spec.GetValidationFailureActionOverrides() { for _, override := range validationFailureActionOverrides {
if override.Action == "enforce" || override.Action == "audit" { if override.Action == "enforce" || override.Action == "audit" {
return []string{msg} return []string{msg}
} }
@ -138,7 +138,14 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
return warnings, fmt.Errorf("custom webhook configurations are only supported in kubernetes version 1.27.0 and above") return warnings, fmt.Errorf("custom webhook configurations are only supported in kubernetes version 1.27.0 and above")
} }
warnings = append(warnings, checkValidationFailureAction(spec)...) warnings = append(warnings, checkValidationFailureAction(spec.ValidationFailureAction, spec.ValidationFailureActionOverrides)...)
for _, rule := range spec.Rules {
if rule.HasValidate() {
if rule.Validation.ValidationFailureAction != nil {
warnings = append(warnings, checkValidationFailureAction(*rule.Validation.ValidationFailureAction, rule.Validation.ValidationFailureActionOverrides)...)
}
}
}
var errs field.ErrorList var errs field.ErrorList
specPath := field.NewPath("spec") specPath := field.NewPath("spec")
@ -206,7 +213,15 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
} }
if !policy.IsNamespaced() { if !policy.IsNamespaced() {
err := validateNamespaces(spec, specPath.Child("validationFailureActionOverrides")) for i, r := range spec.Rules {
if r.HasValidate() {
err := validateNamespaces(r.Validation.ValidationFailureActionOverrides, specPath.Child("rules").Index(i).Child("validate").Child("validationFailureActionOverrides"))
if err != nil {
return warnings, err
}
}
}
err := validateNamespaces(spec.ValidationFailureActionOverrides, specPath.Child("validationFailureActionOverrides"))
if err != nil { if err != nil {
return warnings, err return warnings, err
} }
@ -326,12 +341,20 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
if rule.HasVerifyImages() { if rule.HasVerifyImages() {
isAuditFailureAction := false isAuditFailureAction := false
if spec.GetValidationFailureAction() == kyvernov1.Audit { if spec.ValidationFailureAction.Audit() {
isAuditFailureAction = true isAuditFailureAction = true
} }
verifyImagePath := rulePath.Child("verifyImages") verifyImagePath := rulePath.Child("verifyImages")
for index, i := range rule.VerifyImages { for index, i := range rule.VerifyImages {
action := i.ValidationFailureAction
if action != nil {
if action.Audit() {
isAuditFailureAction = true
} else {
isAuditFailureAction = false
}
}
errs = append(errs, i.Validate(isAuditFailureAction, verifyImagePath.Index(index))...) errs = append(errs, i.Validate(isAuditFailureAction, verifyImagePath.Index(index))...)
} }
if len(errs) != 0 { if len(errs) != 0 {
@ -1538,7 +1561,7 @@ func validateWildcardsWithNamespaces(enforce, audit, enforceW, auditW []string)
return nil return nil
} }
func validateNamespaces(s *kyvernov1.Spec, path *field.Path) error { func validateNamespaces(validationFailureActionOverrides []kyvernov1.ValidationFailureActionOverride, path *field.Path) error {
action := map[string]sets.Set[string]{ action := map[string]sets.Set[string]{
"enforce": sets.New[string](), "enforce": sets.New[string](),
"audit": sets.New[string](), "audit": sets.New[string](),
@ -1546,7 +1569,7 @@ func validateNamespaces(s *kyvernov1.Spec, path *field.Path) error {
"auditW": sets.New[string](), "auditW": sets.New[string](),
} }
for i, vfa := range s.GetValidationFailureActionOverrides() { for i, vfa := range validationFailureActionOverrides {
if !vfa.Action.IsValid() { if !vfa.Action.IsValid() {
return fmt.Errorf("invalid action") return fmt.Errorf("invalid action")
} }

View file

@ -141,28 +141,40 @@ func (h *resourceHandlers) Validate(ctx context.Context, logger logr.Logger, req
var ok bool var ok bool
var msg string var msg string
var warnings []string var warnings []string
var enforceResponses []engineapi.EngineResponse
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
ok, msg, warnings = vh.HandleValidationEnforce(ctx, request, policies, startTime) ok, msg, warnings, enforceResponses = vh.HandleValidationEnforce(ctx, request, policies, startTime)
}() }()
go h.auditPool.Submit(func() {
vh.HandleValidationAudit(ctx, request)
})
if !admissionutils.IsDryRun(request.AdmissionRequest) { if !admissionutils.IsDryRun(request.AdmissionRequest) {
h.handleBackgroundApplies(ctx, logger, request, generatePolicies, mutatePolicies, startTime, nil) h.handleBackgroundApplies(ctx, logger, request, generatePolicies, mutatePolicies, startTime, nil)
} }
if len(policies) == 0 {
return admissionutils.ResponseSuccess(request.UID)
}
wg.Wait() wg.Wait()
if !ok { if !ok {
logger.Info("admission request denied") logger.Info("admission request denied")
events := webhookutils.GenerateEvents(enforceResponses, true)
h.eventGen.Add(events...)
return admissionutils.Response(request.UID, errors.New(msg), warnings...) return admissionutils.Response(request.UID, errors.New(msg), warnings...)
} }
go h.auditPool.Submit(func() {
auditResponses := vh.HandleValidationAudit(ctx, request)
var events []event.Info
switch {
case len(auditResponses) == 0:
events = webhookutils.GenerateEvents(enforceResponses, false)
case len(enforceResponses) == 0:
events = webhookutils.GenerateEvents(auditResponses, false)
default:
responses := mergeEngineResponses(auditResponses, enforceResponses)
events = webhookutils.GenerateEvents(responses, false)
}
h.eventGen.Add(events...)
})
return admissionutils.ResponseSuccess(request.UID, warnings...) return admissionutils.ResponseSuccess(request.UID, warnings...)
} }
@ -310,3 +322,34 @@ func filterPolicies(ctx context.Context, failurePolicy string, policies ...kyver
} }
return results return results
} }
func mergeEngineResponses(auditResponses, enforceResponses []engineapi.EngineResponse) []engineapi.EngineResponse {
responseMap := make(map[string]engineapi.EngineResponse)
var responses []engineapi.EngineResponse
for _, enforceResponse := range enforceResponses {
responseMap[enforceResponse.Policy().GetName()] = enforceResponse
}
for _, auditResponse := range auditResponses {
policyName := auditResponse.Policy().GetName()
if enforceResponse, exists := responseMap[policyName]; exists {
response := auditResponse
for _, ruleResponse := range enforceResponse.PolicyResponse.Rules {
response.PolicyResponse.Add(ruleResponse.Stats(), ruleResponse)
}
responses = append(responses, response)
delete(responseMap, policyName)
} else {
responses = append(responses, auditResponse)
}
}
if len(responseMap) != 0 {
for _, enforceResponse := range responseMap {
responses = append(responses, enforceResponse)
}
}
return responses
}

View file

@ -31,8 +31,8 @@ type ValidationHandler interface {
// HandleValidation handles validating webhook admission request // HandleValidation handles validating webhook admission request
// If there are no errors in validating rule we apply generation rules // If there are no errors in validating rule we apply generation rules
// patchedResource is the (resource + patches) after applying mutation rules // patchedResource is the (resource + patches) after applying mutation rules
HandleValidationEnforce(context.Context, handlers.AdmissionRequest, []kyvernov1.PolicyInterface, time.Time) (bool, string, []string) HandleValidationEnforce(context.Context, handlers.AdmissionRequest, []kyvernov1.PolicyInterface, time.Time) (bool, string, []string, []engineapi.EngineResponse)
HandleValidationAudit(context.Context, handlers.AdmissionRequest) HandleValidationAudit(context.Context, handlers.AdmissionRequest) []engineapi.EngineResponse
} }
func NewValidationHandler( func NewValidationHandler(
@ -82,18 +82,18 @@ func (v *validationHandler) HandleValidationEnforce(
request handlers.AdmissionRequest, request handlers.AdmissionRequest,
policies []kyvernov1.PolicyInterface, policies []kyvernov1.PolicyInterface,
admissionRequestTimestamp time.Time, admissionRequestTimestamp time.Time,
) (bool, string, []string) { ) (bool, string, []string, []engineapi.EngineResponse) {
resourceName := admissionutils.GetResourceName(request.AdmissionRequest) resourceName := admissionutils.GetResourceName(request.AdmissionRequest)
logger := v.log.WithValues("action", "validate", "resource", resourceName, "operation", request.Operation, "gvk", request.Kind) logger := v.log.WithValues("action", "validate", "resource", resourceName, "operation", request.Operation, "gvk", request.Kind)
if len(policies) == 0 { if len(policies) == 0 {
return true, "", nil return true, "", nil, nil
} }
policyContext, err := v.buildPolicyContextFromAdmissionRequest(logger, request) policyContext, err := v.buildPolicyContextFromAdmissionRequest(logger, request)
if err != nil { if err != nil {
msg := fmt.Sprintf("failed to create policy context: %v", err) msg := fmt.Sprintf("failed to create policy context: %v", err)
return false, msg, nil return false, msg, nil, nil
} }
var engineResponses []engineapi.EngineResponse var engineResponses []engineapi.EngineResponse
@ -118,7 +118,7 @@ func (v *validationHandler) HandleValidationEnforce(
engineResponses = append(engineResponses, engineResponse) engineResponses = append(engineResponses, engineResponse)
if !engineResponse.IsSuccessful() { if !engineResponse.IsSuccessful() {
logger.V(2).Info("validation failed", "action", policy.GetSpec().GetValidationFailureAction(), "policy", policy.GetName(), "failed rules", engineResponse.GetFailedRules()) logger.V(2).Info("validation failed", "action", "Enforce", "policy", policy.GetName(), "failed rules", engineResponse.GetFailedRules())
return return
} }
@ -130,12 +130,10 @@ func (v *validationHandler) HandleValidationEnforce(
} }
blocked := webhookutils.BlockRequest(engineResponses, failurePolicy, logger) blocked := webhookutils.BlockRequest(engineResponses, failurePolicy, logger)
events := webhookutils.GenerateEvents(engineResponses, blocked)
v.eventGen.Add(events...)
if blocked { if blocked {
logger.V(4).Info("admission request blocked") logger.V(4).Info("admission request blocked")
return false, webhookutils.GetBlockedMessages(engineResponses), nil return false, webhookutils.GetBlockedMessages(engineResponses), nil, engineResponses
} }
go func() { go func() {
@ -147,37 +145,36 @@ func (v *validationHandler) HandleValidationEnforce(
}() }()
warnings := webhookutils.GetWarningMessages(engineResponses) warnings := webhookutils.GetWarningMessages(engineResponses)
return true, "", warnings return true, "", warnings, engineResponses
} }
func (v *validationHandler) HandleValidationAudit( func (v *validationHandler) HandleValidationAudit(
ctx context.Context, ctx context.Context,
request handlers.AdmissionRequest, request handlers.AdmissionRequest,
) { ) []engineapi.EngineResponse {
gvr := schema.GroupVersionResource(request.Resource) gvr := schema.GroupVersionResource(request.Resource)
policies := v.pCache.GetPolicies(policycache.ValidateAudit, gvr, request.SubResource, request.Namespace) policies := v.pCache.GetPolicies(policycache.ValidateAudit, gvr, request.SubResource, request.Namespace)
if len(policies) == 0 { if len(policies) == 0 {
return return nil
} }
policyContext, err := v.buildPolicyContextFromAdmissionRequest(v.log, request) policyContext, err := v.buildPolicyContextFromAdmissionRequest(v.log, request)
if err != nil { if err != nil {
v.log.Error(err, "failed to build policy context") v.log.Error(err, "failed to build policy context")
return return nil
} }
var responses []engineapi.EngineResponse
needsReport := needsReports(request, policyContext.NewResource(), v.admissionReports) needsReport := needsReports(request, policyContext.NewResource(), v.admissionReports)
tracing.Span( tracing.Span(
context.Background(), context.Background(),
"", "",
fmt.Sprintf("AUDIT %s %s", request.Operation, request.Kind), fmt.Sprintf("AUDIT %s %s", request.Operation, request.Kind),
func(ctx context.Context, span trace.Span) { func(ctx context.Context, span trace.Span) {
responses, err := v.buildAuditResponses(ctx, policyContext, policies) responses, err = v.buildAuditResponses(ctx, policyContext, policies)
if err != nil { if err != nil {
v.log.Error(err, "failed to build audit responses") v.log.Error(err, "failed to build audit responses")
} }
events := webhookutils.GenerateEvents(responses, false)
v.eventGen.Add(events...)
if needsReport { if needsReport {
if err := v.createReports(ctx, policyContext.NewResource(), request, responses...); err != nil { if err := v.createReports(ctx, policyContext.NewResource(), request, responses...); err != nil {
v.log.Error(err, "failed to create report") v.log.Error(err, "failed to create report")
@ -186,6 +183,7 @@ func (v *validationHandler) HandleValidationAudit(
}, },
trace.WithLinks(trace.LinkFromContext(ctx)), trace.WithLinks(trace.LinkFromContext(ctx)),
) )
return responses
} }
func (v *validationHandler) buildAuditResponses( func (v *validationHandler) buildAuditResponses(

View file

@ -3,7 +3,6 @@ kind: ClusterPolicy
metadata: metadata:
name: enforce-label name: enforce-label
spec: spec:
validationFailureAction: Audit
background: false background: false
rules: rules:
- name: enforce-label - name: enforce-label
@ -13,6 +12,7 @@ spec:
kinds: kinds:
- Pod - Pod
validate: validate:
validationFailureAction: Audit
message: "The foo label must be set." message: "The foo label must be set."
pattern: pattern:
metadata: metadata:

View file

@ -19,12 +19,12 @@ spec:
- Pod - Pod
name: validate-image-tag name: validate-image-tag
validate: validate:
validationFailureAction: Audit
message: Using a mutable image tag e.g. 'latest' is not allowed. message: Using a mutable image tag e.g. 'latest' is not allowed.
pattern: pattern:
spec: spec:
containers: containers:
- image: '!*:latest' - image: '!*:latest'
validationFailureAction: Audit
--- ---
apiVersion: kyverno.io/v1 apiVersion: kyverno.io/v1
kind: ClusterPolicy kind: ClusterPolicy
@ -48,6 +48,7 @@ spec:
operator: NotEquals operator: NotEquals
value: DELETE value: DELETE
validate: validate:
validationFailureAction: Audit
foreach: foreach:
- deny: - deny:
conditions: conditions:
@ -57,4 +58,3 @@ spec:
value: '{{ element.securityContext.capabilities.drop || '''' }}' value: '{{ element.securityContext.capabilities.drop || '''' }}'
list: request.object.spec.[ephemeralContainers, initContainers, containers][] list: request.object.spec.[ephemeralContainers, initContainers, containers][]
message: Containers must drop `ALL` capabilities. message: Containers must drop `ALL` capabilities.
validationFailureAction: Audit

View file

@ -19,6 +19,7 @@ spec:
operator: NotEquals operator: NotEquals
value: DELETE value: DELETE
validate: validate:
validationFailureAction: Enforce
foreach: foreach:
- context: - context:
- imageRegistry: - imageRegistry:
@ -35,7 +36,6 @@ spec:
value: ghcr.io value: ghcr.io
list: request.object.spec.containers list: request.object.spec.containers
message: images with root user are not allowed message: images with root user are not allowed
validationFailureAction: Enforce
--- ---
apiVersion: kyverno.io/v1 apiVersion: kyverno.io/v1
kind: ClusterPolicy kind: ClusterPolicy
@ -57,6 +57,7 @@ spec:
operator: NotEquals operator: NotEquals
value: DELETE value: DELETE
validate: validate:
validationFailureAction: Enforce
foreach: foreach:
- context: - context:
- imageRegistry: - imageRegistry:
@ -76,4 +77,3 @@ spec:
list: request.object.spec.containers list: request.object.spec.containers
message: Images must specify a source/base image from which they are built to message: Images must specify a source/base image from which they are built to
be valid. be valid.
validationFailureAction: Enforce

View file

@ -14,10 +14,10 @@ spec:
- Pod - Pod
name: validate-default-proc-mount name: validate-default-proc-mount
validate: validate:
validationFailureAction: Audit
message: Default proc mount should set to Unmasked message: Default proc mount should set to Unmasked
pattern: pattern:
spec: spec:
containers: containers:
- securityContext: - securityContext:
procMount: Unmasked procMount: Unmasked
validationFailureAction: Audit

View file

@ -14,6 +14,7 @@ spec:
- Pod - Pod
name: validate-selinux-options name: validate-selinux-options
validate: validate:
validationFailureAction: Audit
message: SELinux level is required message: SELinux level is required
pattern: pattern:
spec: spec:
@ -21,4 +22,3 @@ spec:
- securityContext: - securityContext:
seLinuxOptions: seLinuxOptions:
level: ?* level: ?*
validationFailureAction: Audit

View file

@ -14,6 +14,7 @@ spec:
- Pod - Pod
name: validate-volumes-whitelist name: validate-volumes-whitelist
validate: validate:
validationFailureAction: Audit
anyPattern: anyPattern:
- spec: - spec:
volumes: volumes:
@ -25,4 +26,3 @@ spec:
volumes: volumes:
- configMap: '*' - configMap: '*'
message: Volume type is not of type hostPath, emptyDir, or configMap. message: Volume type is not of type hostPath, emptyDir, or configMap.
validationFailureAction: Audit

View file

@ -3,7 +3,6 @@ kind: ClusterPolicy
metadata: metadata:
name: disallow-host-namespaces name: disallow-host-namespaces
spec: spec:
validationFailureAction: Enforce
background: false background: false
rules: rules:
- name: host-namespaces - name: host-namespaces
@ -13,6 +12,7 @@ spec:
kinds: kinds:
- Pod - Pod
validate: validate:
validationFailureAction: Enforce
message: >- message: >-
Sharing the host namespaces is disallowed. The fields spec.hostNetwork, Sharing the host namespaces is disallowed. The fields spec.hostNetwork,
spec.hostIPC, and spec.hostPID must be unset or set to `false`. spec.hostIPC, and spec.hostPID must be unset or set to `false`.

View file

@ -3,7 +3,6 @@ kind: ClusterPolicy
metadata: metadata:
name: max-containers name: max-containers
spec: spec:
validationFailureAction: Enforce
background: false background: false
rules: rules:
- name: max-two-containers - name: max-two-containers
@ -13,6 +12,7 @@ spec:
kinds: kinds:
- Pod - Pod
validate: validate:
validationFailureAction: Enforce
message: "A maximum of 2 containers are allowed inside a Pod." message: "A maximum of 2 containers are allowed inside a Pod."
deny: deny:
conditions: conditions:

View file

@ -4,7 +4,6 @@ metadata:
name: psa name: psa
spec: spec:
background: true background: true
validationFailureAction: Enforce
rules: rules:
- name: baseline - name: baseline
match: match:
@ -13,6 +12,7 @@ spec:
kinds: kinds:
- Pod - Pod
validate: validate:
validationFailureAction: Enforce
podSecurity: podSecurity:
level: baseline level: baseline
version: latest version: latest

View file

@ -0,0 +1,21 @@
apiVersion: kyverno.io/v2
kind: PolicyException
metadata:
name: delta-exception
namespace: delta
spec:
exceptions:
- policyName: disallow-host-namespaces
ruleNames:
- host-namespaces
- autogen-host-namespaces
match:
any:
- resources:
kinds:
- Pod
- Deployment
namespaces:
- delta
names:
- important-tool*

View file

@ -0,0 +1,29 @@
apiVersion: cli.kyverno.io/v1alpha1
exceptions:
- exception.yaml
kind: Test
metadata:
name: kyverno-test
policies:
- policy.yaml
resources:
- resources.yaml
results:
- kind: Deployment
policy: disallow-host-namespaces
resources:
- bad-deployment
result: fail
rule: autogen-host-namespaces
- kind: Deployment
policy: disallow-host-namespaces
resources:
- good-deployment
result: pass
rule: autogen-host-namespaces
- kind: Deployment
policy: disallow-host-namespaces
resources:
- important-tool
result: skip
rule: autogen-host-namespaces

View file

@ -0,0 +1,23 @@
apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
name: disallow-host-namespaces
spec:
background: false
validationFailureAction: Enforce
rules:
- name: host-namespaces
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Sharing the host namespaces is disallowed. The fields spec.hostNetwork,
spec.hostIPC, and spec.hostPID must be unset or set to `false`.
pattern:
spec:
=(hostPID): "false"
=(hostIPC): "false"
=(hostNetwork): "false"

View file

@ -0,0 +1,66 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: important-tool
namespace: delta
labels:
app: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
hostIPC: true
containers:
- image: busybox:1.35
name: busybox
command: ["sleep", "1d"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bad-deployment
labels:
app: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
hostIPC: true
containers:
- image: busybox:1.35
name: busybox
command: ["sleep", "1d"]
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: good-deployment
labels:
app: busybox
spec:
replicas: 1
selector:
matchLabels:
app: busybox
template:
metadata:
labels:
app: busybox
spec:
hostIPC: false
containers:
- image: busybox:1.35
name: busybox
command: ["sleep", "1d"]

View file

@ -0,0 +1,15 @@
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: kyverno-test.yaml
policies:
- policy.yaml
resources:
- resources.yaml
results:
- kind: Namespace
policy: restrict-labels
resources:
- kyverno-system-tst
result: fail
rule: restrict-labels

View file

@ -0,0 +1,39 @@
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
annotations:
policies.kyverno.io/category: Labels
policies.kyverno.io/description: This policy prevents the use of an label beginning
with a common key name (in this case "platform.das-schiff.telekom.de/owner |
owner"). This can be useful to ensure users either don't set reserved labels
or to force them to use a newer version of an label.
policies.kyverno.io/minversion: 1.3.0
policies.kyverno.io/title: Restrict Labels on Namespaces
labels:
policy.schiff.telekom.de: enforced
name: restrict-labels
spec:
admission: true
background: false
validationFailureAction: Enforce
rules:
- exclude:
any:
- clusterRoles:
- cluster-admin
resources: {}
match:
any:
- resources:
kinds:
- Namespace
name: restrict-labels
validate:
message: Every namespace has to have `platform.das-schiff.telekom.de/owner`
label. It must not have value `das-schiff` which is reserved for system namespaces
pattern:
metadata:
labels:
=(schiff.telekom.de/owner): '!schiff'
platform.das-schiff.telekom.de/owner: '!das-schiff'

View file

@ -0,0 +1,8 @@
apiVersion: v1
kind: Namespace
metadata:
name: kyverno-system-tst
labels:
name: kyverno-system-tst
schiff.telekom.de/owner: schiff
platform.das-schiff.telekom.de/owner: das-schiff

View file

@ -21,6 +21,7 @@ spec:
- test - test
name: require-image-tag name: require-image-tag
validate: validate:
validationFailureAction: Audit
message: An image tag is required. message: An image tag is required.
pattern: pattern:
spec: spec:

View file

@ -21,6 +21,7 @@ spec:
- test - test
name: require-image-tag name: require-image-tag
validate: validate:
validationFailureAction: Audit
message: An image tag is required. message: An image tag is required.
pattern: pattern:
spec: spec:

View file

@ -21,6 +21,7 @@ spec:
- test - test
name: require-image-tag name: require-image-tag
validate: validate:
validationFailureAction: Audit
message: An image tag is required. message: An image tag is required.
pattern: pattern:
spec: spec:

View file

@ -38,4 +38,3 @@ spec:
kinds: kinds:
- Namespace - Namespace
name: default-deny name: default-deny
validationFailureAction: Audit

View file

@ -57,4 +57,3 @@ spec:
kinds: kinds:
- Namespace - Namespace
name: generate-limitrange name: generate-limitrange
validationFailureAction: Audit

View file

@ -34,4 +34,3 @@ spec:
kinds: kinds:
- Namespace - Namespace
name: clone-list-labelled-secrets name: clone-list-labelled-secrets
validationFailureAction: Audit

View file

@ -32,4 +32,3 @@ spec:
kinds: kinds:
- Namespace - Namespace
name: sync-image-pull-secret name: sync-image-pull-secret
validationFailureAction: Audit

View file

@ -80,4 +80,3 @@ spec:
to_string(@) to_string(@)
}} }}
name: mutate1 name: mutate1
validationFailureAction: Enforce

View file

@ -77,4 +77,3 @@ spec:
- key: '{{ tg_attributes }}' - key: '{{ tg_attributes }}'
operator: Equals operator: Equals
value: "false" value: "false"
validationFailureAction: Audit

View file

@ -24,4 +24,3 @@ spec:
+(sizeLimit): 20Mi +(sizeLimit): 20Mi
name: '{{ element.name }}' name: '{{ element.name }}'
name: setDefault name: setDefault
validationFailureAction: Audit

View file

@ -27,4 +27,3 @@ spec:
op: add op: add
value: "100m" value: "100m"
name: add-default-requests name: add-default-requests
validationFailureAction: Audit

View file

@ -27,7 +27,6 @@ spec:
- key: '{{ request.operation }}' - key: '{{ request.operation }}'
operator: Equals operator: Equals
value: CREATE value: CREATE
validationFailureAction: Audit
--- ---
apiVersion: kyverno.io/v1 apiVersion: kyverno.io/v1
kind: ClusterPolicy kind: ClusterPolicy
@ -53,4 +52,3 @@ spec:
- image: registry.digitalocean.com/runlevl4/{{ images.containers."{{element.name}}".name}}:{{images.containers."{{element.name}}".tag}} - image: registry.digitalocean.com/runlevl4/{{ images.containers."{{element.name}}".name}}:{{images.containers."{{element.name}}".tag}}
name: '{{ element.name }}' name: '{{ element.name }}'
name: test name: test
validationFailureAction: Audit

View file

@ -29,4 +29,3 @@ spec:
value: value:
- CREATE - CREATE
- UPDATE - UPDATE
validationFailureAction: Audit

View file

@ -43,7 +43,6 @@ spec:
- key: not-the-name - key: not-the-name
operator: AllIn operator: AllIn
value: '{{ request.object.metadata.labels | keys(@) }}' value: '{{ request.object.metadata.labels | keys(@) }}'
validationFailureAction: Audit
--- ---
apiVersion: kyverno.io/v1 apiVersion: kyverno.io/v1
kind: Policy kind: Policy
@ -75,7 +74,6 @@ spec:
- name: ndots - name: ndots
value: "1" value: "1"
name: add-ndots name: add-ndots
validationFailureAction: Audit
--- ---
apiVersion: kyverno.io/v1 apiVersion: kyverno.io/v1
kind: ClusterPolicy kind: ClusterPolicy
@ -104,4 +102,3 @@ spec:
op: replace op: replace
value: {{ annotations }} value: {{ annotations }}
name: object_from_lists name: object_from_lists
validationFailureAction: Audit

View file

@ -21,6 +21,7 @@ spec:
- Pod - Pod
name: require-image-tag name: require-image-tag
validate: validate:
validationFailureAction: Audit
message: An image tag is required. message: An image tag is required.
pattern: pattern:
spec: spec:
@ -33,9 +34,9 @@ spec:
- Pod - Pod
name: validate-image-tag name: validate-image-tag
validate: validate:
validationFailureAction: Audit
message: Using a mutable image tag e.g. 'latest' is not allowed. message: Using a mutable image tag e.g. 'latest' is not allowed.
pattern: pattern:
spec: spec:
containers: containers:
- image: '!*:latest' - image: '!*:latest'
validationFailureAction: Audit

View file

@ -0,0 +1,41 @@
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
annotations:
policies.kyverno.io/category: Best Practices
policies.kyverno.io/description: 'The '':latest'' tag is mutable and can lead
to unexpected errors if the image changes. A best practice is to use an immutable
tag that maps to a specific version of an application pod. '
name: disallow-latest-tag
spec:
validationFailureAction: Audit
admission: true
background: false
rules:
- match:
any:
- clusterRoles:
- cluster-admin
resources:
kinds:
- Pod
name: require-image-tag
validate:
message: An image tag is required.
pattern:
spec:
containers:
- image: '*:*'
- match:
any:
- resources:
kinds:
- Pod
name: validate-image-tag
validate:
message: Using a mutable image tag e.g. 'latest' is not allowed.
pattern:
spec:
containers:
- image: '!*:latest'

View file

@ -0,0 +1,26 @@
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: kyverno-test.yaml
policies:
- disallow_latest_tag.yaml
resources:
- resource.yaml
results:
- kind: Pod
policy: disallow-latest-tag
resources:
- myapp-pod1
- myapp-pod2
- myapp-pod3
result: pass
rule: require-image-tag
- kind: Pod
policy: disallow-latest-tag
resources:
- myapp-pod1
- myapp-pod2
- myapp-pod3
result: pass
rule: validate-image-tag
userinfo: user_info.yaml

View file

@ -0,0 +1,34 @@
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod1
labels:
app: myapp1
spec:
containers:
- name: nginx
image: nginx:1.12
---
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod2
labels:
app: myapp2
spec:
containers:
- name: nginx
image: nginx:1.12
---
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod3
labels:
app: myapp3
spec:
containers:
- name: nginx
image: ngnix:1.12

View file

@ -0,0 +1,6 @@
apiVersion: cli.kyverno.io/v1alpha1
clusterRoles:
- cluster-admin
kind: UserInfo
userInfo:
username: molybdenum@somecorp.com

View file

@ -0,0 +1,16 @@
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: kyverno-test.yaml
policies:
- policy.yaml
resources:
- resource.yaml
results:
- kind: Pod
policy: disallow-protected-namespaces
resources:
- namespace2/test2
- namespace1/test1
result: fail
rule: disallow

View file

@ -0,0 +1,22 @@
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-protected-namespaces
spec:
validationFailureAction: Enforce
admission: true
background: false
rules:
- match:
all:
- resources:
kinds:
- '*'
namespaces:
- namespace1
- namespace2
name: disallow
validate:
deny: {}
message: This resource is protected and changes are not allowed.

View file

@ -0,0 +1,31 @@
apiVersion: v1
kind: Pod
metadata:
name: test1
namespace: namespace1
spec:
containers:
- name: nginx
image: nginx:latest
---
apiVersion: v1
kind: Pod
metadata:
name: test2
namespace: namespace2
spec:
containers:
- name: nginx
image: nginx
---
apiVersion: v1
kind: Pod
metadata:
name: test3
namespace: namespace3
spec:
containers:
- name: nginx
image: nginx

View file

@ -17,6 +17,6 @@ spec:
- namespace2 - namespace2
name: disallow name: disallow
validate: validate:
validationFailureAction: Enforce
deny: {} deny: {}
message: This resource is protected and changes are not allowed. message: This resource is protected and changes are not allowed.
validationFailureAction: Enforce

View file

@ -0,0 +1,16 @@
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: kyverno-test.yaml
policies:
- policy.yaml
resources:
- resource.yaml
results:
- kind: Pod
policy: enforce-pod-name
resources:
- test1/test-nginx
result: pass
rule: validate-name
variables: value.yaml

View file

@ -0,0 +1,27 @@
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-pod-name
spec:
validationFailureAction: Audit
admission: true
background: true
rules:
- match:
any:
- resources:
kinds:
- Pod
namespaceSelector:
matchExpressions:
- key: foo.com/managed-state
operator: In
values:
- managed
name: validate-name
validate:
message: The Pod must end with -nginx
pattern:
metadata:
name: '*-nginx'

View file

@ -0,0 +1,9 @@
kind: Pod
apiVersion: v1
metadata:
name: test-nginx
namespace: test1
spec:
containers:
- name: nginx
image: nginx:latest

View file

@ -0,0 +1,6 @@
apiVersion: cli.kyverno.io/v1alpha1
kind: Values
namespaceSelector:
- labels:
foo.com/managed-state: managed
name: test1

View file

@ -20,8 +20,8 @@ spec:
- managed - managed
name: validate-name name: validate-name
validate: validate:
validationFailureAction: Audit
message: The Pod must end with -nginx message: The Pod must end with -nginx
pattern: pattern:
metadata: metadata:
name: '*-nginx' name: '*-nginx'
validationFailureAction: Audit

View file

@ -14,6 +14,7 @@ spec:
- Service - Service
name: check-loadbalancer-public name: check-loadbalancer-public
validate: validate:
validationFailureAction: Enforce
anyPattern: anyPattern:
- metadata: - metadata:
annotations: annotations:
@ -26,4 +27,3 @@ spec:
message: Service of type 'LoadBalancer' is public and does not explicitly define message: Service of type 'LoadBalancer' is public and does not explicitly define
network security. To use a public LB you must supply either spec[loadBalancerSourceRanges] network security. To use a public LB you must supply either spec[loadBalancerSourceRanges]
or the 'service.beta.kubernetes.io/aws-load-balancer-security-groups' annotation. or the 'service.beta.kubernetes.io/aws-load-balancer-security-groups' annotation.
validationFailureAction: Enforce

View file

@ -14,10 +14,10 @@ spec:
- Pod - Pod
name: check-for-labels name: check-for-labels
validate: validate:
validationFailureAction: Enforce
message: Both `app` and `owner` labels must be set on all workloads message: Both `app` and `owner` labels must be set on all workloads
pattern: pattern:
metadata: metadata:
labels: labels:
app: ?* app: ?*
owner: ?* owner: ?*
validationFailureAction: Enforce

View file

@ -0,0 +1,22 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-host-path
spec:
background: false
validationFailureAction: Audit
rules:
- name: host-path
match:
any:
- resources:
kinds:
- Pod
celPreconditions:
- expression: "object.metadata.labels['color'] == 'red'"
name: "Label should be red"
validate:
cel:
expressions:
- expression: "!has(object.spec.volumes) || object.spec.volumes.all(volume, !has(volume.hostPath))"
message: "HostPath volumes are forbidden. The field spec.volumes[*].hostPath must be unset."

View file

@ -0,0 +1,27 @@
apiVersion: cli.kyverno.io/v1alpha1
kind: Test
metadata:
name: kyverno-test.yaml
policies:
- disallow-host-path.yaml
resources:
- resources.yaml
results:
- kind: Pod
policy: disallow-host-path
resources:
- bad-pod
result: fail
rule: host-path
- kind: Pod
policy: disallow-host-path
resources:
- good-pod
result: pass
rule: host-path
- kind: Pod
policy: disallow-host-path
resources:
- skipped-pod
result: skip
rule: host-path

View file

@ -0,0 +1,52 @@
apiVersion: v1
kind: Pod
metadata:
name: skipped-pod
labels:
color: blue
spec:
containers:
- name: nginx-container
image: nginx:latest
volumeMounts:
- name: hostpath-volume
mountPath: /var/www/html
volumes:
- name: hostpath-volume
hostPath:
path: /var/log
---
apiVersion: v1
kind: Pod
metadata:
name: bad-pod
labels:
color: red
spec:
containers:
- name: nginx-container
image: nginx:latest
volumeMounts:
- name: hostpath-volume
mountPath: /var/www/html
volumes:
- name: hostpath-volume
hostPath:
path: /var/log
---
apiVersion: v1
kind: Pod
metadata:
name: good-pod
labels:
color: red
spec:
containers:
- name: nginx-container
image: nginx:latest
volumeMounts:
- name: hostpath-volume
mountPath: /var/www/html
volumes:
- name: hostpath-volume
emptyDir: {}

Some files were not shown because too many files have changed in this diff Show more