Example #1
0
				}
			}
			return false, nil
		})
		return ev, err
	}

	BeforeEach(func() {
		podClient = f.PodClient()
	})

	It("should support sysctls", func() {
		pod := testPod()
		pod.Annotations[api.SysctlsPodAnnotationKey] = api.PodAnnotationsFromSysctls([]api.Sysctl{
			{
				Name:  "kernel.shm_rmid_forced",
				Value: "1",
			},
		})
		pod.Spec.Containers[0].Command = []string{"/bin/sysctl", "kernel.shm_rmid_forced"}

		By("Creating a pod with the kernel.shm_rmid_forced sysctl")
		pod = podClient.Create(pod)

		By("Watching for error events or started pod")
		// watch for events instead of termination of pod because the kubelet deletes
		// failed pods without running containers. This would create a race as the pod
		// might have already been deleted here.
		ev, err := waitForPodErrorEventOrStarted(pod)
		Expect(err).NotTo(HaveOccurred())
		if ev != nil && ev.Reason == sysctl.UnsupportedReason {
			framework.Skipf("No sysctl support in Docker <1.12")
func TestValidate(t *testing.T) {
	tests := map[string]struct {
		patterns   []string
		allowed    []string
		disallowed []string
	}{
		// no container requests
		"nil": {
			patterns: nil,
			allowed:  []string{"foo"},
		},
		"empty": {
			patterns:   []string{},
			disallowed: []string{"foo"},
		},
		"without wildcard": {
			patterns:   []string{"a", "a.b"},
			allowed:    []string{"a", "a.b"},
			disallowed: []string{"b"},
		},
		"with catch-all wildcard": {
			patterns: []string{"*"},
			allowed:  []string{"a", "a.b"},
		},
		"with catch-all wildcard and non-wildcard": {
			patterns: []string{"a.b.c", "*"},
			allowed:  []string{"a", "a.b", "a.b.c", "b"},
		},
		"without catch-all wildcard": {
			patterns:   []string{"a.*", "b.*", "c.d.e", "d.e.f.*"},
			allowed:    []string{"a.b", "b.c", "c.d.e", "d.e.f.g.h"},
			disallowed: []string{"a", "b", "c", "c.d", "d.e", "d.e.f"},
		},
	}

	for k, v := range tests {
		strategy, err := NewMustMatchPatterns(v.patterns)
		if err != nil {
			t.Errorf("%s failed: %v", k, err)
			continue
		}

		pod := &api.Pod{}
		errs := strategy.Validate(pod)
		if len(errs) != 0 {
			t.Errorf("%s: unexpected validaton errors for empty sysctls: %v", k, errs)
		}

		sysctls := []api.Sysctl{}
		for _, s := range v.allowed {
			sysctls = append(sysctls, api.Sysctl{
				Name:  s,
				Value: "dummy",
			})
		}
		testAllowed := func(key string, category string) {
			pod.Annotations = map[string]string{
				key: api.PodAnnotationsFromSysctls(sysctls),
			}
			errs = strategy.Validate(pod)
			if len(errs) != 0 {
				t.Errorf("%s: unexpected validaton errors for %s sysctls: %v", k, category, errs)
			}
		}
		testDisallowed := func(key string, category string) {
			for _, s := range v.disallowed {
				pod.Annotations = map[string]string{
					key: api.PodAnnotationsFromSysctls([]api.Sysctl{{s, "dummy"}}),
				}
				errs = strategy.Validate(pod)
				if len(errs) == 0 {
					t.Errorf("%s: expected error for %s sysctl %q", k, category, s)
				}
			}
		}

		testAllowed(api.SysctlsPodAnnotationKey, "safe")
		testAllowed(api.UnsafeSysctlsPodAnnotationKey, "unsafe")
		testDisallowed(api.SysctlsPodAnnotationKey, "safe")
		testDisallowed(api.UnsafeSysctlsPodAnnotationKey, "unsafe")
	}
}
Example #3
0
func TestAdmitSysctls(t *testing.T) {
	podWithSysctls := func(safeSysctls []string, unsafeSysctls []string) *kapi.Pod {
		pod := goodPod()
		dummySysctls := func(names []string) []kapi.Sysctl {
			sysctls := make([]kapi.Sysctl, len(names))
			for i, n := range names {
				sysctls[i].Name = n
				sysctls[i].Value = "dummy"
			}
			return sysctls
		}
		pod.Annotations[kapi.SysctlsPodAnnotationKey] = kapi.PodAnnotationsFromSysctls(dummySysctls(safeSysctls))
		pod.Annotations[kapi.UnsafeSysctlsPodAnnotationKey] = kapi.PodAnnotationsFromSysctls(dummySysctls(unsafeSysctls))
		return pod
	}

	noSysctls := restrictivePSP()
	noSysctls.Name = "no sysctls"

	emptySysctls := restrictivePSP()
	emptySysctls.Name = "empty sysctls"
	emptySysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = ""

	mixedSysctls := restrictivePSP()
	mixedSysctls.Name = "wildcard sysctls"
	mixedSysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a.*,b.*,c,d.e.f"

	aSysctl := restrictivePSP()
	aSysctl.Name = "a sysctl"
	aSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "a"

	bSysctl := restrictivePSP()
	bSysctl.Name = "b sysctl"
	bSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "b"

	cSysctl := restrictivePSP()
	cSysctl.Name = "c sysctl"
	cSysctl.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "c"

	catchallSysctls := restrictivePSP()
	catchallSysctls.Name = "catchall sysctl"
	catchallSysctls.Annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] = "*"

	tests := map[string]struct {
		pod         *kapi.Pod
		psps        []*extensions.PodSecurityPolicy
		shouldPass  bool
		expectedPSP string
	}{
		"pod without unsafe sysctls request allowed under noSysctls PSP": {
			pod:         goodPod(),
			psps:        []*extensions.PodSecurityPolicy{noSysctls},
			shouldPass:  true,
			expectedPSP: noSysctls.Name,
		},
		"pod without any sysctls request allowed under emptySysctls PSP": {
			pod:         goodPod(),
			psps:        []*extensions.PodSecurityPolicy{emptySysctls},
			shouldPass:  true,
			expectedPSP: emptySysctls.Name,
		},
		"pod with safe sysctls request allowed under noSysctls PSP": {
			pod:         podWithSysctls([]string{"a", "b"}, []string{}),
			psps:        []*extensions.PodSecurityPolicy{noSysctls},
			shouldPass:  true,
			expectedPSP: noSysctls.Name,
		},
		"pod with unsafe sysctls request allowed under noSysctls PSP": {
			pod:         podWithSysctls([]string{}, []string{"a", "b"}),
			psps:        []*extensions.PodSecurityPolicy{noSysctls},
			shouldPass:  true,
			expectedPSP: noSysctls.Name,
		},
		"pod with safe sysctls request disallowed under emptySysctls PSP": {
			pod:        podWithSysctls([]string{"a", "b"}, []string{}),
			psps:       []*extensions.PodSecurityPolicy{emptySysctls},
			shouldPass: false,
		},
		"pod with unsafe sysctls request disallowed under emptySysctls PSP": {
			pod:        podWithSysctls([]string{}, []string{"a", "b"}),
			psps:       []*extensions.PodSecurityPolicy{emptySysctls},
			shouldPass: false,
		},
		"pod with matching sysctls request allowed under mixedSysctls PSP": {
			pod:         podWithSysctls([]string{"a.b", "b.c"}, []string{"c", "d.e.f"}),
			psps:        []*extensions.PodSecurityPolicy{mixedSysctls},
			shouldPass:  true,
			expectedPSP: mixedSysctls.Name,
		},
		"pod with not-matching unsafe sysctls request allowed under mixedSysctls PSP": {
			pod:        podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f"}, []string{"e"}),
			psps:       []*extensions.PodSecurityPolicy{mixedSysctls},
			shouldPass: false,
		},
		"pod with not-matching safe sysctls request allowed under mixedSysctls PSP": {
			pod:        podWithSysctls([]string{"a.b", "b.c", "c", "d.e.f", "e"}, []string{}),
			psps:       []*extensions.PodSecurityPolicy{mixedSysctls},
			shouldPass: false,
		},
		"pod with sysctls request allowed under catchallSysctls PSP": {
			pod:         podWithSysctls([]string{"e"}, []string{"f"}),
			psps:        []*extensions.PodSecurityPolicy{catchallSysctls},
			shouldPass:  true,
			expectedPSP: catchallSysctls.Name,
		},
		"pod with sysctls request allowed under catchallSysctls PSP, not under mixedSysctls or emptySysctls PSP": {
			pod:         podWithSysctls([]string{"e"}, []string{"f"}),
			psps:        []*extensions.PodSecurityPolicy{mixedSysctls, catchallSysctls, emptySysctls},
			shouldPass:  true,
			expectedPSP: catchallSysctls.Name,
		},
		"pod with safe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": {
			pod:         podWithSysctls([]string{}, []string{"c"}),
			psps:        []*extensions.PodSecurityPolicy{aSysctl, bSysctl, cSysctl},
			shouldPass:  true,
			expectedPSP: cSysctl.Name,
		},
		"pod with unsafe c sysctl request allowed under cSysctl PSP, not under aSysctl or bSysctl PSP": {
			pod:         podWithSysctls([]string{"c"}, []string{}),
			psps:        []*extensions.PodSecurityPolicy{aSysctl, bSysctl, cSysctl},
			shouldPass:  true,
			expectedPSP: cSysctl.Name,
		},
	}

	for k, v := range tests {
		origSafeSysctls, origUnsafeSysctls, err := kapi.SysctlsFromPodAnnotations(v.pod.Annotations)
		if err != nil {
			t.Fatalf("invalid sysctl annotation: %v", err)
		}

		testPSPAdmit(k, v.psps, v.pod, v.shouldPass, v.expectedPSP, t)

		if v.shouldPass {
			safeSysctls, unsafeSysctls, _ := kapi.SysctlsFromPodAnnotations(v.pod.Annotations)
			if !reflect.DeepEqual(safeSysctls, origSafeSysctls) {
				t.Errorf("%s: wrong safe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls)
			}
			if !reflect.DeepEqual(unsafeSysctls, origUnsafeSysctls) {
				t.Errorf("%s: wrong unsafe sysctls: expected=%v, got=%v", k, origSafeSysctls, safeSysctls)
			}
		}
	}
}