Skip to content

Commit

Permalink
admission_test.go(TestAdmit): split to TestAdmitSuccess and TestAdmit…
Browse files Browse the repository at this point in the history
…Failure.
  • Loading branch information
php-coder committed Nov 14, 2017
1 parent c634e11 commit d935b12
Showing 1 changed file with 184 additions and 120 deletions.
304 changes: 184 additions & 120 deletions pkg/security/admission/admission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func testSCCAdmit(testCaseName string, sccs []*securityapi.SecurityContextConstr
}
}

func TestAdmit(t *testing.T) {
func TestAdmitSuccess(t *testing.T) {
// create the annotated namespace and add it to the fake client
namespace := admissiontesting.CreateNamespaceForTest()
serviceAccount := admissiontesting.CreateSAForTest()
Expand Down Expand Up @@ -251,20 +251,6 @@ func TestAdmit(t *testing.T) {
// create the admission plugin
p := NewTestAdmission(cache, tc)

// setup test data
uidNotInRange := goodPod()
var uid int64 = 1001
uidNotInRange.Spec.Containers[0].SecurityContext.RunAsUser = &uid

invalidMCSLabels := goodPod()
invalidMCSLabels.Spec.Containers[0].SecurityContext.SELinuxOptions = &kapi.SELinuxOptions{
Level: "s1:q0,q1",
}

disallowedPriv := goodPod()
var priv bool = true
disallowedPriv.Spec.Containers[0].SecurityContext.Privileged = &priv

// specifies a UID in the range of the preallocated UID annotation
specifyUIDInRange := goodPod()
var goodUID int64 = 3
Expand Down Expand Up @@ -293,174 +279,254 @@ func TestAdmit(t *testing.T) {
Level: "s0:c1,c0",
}

requestsHostNetwork := goodPod()
requestsHostNetwork.Spec.SecurityContext.HostNetwork = true

requestsHostPID := goodPod()
requestsHostPID.Spec.SecurityContext.HostPID = true

requestsHostIPC := goodPod()
requestsHostIPC.Spec.SecurityContext.HostIPC = true

requestsHostPorts := goodPod()
requestsHostPorts.Spec.Containers[0].Ports = []kapi.ContainerPort{{HostPort: 1}}

requestsSupplementalGroup := goodPod()
requestsSupplementalGroup.Spec.SecurityContext.SupplementalGroups = []int64{1}

requestsFSGroup := goodPod()
fsGroup := int64(1)
requestsFSGroup.Spec.SecurityContext.FSGroup = &fsGroup

requestsPodLevelMCS := goodPod()
requestsPodLevelMCS.Spec.SecurityContext.SELinuxOptions = &kapi.SELinuxOptions{
User: "user",
Type: "type",
Role: "role",
Level: "level",
}

testCases := map[string]struct {
pod *kapi.Pod
shouldAdmit bool
expectedUID int64
expectedLevel string
expectedFSGroup int64
expectedSupGroups []int64
expectedPriv bool
}{
"uidNotInRange": {
pod: uidNotInRange,
shouldAdmit: false,
},
"invalidMCSLabels": {
pod: invalidMCSLabels,
shouldAdmit: false,
},
"disallowedPriv": {
pod: disallowedPriv,
shouldAdmit: false,
},
"specifyUIDInRange": {
pod: specifyUIDInRange,
shouldAdmit: true,
expectedUID: *specifyUIDInRange.Spec.Containers[0].SecurityContext.RunAsUser,
expectedLevel: "s0:c1,c0",
expectedFSGroup: defaultGroup,
expectedSupGroups: []int64{defaultGroup},
},
"specifyLabels": {
pod: specifyLabels,
shouldAdmit: true,
expectedUID: 1,
expectedLevel: specifyLabels.Spec.Containers[0].SecurityContext.SELinuxOptions.Level,
expectedFSGroup: defaultGroup,
expectedSupGroups: []int64{defaultGroup},
},
"specifyFSGroup": {
pod: specifyFSGroupInRange,
shouldAdmit: true,
expectedUID: 1,
expectedLevel: "s0:c1,c0",
expectedFSGroup: *specifyFSGroupInRange.Spec.SecurityContext.FSGroup,
expectedSupGroups: []int64{defaultGroup},
},
"specifySupGroup": {
pod: specifySupGroup,
shouldAdmit: true,
expectedUID: 1,
expectedLevel: "s0:c1,c0",
expectedFSGroup: defaultGroup,
expectedSupGroups: []int64{specifySupGroup.Spec.SecurityContext.SupplementalGroups[0]},
},
"specifyPodLevelSELinuxLevel": {
pod: specifyPodLevelSELinux,
shouldAdmit: true,
expectedUID: 1,
expectedLevel: "s0:c1,c0",
expectedFSGroup: defaultGroup,
expectedSupGroups: []int64{defaultGroup},
},
}

for i := 0; i < 2; i++ {
for k, v := range testCases {
v.pod.Spec.Containers, v.pod.Spec.InitContainers = v.pod.Spec.InitContainers, v.pod.Spec.Containers
containers := v.pod.Spec.Containers
if i == 0 {
containers = v.pod.Spec.InitContainers
}
attrs := kadmission.NewAttributesRecord(v.pod, nil, kapi.Kind("Pod").WithVersion("version"), v.pod.Namespace, v.pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{})
err := p.Admit(attrs)

if err != nil {
t.Fatalf("%s expected no errors but received %v", k, err)
}

validatedSCC, ok := v.pod.Annotations[allocator.ValidatedSCCAnnotation]
if !ok {
t.Errorf("%s expected to find the validated annotation on the pod for the scc but found none", k)
}
if validatedSCC != saSCC.Name {
t.Errorf("%s should have validated against %s but found %s", k, saSCC.Name, validatedSCC)
}

// ensure anything we expected to be defaulted on the container level is set
if *containers[0].SecurityContext.RunAsUser != v.expectedUID {
t.Errorf("%s expected UID %d but found %d", k, v.expectedUID, *containers[0].SecurityContext.RunAsUser)
}
if containers[0].SecurityContext.SELinuxOptions.Level != v.expectedLevel {
t.Errorf("%s expected Level %s but found %s", k, v.expectedLevel, containers[0].SecurityContext.SELinuxOptions.Level)
}

// ensure anything we expected to be defaulted on the pod level is set
if v.pod.Spec.SecurityContext.SELinuxOptions.Level != v.expectedLevel {
t.Errorf("%s expected pod level SELinux Level %s but found %s", k, v.expectedLevel, v.pod.Spec.SecurityContext.SELinuxOptions.Level)
}
if *v.pod.Spec.SecurityContext.FSGroup != v.expectedFSGroup {
t.Errorf("%s expected fsgroup %d but found %d", k, v.expectedFSGroup, *v.pod.Spec.SecurityContext.FSGroup)
}
if len(v.pod.Spec.SecurityContext.SupplementalGroups) != len(v.expectedSupGroups) {
t.Errorf("%s found unexpected supplemental groups. Expected: %v, actual %v", k, v.expectedSupGroups, v.pod.Spec.SecurityContext.SupplementalGroups)
}
for _, g := range v.expectedSupGroups {
if !hasSupGroup(g, v.pod.Spec.SecurityContext.SupplementalGroups) {
t.Errorf("%s expected sup group %d", k, g)
}
}
}
}
}

func TestAdmitFailure(t *testing.T) {
// create the annotated namespace and add it to the fake client
namespace := admissiontesting.CreateNamespaceForTest()
serviceAccount := admissiontesting.CreateSAForTest()

tc := clientsetfake.NewSimpleClientset(namespace, serviceAccount)

// create scc that requires allocation retrieval
saSCC := &securityapi.SecurityContextConstraints{
ObjectMeta: metav1.ObjectMeta{
Name: "scc-sa",
},
RunAsUser: securityapi.RunAsUserStrategyOptions{
Type: securityapi.RunAsUserStrategyMustRunAsRange,
},
SELinuxContext: securityapi.SELinuxContextStrategyOptions{
Type: securityapi.SELinuxStrategyMustRunAs,
},
FSGroup: securityapi.FSGroupStrategyOptions{
Type: securityapi.FSGroupStrategyMustRunAs,
},
SupplementalGroups: securityapi.SupplementalGroupsStrategyOptions{
Type: securityapi.SupplementalGroupsStrategyMustRunAs,
},
Groups: []string{"system:serviceaccounts"},
}
// create scc that has specific requirements that shouldn't match but is permissioned to
// service accounts to test that even though this has matching priorities (0) and a
// lower point value score (which will cause it to be sorted in front of scc-sa) it should not
// validate the requests so we should try scc-sa.
var exactUID int64 = 999
saExactSCC := &securityapi.SecurityContextConstraints{
ObjectMeta: metav1.ObjectMeta{
Name: "scc-sa-exact",
},
RunAsUser: securityapi.RunAsUserStrategyOptions{
Type: securityapi.RunAsUserStrategyMustRunAs,
UID: &exactUID,
},
SELinuxContext: securityapi.SELinuxContextStrategyOptions{
Type: securityapi.SELinuxStrategyMustRunAs,
SELinuxOptions: &kapi.SELinuxOptions{
Level: "s9:z0,z1",
},
},
FSGroup: securityapi.FSGroupStrategyOptions{
Type: securityapi.FSGroupStrategyMustRunAs,
Ranges: []securityapi.IDRange{
{Min: 999, Max: 999},
},
},
SupplementalGroups: securityapi.SupplementalGroupsStrategyOptions{
Type: securityapi.SupplementalGroupsStrategyMustRunAs,
Ranges: []securityapi.IDRange{
{Min: 999, Max: 999},
},
},
Groups: []string{"system:serviceaccounts"},
}

indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
cache := securitylisters.NewSecurityContextConstraintsLister(indexer)

indexer.Add(saExactSCC)
indexer.Add(saSCC)

// create the admission plugin
p := NewTestAdmission(cache, tc)

// setup test data
uidNotInRange := goodPod()
var uid int64 = 1001
uidNotInRange.Spec.Containers[0].SecurityContext.RunAsUser = &uid

invalidMCSLabels := goodPod()
invalidMCSLabels.Spec.Containers[0].SecurityContext.SELinuxOptions = &kapi.SELinuxOptions{
Level: "s1:q0,q1",
}

disallowedPriv := goodPod()
var priv bool = true
disallowedPriv.Spec.Containers[0].SecurityContext.Privileged = &priv

requestsHostNetwork := goodPod()
requestsHostNetwork.Spec.SecurityContext.HostNetwork = true

requestsHostPorts := goodPod()
requestsHostPorts.Spec.Containers[0].Ports = []kapi.ContainerPort{{HostPort: 1}}

requestsHostPID := goodPod()
requestsHostPID.Spec.SecurityContext.HostPID = true

requestsHostIPC := goodPod()
requestsHostIPC.Spec.SecurityContext.HostIPC = true

requestsSupplementalGroup := goodPod()
requestsSupplementalGroup.Spec.SecurityContext.SupplementalGroups = []int64{1}

requestsFSGroup := goodPod()
fsGroup := int64(1)
requestsFSGroup.Spec.SecurityContext.FSGroup = &fsGroup

requestsPodLevelMCS := goodPod()
requestsPodLevelMCS.Spec.SecurityContext.SELinuxOptions = &kapi.SELinuxOptions{
User: "user",
Type: "type",
Role: "role",
Level: "level",
}

testCases := map[string]struct {
pod *kapi.Pod
}{
"uidNotInRange": {
pod: uidNotInRange,
},
"invalidMCSLabels": {
pod: invalidMCSLabels,
},
"disallowedPriv": {
pod: disallowedPriv,
},
"requestsHostNetwork": {
pod: requestsHostNetwork,
shouldAdmit: false,
pod: requestsHostNetwork,
},
"requestsHostPorts": {
pod: requestsHostPorts,
shouldAdmit: false,
pod: requestsHostPorts,
},
"requestsHostPID": {
pod: requestsHostPID,
shouldAdmit: false,
pod: requestsHostPID,
},
"requestsHostIPC": {
pod: requestsHostIPC,
shouldAdmit: false,
pod: requestsHostIPC,
},
"requestsSupplementalGroup": {
pod: requestsSupplementalGroup,
shouldAdmit: false,
pod: requestsSupplementalGroup,
},
"requestsFSGroup": {
pod: requestsFSGroup,
shouldAdmit: false,
pod: requestsFSGroup,
},
"requestsPodLevelMCS": {
pod: requestsPodLevelMCS,
shouldAdmit: false,
pod: requestsPodLevelMCS,
},
}

for i := 0; i < 2; i++ {
for k, v := range testCases {
v.pod.Spec.Containers, v.pod.Spec.InitContainers = v.pod.Spec.InitContainers, v.pod.Spec.Containers
containers := v.pod.Spec.Containers
if i == 0 {
containers = v.pod.Spec.InitContainers
}
attrs := kadmission.NewAttributesRecord(v.pod, nil, kapi.Kind("Pod").WithVersion("version"), v.pod.Namespace, v.pod.Name, kapi.Resource("pods").WithVersion("version"), "", kadmission.Create, &user.DefaultInfo{})
err := p.Admit(attrs)

if v.shouldAdmit && err != nil {
t.Fatalf("%s expected no errors but received %v", k, err)
}
if !v.shouldAdmit && err == nil {
if err == nil {
t.Errorf("%s expected errors but received none", k)
}

if v.shouldAdmit {
validatedSCC, ok := v.pod.Annotations[allocator.ValidatedSCCAnnotation]
if !ok {
t.Errorf("%s expected to find the validated annotation on the pod for the scc but found none", k)
}
if validatedSCC != saSCC.Name {
t.Errorf("%s should have validated against %s but found %s", k, saSCC.Name, validatedSCC)
}

// ensure anything we expected to be defaulted on the container level is set
if *containers[0].SecurityContext.RunAsUser != v.expectedUID {
t.Errorf("%s expected UID %d but found %d", k, v.expectedUID, *containers[0].SecurityContext.RunAsUser)
}
if containers[0].SecurityContext.SELinuxOptions.Level != v.expectedLevel {
t.Errorf("%s expected Level %s but found %s", k, v.expectedLevel, containers[0].SecurityContext.SELinuxOptions.Level)
}

// ensure anything we expected to be defaulted on the pod level is set
if v.pod.Spec.SecurityContext.SELinuxOptions.Level != v.expectedLevel {
t.Errorf("%s expected pod level SELinux Level %s but found %s", k, v.expectedLevel, v.pod.Spec.SecurityContext.SELinuxOptions.Level)
}
if *v.pod.Spec.SecurityContext.FSGroup != v.expectedFSGroup {
t.Errorf("%s expected fsgroup %d but found %d", k, v.expectedFSGroup, *v.pod.Spec.SecurityContext.FSGroup)
}
if len(v.pod.Spec.SecurityContext.SupplementalGroups) != len(v.expectedSupGroups) {
t.Errorf("%s found unexpected supplemental groups. Expected: %v, actual %v", k, v.expectedSupGroups, v.pod.Spec.SecurityContext.SupplementalGroups)
}
for _, g := range v.expectedSupGroups {
if !hasSupGroup(g, v.pod.Spec.SecurityContext.SupplementalGroups) {
t.Errorf("%s expected sup group %d", k, g)
}
}
}
}
}

Expand Down Expand Up @@ -496,10 +562,8 @@ func TestAdmit(t *testing.T) {
for k, v := range testCases {
v.pod.Spec.Containers, v.pod.Spec.InitContainers = v.pod.Spec.InitContainers, v.pod.Spec.Containers

if !v.shouldAdmit {
// pods that were rejected by strict SCC, should pass with relaxed SCC
testSCCAdmission(v.pod, p, adminSCC.Name, k, t)
}
// pods that were rejected by strict SCC, should pass with relaxed SCC
testSCCAdmission(v.pod, p, adminSCC.Name, k, t)
}
}
}
Expand Down

0 comments on commit d935b12

Please sign in to comment.