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

feat: support podSecurity exclusion in exceptions (#9343)

Signed-off-by: Mariam Fahmy <mariam.fahmy@nirmata.com>
This commit is contained in:
Mariam Fahmy 2024-01-26 20:43:07 +02:00 committed by GitHub
parent 8781a38849
commit f01f0d6dc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 1331 additions and 29 deletions

View file

@ -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 {

View file

@ -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
}

View file

@ -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 {

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -2825,7 +2825,9 @@ Allowed values are v1.19, v1.20, v1.21, v1.22, v1.23, v1.24, v1.25, v1.26, lates
</h3>
<p>
(<em>Appears on:</em>
<a href="#kyverno.io/v1.PodSecurity">PodSecurity</a>)
<a href="#kyverno.io/v1.PodSecurity">PodSecurity</a>,
<a href="#kyverno.io/v2.PolicyExceptionSpec">PolicyExceptionSpec</a>,
<a href="#kyverno.io/v2beta1.PolicyExceptionSpec">PolicyExceptionSpec</a>)
</p>
<p>
<p>PodSecurityStandard specifies the Pod Security Standard controls to be excluded.</p>
@ -6193,6 +6195,21 @@ set of conditions. The declaration can contain nested <code>any</code> or <code>
<p>Exceptions is a list policy/rules to be excluded</p>
</td>
</tr>
<tr>
<td>
<code>podSecurity</code><br/>
<em>
<a href="#kyverno.io/v1.PodSecurityStandard">
[]PodSecurityStandard
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>PodSecurity specifies the Pod Security Standard controls to be excluded.
Applicable only to policies that have validate.podSecurity subrule.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -6958,6 +6975,21 @@ set of conditions. The declaration can contain nested <code>any</code> or <code>
<p>Exceptions is a list policy/rules to be excluded</p>
</td>
</tr>
<tr>
<td>
<code>podSecurity</code><br/>
<em>
<a href="#kyverno.io/v1.PodSecurityStandard">
[]PodSecurityStandard
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>PodSecurity specifies the Pod Security Standard controls to be excluded.
Applicable only to policies that have validate.podSecurity subrule.</p>
</td>
</tr>
</tbody>
</table>
<hr />
@ -7677,6 +7709,21 @@ set of conditions. The declaration can contain nested <code>any</code> or <code>
<p>Exceptions is a list policy/rules to be excluded</p>
</td>
</tr>
<tr>
<td>
<code>podSecurity</code><br/>
<em>
<a href="#kyverno.io/v1.PodSecurityStandard">
[]PodSecurityStandard
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>PodSecurity specifies the Pod Security Standard controls to be excluded.
Applicable only to policies that have validate.podSecurity subrule.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -8635,6 +8682,21 @@ set of conditions. The declaration can contain nested <code>any</code> or <code>
<p>Exceptions is a list policy/rules to be excluded</p>
</td>
</tr>
<tr>
<td>
<code>podSecurity</code><br/>
<em>
<a href="#kyverno.io/v1.PodSecurityStandard">
[]PodSecurityStandard
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>PodSecurity specifies the Pod Security Standard controls to be excluded.
Applicable only to policies that have validate.podSecurity subrule.</p>
</td>
</tr>
</table>
</td>
</tr>
@ -9288,6 +9350,21 @@ set of conditions. The declaration can contain nested <code>any</code> or <code>
<p>Exceptions is a list policy/rules to be excluded</p>
</td>
</tr>
<tr>
<td>
<code>podSecurity</code><br/>
<em>
<a href="#kyverno.io/v1.PodSecurityStandard">
[]PodSecurityStandard
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>PodSecurity specifies the Pod Security Standard controls to be excluded.
Applicable only to policies that have validate.podSecurity subrule.</p>
</td>
</tr>
</tbody>
</table>
<hr />

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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*

View file

@ -0,0 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
name: policy-exception-ns
---
apiVersion: v1
kind: Namespace
metadata:
name: staging-ns

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,9 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: psa-1
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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"

View file

@ -0,0 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
name: policy-exception-ns-3
---
apiVersion: v1
kind: Namespace
metadata:
name: staging-ns-3

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,9 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: psa-3
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,9 @@
apiVersion: v1
kind: Namespace
metadata:
name: policy-exception-ns-1
---
apiVersion: v1
kind: Namespace
metadata:
name: staging-ns-1

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: goodpod-03
namespace: default
spec:
hostIPC: true
containers:
- name: container01
image: dummyimagename

View file

@ -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

View file

@ -0,0 +1,9 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: psa-2
status:
conditions:
- reason: Succeeded
status: "True"
type: Ready

View file

@ -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