diff --git a/pkg/security/podsecuritypolicy/BUILD b/pkg/security/podsecuritypolicy/BUILD index 7859a6e2d9..715f9bb694 100644 --- a/pkg/security/podsecuritypolicy/BUILD +++ b/pkg/security/podsecuritypolicy/BUILD @@ -48,6 +48,8 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/github.com/davecgh/go-spew/spew:go_default_library", + "//vendor/github.com/stretchr/testify/assert:go_default_library", + "//vendor/github.com/stretchr/testify/require:go_default_library", ], ) diff --git a/pkg/security/podsecuritypolicy/provider_test.go b/pkg/security/podsecuritypolicy/provider_test.go index e774f70f43..c246e7b529 100644 --- a/pkg/security/podsecuritypolicy/provider_test.go +++ b/pkg/security/podsecuritypolicy/provider_test.go @@ -19,10 +19,13 @@ package podsecuritypolicy import ( "fmt" "reflect" + "strconv" "strings" "testing" "github.com/davecgh/go-spew/spew" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -1232,110 +1235,64 @@ func TestValidateAllowedVolumes(t *testing.T) { } } -// TestValidateAllowPrivilegeEscalation will test that when the podSecurityPolicy -// AllowPrivilegeEscalation is false we cannot set a container's securityContext -// to allowPrivilegeEscalation, but when it is true we can. -func TestValidateAllowPrivilegeEscalation(t *testing.T) { - pod := defaultPod() - pe := true - pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &pe - - // create a PSP that does not allow privilege escalation - psp := defaultPSP() - psp.Spec.AllowPrivilegeEscalation = false - - provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory()) - if err != nil { - t.Errorf("error creating provider: %v", err.Error()) +func TestAllowPrivilegeEscalation(t *testing.T) { + ptr := func(b bool) *bool { return &b } + tests := []struct { + pspAPE bool // PSP AllowPrivilegeEscalation + pspDAPE *bool // PSP DefaultAllowPrivilegeEscalation + podAPE *bool // Pod AllowPrivilegeEscalation + expectErr bool + expectAPE *bool // Expected value of pod APE (if no error) + }{ + // Test all valid combinations of PSP AllowPrivilegeEscalation, + // DefaultAllowPrivilegeEscalation, and Pod AllowPrivilegeEscalation. + {true, nil, nil, false, nil}, + {true, nil, ptr(false), false, ptr(false)}, + {true, nil, ptr(true), false, ptr(true)}, + {true, ptr(false), nil, false, ptr(false)}, + {true, ptr(false), ptr(false), false, ptr(false)}, + {true, ptr(false), ptr(true), false, ptr(true)}, + {true, ptr(true), nil, false, ptr(true)}, + {true, ptr(true), ptr(false), false, ptr(false)}, + {true, ptr(true), ptr(true), false, ptr(true)}, + {false, nil, nil, false, ptr(false)}, + {false, nil, ptr(false), false, ptr(false)}, + {false, nil, ptr(true), true, nil}, + {false, ptr(false), nil, false, ptr(false)}, + {false, ptr(false), ptr(false), false, ptr(false)}, + {false, ptr(false), ptr(true), true, nil}, + // Invalid cases: pspAPE=false, pspDAPE=true } - // expect a denial for this PSP and test the error message to ensure it's related to allowPrivilegeEscalation - errs := provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 1 { - t.Errorf("expected exactly 1 error but got %v", errs) - } else { - if !strings.Contains(errs.ToAggregate().Error(), "Allowing privilege escalation for containers is not allowed") { - t.Errorf("did not find the expected error, received: %v", errs) + fmtPtr := func(b *bool) string { + if b == nil { + return "nil" } + return strconv.FormatBool(*b) } + for _, test := range tests { + t.Run(fmt.Sprintf("pspAPE:%t_pspDAPE:%s_podAPE:%s", test.pspAPE, fmtPtr(test.pspDAPE), fmtPtr(test.podAPE)), func(t *testing.T) { + pod := defaultPod() + pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = test.podAPE - // now add allowPrivilegeEscalation to the podSecurityPolicy - psp.Spec.AllowPrivilegeEscalation = true - errs = provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 0 { - t.Errorf("directly allowing privilege escalation expected no errors but got %v", errs) - } -} - -// TestValidateDefaultAllowPrivilegeEscalation will test that when the podSecurityPolicy -// DefaultAllowPrivilegeEscalation is false we cannot set a container's -// securityContext to allowPrivilegeEscalation but when it is true we can. -func TestValidateDefaultAllowPrivilegeEscalation(t *testing.T) { - pod := defaultPod() - pe := true - pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = &pe - - // create a PSP that does not allow privilege escalation - psp := defaultPSP() - dpe := false - psp.Spec.DefaultAllowPrivilegeEscalation = &dpe - psp.Spec.AllowPrivilegeEscalation = false - - provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory()) - if err != nil { - t.Errorf("error creating provider: %v", err.Error()) - } - - // expect a denial for this PSP and test the error message to ensure it's related to allowPrivilegeEscalation - errs := provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 1 { - t.Errorf("expected exactly 1 error but got %v", errs) - } else { - if !strings.Contains(errs.ToAggregate().Error(), "Allowing privilege escalation for containers is not allowed") { - t.Errorf("did not find the expected error, received: %v", errs) - } - } - - // now add DefaultAllowPrivilegeEscalation to the podSecurityPolicy - dpe = true - psp.Spec.DefaultAllowPrivilegeEscalation = &dpe - psp.Spec.AllowPrivilegeEscalation = false - - // expect a denial for this PSP because we did not allowPrivilege Escalation via the PodSecurityPolicy - // and test the error message to ensure it's related to allowPrivilegeEscalation - errs = provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 1 { - t.Errorf("expected exactly 1 error but got %v", errs) - } else { - if !strings.Contains(errs.ToAggregate().Error(), "Allowing privilege escalation for containers is not allowed") { - t.Errorf("did not find the expected error, received: %v", errs) - } - } - - // Now set AllowPrivilegeEscalation - psp.Spec.AllowPrivilegeEscalation = true - errs = provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 0 { - t.Errorf("directly allowing privilege escalation expected no errors but got %v", errs) - } - - // Now set the psp spec to false and reset AllowPrivilegeEscalation - psp.Spec.AllowPrivilegeEscalation = false - pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = nil - errs = provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 1 { - t.Errorf("expected exactly 1 error but got %v", errs) - } else { - if !strings.Contains(errs.ToAggregate().Error(), "Allowing privilege escalation for containers is not allowed") { - t.Errorf("did not find the expected error, received: %v", errs) - } - } - - // Now unset both AllowPrivilegeEscalation - psp.Spec.AllowPrivilegeEscalation = true - pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = nil - errs = provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) - if len(errs) != 0 { - t.Errorf("resetting allowing privilege escalation expected no errors but got %v", errs) + psp := defaultPSP() + psp.Spec.AllowPrivilegeEscalation = test.pspAPE + psp.Spec.DefaultAllowPrivilegeEscalation = test.pspDAPE + + provider, err := NewSimpleProvider(psp, "namespace", NewSimpleStrategyFactory()) + require.NoError(t, err) + + err = provider.DefaultContainerSecurityContext(pod, &pod.Spec.Containers[0]) + require.NoError(t, err) + + errs := provider.ValidateContainer(pod, &pod.Spec.Containers[0], field.NewPath("")) + if test.expectErr { + assert.NotEmpty(t, errs, "expected validation error") + } else { + assert.Empty(t, errs, "expected no validation errors") + ape := pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation + assert.Equal(t, test.expectAPE, ape, "expected pod AllowPrivilegeEscalation") + } + }) } }