From 2b88dc381e12415e349b78f644e4e90711d00e39 Mon Sep 17 00:00:00 2001
From: njuptlzf
Date: Fri, 9 Jul 2021 09:13:38 +0800
Subject: [PATCH] [PodSecurity] Add test coverage for pod-template-containing
objects
---
.../admission/admission_test.go | 183 ++++++++++++++++++
1 file changed, 183 insertions(+)
diff --git a/staging/src/k8s.io/pod-security-admission/admission/admission_test.go b/staging/src/k8s.io/pod-security-admission/admission/admission_test.go
index c2e0478ef0c..d710f8cc440 100644
--- a/staging/src/k8s.io/pod-security-admission/admission/admission_test.go
+++ b/staging/src/k8s.io/pod-security-admission/admission/admission_test.go
@@ -184,6 +184,14 @@ func (t *testEvaluator) EvaluatePod(lv api.LevelVersion, meta *metav1.ObjectMeta
}
}
+type testNamespaceGetter struct {
+ ns *corev1.Namespace
+}
+
+func (t *testNamespaceGetter) GetNamespace(ctx context.Context, name string) (*corev1.Namespace, error) {
+ return t.ns, nil
+}
+
type testPodLister struct {
called bool
pods []*corev1.Pod
@@ -457,3 +465,178 @@ func TestValidateNamespace(t *testing.T) {
})
}
}
+
+func TestValidatePodController(t *testing.T) {
+ testName, testNamespace := "testname", "default"
+ objMetadata := metav1.ObjectMeta{Name: testName, Namespace: testNamespace, Labels: map[string]string{"foo": "bar"}}
+ // One of the pod-template objects
+ goodDeploy := appsv1.Deployment{
+ ObjectMeta: objMetadata,
+ Spec: appsv1.DeploymentSpec{
+ Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
+ Template: corev1.PodTemplateSpec{
+ ObjectMeta: objMetadata,
+ Spec: corev1.PodSpec{
+ RuntimeClassName: pointer.String("containerd"),
+ },
+ },
+ },
+ }
+ badDeploy := appsv1.Deployment{
+ ObjectMeta: objMetadata,
+ Spec: appsv1.DeploymentSpec{
+ Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}},
+ Template: corev1.PodTemplateSpec{
+ ObjectMeta: objMetadata,
+ Spec: corev1.PodSpec{
+ SecurityContext: &corev1.PodSecurityContext{
+ // out of allowed sysctls to return auditAnnotation or warning
+ Sysctls: []corev1.Sysctl{{Name: "unknown", Value: "unknown"}},
+ },
+ RuntimeClassName: pointer.String("containerd"),
+ },
+ },
+ },
+ }
+
+ // Ensure that under the baseline policy,
+ // the pod-template object of all tests returns correct information or is exempted
+ nsLabels := map[string]string{
+ api.EnforceLevelLabel: string(api.LevelBaseline),
+ api.WarnLevelLabel: string(api.LevelBaseline),
+ api.AuditLevelLabel: string(api.LevelBaseline),
+ }
+
+ testCases := []struct {
+ desc string
+ exemptNamespaces []string
+ exemptRuntimeClasses []string
+ exemptUsers []string
+ // request subresource
+ subresource string
+ // for create
+ newObject runtime.Object
+ // for update
+ oldObject runtime.Object
+ gvr schema.GroupVersionResource
+
+ expectWarnings []string
+ expectAuditAnnotations map[string]string
+ }{
+ {
+ desc: "subresource(status) updates don't produce warnings",
+ subresource: "status",
+ newObject: &badDeploy,
+ oldObject: &goodDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ },
+ {
+ desc: "namespace in exemptNamespaces will be exempted",
+ newObject: &badDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ exemptNamespaces: []string{testNamespace},
+ },
+ {
+ desc: "runtimeClass in exemptRuntimeClasses will be exempted",
+ newObject: &badDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ exemptRuntimeClasses: []string{"containerd"},
+ },
+ {
+ desc: "user in exemptUsers will be exempted",
+ newObject: &badDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ exemptUsers: []string{"testuser"},
+ },
+ {
+ desc: "podMetadata == nil && podSpec == nil will skip verification",
+ newObject: &corev1.ReplicationController{ObjectMeta: metav1.ObjectMeta{Name: "foo-rc"}},
+ gvr: schema.GroupVersionResource{Group: "", Version: "v1", Resource: "replicationcontrollers"},
+ },
+ {
+ desc: "good deploy creates and produce nothing",
+ newObject: &goodDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ expectAuditAnnotations: map[string]string{},
+ },
+ {
+ desc: "bad deploy creates produce correct user-visible warnings and correct auditAnnotations",
+ newObject: &badDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ expectAuditAnnotations: map[string]string{"audit": "forbidden sysctls (unknown)"},
+ expectWarnings: []string{"would violate \"latest\" version of \"baseline\" PodSecurity profile: forbidden sysctls (unknown)"},
+ },
+ {
+ desc: "bad spec updates don't block on enforce failures and returns correct information",
+ newObject: &badDeploy,
+ oldObject: &goodDeploy,
+ gvr: schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"},
+ expectAuditAnnotations: map[string]string{"audit": "forbidden sysctls (unknown)"},
+ expectWarnings: []string{"would violate \"latest\" version of \"baseline\" PodSecurity profile: forbidden sysctls (unknown)"},
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ var operation = admissionv1.Create
+ if tc.oldObject != nil {
+ operation = admissionv1.Update
+ }
+
+ attrs := &AttributesRecord{
+ testName,
+ testNamespace,
+ tc.gvr,
+ tc.subresource,
+ operation,
+ tc.newObject,
+ tc.oldObject,
+ "testuser",
+ }
+
+ defaultPolicy := api.Policy{
+ Enforce: api.LevelVersion{Level: api.LevelPrivileged, Version: api.LatestVersion()},
+ Audit: api.LevelVersion{Level: api.LevelPrivileged, Version: api.LatestVersion()},
+ Warn: api.LevelVersion{Level: api.LevelPrivileged, Version: api.LatestVersion()},
+ }
+
+ podLister := &testPodLister{}
+ evaluator, err := policy.NewEvaluator(policy.DefaultChecks())
+ assert.NoError(t, err)
+ nsGetter := &testNamespaceGetter{
+ ns: &corev1.Namespace{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: testName,
+ Namespace: testNamespace,
+ Labels: nsLabels}},
+ }
+ PodSpecExtractor := &DefaultPodSpecExtractor{}
+ a := &Admission{
+ PodLister: podLister,
+ Evaluator: evaluator,
+ PodSpecExtractor: PodSpecExtractor,
+ Configuration: &admissionapi.PodSecurityConfiguration{
+ Exemptions: admissionapi.PodSecurityExemptions{
+ Namespaces: tc.exemptNamespaces,
+ RuntimeClasses: tc.exemptRuntimeClasses,
+ Usernames: tc.exemptUsers,
+ },
+ },
+ defaultPolicy: defaultPolicy,
+ NamespaceGetter: nsGetter,
+ }
+
+ result := a.ValidatePodController(context.TODO(), attrs)
+ // podContorller will not return an error due to correct evaluation
+ resultError := ""
+ if result.Result != nil {
+ resultError = result.Result.Message
+ }
+
+ assert.Equal(t, true, result.Allowed)
+ assert.Empty(t, resultError)
+ assert.Equal(t, tc.expectAuditAnnotations, result.AuditAnnotations, "unexpected AuditAnnotations")
+ assert.Equal(t, tc.expectWarnings, result.Warnings, "unexpected Warnings")
+ })
+ }
+}