From f31ccec18c59001e0ba3787a1196a069f493a917 Mon Sep 17 00:00:00 2001 From: pweil- Date: Wed, 6 Jul 2016 10:32:23 -0400 Subject: [PATCH] SCC seccomp admission --- pkg/security/admission/admission.go | 6 +- pkg/security/admission/admission_test.go | 111 +++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/pkg/security/admission/admission.go b/pkg/security/admission/admission.go index c0bd745dec1c..7c3edc1875c2 100644 --- a/pkg/security/admission/admission.go +++ b/pkg/security/admission/admission.go @@ -169,7 +169,7 @@ func assignSecurityContext(provider scc.SecurityContextConstraintsProvider, pod errs := field.ErrorList{} - psc, err := provider.CreatePodSecurityContext(pod) + psc, generatedAnnotations, err := provider.CreatePodSecurityContext(pod) if err != nil { errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error())) } @@ -178,7 +178,10 @@ func assignSecurityContext(provider scc.SecurityContextConstraintsProvider, pod // set for container generation/validation. We will reset to original post container // validation. originalPSC := pod.Spec.SecurityContext + originalAnnotations := pod.Annotations + pod.Spec.SecurityContext = psc + pod.Annotations = generatedAnnotations errs = append(errs, provider.ValidatePodSecurityContext(pod, field.NewPath("spec", "securityContext"))...) // Note: this is not changing the original container, we will set container SCs later so long @@ -209,6 +212,7 @@ func assignSecurityContext(provider scc.SecurityContextConstraintsProvider, pod if len(errs) > 0 { // ensure psc is not mutated if there are errors pod.Spec.SecurityContext = originalPSC + pod.Annotations = originalAnnotations return errs } diff --git a/pkg/security/admission/admission_test.go b/pkg/security/admission/admission_test.go index 66b52cf78c6a..d9fdda4e7245 100644 --- a/pkg/security/admission/admission_test.go +++ b/pkg/security/admission/admission_test.go @@ -1485,6 +1485,117 @@ func TestAdmitWithPrioritizedSCC(t *testing.T) { testSCCAdmission(matchingPriorityAndScoreSCCOnePod, plugin, matchingPriorityAndScoreSCCOne.Name, t) } +func TestAdmitSeccomp(t *testing.T) { + createPodWithSeccomp := func(podAnnotation, containerAnnotation string) *kapi.Pod { + pod := goodPod() + pod.Annotations = map[string]string{} + if podAnnotation != "" { + pod.Annotations[kapi.SeccompPodAnnotationKey] = podAnnotation + } + if containerAnnotation != "" { + pod.Annotations[kapi.SeccompContainerAnnotationKeyPrefix+"container"] = containerAnnotation + } + pod.Spec.Containers[0].Name = "container" + return pod + } + + noSeccompSCC := restrictiveSCC() + noSeccompSCC.Name = "noseccomp" + + seccompSCC := restrictiveSCC() + seccompSCC.Name = "seccomp" + seccompSCC.SeccompProfiles = []string{"foo"} + + wildcardSCC := restrictiveSCC() + wildcardSCC.Name = "wildcard" + wildcardSCC.SeccompProfiles = []string{"*"} + + tests := map[string]struct { + pod *kapi.Pod + sccs []*kapi.SecurityContextConstraints + shouldPass bool + expectedPodAnnotation string + expectedSCC string + }{ + "no seccomp, no requests": { + pod: goodPod(), + sccs: []*kapi.SecurityContextConstraints{noSeccompSCC}, + shouldPass: true, + expectedSCC: noSeccompSCC.Name, + }, + "no seccomp, bad container requests": { + pod: createPodWithSeccomp("foo", "bar"), + sccs: []*kapi.SecurityContextConstraints{noSeccompSCC}, + shouldPass: false, + }, + "seccomp, no requests": { + pod: goodPod(), + sccs: []*kapi.SecurityContextConstraints{seccompSCC}, + shouldPass: true, + expectedPodAnnotation: "foo", + expectedSCC: seccompSCC.Name, + }, + "seccomp, valid pod annotation, no container annotation": { + pod: createPodWithSeccomp("foo", ""), + sccs: []*kapi.SecurityContextConstraints{seccompSCC}, + shouldPass: true, + expectedPodAnnotation: "foo", + expectedSCC: seccompSCC.Name, + }, + "seccomp, no pod annotation, valid container annotation": { + pod: createPodWithSeccomp("", "foo"), + sccs: []*kapi.SecurityContextConstraints{seccompSCC}, + shouldPass: true, + expectedPodAnnotation: "foo", + expectedSCC: seccompSCC.Name, + }, + "seccomp, valid pod annotation, invalid container annotation": { + pod: createPodWithSeccomp("foo", "bar"), + sccs: []*kapi.SecurityContextConstraints{seccompSCC}, + shouldPass: false, + }, + "wild card, no requests": { + pod: goodPod(), + sccs: []*kapi.SecurityContextConstraints{wildcardSCC}, + shouldPass: true, + expectedSCC: wildcardSCC.Name, + }, + "wild card, requests": { + pod: createPodWithSeccomp("foo", "bar"), + sccs: []*kapi.SecurityContextConstraints{wildcardSCC}, + shouldPass: true, + expectedPodAnnotation: "foo", + expectedSCC: wildcardSCC.Name, + }, + } + + for k, v := range tests { + testSCCAdmit(k, v.sccs, v.pod, v.shouldPass, t) + + if v.shouldPass { + validatedSCC, ok := v.pod.Annotations[allocator.ValidatedSCCAnnotation] + if !ok { + t.Errorf("expected to find the validated annotation on the pod for the scc but found none") + return + } + if validatedSCC != v.expectedSCC { + t.Errorf("should have validated against %s but found %s", v.expectedSCC, validatedSCC) + } + + if len(v.expectedPodAnnotation) > 0 { + annotation, found := v.pod.Annotations[kapi.SeccompPodAnnotationKey] + if !found { + t.Errorf("%s expected to have pod annotation for seccomp but found none", k) + } + if found && annotation != v.expectedPodAnnotation { + t.Errorf("%s expected pod annotation to be %s but found %s", k, v.expectedPodAnnotation, annotation) + } + } + } + } + +} + // testSCCAdmission is a helper to admit the pod and ensure it was validated against the expected // SCC. func testSCCAdmission(pod *kapi.Pod, plugin kadmission.Interface, expectedSCC string, t *testing.T) {