1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-28 02:18:15 +00:00

Support PSa integration by controlName only (#4710)

* Remove "restrictedField" and "values" from podSecurity.exclude

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* Remove commented code

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* Add unit tests for restricted_runAsNonRoot

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* Add baseline unit tests

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* Add unit tests for restricted controls

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* Removes PSa tests at the engine level

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* - Update API docs; - Add unit tests for wildcard images

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* Remove autogen conversion for PSa policies

Signed-off-by: ShutingZhao <shuting@nirmata.com>

* copy pod with DeepCopy()

Signed-off-by: ShutingZhao <shuting@nirmata.com>

Signed-off-by: ShutingZhao <shuting@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
shuting 2022-09-28 18:03:53 +08:00 committed by GitHub
parent 56c74272bb
commit 34c6920129
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 8368 additions and 13113 deletions

View file

@ -345,19 +345,11 @@ type PodSecurityStandard struct {
// See: https://kubernetes.io/docs/concepts/security/pod-security-standards/
ControlName string `json:"controlName" yaml:"controlName"`
// Images is a list of matching image patterns.
// 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.
// +optional
Images []string `json:"images,omitempty" yaml:"images,omitempty"`
// RestrictedField selects the field for the given Pod Security Standard control.
// When not set, all restricted fields for the control are selected.
// +optional
RestrictedField string `json:"restrictedField,omitempty" yaml:"restrictedField,omitempty"`
// Values defines the allowed values that can be excluded.
// +optional
Values []string `json:"values,omitempty" yaml:"values,omitempty"`
}
// DeserializeAnyPattern deserialize apiextensions.JSON to []interface{}

View file

@ -958,11 +958,6 @@ func (in *PodSecurityStandard) DeepCopyInto(out *PodSecurityStandard) {
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Values != nil {
in, out := &in.Values, &out.Values
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSecurityStandard.

View file

@ -1475,15 +1475,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -3172,15 +3164,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -4821,15 +4805,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -6493,15 +6469,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -9010,15 +8978,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -10707,15 +10667,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -12356,15 +12308,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -14028,15 +13972,7 @@ spec:
description: 'ControlName specifies the name of the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image patterns. Each image is the image name consisting of the registry address, repository, image, and tag.
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.
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.
items:
type: string
type: array

View file

@ -2320,22 +2320,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -5118,22 +5108,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -7715,22 +7695,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -10473,22 +10443,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array

View file

@ -2321,22 +2321,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -5120,22 +5110,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -7718,22 +7698,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -10476,22 +10446,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array

File diff suppressed because it is too large Load diff

View file

@ -2335,22 +2335,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -5133,22 +5123,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -7730,22 +7710,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -10488,22 +10458,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -14263,22 +14223,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -17062,22 +17012,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array
@ -19660,22 +19600,12 @@ spec:
the Pod Security Standard control. See: https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching image
patterns. Each image is the image name consisting
of the registry address, repository, image,
and tag.
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.
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.
items:
type: string
type: array
@ -22418,22 +22348,12 @@ spec:
https://kubernetes.io/docs/concepts/security/pod-security-standards/'
type: string
images:
description: Images is a list of matching
image patterns. Each image is the image
name consisting of the registry address,
repository, image, and tag.
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.
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.
items:
type: string
type: array

View file

@ -2658,33 +2658,9 @@ See: <a href="https://kubernetes.io/docs/concepts/security/pod-security-standard
</td>
<td>
<em>(Optional)</em>
<p>Images is a list of matching image patterns.
Each image is the image name consisting of the registry address, repository, image, and tag.</p>
</td>
</tr>
<tr>
<td>
<code>restrictedField</code><br/>
<em>
string
</em>
</td>
<td>
<em>(Optional)</em>
<p>RestrictedField selects the field for the given Pod Security Standard control.
When not set, all restricted fields for the control are selected.</p>
</td>
</tr>
<tr>
<td>
<code>values</code><br/>
<em>
[]string
</em>
</td>
<td>
<em>(Optional)</em>
<p>Values defines the allowed values that can be excluded.</p>
<p>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.</p>
</td>
</tr>
</tbody>

View file

@ -607,37 +607,6 @@ func Test_Deny(t *testing.T) {
}
}
func Test_ValidatePodSecurity(t *testing.T) {
dir, err := os.Getwd()
baseDir := filepath.Dir(filepath.Dir(dir))
assert.NilError(t, err)
file, err := ioutil.ReadFile(baseDir + "/test/policy/validate/enforce-baseline-exclude-selinuxoptions.yaml")
if err != nil {
t.Log(err)
}
policies, err := yamlutils.GetPolicy(file)
if err != nil {
t.Log(err)
}
policy := policies[0]
spec := policy.GetSpec()
rulePatches, errs := GenerateRulePatches(spec, PodControllers)
if len(errs) != 0 {
t.Log(errs)
}
expectedPatches := [][]byte{
[]byte(`{"path":"/spec/rules/1","op":"add","value":{"name":"autogen-enforce-baseline-exclude-se-linux-options","match":{"any":[{"resources":{"kinds":["DaemonSet","Deployment","Job","StatefulSet"],"namespaces":["privileged-pss-with-kyverno"]}}],"resources":{}},"validate":{"podSecurity":{"level":"baseline","version":"v1.24","exclude":[{"controlName":"SELinux","images":["nginx"],"restrictedField":"spec.template.spec.containers[*].securityContext.seLinuxOptions.role","values":["baz"]},{"controlName":"SELinux","images":["nodejs"],"restrictedField":"spec.template.spec.initContainers[*].securityContext.seLinuxOptions.role","values":["init-bazo"]}]}}}}`),
[]byte(`{"path":"/spec/rules/2","op":"add","value":{"name":"autogen-cronjob-enforce-baseline-exclude-se-linux-options","match":{"any":[{"resources":{"kinds":["CronJob"],"namespaces":["privileged-pss-with-kyverno"]}}],"resources":{}},"validate":{"podSecurity":{"level":"baseline","version":"v1.24","exclude":[{"controlName":"SELinux","images":["nginx"],"restrictedField":"spec.jobTemplate.spec.template.spec.containers[*].securityContext.seLinuxOptions.role","values":["baz"]},{"controlName":"SELinux","images":["nodejs"],"restrictedField":"spec.jobTemplate.spec.template.spec.initContainers[*].securityContext.seLinuxOptions.role","values":["init-bazo"]}]}}}}`),
}
for i, ep := range expectedPatches {
assert.Equal(t, string(rulePatches[i]), string(ep),
fmt.Sprintf("unexpected patch: %s\nexpected: %s", rulePatches[i], ep))
}
}
func Test_ComputeRules(t *testing.T) {
intPtr := func(i int) *int { return &i }
testCases := []struct {

View file

@ -26,7 +26,6 @@ import (
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/pod-security-admission/api"
"sigs.k8s.io/controller-runtime/pkg/log"
)
@ -511,37 +510,20 @@ func (v *validator) validatePodSecurity() *response.RuleResponse {
if err != nil {
return ruleError(v.rule, response.Validation, "Error while getting new resource", err)
}
// Get pod security admission version
var apiVersion api.Version
// Version set to "latest" by default
if v.podSecurity.Version == "" || v.podSecurity.Version == "latest" {
apiVersion = api.LatestVersion()
} else {
parsedApiVersion, err := api.ParseVersion(v.podSecurity.Version)
if err != nil {
return ruleError(v.rule, response.Validation, "failed to parse pod security api version", err)
}
apiVersion = api.MajorMinorVersion(parsedApiVersion.Major(), parsedApiVersion.Minor())
}
level := &api.LevelVersion{
Level: v.podSecurity.Level,
Version: apiVersion,
}
pod := &corev1.Pod{
Spec: *podSpec,
ObjectMeta: *metadata,
}
allowed, pssChecks, err := pss.EvaluatePod(v.podSecurity, pod, level)
allowed, pssChecks, err := pss.EvaluatePod(v.podSecurity, pod)
if err != nil {
msg := fmt.Sprintf("Failed to evaluate validation rule `%s`: %v", v.rule.Name, err)
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusError, nil)
return ruleError(v.rule, response.Validation, "failed to parse pod security api version", err)
}
if allowed {
msg := fmt.Sprintf("Validation rule '%s' passed.", v.rule.Name)
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusPass, nil)
} else {
msg := fmt.Sprintf(`Validation rule '%s' failed. It violates PodSecurity "%s:%s": %s`, v.rule.Name, level.Level, level.Version, pss.FormatChecksPrint(pssChecks))
msg := fmt.Sprintf(`Validation rule '%s' failed. It violates PodSecurity "%s:%s": %s`, v.rule.Name, v.podSecurity.Level, v.podSecurity.Version, pss.FormatChecksPrint(pssChecks))
return ruleResponse(*v.rule, response.Validation, msg, response.RuleStatusFail, nil)
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,30 +1,14 @@
package pss
import (
"fmt"
"reflect"
"strconv"
"strings"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
"github.com/kyverno/kyverno/pkg/utils"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/pod-security-admission/api"
"k8s.io/pod-security-admission/policy"
)
func FormatChecksPrint(checks []PSSCheckResult) string {
var str string
for _, check := range checks {
str += fmt.Sprintf("(%+v)\n", check.CheckResult)
}
return str
}
// Evaluate Pod's specified containers only and get PSSCheckResults
func evaluatePSS(level *api.LevelVersion, pod *corev1.Pod) (results []PSSCheckResult) {
func evaluatePSS(level *api.LevelVersion, pod corev1.Pod) (results []pssCheckResult) {
checks := policy.DefaultChecks()
for _, check := range checks {
@ -34,12 +18,12 @@ func evaluatePSS(level *api.LevelVersion, pod *corev1.Pod) (results []PSSCheckRe
// check version
for _, versionCheck := range check.Versions {
checkResult := versionCheck.CheckPod(&pod.ObjectMeta, &pod.Spec)
// Append only if the checkResult is not already in PSSCheckResults
// Append only if the checkResult is not already in pssCheckResult
if !checkResult.Allowed {
results = append(results, PSSCheckResult{
ID: check.ID,
CheckResult: checkResult,
RestrictedFields: getRestrictedFields(check),
results = append(results, pssCheckResult{
id: check.ID,
checkResult: checkResult,
restrictedFields: getRestrictedFields(check),
})
}
}
@ -47,322 +31,73 @@ func evaluatePSS(level *api.LevelVersion, pod *corev1.Pod) (results []PSSCheckRe
return results
}
// When we specify the controlName only we want to exclude all restrictedFields for this control.
// Remove all PSSChecks related to this control
func trimExemptedChecks(pssChecks []PSSCheckResult, rule *kyvernov1.PodSecurity) []PSSCheckResult {
// Keep in memory the number of checks that have been removed
// to avoid panics when removing a new check.
removedChecks := 0
for checkIndex, check := range pssChecks {
for _, exclude := range rule.Exclude {
// Translate PSS control to check_id and remove it from PSSChecks if it's specified in exclude block
for _, CheckID := range PSS_controls_to_check_id[exclude.ControlName] {
if check.ID == CheckID && exclude.RestrictedField == "" && checkIndex <= len(pssChecks) {
index := checkIndex - removedChecks
pssChecks = append(pssChecks[:index], pssChecks[index+1:]...)
removedChecks++
}
func exemptKyvernoExclusion(defaultCheckResults, excludeCheckResults []pssCheckResult, exclude kyvernov1.PodSecurityStandard) []pssCheckResult {
defaultCheckResultsMap := make(map[string]pssCheckResult, len(defaultCheckResults))
for _, result := range defaultCheckResults {
defaultCheckResultsMap[result.id] = result
}
for _, excludeResult := range excludeCheckResults {
for _, checkID := range PSS_controls_to_check_id[exclude.ControlName] {
if excludeResult.id == checkID {
delete(defaultCheckResultsMap, checkID)
}
}
}
return pssChecks
var newDefaultCheckResults []pssCheckResult
for _, result := range defaultCheckResultsMap {
newDefaultCheckResults = append(newDefaultCheckResults, result)
}
return newDefaultCheckResults
}
func forbiddenValuesExempted(ctx enginectx.Interface, pod *corev1.Pod, check PSSCheckResult, exclude kyvernov1.PodSecurityStandard, restrictedField string) (bool, error) {
if err := enginectx.AddJSONObject(ctx, pod); err != nil {
return false, errors.Wrap(err, "failed to add podSpec to engine context")
func parseVersion(rule *kyvernov1.PodSecurity) (*api.LevelVersion, error) {
// Get pod security admission version
var apiVersion api.Version
// Version set to "latest" by default
if rule.Version == "" || rule.Version == "latest" {
apiVersion = api.LatestVersion()
} else {
parsedApiVersion, err := api.ParseVersion(rule.Version)
if err != nil {
return nil, err
}
apiVersion = api.MajorMinorVersion(parsedApiVersion.Major(), parsedApiVersion.Minor())
}
value, err := ctx.Query(restrictedField)
return &api.LevelVersion{
Level: rule.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, []pssCheckResult, error) {
level, err := parseVersion(rule)
if err != nil {
return false, errors.Wrap(err, fmt.Sprintf("failed to query value with the given path %s", exclude.RestrictedField))
return false, nil, err
}
if !allowedValues(value, exclude, PSS_controls[check.ID]) {
return false, nil
}
return true, nil
}
func checkContainer(ctx enginectx.Interface, pod *corev1.Pod, check PSSCheckResult, exclude []kyvernov1.PodSecurityStandard, restrictedField restrictedField, containerName string, containerTypePrefix string) (bool, error) {
matchedOnce := false
// Container.Name with double quotes
formatedContainerName := fmt.Sprintf(`"%s"`, containerName)
if !strings.Contains(check.CheckResult.ForbiddenDetail, formatedContainerName) {
return true, nil
}
for _, exclude := range exclude {
if !strings.Contains(exclude.RestrictedField, containerTypePrefix) {
continue
}
defaultCheckResults := evaluatePSS(level, *pod)
// Get values of this container only.
// spec.containers[*].securityContext.privileged -> spec.containers[?name=="nginx"].securityContext.privileged
newRestrictedField := strings.Replace(restrictedField.path, "*", fmt.Sprintf(`?name=='%s'`, containerName), 1)
// No need to check if exclude.Images contains container.Image
// Since we only have containers matching the exclude.images with getPodWithMatchingContainers()
exempted, err := forbiddenValuesExempted(ctx, pod, check, exclude, newRestrictedField)
if err != nil || !exempted {
return false, nil
}
matchedOnce = true
}
// If container name is in check.Forbidden but isn't exempted by an exclude then pod creation is forbidden
if strings.Contains(check.CheckResult.ForbiddenDetail, formatedContainerName) && !matchedOnce {
return false, nil
}
return true, nil
}
func checkContainerLevelFields(ctx enginectx.Interface, pod *corev1.Pod, check PSSCheckResult, exclude []kyvernov1.PodSecurityStandard, restrictedField restrictedField) (bool, error) {
if strings.Contains(restrictedField.path, "spec.containers[*]") {
for _, container := range pod.Spec.Containers {
allowed, err := checkContainer(ctx, pod, check, exclude, restrictedField, container.Name, "spec.containers[*]")
if err != nil || !allowed {
return false, nil
}
}
}
if strings.Contains(restrictedField.path, "spec.initContainers[*]") {
for _, container := range pod.Spec.InitContainers {
allowed, err := checkContainer(ctx, pod, check, exclude, restrictedField, container.Name, "spec.initContainers[*]")
if err != nil || !allowed {
return false, nil
}
}
}
if strings.Contains(restrictedField.path, "spec.ephemeralContainers[*]") {
for _, container := range pod.Spec.EphemeralContainers {
allowed, err := checkContainer(ctx, pod, check, exclude, restrictedField, container.Name, "spec.ephemeralContainers[*]")
if err != nil || !allowed {
return false, nil
}
}
}
return true, nil
}
func checkHostNamespacesControl(check PSSCheckResult, restrictedField string) bool {
hostNamespace := strings.Trim(restrictedField, "spec.")
return strings.Contains(check.CheckResult.ForbiddenDetail, hostNamespace)
}
func checkPodLevelFields(ctx enginectx.Interface, pod *corev1.Pod, check PSSCheckResult, rule *kyvernov1.PodSecurity, restrictedField restrictedField) (bool, error) {
// Specific checks for controls with multiple pod-level restrictedFields
// TO DO: SELinux control
if check.ID == "hostNamespaces" {
if !checkHostNamespacesControl(check, restrictedField.path) {
return true, nil
}
}
matchedOnce := false
for _, exclude := range rule.Exclude {
if !strings.Contains(exclude.RestrictedField, restrictedField.path) {
continue
}
spec, matching := getPodWithMatchingContainers(exclude, pod)
exempted, err := forbiddenValuesExempted(ctx, pod, check, exclude, exclude.RestrictedField)
if err != nil || !exempted {
return false, nil
switch {
// exclude pod level checks
case spec != nil:
excludeCheckResults := evaluatePSS(level, *spec)
defaultCheckResults = exemptKyvernoExclusion(defaultCheckResults, excludeCheckResults, exclude)
// exclude container level checks
default:
excludeCheckResults := evaluatePSS(level, *matching)
defaultCheckResults = exemptKyvernoExclusion(defaultCheckResults, excludeCheckResults, exclude)
}
matchedOnce = true
}
if !matchedOnce {
return false, nil
}
return true, nil
}
func exemptProfile(checks []PSSCheckResult, rule *kyvernov1.PodSecurity, pod *corev1.Pod) (bool, error) {
ctx := enginectx.NewContext()
// 1. Iterate over check.RestrictedFields
// 2. Check if it's a `container-level` or `pod-level` restrictedField
// - `container-level`: container has a disallowed check (container name in check.ForbiddenDetail) && exempted by an exclude rule ? continue : pod creation is forbbiden
// - `pod-level`: Exempted by an exclude rule ? good : pod creation is forbbiden
for _, check := range checks {
for _, restrictedField := range check.RestrictedFields {
// Is a container-level restrictedField
// RestrictedField.path can contain:
// - containers[*]
// - initContainers[*]
// - ephemeralContainers[*]
// So we check if it contains `ontainers[*]` to know if there is a CheckResult related to containers.
if strings.Contains(restrictedField.path, "ontainers[*]") {
allowed, err := checkContainerLevelFields(ctx, pod, check, rule.Exclude, restrictedField)
if err != nil {
return false, errors.Wrap(err, err.Error())
}
if !allowed {
return false, nil
}
} else {
// Is a pod-level restrictedField
if !strings.HasPrefix(check.CheckResult.ForbiddenDetail, "pod") && containsContainerLevelControl(check.RestrictedFields) {
continue
}
allowed, err := checkPodLevelFields(ctx, pod, check, rule, restrictedField)
if err != nil {
return false, errors.Wrap(err, err.Error())
}
if !allowed {
return false, nil
}
}
}
}
return true, nil
}
// Check if the pod creation is allowed after exempting some PSS controls
func EvaluatePod(rule *kyvernov1.PodSecurity, pod *corev1.Pod, level *api.LevelVersion) (bool, []PSSCheckResult, error) {
// 1. Evaluate containers that match images specified in exclude
podWithMatchingContainers := getPodWithMatchingContainers(rule.Exclude, pod)
pssChecks := evaluatePSS(level, &podWithMatchingContainers)
pssChecks = trimExemptedChecks(pssChecks, rule)
// 2. Check if all PSSCheckResults are exempted by exclude values
allowed, err := exemptProfile(pssChecks, rule, &podWithMatchingContainers)
if err != nil {
return false, pssChecks, err
}
// Good to have: remove checks that are exempted and return only forbidden ones
if !allowed {
return false, pssChecks, nil
}
// 3. Check the remaining containers
podWithNotMatchingContainers := getPodWithNotMatchingContainers(rule.Exclude, pod, &podWithMatchingContainers)
pssChecks = evaluatePSS(level, &podWithNotMatchingContainers)
if len(pssChecks) > 0 {
return false, pssChecks, nil
}
return true, pssChecks, nil
}
func appendAllowedValues(controls []restrictedField, exclude *kyvernov1.PodSecurityStandard) {
for _, control := range controls {
if control.path == exclude.RestrictedField {
for _, allowedValue := range control.allowedValues {
switch v := allowedValue.(type) {
case string:
if !utils.ContainsString(exclude.Values, v) {
exclude.Values = append(exclude.Values, v)
}
}
}
}
}
}
func allowedValuesSlice(excludeValues []interface{}, exclude kyvernov1.PodSecurityStandard) bool {
for _, values := range excludeValues {
v := reflect.TypeOf(values)
switch v.Kind() {
case reflect.Slice:
for _, value := range values.([]interface{}) {
if reflect.TypeOf(value).Kind() == reflect.Float64 {
if !utils.ContainsString(exclude.Values, fmt.Sprintf("%.f", value)) {
return false
}
} else if reflect.TypeOf(value).Kind() == reflect.String {
if !utils.ContainsString(exclude.Values, value.(string)) {
return false
}
}
}
case reflect.Map:
for key, value := range values.(map[string]interface{}) {
if exclude.RestrictedField == "spec.volumes[*]" {
if key == "name" {
continue
}
matchedOnce := false
for _, excludeValue := range exclude.Values {
// Remove `spec.volumes[*].` prefix
if strings.TrimPrefix(excludeValue, "spec.volumes[*].") == key {
matchedOnce = true
}
}
if !matchedOnce {
return false
}
}
// "HostPath volume" control: check the path of the hostPath volume since the type is optional
// volumes:
// - name: test-volume
// hostPath:
// # directory location on host
// path: /data <--- Check the path
// # this field is optional
// type: Directory
if exclude.RestrictedField == "spec.volumes[*].hostPath" {
if key != "path" {
continue
}
if !utils.ContainsString(exclude.Values, value.(string)) {
return false
}
}
}
case reflect.String:
if !utils.ContainsString(exclude.Values, values.(string)) {
return false
}
case reflect.Bool:
if !utils.ContainsString(exclude.Values, strconv.FormatBool(values.(bool))) {
return false
}
case reflect.Float64:
if !utils.ContainsString(exclude.Values, fmt.Sprintf("%.f", values)) {
return false
}
}
}
return true
}
func allowedValues(resourceValue interface{}, exclude kyvernov1.PodSecurityStandard, controls []restrictedField) bool {
appendAllowedValues(controls, &exclude)
v := reflect.TypeOf(resourceValue)
switch v.Kind() {
case reflect.Bool:
if !utils.ContainsString(exclude.Values, strconv.FormatBool(resourceValue.(bool))) {
return false
}
return true
case reflect.String:
if !utils.ContainsString(exclude.Values, resourceValue.(string)) {
return false
}
return true
case reflect.Float64:
if !utils.ContainsString(exclude.Values, fmt.Sprintf("%.f", resourceValue)) {
return false
}
return true
case reflect.Map:
// `AppArmor` control
for key, value := range resourceValue.(map[string]interface{}) {
if !strings.Contains(key, "container.apparmor.security.beta.kubernetes.io/") {
continue
}
// For allowed value: "localhost/*"
if strings.Contains(value.(string), "localhost/") {
continue
}
if !utils.ContainsString(exclude.Values, value.(string)) {
return false
}
}
return true
case reflect.Slice:
exempted := allowedValuesSlice(resourceValue.([]interface{}), exclude)
if !exempted {
return false
}
}
return true
return len(defaultCheckResults) == 0, defaultCheckResults, nil
}

5188
pkg/pss/evaluate_test.go Normal file

File diff suppressed because it is too large Load diff

View file

@ -7,10 +7,10 @@ type restrictedField struct {
allowedValues []interface{}
}
type PSSCheckResult struct {
ID string
CheckResult policy.CheckResult
RestrictedFields []restrictedField
type pssCheckResult struct {
id string
checkResult policy.CheckResult
restrictedFields []restrictedField
}
// Translate PSS control to CheckResult.ID so that we can use PSS control in Kyverno policy
@ -18,10 +18,12 @@ type PSSCheckResult struct {
// For CheckResult.ID see: https://github.com/kubernetes/pod-security-admission/tree/master/policy
var PSS_controls_to_check_id = map[string][]string{
// Controls with 2 different controls for each level
// container-level control
"Capabilities": {
"capabilities_baseline",
"capabilities_restricted",
},
// Container and Pod-level control
"Seccomp": {
"seccompProfile_baseline",
"seccompProfile_restricted",
@ -38,9 +40,6 @@ var PSS_controls_to_check_id = map[string][]string{
"/proc Mount Type": {
"procMount",
},
"procMount": {
"hostPorts",
},
// Container and pod-level controls
"HostProcess": {
@ -67,10 +66,10 @@ var PSS_controls_to_check_id = map[string][]string{
},
// === Restricted
// Container and pod-level controls
"Privilege Escalation": {
"allowPrivilegeEscalation",
},
// Container and pod-level controls
"Running as Non-root": {
"runAsNonRoot",
},

View file

@ -1,125 +1,51 @@
package pss
import (
"strings"
"fmt"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/utils"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/pod-security-admission/policy"
)
func containsContainer(containers interface{}, containerName string) bool {
switch v := containers.(type) {
case []interface{}:
for _, container := range v {
switch v := container.(type) {
case corev1.Container:
if v.Name == containerName {
return true
}
case corev1.EphemeralContainer:
if v.Name == containerName {
return true
}
}
}
case []corev1.Container:
for _, container := range v {
if container.Name == containerName {
return true
}
}
case []corev1.EphemeralContainer:
for _, container := range v {
if container.Name == containerName {
return true
}
}
// getPodWithMatchingContainers extracts matching container/pod info by the given exclude rule
// and returns pod manifests containing spec and container info respectively
func getPodWithMatchingContainers(exclude kyvernov1.PodSecurityStandard, pod *corev1.Pod) (podSpec, matching *corev1.Pod) {
if len(exclude.Images) == 0 {
podSpec = pod.DeepCopy()
podSpec.Spec.Containers = []corev1.Container{{Name: "fake"}}
podSpec.Spec.InitContainers = nil
podSpec.Spec.EphemeralContainers = nil
return podSpec, nil
}
return false
}
// Get copy of pod with containers (containers, initContainers, ephemeralContainers) matching the exclude.image
func getPodWithMatchingContainers(exclude []kyvernov1.PodSecurityStandard, pod *corev1.Pod) (podCopy corev1.Pod) {
podCopy = *pod
podCopy.Spec.Containers = []corev1.Container{}
podCopy.Spec.InitContainers = []corev1.Container{}
podCopy.Spec.EphemeralContainers = []corev1.EphemeralContainer{}
matchingImages := exclude.Images
matching = &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: pod.GetName(),
Namespace: pod.GetNamespace(),
},
}
for _, container := range pod.Spec.Containers {
for _, excludeRule := range exclude {
// Ignore all restrictedFields when we only specify the `controlName` with no `restrictedField`
controlNameOnly := excludeRule.RestrictedField == ""
if !utils.ContainsString(excludeRule.Images, container.Image) {
continue
}
if strings.Contains(excludeRule.RestrictedField, "spec.containers[*]") || controlNameOnly {
// Add to matchingContainers if either it's empty or is unique
if len(podCopy.Spec.Containers) == 0 || !containsContainer(podCopy.Spec.Containers, container.Name) {
podCopy.Spec.Containers = append(podCopy.Spec.Containers, container)
}
}
if utils.ContainsWildcardPatterns(matchingImages, container.Image) {
matching.Spec.Containers = append(matching.Spec.Containers, container)
}
}
for _, container := range pod.Spec.InitContainers {
for _, excludeRule := range exclude {
// Ignore all restrictedFields when we only specify the `controlName` with no `restrictedField`
controlNameOnly := excludeRule.RestrictedField == ""
if !utils.ContainsString(excludeRule.Images, container.Image) {
continue
}
if strings.Contains(excludeRule.RestrictedField, "spec.initContainers[*]") || controlNameOnly {
// Add to matchingContainers if either it's empty or is unique
if len(podCopy.Spec.InitContainers) == 0 || !containsContainer(podCopy.Spec.InitContainers, container.Name) {
podCopy.Spec.InitContainers = append(podCopy.Spec.InitContainers, container)
}
}
if utils.ContainsWildcardPatterns(matchingImages, container.Image) {
matching.Spec.InitContainers = append(matching.Spec.InitContainers, container)
}
}
for _, container := range pod.Spec.EphemeralContainers {
for _, excludeRule := range exclude {
// Ignore all restrictedFields when we only specify the `controlName` with no `restrictedField`
controlNameOnly := excludeRule.RestrictedField == ""
if !utils.ContainsString(excludeRule.Images, container.Image) {
continue
}
if strings.Contains(excludeRule.RestrictedField, "spec.ephemeralContainers[*]") || controlNameOnly {
// Add to matchingContainers if either it's empty or is unique
if len(podCopy.Spec.EphemeralContainers) == 0 || !containsContainer(podCopy.Spec.EphemeralContainers, container.Name) {
podCopy.Spec.EphemeralContainers = append(podCopy.Spec.EphemeralContainers, container)
}
}
}
}
return podCopy
}
// Get containers NOT matching images specified in Exclude values
func getPodWithNotMatchingContainers(exclude []kyvernov1.PodSecurityStandard, pod *corev1.Pod, podWithMatchingContainers *corev1.Pod) (podCopy corev1.Pod) {
// Only copy containers because we have already evaluated the pod-level controls
// e.g.: spec.securityContext.hostProcess
podCopy.Spec.Containers = []corev1.Container{}
podCopy.Spec.InitContainers = []corev1.Container{}
podCopy.Spec.EphemeralContainers = []corev1.EphemeralContainer{}
// Append containers that are not in podWithMatchingContainers already evaluated in EvaluatePod()
for _, container := range pod.Spec.Containers {
if !containsContainer(podWithMatchingContainers.Spec.Containers, container.Name) {
podCopy.Spec.Containers = append(podCopy.Spec.Containers, container)
}
}
for _, container := range pod.Spec.InitContainers {
if !containsContainer(podWithMatchingContainers.Spec.InitContainers, container.Name) {
podCopy.Spec.InitContainers = append(podCopy.Spec.InitContainers, container)
}
}
for _, container := range pod.Spec.EphemeralContainers {
if !containsContainer(podWithMatchingContainers.Spec.EphemeralContainers, container.Name) {
podCopy.Spec.EphemeralContainers = append(podCopy.Spec.EphemeralContainers, container)
if utils.ContainsWildcardPatterns(matchingImages, container.Image) {
matching.Spec.EphemeralContainers = append(matching.Spec.EphemeralContainers, container)
}
}
return podCopy
return nil, matching
}
// Get restrictedFields from Check.ID
@ -134,11 +60,10 @@ func getRestrictedFields(check policy.Check) []restrictedField {
return nil
}
func containsContainerLevelControl(restrictedFields []restrictedField) bool {
for _, restrictedField := range restrictedFields {
if strings.Contains(restrictedField.path, "ontainers[*]") {
return true
}
func FormatChecksPrint(checks []pssCheckResult) string {
var str string
for _, check := range checks {
str += fmt.Sprintf("(%+v)\n", check.checkResult)
}
return false
return str
}

View file

@ -83,7 +83,7 @@ func contains(list []string, element string, fn func(string, string) bool) bool
// ContainsNamepace check if namespace satisfies any list of pattern(regex)
func ContainsNamepace(patterns []string, ns string) bool {
return contains(patterns, ns, compareNamespaces)
return contains(patterns, ns, comparePatterns)
}
// ContainsString checks if the string is contained in the list
@ -91,7 +91,11 @@ func ContainsString(list []string, element string) bool {
return contains(list, element, compareString)
}
func compareNamespaces(pattern, ns string) bool {
func ContainsWildcardPatterns(patterns []string, key string) bool {
return contains(patterns, key, comparePatterns)
}
func comparePatterns(pattern, ns string) bool {
return wildcard.Match(pattern, ns)
}

View file

@ -1,32 +0,0 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-baseline-exclude-se-linux-options
spec:
validationFailureAction: enforce
rules:
- name: enforce-baseline-exclude-se-linux-options
match:
any:
- resources:
kinds:
- Pod
namespaces:
- privileged-pss-with-kyverno
validate:
podSecurity:
level: baseline
version: v1.24
exclude:
- controlName: "SELinux"
restrictedField: spec.containers[*].securityContext.seLinuxOptions.role
images:
- nginx
values:
- baz
- controlName: "SELinux"
restrictedField: spec.initContainers[*].securityContext.seLinuxOptions.role
images:
- nodejs
values:
- init-bazo