diff --git a/api/kyverno/v2/policy_exception_types.go b/api/kyverno/v2/policy_exception_types.go index fbf0c1ca5e..4f11c9337a 100644 --- a/api/kyverno/v2/policy_exception_types.go +++ b/api/kyverno/v2/policy_exception_types.go @@ -16,6 +16,7 @@ limitations under the License. package v2 import ( + kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" kyvernov2beta1 "github.com/kyverno/kyverno/api/kyverno/v2beta1" "github.com/kyverno/kyverno/ext/wildcard" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,6 +52,11 @@ func (p *PolicyException) GetKind() string { return "PolicyException" } +// HasPodSecurity checks if podSecurity controls is specified +func (p *PolicyException) HasPodSecurity() bool { + return len(p.Spec.PodSecurity) > 0 +} + // PolicyExceptionSpec stores policy exception spec type PolicyExceptionSpec struct { // Background controls if exceptions are applied to existing policies during a background scan. @@ -68,6 +74,11 @@ type PolicyExceptionSpec struct { // Exceptions is a list policy/rules to be excluded Exceptions []Exception `json:"exceptions" yaml:"exceptions"` + + // PodSecurity specifies the Pod Security Standard controls to be excluded. + // Applicable only to policies that have validate.podSecurity subrule. + // +optional + PodSecurity []kyvernov1.PodSecurityStandard `json:"podSecurity,omitempty" yaml:"podSecurity,omitempty"` } func (p *PolicyExceptionSpec) BackgroundProcessingEnabled() bool { diff --git a/api/kyverno/v2/zz_generated.deepcopy.go b/api/kyverno/v2/zz_generated.deepcopy.go index 3be826dc3d..a433a13ef2 100644 --- a/api/kyverno/v2/zz_generated.deepcopy.go +++ b/api/kyverno/v2/zz_generated.deepcopy.go @@ -709,6 +709,13 @@ func (in *PolicyExceptionSpec) DeepCopyInto(out *PolicyExceptionSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.PodSecurity != nil { + in, out := &in.PodSecurity, &out.PodSecurity + *out = make([]kyvernov1.PodSecurityStandard, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/api/kyverno/v2beta1/policy_exception_types.go b/api/kyverno/v2beta1/policy_exception_types.go index 7e22fe3ce8..b48c6dbb4b 100644 --- a/api/kyverno/v2beta1/policy_exception_types.go +++ b/api/kyverno/v2beta1/policy_exception_types.go @@ -16,6 +16,7 @@ limitations under the License. package v2beta1 import ( + kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/ext/wildcard" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/validation/field" @@ -51,6 +52,11 @@ func (p *PolicyException) GetKind() string { return "PolicyException" } +// HasPodSecurity checks if podSecurity controls is specified +func (p *PolicyException) HasPodSecurity() bool { + return len(p.Spec.PodSecurity) > 0 +} + // PolicyExceptionSpec stores policy exception spec type PolicyExceptionSpec struct { // Background controls if exceptions are applied to existing policies during a background scan. @@ -68,6 +74,11 @@ type PolicyExceptionSpec struct { // Exceptions is a list policy/rules to be excluded Exceptions []Exception `json:"exceptions" yaml:"exceptions"` + + // PodSecurity specifies the Pod Security Standard controls to be excluded. + // Applicable only to policies that have validate.podSecurity subrule. + // +optional + PodSecurity []kyvernov1.PodSecurityStandard `json:"podSecurity,omitempty" yaml:"podSecurity,omitempty"` } func (p *PolicyExceptionSpec) BackgroundProcessingEnabled() bool { diff --git a/api/kyverno/v2beta1/zz_generated.deepcopy.go b/api/kyverno/v2beta1/zz_generated.deepcopy.go index b3326b74eb..1c0ca94bc8 100755 --- a/api/kyverno/v2beta1/zz_generated.deepcopy.go +++ b/api/kyverno/v2beta1/zz_generated.deepcopy.go @@ -552,6 +552,13 @@ func (in *PolicyExceptionSpec) DeepCopyInto(out *PolicyExceptionSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.PodSecurity != nil { + in, out := &in.PodSecurity, &out.PodSecurity + *out = make([]v1.PodSecurityStandard, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/charts/kyverno/charts/crds/templates/crds.yaml b/charts/kyverno/charts/crds/templates/crds.yaml index 155454b441..66946c7aa8 100644 --- a/charts/kyverno/charts/crds/templates/crds.yaml +++ b/charts/kyverno/charts/crds/templates/crds.yaml @@ -46256,6 +46256,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -46847,6 +46899,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -47438,6 +47542,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match diff --git a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policyexceptions.yaml b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policyexceptions.yaml index 0316731972..a5b2d0c523 100644 --- a/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policyexceptions.yaml +++ b/cmd/cli/kubectl-kyverno/data/crds/kyverno.io_policyexceptions.yaml @@ -600,6 +600,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -1191,6 +1243,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -1782,6 +1886,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match diff --git a/config/crds/kyverno.io_policyexceptions.yaml b/config/crds/kyverno.io_policyexceptions.yaml index 0316731972..a5b2d0c523 100644 --- a/config/crds/kyverno.io_policyexceptions.yaml +++ b/config/crds/kyverno.io_policyexceptions.yaml @@ -600,6 +600,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -1191,6 +1243,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -1782,6 +1886,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match diff --git a/config/install-latest-testing.yaml b/config/install-latest-testing.yaml index 580a96e71a..e4e799170b 100644 --- a/config/install-latest-testing.yaml +++ b/config/install-latest-testing.yaml @@ -46479,6 +46479,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -47070,6 +47122,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match @@ -47661,6 +47765,58 @@ spec: type: object type: array type: object + podSecurity: + description: PodSecurity specifies the Pod Security Standard controls + to be excluded. Applicable only to policies that have validate.podSecurity + subrule. + items: + description: PodSecurityStandard specifies the Pod Security Standard + controls to be excluded. + properties: + controlName: + description: 'ControlName specifies the name of the Pod Security + Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/' + enum: + - HostProcess + - Host Namespaces + - Privileged Containers + - Capabilities + - HostPath Volumes + - Host Ports + - AppArmor + - SELinux + - /proc Mount Type + - Seccomp + - Sysctls + - Volume Types + - Privilege Escalation + - Running as Non-root + - Running as Non-root user + type: string + images: + description: 'Images selects matching containers and applies + the container level PSS. Each image is the image name consisting + of the registry address, repository, image, and tag. Empty + list matches no containers, PSS checks are applied at the + pod level only. Wildcards (''*'' and ''?'') are allowed. See: + https://kubernetes.io/docs/concepts/containers/images.' + items: + type: string + type: array + restrictedField: + description: RestrictedField selects the field for the given + Pod Security Standard control. When not set, all restricted + fields for the control are selected. + type: string + values: + description: Values defines the allowed values that can be excluded. + items: + type: string + type: array + required: + - controlName + type: object + type: array required: - exceptions - match diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index baa6c0a3e4..136378e9df 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -2825,7 +2825,9 @@ Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, lates
(Appears on: -PodSecurity) +PodSecurity, +PolicyExceptionSpec, +PolicyExceptionSpec)
PodSecurityStandard specifies the Pod Security Standard controls to be excluded.
@@ -6193,6 +6195,21 @@ set of conditions. The declaration can contain nestedany
or
Exceptions is a list policy/rules to be excluded
+
+
+podSecurity
+
+
+[]PodSecurityStandard
+
+
+
+
+(Optional)
+PodSecurity specifies the Pod Security Standard controls to be excluded.
+Applicable only to policies that have validate.podSecurity subrule.
+
+
@@ -6958,6 +6975,21 @@ set of conditions. The declaration can contain nested any
or
Exceptions is a list policy/rules to be excluded
+
+
+podSecurity
+
+
+[]PodSecurityStandard
+
+
+
+
+(Optional)
+PodSecurity specifies the Pod Security Standard controls to be excluded.
+Applicable only to policies that have validate.podSecurity subrule.
+
+
@@ -7677,6 +7709,21 @@ set of conditions. The declaration can contain nested any
or
Exceptions is a list policy/rules to be excluded
+
+
+podSecurity
+
+
+[]PodSecurityStandard
+
+
+
+
+(Optional)
+PodSecurity specifies the Pod Security Standard controls to be excluded.
+Applicable only to policies that have validate.podSecurity subrule.
+
+
@@ -8635,6 +8682,21 @@ set of conditions. The declaration can contain nested any
or
Exceptions is a list policy/rules to be excluded
+
+
+podSecurity
+
+
+[]PodSecurityStandard
+
+
+
+
+(Optional)
+PodSecurity specifies the Pod Security Standard controls to be excluded.
+Applicable only to policies that have validate.podSecurity subrule.
+
+
@@ -9288,6 +9350,21 @@ set of conditions. The declaration can contain nested any
or
Exceptions is a list policy/rules to be excluded
+
+
+podSecurity
+
+
+[]PodSecurityStandard
+
+
+
+
+(Optional)
+PodSecurity specifies the Pod Security Standard controls to be excluded.
+Applicable only to policies that have validate.podSecurity subrule.
+
+
diff --git a/pkg/client/applyconfigurations/kyverno/v2/policyexceptionspec.go b/pkg/client/applyconfigurations/kyverno/v2/policyexceptionspec.go
index 65c8b6e7af..c26cb9f34c 100644
--- a/pkg/client/applyconfigurations/kyverno/v2/policyexceptionspec.go
+++ b/pkg/client/applyconfigurations/kyverno/v2/policyexceptionspec.go
@@ -19,16 +19,18 @@ limitations under the License.
package v2
import (
+ v1 "github.com/kyverno/kyverno/pkg/client/applyconfigurations/kyverno/v1"
v2beta1 "github.com/kyverno/kyverno/pkg/client/applyconfigurations/kyverno/v2beta1"
)
// PolicyExceptionSpecApplyConfiguration represents an declarative configuration of the PolicyExceptionSpec type for use
// with apply.
type PolicyExceptionSpecApplyConfiguration struct {
- Background *bool `json:"background,omitempty"`
- Match *v2beta1.MatchResourcesApplyConfiguration `json:"match,omitempty"`
- Conditions *v2beta1.AnyAllConditionsApplyConfiguration `json:"conditions,omitempty"`
- Exceptions []ExceptionApplyConfiguration `json:"exceptions,omitempty"`
+ Background *bool `json:"background,omitempty"`
+ Match *v2beta1.MatchResourcesApplyConfiguration `json:"match,omitempty"`
+ Conditions *v2beta1.AnyAllConditionsApplyConfiguration `json:"conditions,omitempty"`
+ Exceptions []ExceptionApplyConfiguration `json:"exceptions,omitempty"`
+ PodSecurity []v1.PodSecurityStandardApplyConfiguration `json:"podSecurity,omitempty"`
}
// PolicyExceptionSpecApplyConfiguration constructs an declarative configuration of the PolicyExceptionSpec type for use with
@@ -73,3 +75,16 @@ func (b *PolicyExceptionSpecApplyConfiguration) WithExceptions(values ...*Except
}
return b
}
+
+// WithPodSecurity adds the given value to the PodSecurity field in the declarative configuration
+// and returns the receiver, so that objects can be build by chaining "With" function invocations.
+// If called multiple times, values provided by each call will be appended to the PodSecurity field.
+func (b *PolicyExceptionSpecApplyConfiguration) WithPodSecurity(values ...*v1.PodSecurityStandardApplyConfiguration) *PolicyExceptionSpecApplyConfiguration {
+ for i := range values {
+ if values[i] == nil {
+ panic("nil value passed to WithPodSecurity")
+ }
+ b.PodSecurity = append(b.PodSecurity, *values[i])
+ }
+ return b
+}
diff --git a/pkg/client/applyconfigurations/kyverno/v2beta1/policyexceptionspec.go b/pkg/client/applyconfigurations/kyverno/v2beta1/policyexceptionspec.go
index d93cf5b338..69c5d0fa1a 100644
--- a/pkg/client/applyconfigurations/kyverno/v2beta1/policyexceptionspec.go
+++ b/pkg/client/applyconfigurations/kyverno/v2beta1/policyexceptionspec.go
@@ -18,13 +18,18 @@ limitations under the License.
package v2beta1
+import (
+ v1 "github.com/kyverno/kyverno/pkg/client/applyconfigurations/kyverno/v1"
+)
+
// PolicyExceptionSpecApplyConfiguration represents an declarative configuration of the PolicyExceptionSpec type for use
// with apply.
type PolicyExceptionSpecApplyConfiguration struct {
- Background *bool `json:"background,omitempty"`
- Match *MatchResourcesApplyConfiguration `json:"match,omitempty"`
- Conditions *AnyAllConditionsApplyConfiguration `json:"conditions,omitempty"`
- Exceptions []ExceptionApplyConfiguration `json:"exceptions,omitempty"`
+ Background *bool `json:"background,omitempty"`
+ Match *MatchResourcesApplyConfiguration `json:"match,omitempty"`
+ Conditions *AnyAllConditionsApplyConfiguration `json:"conditions,omitempty"`
+ Exceptions []ExceptionApplyConfiguration `json:"exceptions,omitempty"`
+ PodSecurity []v1.PodSecurityStandardApplyConfiguration `json:"podSecurity,omitempty"`
}
// PolicyExceptionSpecApplyConfiguration constructs an declarative configuration of the PolicyExceptionSpec type for use with
@@ -69,3 +74,16 @@ func (b *PolicyExceptionSpecApplyConfiguration) WithExceptions(values ...*Except
}
return b
}
+
+// WithPodSecurity adds the given value to the PodSecurity field in the declarative configuration
+// and returns the receiver, so that objects can be build by chaining "With" function invocations.
+// If called multiple times, values provided by each call will be appended to the PodSecurity field.
+func (b *PolicyExceptionSpecApplyConfiguration) WithPodSecurity(values ...*v1.PodSecurityStandardApplyConfiguration) *PolicyExceptionSpecApplyConfiguration {
+ for i := range values {
+ if values[i] == nil {
+ panic("nil value passed to WithPodSecurity")
+ }
+ b.PodSecurity = append(b.PodSecurity, *values[i])
+ }
+ return b
+}
diff --git a/pkg/engine/handlers/validation/validate_pss.go b/pkg/engine/handlers/validation/validate_pss.go
index f9e9a01c69..78d5bf7a01 100644
--- a/pkg/engine/handlers/validation/validate_pss.go
+++ b/pkg/engine/handlers/validation/validate_pss.go
@@ -44,7 +44,7 @@ func (h validatePssHandler) Process(
// check if there is a policy exception matches the incoming resource
exception := engineutils.MatchesException(exceptions, policyContext, logger)
- if exception != nil {
+ if exception != nil && !exception.HasPodSecurity() {
key, err := cache.MetaNamespaceKeyFunc(exception)
if err != nil {
logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
@@ -70,10 +70,11 @@ func (h validatePssHandler) Process(
Spec: *podSpec,
ObjectMeta: *metadata,
}
- allowed, pssChecks, err := pss.EvaluatePod(podSecurity, pod)
+ levelVersion, err := pss.ParseVersion(podSecurity.Level, podSecurity.Version)
if err != nil {
return resource, handlers.WithError(rule, engineapi.Validation, "failed to parse pod security api version", err)
}
+ allowed, pssChecks := pss.EvaluatePod(levelVersion, podSecurity.Exclude, pod)
pssChecks = convertChecks(pssChecks, resource.GetKind())
podSecurityChecks := engineapi.PodSecurityChecks{
Level: podSecurity.Level,
@@ -86,6 +87,23 @@ func (h validatePssHandler) Process(
engineapi.RulePass(rule.Name, engineapi.Validation, msg).WithPodSecurityChecks(podSecurityChecks),
)
} else {
+ // apply pod security exceptions if exist
+ if exception != nil && exception.HasPodSecurity() {
+ pssChecks, err = pss.ApplyPodSecurityExclusion(levelVersion, exception.Spec.PodSecurity, pssChecks, pod)
+ if len(pssChecks) == 0 && err == nil {
+ key, err := cache.MetaNamespaceKeyFunc(exception)
+ if err != nil {
+ logger.Error(err, "failed to compute policy exception key", "namespace", exception.GetNamespace(), "name", exception.GetName())
+ return resource, handlers.WithError(rule, engineapi.Validation, "failed to compute exception key", err)
+ } else {
+ podSecurityChecks.Checks = pssChecks
+ logger.V(3).Info("policy rule skipped due to policy exception", "exception", key)
+ return resource, handlers.WithResponses(
+ engineapi.RuleSkip(rule.Name, engineapi.Validation, "rule skipped due to policy exception "+key).WithException(exception).WithPodSecurityChecks(podSecurityChecks),
+ )
+ }
+ }
+ }
msg := fmt.Sprintf(`Validation rule '%s' failed. It violates PodSecurity "%s:%s": %s`, rule.Name, podSecurity.Level, podSecurity.Version, pss.FormatChecksPrint(pssChecks))
return resource, handlers.WithResponses(
engineapi.RuleFail(rule.Name, engineapi.Validation, msg).WithPodSecurityChecks(podSecurityChecks),
@@ -161,7 +179,7 @@ func getSpec(resource unstructured.Unstructured) (podSpec *corev1.PodSpec, metad
metadata = &pod.ObjectMeta
return podSpec, metadata, nil
} else {
- return nil, nil, fmt.Errorf("Could not find correct resource type")
+ return nil, nil, fmt.Errorf("could not find correct resource type")
}
if err != nil {
return nil, nil, err
diff --git a/pkg/pss/evaluate.go b/pkg/pss/evaluate.go
index c4c362288d..e35ec800b1 100644
--- a/pkg/pss/evaluate.go
+++ b/pkg/pss/evaluate.go
@@ -218,54 +218,64 @@ func getContainerInfo(pod *corev1.Pod, index int, containerType string) corev1.C
return container
}
-func parseVersion(rule *kyvernov1.PodSecurity) (*api.LevelVersion, error) {
+func ParseVersion(level api.Level, version string) (*api.LevelVersion, error) {
// Get pod security admission version
var apiVersion api.Version
// Version set to "latest" by default
- if rule.Version == "" || rule.Version == "latest" {
+ if version == "" || version == "latest" {
apiVersion = api.LatestVersion()
} else {
- parsedApiVersion, err := api.ParseVersion(rule.Version)
+ parsedApiVersion, err := api.ParseVersion(version)
if err != nil {
return nil, err
}
apiVersion = api.MajorMinorVersion(parsedApiVersion.Major(), parsedApiVersion.Minor())
}
return &api.LevelVersion{
- Level: rule.Level,
+ Level: level,
Version: apiVersion,
}, nil
}
// EvaluatePod applies PSS checks to the pod and exempts controls specified in the rule
-func EvaluatePod(rule *kyvernov1.PodSecurity, pod *corev1.Pod) (bool, []pssutils.PSSCheckResult, error) {
- levelVersion, err := parseVersion(rule)
- if err != nil {
- return false, nil, err
+func EvaluatePod(levelVersion *api.LevelVersion, excludes []kyvernov1.PodSecurityStandard, pod *corev1.Pod) (bool, []pssutils.PSSCheckResult) {
+ var err error
+ // apply the pod security checks on pods
+ defaultCheckResults := evaluatePSS(levelVersion, *pod)
+ // exclude pod security controls if specified
+ if len(excludes) > 0 {
+ defaultCheckResults, err = ApplyPodSecurityExclusion(levelVersion, excludes, defaultCheckResults, pod)
}
- defaultCheckResults := evaluatePSS(levelVersion, *pod)
+ return (len(defaultCheckResults) == 0 && err == nil), defaultCheckResults
+}
- for _, exclude := range rule.Exclude {
+// ApplyPodSecurityExclusion excludes pod security controls
+func ApplyPodSecurityExclusion(
+ levelVersion *api.LevelVersion,
+ excludes []kyvernov1.PodSecurityStandard,
+ defaultCheckResults []pssutils.PSSCheckResult,
+ pod *corev1.Pod,
+) ([]pssutils.PSSCheckResult, error) {
+ var err error
+ for _, exclude := range excludes {
spec, matching := GetPodWithMatchingContainers(exclude, pod)
switch {
// exclude pod level checks
case spec != nil:
- isContainerLevelExclusion := false
excludeCheckResults := evaluatePSS(levelVersion, *spec)
- defaultCheckResults, err = exemptExclusions(defaultCheckResults, excludeCheckResults, exclude, pod, matching, isContainerLevelExclusion)
+ defaultCheckResults, err = exemptExclusions(defaultCheckResults, excludeCheckResults, exclude, pod, matching, false)
// exclude container level checks
default:
- isContainerLevelExclusion := true
excludeCheckResults := evaluatePSS(levelVersion, *matching)
- defaultCheckResults, err = exemptExclusions(defaultCheckResults, excludeCheckResults, exclude, pod, matching, isContainerLevelExclusion)
+ defaultCheckResults, err = exemptExclusions(defaultCheckResults, excludeCheckResults, exclude, pod, matching, true)
}
}
- return (len(defaultCheckResults) == 0 && err == nil), defaultCheckResults, err
+ return defaultCheckResults, err
}
// GetPodWithMatchingContainers extracts matching container/pod info by the given exclude rule
diff --git a/pkg/pss/evaluate_test.go b/pkg/pss/evaluate_test.go
index 486fc3acb8..066f7034aa 100644
--- a/pkg/pss/evaluate_test.go
+++ b/pkg/pss/evaluate_test.go
@@ -46,9 +46,10 @@ func Test_EvaluatePod(t *testing.T) {
err = json.Unmarshal(test.rawRule, &rule)
assert.NilError(t, err)
- allowed, checkResults, err := EvaluatePod(&rule, &pod)
+ levelVersion, err := ParseVersion(rule.Level, rule.Version)
assert.Assert(t, err == nil)
+ allowed, checkResults := EvaluatePod(levelVersion, rule.Exclude, &pod)
if allowed != test.allowed {
for _, result := range checkResults {
fmt.Printf("failed check result: %v\n", result)
diff --git a/pkg/pss/fuzz_test.go b/pkg/pss/fuzz_test.go
index f1b6d5e97b..39630b5532 100644
--- a/pkg/pss/fuzz_test.go
+++ b/pkg/pss/fuzz_test.go
@@ -423,7 +423,8 @@ func FuzzBaselinePS(f *testing.F) {
rule = baselineLatestRule
}
- allowed, _, _ := EvaluatePod(&rule, pod)
+ levelVersion, _ := ParseVersion(rule.Level, rule.Version)
+ allowed, _ := EvaluatePod(levelVersion, rule.Exclude, pod)
if allowPod != allowed {
pJson, err := json.MarshalIndent(pod, "", "")
if err != nil {
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/README.md b/test/conformance/chainsaw/exceptions/exclude-capabilities/README.md
new file mode 100644
index 0000000000..386acdaa22
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/README.md
@@ -0,0 +1,13 @@
+## Description
+
+This test creates a policy that enforces the restricted profile and a policy exception that exempts containers running either the nginx or redis image from the Capabilities control.
+The policy exception is configured to apply only to the pods that in `staging-ns` namespace.
+
+## Steps
+
+1. - Create a cluster policy
+ - Assert the policy becomes ready
+1. - Create a policy exception for the cluster policy created above.
+1. - Try to create a pod named `goodpod01` whose image is `nginx` in the `staging-ns` namespace that violates the policy, expecting the creation to succeed
+ - Try to create a pod named `badpod01` whose image is `nginx` in the `default` namespace that violates the policy, expecting the creation to fail
+ - Try to create a pod named `badpod02` whose image is `busybox` in the `staging-ns` namespace that violates the policy,, expecting the creation to fail
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/chainsaw-test.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/chainsaw-test.yaml
new file mode 100755
index 0000000000..80e7c2ca9f
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/chainsaw-test.yaml
@@ -0,0 +1,37 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: exclude-capabilities
+spec:
+ steps:
+ - name: step-01
+ try:
+ - apply:
+ file: policy.yaml
+ - assert:
+ file: policy-assert.yaml
+ - name: step-02
+ try:
+ - apply:
+ file: ns.yaml
+ - assert:
+ file: ns.yaml
+ - name: step-03
+ try:
+ - apply:
+ file: exception.yaml
+ - name: step-04
+ try:
+ - apply:
+ file: pod-allowed.yaml
+ - apply:
+ expect:
+ - check:
+ ($error != null): true
+ file: pod-rejected-1.yaml
+ - apply:
+ expect:
+ - check:
+ ($error != null): true
+ file: pod-rejected-2.yaml
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/exception.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/exception.yaml
new file mode 100644
index 0000000000..64cc01904a
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/exception.yaml
@@ -0,0 +1,20 @@
+apiVersion: kyverno.io/v2beta1
+kind: PolicyException
+metadata:
+ name: pod-security-exception
+ namespace: policy-exception-ns
+spec:
+ exceptions:
+ - policyName: psa-1
+ ruleNames:
+ - restricted
+ match:
+ any:
+ - resources:
+ namespaces:
+ - staging-ns
+ podSecurity:
+ - controlName: Capabilities
+ images:
+ - nginx*
+ - redis*
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/ns.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/ns.yaml
new file mode 100644
index 0000000000..2e951f10d4
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/ns.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: policy-exception-ns
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: staging-ns
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-allowed.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-allowed.yaml
new file mode 100644
index 0000000000..5f71bc34f5
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-allowed.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: goodpod01
+ namespace: staging-ns
+spec:
+ containers:
+ - name: container01
+ image: nginx:1.1.9
+ securityContext:
+ allowPrivilegeEscalation: false
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ capabilities:
+ add:
+ - SYS_ADMIN
+ drop:
+ - ALL
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-rejected-1.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-rejected-1.yaml
new file mode 100644
index 0000000000..0a1d765faf
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-rejected-1.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: badpod01
+ namespace: default
+spec:
+ containers:
+ - name: container01
+ image: nginx:1.1.9
+ securityContext:
+ allowPrivilegeEscalation: false
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ capabilities:
+ add:
+ - SYS_ADMIN
+ drop:
+ - ALL
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-rejected-2.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-rejected-2.yaml
new file mode 100644
index 0000000000..be836a239b
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/pod-rejected-2.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: badpod02
+ namespace: staging-ns
+spec:
+ containers:
+ - name: container01
+ image: busybox:1.28
+ securityContext:
+ allowPrivilegeEscalation: false
+ runAsNonRoot: true
+ seccompProfile:
+ type: RuntimeDefault
+ capabilities:
+ add:
+ - SYS_ADMIN
+ drop:
+ - ALL
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/policy-assert.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/policy-assert.yaml
new file mode 100644
index 0000000000..d52b6efde4
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/policy-assert.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: psa-1
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
diff --git a/test/conformance/chainsaw/exceptions/exclude-capabilities/policy.yaml b/test/conformance/chainsaw/exceptions/exclude-capabilities/policy.yaml
new file mode 100644
index 0000000000..70dfebfda1
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-capabilities/policy.yaml
@@ -0,0 +1,18 @@
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: psa-1
+spec:
+ background: true
+ validationFailureAction: Enforce
+ rules:
+ - name: restricted
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ validate:
+ podSecurity:
+ level: restricted
+ version: latest
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/README.md b/test/conformance/chainsaw/exceptions/exclude-host-ports/README.md
new file mode 100644
index 0000000000..70e1be5432
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/README.md
@@ -0,0 +1,13 @@
+## Description
+
+This test creates a policy that enforces the baseline profile and a policy exception that exempts any pod whose image is `nginx` and hostPort set to either 10 or 20.
+The policy exception is configured to apply only to the pods that in `staging-ns-3` namespace.
+
+## Steps
+
+1. - Create a cluster policy
+ - Assert the policy becomes ready
+1. - Create a policy exception for the cluster policy created above.
+1. - Try to create a pod named `good-pod-1` in the `default` namespace whose hostPort is set to zero, expecting the creation to succeed.
+ - Try to create a pod named `good-pod-2` in the `staging-ns-3` namespace that uses the HostPort control whose values are 10 and 20, expecting the creation to succeed.
+ - Try to create a pod named `bad-pod` in the `default` namespace that uses both the HostProcess controls with value 20, expecting the creation to fail.
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/chainsaw-test.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/chainsaw-test.yaml
new file mode 100755
index 0000000000..b96ee034ec
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/chainsaw-test.yaml
@@ -0,0 +1,34 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: exclude-host-ports
+spec:
+ steps:
+ - name: step-01
+ try:
+ - apply:
+ file: policy.yaml
+ - assert:
+ file: policy-assert.yaml
+ - name: step-02
+ try:
+ - apply:
+ file: ns.yaml
+ - assert:
+ file: ns.yaml
+ - name: step-03
+ try:
+ - apply:
+ file: exception.yaml
+ - name: step-04
+ try:
+ - apply:
+ file: pod-allowed-1.yaml
+ - apply:
+ file: pod-allowed-2.yaml
+ - apply:
+ expect:
+ - check:
+ ($error != null): true
+ file: pod-rejected.yaml
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/exception.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/exception.yaml
new file mode 100644
index 0000000000..3a3aa8b001
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/exception.yaml
@@ -0,0 +1,28 @@
+apiVersion: kyverno.io/v2beta1
+kind: PolicyException
+metadata:
+ name: pod-security-exception
+ namespace: policy-exception-ns-3
+spec:
+ exceptions:
+ - policyName: psa-3
+ ruleNames:
+ - baseline
+ match:
+ any:
+ - resources:
+ namespaces:
+ - staging-ns-3
+ podSecurity:
+ - controlName: "Host Ports"
+ images:
+ - nginx
+ restrictedField: "spec.containers[*].ports[*].hostPort"
+ values:
+ - "10"
+ - controlName: "Host Ports"
+ images:
+ - nginx
+ restrictedField: "spec.initContainers[*].ports[*].hostPort"
+ values:
+ - "20"
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/ns.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/ns.yaml
new file mode 100644
index 0000000000..4f510c6f7c
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/ns.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: policy-exception-ns-3
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: staging-ns-3
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-allowed-1.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-allowed-1.yaml
new file mode 100644
index 0000000000..f4a1662af6
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-allowed-1.yaml
@@ -0,0 +1,24 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: good-pod-1
+ namespace: default
+spec:
+ containers:
+ - name: nginx1
+ image: nginx
+ args:
+ - sleep
+ - 1d
+ ports:
+ - hostPort: 0
+ containerPort: 80
+ initContainers:
+ - name: nginx2
+ image: nginx
+ args:
+ - sleep
+ - 1d
+ ports:
+ - hostPort: 0
+ containerPort: 8080
\ No newline at end of file
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-allowed-2.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-allowed-2.yaml
new file mode 100644
index 0000000000..827acece94
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-allowed-2.yaml
@@ -0,0 +1,24 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: good-pod-2
+ namespace: staging-ns-3
+spec:
+ containers:
+ - name: nginx1
+ image: nginx
+ args:
+ - sleep
+ - 1d
+ ports:
+ - hostPort: 10
+ containerPort: 80
+ initContainers:
+ - name: nginx2
+ image: nginx
+ args:
+ - sleep
+ - 1d
+ ports:
+ - hostPort: 20
+ containerPort: 80
\ No newline at end of file
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-rejected.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-rejected.yaml
new file mode 100644
index 0000000000..43914ea4ef
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/pod-rejected.yaml
@@ -0,0 +1,24 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: bad-pod
+ namespace: default
+spec:
+ containers:
+ - name: nginx1
+ image: nginx
+ args:
+ - sleep
+ - 1d
+ ports:
+ - hostPort: 20
+ containerPort: 80
+ initContainers:
+ - name: nginx2
+ image: nginx
+ args:
+ - sleep
+ - 1d
+ ports:
+ - hostPort: 20
+ containerPort: 80
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/policy-assert.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/policy-assert.yaml
new file mode 100644
index 0000000000..43944a468a
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/policy-assert.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: psa-3
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-ports/policy.yaml b/test/conformance/chainsaw/exceptions/exclude-host-ports/policy.yaml
new file mode 100644
index 0000000000..8bf4dedbe8
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-ports/policy.yaml
@@ -0,0 +1,18 @@
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: psa-3
+spec:
+ background: true
+ validationFailureAction: Enforce
+ rules:
+ - name: baseline
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ validate:
+ podSecurity:
+ level: baseline
+ version: latest
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/README.md b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/README.md
new file mode 100644
index 0000000000..ca4c0dd608
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/README.md
@@ -0,0 +1,14 @@
+## Description
+
+This test creates a policy that enforces the baseline profile and exempts any pod that violates the Host Namespaces control and a policy exception that exempts any pod that violates the HostProcess control.
+The policy exception is configured to apply only to the pods that in `staging-ns-1` namespace.
+
+## Steps
+
+1. - Create a cluster policy
+ - Assert the policy becomes ready
+1. - Create a policy exception for the cluster policy created above.
+1. - Try to create a pod named `goodpod-01` in the `staging-ns-1` namespace that uses both the Host Namespace and the HostProcess controls, expecting the creation to succeed.
+ - Try to create a pod named `goodpod-02` in the `staging-ns-1` namespace that uses the HostProcess control, expecting the creation to succeed.
+ - Try to create a pod named `goodpod-03` in the `default` namespace that uses the Host Namespace control, expecting the creation to succeed.
+ - Try to create a pod named `badpod-01` in the `default` namespace that uses both the Host Namespace and the HostProcess controls, expecting the creation to fail.
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/chainsaw-test.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/chainsaw-test.yaml
new file mode 100755
index 0000000000..ff18b07197
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/chainsaw-test.yaml
@@ -0,0 +1,36 @@
+apiVersion: chainsaw.kyverno.io/v1alpha1
+kind: Test
+metadata:
+ creationTimestamp: null
+ name: exclude-host-process-and-host-namespaces
+spec:
+ steps:
+ - name: step-01
+ try:
+ - apply:
+ file: policy.yaml
+ - assert:
+ file: policy-assert.yaml
+ - name: step-02
+ try:
+ - apply:
+ file: ns.yaml
+ - assert:
+ file: ns.yaml
+ - name: step-03
+ try:
+ - apply:
+ file: exception.yaml
+ - name: step-04
+ try:
+ - apply:
+ file: pod-allowed-1.yaml
+ - apply:
+ file: pod-allowed-2.yaml
+ - apply:
+ file: pod-allowed-3.yaml
+ - apply:
+ expect:
+ - check:
+ ($error != null): true
+ file: pod-rejected.yaml
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/exception.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/exception.yaml
new file mode 100644
index 0000000000..989c1cc748
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/exception.yaml
@@ -0,0 +1,17 @@
+apiVersion: kyverno.io/v2beta1
+kind: PolicyException
+metadata:
+ name: pod-security-exception
+ namespace: policy-exception-ns-1
+spec:
+ exceptions:
+ - policyName: psa-2
+ ruleNames:
+ - baseline
+ match:
+ any:
+ - resources:
+ namespaces:
+ - staging-ns-1
+ podSecurity:
+ - controlName: HostProcess
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/ns.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/ns.yaml
new file mode 100644
index 0000000000..84ec947882
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/ns.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: policy-exception-ns-1
+---
+apiVersion: v1
+kind: Namespace
+metadata:
+ name: staging-ns-1
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-1.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-1.yaml
new file mode 100644
index 0000000000..64f95fbe92
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-1.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: goodpod-01
+ namespace: staging-ns-1
+spec:
+ hostIPC: true
+ hostNetwork: true
+ securityContext:
+ windowsOptions:
+ hostProcess: true
+ containers:
+ - name: container01
+ image: dummyimagename
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-2.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-2.yaml
new file mode 100644
index 0000000000..c85da123d6
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-2.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: goodpod-02
+ namespace: staging-ns-1
+spec:
+ hostNetwork: true
+ securityContext:
+ windowsOptions:
+ hostProcess: true
+ containers:
+ - name: container01
+ image: dummyimagename
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-3.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-3.yaml
new file mode 100644
index 0000000000..381bb99755
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-allowed-3.yaml
@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: goodpod-03
+ namespace: default
+spec:
+ hostIPC: true
+ containers:
+ - name: container01
+ image: dummyimagename
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-rejected.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-rejected.yaml
new file mode 100644
index 0000000000..522e1bdd03
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/pod-rejected.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: badpod-01
+ namespace: default
+spec:
+ hostIPC: true
+ hostNetwork: true
+ securityContext:
+ windowsOptions:
+ hostProcess: true
+ containers:
+ - name: container01
+ image: dummyimagename
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/policy-assert.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/policy-assert.yaml
new file mode 100644
index 0000000000..2fa6a45c50
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/policy-assert.yaml
@@ -0,0 +1,9 @@
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: psa-2
+status:
+ conditions:
+ - reason: Succeeded
+ status: "True"
+ type: Ready
diff --git a/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/policy.yaml b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/policy.yaml
new file mode 100644
index 0000000000..f8614b068e
--- /dev/null
+++ b/test/conformance/chainsaw/exceptions/exclude-host-process-and-host-namespaces/policy.yaml
@@ -0,0 +1,20 @@
+apiVersion: kyverno.io/v1
+kind: ClusterPolicy
+metadata:
+ name: psa-2
+spec:
+ background: true
+ validationFailureAction: Enforce
+ rules:
+ - name: baseline
+ match:
+ any:
+ - resources:
+ kinds:
+ - Pod
+ validate:
+ podSecurity:
+ level: baseline
+ version: latest
+ exclude:
+ - controlName: Host Namespaces