8e5b17cf13
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
334 lines
9 KiB
Go
334 lines
9 KiB
Go
/*
|
|
Copyright 2014 The Kubernetes Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package securitycontext
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
"testing"
|
|
|
|
dockercontainer "github.com/docker/engine-api/types/container"
|
|
apitesting "k8s.io/kubernetes/pkg/api/testing"
|
|
"k8s.io/kubernetes/pkg/api/v1"
|
|
)
|
|
|
|
func TestModifyContainerConfig(t *testing.T) {
|
|
var uid int64 = 123
|
|
var overrideUid int64 = 321
|
|
|
|
cases := []struct {
|
|
name string
|
|
podSc *v1.PodSecurityContext
|
|
sc *v1.SecurityContext
|
|
expected *dockercontainer.Config
|
|
}{
|
|
{
|
|
name: "container.SecurityContext.RunAsUser set",
|
|
sc: &v1.SecurityContext{
|
|
RunAsUser: &uid,
|
|
},
|
|
expected: &dockercontainer.Config{
|
|
User: strconv.FormatInt(uid, 10),
|
|
},
|
|
},
|
|
{
|
|
name: "no RunAsUser value set",
|
|
sc: &v1.SecurityContext{},
|
|
expected: &dockercontainer.Config{},
|
|
},
|
|
{
|
|
name: "pod.Spec.SecurityContext.RunAsUser set",
|
|
podSc: &v1.PodSecurityContext{
|
|
RunAsUser: &uid,
|
|
},
|
|
expected: &dockercontainer.Config{
|
|
User: strconv.FormatInt(uid, 10),
|
|
},
|
|
},
|
|
{
|
|
name: "container.SecurityContext.RunAsUser overrides pod.Spec.SecurityContext.RunAsUser",
|
|
podSc: &v1.PodSecurityContext{
|
|
RunAsUser: &uid,
|
|
},
|
|
sc: &v1.SecurityContext{
|
|
RunAsUser: &overrideUid,
|
|
},
|
|
expected: &dockercontainer.Config{
|
|
User: strconv.FormatInt(overrideUid, 10),
|
|
},
|
|
},
|
|
}
|
|
|
|
provider := NewSimpleSecurityContextProvider()
|
|
dummyContainer := &v1.Container{}
|
|
for _, tc := range cases {
|
|
pod := &v1.Pod{Spec: v1.PodSpec{SecurityContext: tc.podSc}}
|
|
dummyContainer.SecurityContext = tc.sc
|
|
dockerCfg := &dockercontainer.Config{}
|
|
|
|
provider.ModifyContainerConfig(pod, dummyContainer, dockerCfg)
|
|
|
|
if e, a := tc.expected, dockerCfg; !reflect.DeepEqual(e, a) {
|
|
t.Errorf("%v: unexpected modification of docker config\nExpected:\n\n%#v\n\nGot:\n\n%#v", tc.name, e, a)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestModifyHostConfig(t *testing.T) {
|
|
priv := true
|
|
setPrivSC := &v1.SecurityContext{}
|
|
setPrivSC.Privileged = &priv
|
|
setPrivHC := &dockercontainer.HostConfig{
|
|
Privileged: true,
|
|
}
|
|
|
|
setCapsHC := &dockercontainer.HostConfig{
|
|
CapAdd: []string{"addCapA", "addCapB"},
|
|
CapDrop: []string{"dropCapA", "dropCapB"},
|
|
}
|
|
|
|
setSELinuxHC := &dockercontainer.HostConfig{}
|
|
setSELinuxHC.SecurityOpt = []string{
|
|
fmt.Sprintf("%s:%s", DockerLabelUser, "user"),
|
|
fmt.Sprintf("%s:%s", DockerLabelRole, "role"),
|
|
fmt.Sprintf("%s:%s", DockerLabelType, "type"),
|
|
fmt.Sprintf("%s:%s", DockerLabelLevel, "level"),
|
|
}
|
|
|
|
// seLinuxLabelsSC := fullValidSecurityContext()
|
|
// seLinuxLabelsHC := fullValidHostConfig()
|
|
|
|
cases := []struct {
|
|
name string
|
|
podSc *v1.PodSecurityContext
|
|
sc *v1.SecurityContext
|
|
expected *dockercontainer.HostConfig
|
|
}{
|
|
{
|
|
name: "fully set container.SecurityContext",
|
|
sc: fullValidSecurityContext(),
|
|
expected: fullValidHostConfig(),
|
|
},
|
|
{
|
|
name: "container.SecurityContext.Privileged",
|
|
sc: setPrivSC,
|
|
expected: setPrivHC,
|
|
},
|
|
{
|
|
name: "container.SecurityContext.Capabilities",
|
|
sc: &v1.SecurityContext{
|
|
Capabilities: inputCapabilities(),
|
|
},
|
|
expected: setCapsHC,
|
|
},
|
|
{
|
|
name: "container.SecurityContext.SELinuxOptions",
|
|
sc: &v1.SecurityContext{
|
|
SELinuxOptions: inputSELinuxOptions(),
|
|
},
|
|
expected: setSELinuxHC,
|
|
},
|
|
{
|
|
name: "pod.Spec.SecurityContext.SELinuxOptions",
|
|
podSc: &v1.PodSecurityContext{
|
|
SELinuxOptions: inputSELinuxOptions(),
|
|
},
|
|
expected: setSELinuxHC,
|
|
},
|
|
{
|
|
name: "container.SecurityContext overrides pod.Spec.SecurityContext",
|
|
podSc: overridePodSecurityContext(),
|
|
sc: fullValidSecurityContext(),
|
|
expected: fullValidHostConfig(),
|
|
},
|
|
}
|
|
|
|
provider := NewSimpleSecurityContextProvider()
|
|
dummyContainer := &v1.Container{}
|
|
|
|
for _, tc := range cases {
|
|
pod := &v1.Pod{Spec: v1.PodSpec{SecurityContext: tc.podSc}}
|
|
dummyContainer.SecurityContext = tc.sc
|
|
dockerCfg := &dockercontainer.HostConfig{}
|
|
|
|
provider.ModifyHostConfig(pod, dummyContainer, dockerCfg, nil)
|
|
|
|
if e, a := tc.expected, dockerCfg; !reflect.DeepEqual(e, a) {
|
|
t.Errorf("%v: unexpected modification of host config\nExpected:\n\n%#v\n\nGot:\n\n%#v", tc.name, e, a)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestModifyHostConfigPodSecurityContext(t *testing.T) {
|
|
supplementalGroupsSC := &v1.PodSecurityContext{}
|
|
supplementalGroupsSC.SupplementalGroups = []int64{2222}
|
|
supplementalGroupHC := fullValidHostConfig()
|
|
supplementalGroupHC.GroupAdd = []string{"2222"}
|
|
fsGroupHC := fullValidHostConfig()
|
|
fsGroupHC.GroupAdd = []string{"1234"}
|
|
extraSupplementalGroupHC := fullValidHostConfig()
|
|
extraSupplementalGroupHC.GroupAdd = []string{"1234"}
|
|
bothHC := fullValidHostConfig()
|
|
bothHC.GroupAdd = []string{"2222", "1234"}
|
|
fsGroup := int64(1234)
|
|
extraSupplementalGroup := []int64{1234}
|
|
|
|
testCases := map[string]struct {
|
|
securityContext *v1.PodSecurityContext
|
|
expected *dockercontainer.HostConfig
|
|
extraSupplementalGroups []int64
|
|
}{
|
|
"nil": {
|
|
securityContext: nil,
|
|
expected: fullValidHostConfig(),
|
|
extraSupplementalGroups: nil,
|
|
},
|
|
"SupplementalGroup": {
|
|
securityContext: supplementalGroupsSC,
|
|
expected: supplementalGroupHC,
|
|
extraSupplementalGroups: nil,
|
|
},
|
|
"FSGroup": {
|
|
securityContext: &v1.PodSecurityContext{FSGroup: &fsGroup},
|
|
expected: fsGroupHC,
|
|
extraSupplementalGroups: nil,
|
|
},
|
|
"FSGroup + SupplementalGroups": {
|
|
securityContext: &v1.PodSecurityContext{
|
|
SupplementalGroups: []int64{2222},
|
|
FSGroup: &fsGroup,
|
|
},
|
|
expected: bothHC,
|
|
extraSupplementalGroups: nil,
|
|
},
|
|
"ExtraSupplementalGroup": {
|
|
securityContext: nil,
|
|
expected: extraSupplementalGroupHC,
|
|
extraSupplementalGroups: extraSupplementalGroup,
|
|
},
|
|
"ExtraSupplementalGroup + SupplementalGroups": {
|
|
securityContext: supplementalGroupsSC,
|
|
expected: bothHC,
|
|
extraSupplementalGroups: extraSupplementalGroup,
|
|
},
|
|
}
|
|
|
|
provider := NewSimpleSecurityContextProvider()
|
|
dummyContainer := &v1.Container{}
|
|
dummyContainer.SecurityContext = fullValidSecurityContext()
|
|
dummyPod := &v1.Pod{
|
|
Spec: apitesting.V1DeepEqualSafePodSpec(),
|
|
}
|
|
|
|
for k, v := range testCases {
|
|
dummyPod.Spec.SecurityContext = v.securityContext
|
|
dockerCfg := &dockercontainer.HostConfig{}
|
|
provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg, v.extraSupplementalGroups)
|
|
if !reflect.DeepEqual(v.expected, dockerCfg) {
|
|
t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestModifySecurityOption(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
config []string
|
|
optName string
|
|
optVal string
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "Empty val",
|
|
config: []string{"a:b", "c:d"},
|
|
optName: "optA",
|
|
optVal: "",
|
|
expected: []string{"a:b", "c:d"},
|
|
},
|
|
{
|
|
name: "Valid",
|
|
config: []string{"a:b", "c:d"},
|
|
optName: "e",
|
|
optVal: "f",
|
|
expected: []string{"a:b", "c:d", "e:f"},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
actual := modifySecurityOption(tc.config, tc.optName, tc.optVal)
|
|
if !reflect.DeepEqual(tc.expected, actual) {
|
|
t.Errorf("Failed to apply options correctly for tc: %s. Expected: %v but got %v", tc.name, tc.expected, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func overridePodSecurityContext() *v1.PodSecurityContext {
|
|
return &v1.PodSecurityContext{
|
|
SELinuxOptions: &v1.SELinuxOptions{
|
|
User: "user2",
|
|
Role: "role2",
|
|
Type: "type2",
|
|
Level: "level2",
|
|
},
|
|
}
|
|
}
|
|
|
|
func fullValidPodSecurityContext() *v1.PodSecurityContext {
|
|
return &v1.PodSecurityContext{
|
|
SELinuxOptions: inputSELinuxOptions(),
|
|
}
|
|
}
|
|
|
|
func fullValidSecurityContext() *v1.SecurityContext {
|
|
priv := true
|
|
return &v1.SecurityContext{
|
|
Privileged: &priv,
|
|
Capabilities: inputCapabilities(),
|
|
SELinuxOptions: inputSELinuxOptions(),
|
|
}
|
|
}
|
|
|
|
func inputCapabilities() *v1.Capabilities {
|
|
return &v1.Capabilities{
|
|
Add: []v1.Capability{"addCapA", "addCapB"},
|
|
Drop: []v1.Capability{"dropCapA", "dropCapB"},
|
|
}
|
|
}
|
|
|
|
func inputSELinuxOptions() *v1.SELinuxOptions {
|
|
return &v1.SELinuxOptions{
|
|
User: "user",
|
|
Role: "role",
|
|
Type: "type",
|
|
Level: "level",
|
|
}
|
|
}
|
|
|
|
func fullValidHostConfig() *dockercontainer.HostConfig {
|
|
return &dockercontainer.HostConfig{
|
|
Privileged: true,
|
|
CapAdd: []string{"addCapA", "addCapB"},
|
|
CapDrop: []string{"dropCapA", "dropCapB"},
|
|
SecurityOpt: []string{
|
|
fmt.Sprintf("%s:%s", DockerLabelUser, "user"),
|
|
fmt.Sprintf("%s:%s", DockerLabelRole, "role"),
|
|
fmt.Sprintf("%s:%s", DockerLabelType, "type"),
|
|
fmt.Sprintf("%s:%s", DockerLabelLevel, "level"),
|
|
},
|
|
}
|
|
}
|