Example #1
0
func init() {
	admission.RegisterPlugin(PluginName, func(client clientset.Interface, config io.Reader) (admission.Interface, error) {
		plugin := NewPlugin(client, psp.NewSimpleStrategyFactory(), getMatchingPolicies, false)
		plugin.Run()
		return plugin, nil
	})
}
Example #2
0
func NewTestAdmission(store cache.Store, kclient clientset.Interface) kadmission.Interface {
	return &podSecurityPolicyPlugin{
		Handler:         kadmission.NewHandler(kadmission.Create),
		client:          kclient,
		store:           store,
		strategyFactory: kpsp.NewSimpleStrategyFactory(),
		pspMatcher:      getMatchingPolicies,
	}
}
Example #3
0
func init() {
	admission.RegisterPlugin(PluginName, func(config io.Reader) (admission.Interface, error) {
		plugin := NewPlugin(psp.NewSimpleStrategyFactory(), getMatchingPolicies, true)
		return plugin, nil
	})
}
Example #4
0
func TestAssignSecurityContext(t *testing.T) {
	// psp that will deny privileged container requests and has a default value for a field (uid)
	psp := restrictivePSP()
	provider, err := kpsp.NewSimpleProvider(psp, "namespace", kpsp.NewSimpleStrategyFactory())
	if err != nil {
		t.Fatalf("failed to create provider: %v", err)
	}

	createContainer := func(priv bool) kapi.Container {
		return kapi.Container{
			SecurityContext: &kapi.SecurityContext{
				Privileged: &priv,
			},
		}
	}

	// these are set up such that the containers always have a nil uid.  If the case should not
	// validate then the uids should not have been updated by the strategy.  If the case should
	// validate then uids should be set.  This is ensuring that we're hanging on to the old SC
	// as we generate/validate and only updating the original container if the entire pod validates
	testCases := map[string]struct {
		pod            *kapi.Pod
		shouldValidate bool
		expectedUID    *int64
	}{
		"pod and container SC is not changed when invalid": {
			pod: &kapi.Pod{
				Spec: kapi.PodSpec{
					SecurityContext: &kapi.PodSecurityContext{},
					Containers:      []kapi.Container{createContainer(true)},
				},
			},
			shouldValidate: false,
		},
		"must validate all containers": {
			pod: &kapi.Pod{
				Spec: kapi.PodSpec{
					// good container and bad container
					SecurityContext: &kapi.PodSecurityContext{},
					Containers:      []kapi.Container{createContainer(false), createContainer(true)},
				},
			},
			shouldValidate: false,
		},
		"pod validates": {
			pod: &kapi.Pod{
				Spec: kapi.PodSpec{
					SecurityContext: &kapi.PodSecurityContext{},
					Containers:      []kapi.Container{createContainer(false)},
				},
			},
			shouldValidate: true,
		},
	}

	for k, v := range testCases {
		errs := assignSecurityContext(provider, v.pod, nil)
		if v.shouldValidate && len(errs) > 0 {
			t.Errorf("%s expected to validate but received errors %v", k, errs)
			continue
		}
		if !v.shouldValidate && len(errs) == 0 {
			t.Errorf("%s expected validation errors but received none", k)
			continue
		}

		// if we shouldn't have validated ensure that uid is not set on the containers
		if !v.shouldValidate {
			for _, c := range v.pod.Spec.Containers {
				if c.SecurityContext.RunAsUser != nil {
					t.Errorf("%s had non-nil UID %d.  UID should not be set on test cases that don't validate", k, *c.SecurityContext.RunAsUser)
				}
			}
		}

		// if we validated then the pod sc should be updated now with the defaults from the psp
		if v.shouldValidate {
			for _, c := range v.pod.Spec.Containers {
				if *c.SecurityContext.RunAsUser != 999 {
					t.Errorf("%s expected uid to be defaulted to 999 but found %v", k, *c.SecurityContext.RunAsUser)
				}
			}
		}
	}
}
Example #5
0
func TestCreateProvidersFromConstraints(t *testing.T) {
	testCases := map[string]struct {
		// use a generating function so we can test for non-mutation
		psp         func() *extensions.PodSecurityPolicy
		expectedErr string
	}{
		"valid psp": {
			psp: func() *extensions.PodSecurityPolicy {
				return &extensions.PodSecurityPolicy{
					ObjectMeta: kapi.ObjectMeta{
						Name: "valid psp",
					},
					Spec: extensions.PodSecurityPolicySpec{
						SELinux: extensions.SELinuxStrategyOptions{
							Rule: extensions.SELinuxStrategyRunAsAny,
						},
						RunAsUser: extensions.RunAsUserStrategyOptions{
							Rule: extensions.RunAsUserStrategyRunAsAny,
						},
						FSGroup: extensions.FSGroupStrategyOptions{
							Rule: extensions.FSGroupStrategyRunAsAny,
						},
						SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{
							Rule: extensions.SupplementalGroupsStrategyRunAsAny,
						},
					},
				}
			},
		},
		"bad psp strategy options": {
			psp: func() *extensions.PodSecurityPolicy {
				return &extensions.PodSecurityPolicy{
					ObjectMeta: kapi.ObjectMeta{
						Name: "bad psp user options",
					},
					Spec: extensions.PodSecurityPolicySpec{
						SELinux: extensions.SELinuxStrategyOptions{
							Rule: extensions.SELinuxStrategyRunAsAny,
						},
						RunAsUser: extensions.RunAsUserStrategyOptions{
							Rule: extensions.RunAsUserStrategyMustRunAs,
						},
						FSGroup: extensions.FSGroupStrategyOptions{
							Rule: extensions.FSGroupStrategyRunAsAny,
						},
						SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{
							Rule: extensions.SupplementalGroupsStrategyRunAsAny,
						},
					},
				}
			},
			expectedErr: "MustRunAsRange requires at least one range",
		},
	}

	for k, v := range testCases {
		store := cache.NewStore(cache.MetaNamespaceKeyFunc)

		tc := clientsetfake.NewSimpleClientset()
		admit := &podSecurityPolicyPlugin{
			Handler:         kadmission.NewHandler(kadmission.Create, kadmission.Update),
			client:          tc,
			store:           store,
			strategyFactory: kpsp.NewSimpleStrategyFactory(),
		}

		psp := v.psp()
		_, errs := admit.createProvidersFromPolicies([]*extensions.PodSecurityPolicy{psp}, "namespace")

		if !reflect.DeepEqual(psp, v.psp()) {
			diff := diff.ObjectDiff(psp, v.psp())
			t.Errorf("%s createProvidersFromPolicies mutated policy. diff:\n%s", k, diff)
		}
		if len(v.expectedErr) > 0 && len(errs) != 1 {
			t.Errorf("%s expected a single error '%s' but received %v", k, v.expectedErr, errs)
			continue
		}
		if len(v.expectedErr) == 0 && len(errs) != 0 {
			t.Errorf("%s did not expect an error but received %v", k, errs)
			continue
		}

		// check that we got the error we expected
		if len(v.expectedErr) > 0 {
			if !strings.Contains(errs[0].Error(), v.expectedErr) {
				t.Errorf("%s expected error '%s' but received %v", k, v.expectedErr, errs[0])
			}
		}
	}
}