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 }) }
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, } }
func init() { admission.RegisterPlugin(PluginName, func(config io.Reader) (admission.Interface, error) { plugin := NewPlugin(psp.NewSimpleStrategyFactory(), getMatchingPolicies, true) return plugin, nil }) }
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) } } } } }
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]) } } } }