mirror of https://github.com/k3s-io/k3s
769 lines
24 KiB
Go
769 lines
24 KiB
Go
/*
|
|
Copyright 2017 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 (
|
|
"reflect"
|
|
"testing"
|
|
|
|
"k8s.io/apimachinery/pkg/util/diff"
|
|
api "k8s.io/kubernetes/pkg/apis/core"
|
|
)
|
|
|
|
func TestPodSecurityContextAccessor(t *testing.T) {
|
|
fsGroup := int64(2)
|
|
runAsUser := int64(1)
|
|
runAsGroup := int64(1)
|
|
runAsNonRoot := true
|
|
|
|
testcases := []*api.PodSecurityContext{
|
|
nil,
|
|
{},
|
|
{FSGroup: &fsGroup},
|
|
{HostIPC: true},
|
|
{HostNetwork: true},
|
|
{HostPID: true},
|
|
{RunAsNonRoot: &runAsNonRoot},
|
|
{RunAsUser: &runAsUser},
|
|
{RunAsGroup: &runAsGroup},
|
|
{SELinuxOptions: &api.SELinuxOptions{User: "bob"}},
|
|
{SupplementalGroups: []int64{1, 2, 3}},
|
|
}
|
|
|
|
for i, tc := range testcases {
|
|
expected := tc
|
|
if expected == nil {
|
|
expected = &api.PodSecurityContext{}
|
|
}
|
|
|
|
a := NewPodSecurityContextAccessor(tc)
|
|
|
|
if v := a.FSGroup(); !reflect.DeepEqual(expected.FSGroup, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.FSGroup, v)
|
|
}
|
|
if v := a.HostIPC(); !reflect.DeepEqual(expected.HostIPC, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.HostIPC, v)
|
|
}
|
|
if v := a.HostNetwork(); !reflect.DeepEqual(expected.HostNetwork, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.HostNetwork, v)
|
|
}
|
|
if v := a.HostPID(); !reflect.DeepEqual(expected.HostPID, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.HostPID, v)
|
|
}
|
|
if v := a.RunAsNonRoot(); !reflect.DeepEqual(expected.RunAsNonRoot, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsNonRoot, v)
|
|
}
|
|
if v := a.RunAsUser(); !reflect.DeepEqual(expected.RunAsUser, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsUser, v)
|
|
}
|
|
if v := a.RunAsGroup(); !reflect.DeepEqual(expected.RunAsGroup, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsGroup, v)
|
|
}
|
|
if v := a.SELinuxOptions(); !reflect.DeepEqual(expected.SELinuxOptions, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.SELinuxOptions, v)
|
|
}
|
|
if v := a.SupplementalGroups(); !reflect.DeepEqual(expected.SupplementalGroups, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.SupplementalGroups, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPodSecurityContextMutator(t *testing.T) {
|
|
testcases := map[string]struct {
|
|
newSC func() *api.PodSecurityContext
|
|
}{
|
|
"nil": {
|
|
newSC: func() *api.PodSecurityContext { return nil },
|
|
},
|
|
"zero": {
|
|
newSC: func() *api.PodSecurityContext { return &api.PodSecurityContext{} },
|
|
},
|
|
"populated": {
|
|
newSC: func() *api.PodSecurityContext {
|
|
return &api.PodSecurityContext{
|
|
HostNetwork: true,
|
|
HostIPC: true,
|
|
HostPID: true,
|
|
SELinuxOptions: &api.SELinuxOptions{},
|
|
RunAsUser: nil,
|
|
RunAsGroup: nil,
|
|
RunAsNonRoot: nil,
|
|
SupplementalGroups: nil,
|
|
FSGroup: nil,
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
nonNilSC := func(sc *api.PodSecurityContext) *api.PodSecurityContext {
|
|
if sc == nil {
|
|
return &api.PodSecurityContext{}
|
|
}
|
|
return sc
|
|
}
|
|
|
|
for k, tc := range testcases {
|
|
{
|
|
sc := tc.newSC()
|
|
originalSC := tc.newSC()
|
|
m := NewPodSecurityContextMutator(sc)
|
|
|
|
// no-op sets should not modify the object
|
|
m.SetFSGroup(m.FSGroup())
|
|
m.SetHostNetwork(m.HostNetwork())
|
|
m.SetHostIPC(m.HostIPC())
|
|
m.SetHostPID(m.HostPID())
|
|
m.SetRunAsNonRoot(m.RunAsNonRoot())
|
|
m.SetRunAsUser(m.RunAsUser())
|
|
m.SetRunAsGroup(m.RunAsGroup())
|
|
m.SetSELinuxOptions(m.SELinuxOptions())
|
|
m.SetSupplementalGroups(m.SupplementalGroups())
|
|
if !reflect.DeepEqual(sc, originalSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, sc, originalSC)
|
|
}
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), originalSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, m.PodSecurityContext(), originalSC)
|
|
}
|
|
}
|
|
|
|
// FSGroup
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
i := int64(1123)
|
|
modifiedSC.FSGroup = &i
|
|
m.SetFSGroup(&i)
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// HostNetwork
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
modifiedSC.HostNetwork = !modifiedSC.HostNetwork
|
|
m.SetHostNetwork(!m.HostNetwork())
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// HostIPC
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
modifiedSC.HostIPC = !modifiedSC.HostIPC
|
|
m.SetHostIPC(!m.HostIPC())
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// HostPID
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
modifiedSC.HostPID = !modifiedSC.HostPID
|
|
m.SetHostPID(!m.HostPID())
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsNonRoot
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
b := true
|
|
modifiedSC.RunAsNonRoot = &b
|
|
m.SetRunAsNonRoot(&b)
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsUser
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
i := int64(1123)
|
|
modifiedSC.RunAsUser = &i
|
|
m.SetRunAsUser(&i)
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsGroup
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
i := int64(1123)
|
|
modifiedSC.RunAsGroup = &i
|
|
m.SetRunAsGroup(&i)
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// SELinuxOptions
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
modifiedSC.SELinuxOptions = &api.SELinuxOptions{User: "bob"}
|
|
m.SetSELinuxOptions(&api.SELinuxOptions{User: "bob"})
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// SupplementalGroups
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewPodSecurityContextMutator(tc.newSC())
|
|
modifiedSC.SupplementalGroups = []int64{1, 1, 2, 3}
|
|
m.SetSupplementalGroups([]int64{1, 1, 2, 3})
|
|
if !reflect.DeepEqual(m.PodSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.PodSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestContainerSecurityContextAccessor(t *testing.T) {
|
|
privileged := true
|
|
runAsUser := int64(1)
|
|
runAsNonRoot := true
|
|
readOnlyRootFilesystem := true
|
|
allowPrivilegeEscalation := true
|
|
|
|
testcases := []*api.SecurityContext{
|
|
nil,
|
|
{},
|
|
{Capabilities: &api.Capabilities{Drop: []api.Capability{"test"}}},
|
|
{Privileged: &privileged},
|
|
{SELinuxOptions: &api.SELinuxOptions{User: "bob"}},
|
|
{RunAsUser: &runAsUser},
|
|
{RunAsNonRoot: &runAsNonRoot},
|
|
{ReadOnlyRootFilesystem: &readOnlyRootFilesystem},
|
|
{AllowPrivilegeEscalation: &allowPrivilegeEscalation},
|
|
}
|
|
|
|
for i, tc := range testcases {
|
|
expected := tc
|
|
if expected == nil {
|
|
expected = &api.SecurityContext{}
|
|
}
|
|
|
|
a := NewContainerSecurityContextAccessor(tc)
|
|
|
|
if v := a.Capabilities(); !reflect.DeepEqual(expected.Capabilities, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.Capabilities, v)
|
|
}
|
|
if v := a.Privileged(); !reflect.DeepEqual(expected.Privileged, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.Privileged, v)
|
|
}
|
|
if v := a.RunAsNonRoot(); !reflect.DeepEqual(expected.RunAsNonRoot, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsNonRoot, v)
|
|
}
|
|
if v := a.RunAsUser(); !reflect.DeepEqual(expected.RunAsUser, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsUser, v)
|
|
}
|
|
if v := a.SELinuxOptions(); !reflect.DeepEqual(expected.SELinuxOptions, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.SELinuxOptions, v)
|
|
}
|
|
if v := a.ReadOnlyRootFilesystem(); !reflect.DeepEqual(expected.ReadOnlyRootFilesystem, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.ReadOnlyRootFilesystem, v)
|
|
}
|
|
if v := a.AllowPrivilegeEscalation(); !reflect.DeepEqual(expected.AllowPrivilegeEscalation, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.AllowPrivilegeEscalation, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestContainerSecurityContextMutator(t *testing.T) {
|
|
testcases := map[string]struct {
|
|
newSC func() *api.SecurityContext
|
|
}{
|
|
"nil": {
|
|
newSC: func() *api.SecurityContext { return nil },
|
|
},
|
|
"zero": {
|
|
newSC: func() *api.SecurityContext { return &api.SecurityContext{} },
|
|
},
|
|
"populated": {
|
|
newSC: func() *api.SecurityContext {
|
|
return &api.SecurityContext{
|
|
Capabilities: &api.Capabilities{Drop: []api.Capability{"test"}},
|
|
SELinuxOptions: &api.SELinuxOptions{},
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
nonNilSC := func(sc *api.SecurityContext) *api.SecurityContext {
|
|
if sc == nil {
|
|
return &api.SecurityContext{}
|
|
}
|
|
return sc
|
|
}
|
|
|
|
for k, tc := range testcases {
|
|
{
|
|
sc := tc.newSC()
|
|
originalSC := tc.newSC()
|
|
m := NewContainerSecurityContextMutator(sc)
|
|
|
|
// no-op sets should not modify the object
|
|
m.SetAllowPrivilegeEscalation(m.AllowPrivilegeEscalation())
|
|
m.SetCapabilities(m.Capabilities())
|
|
m.SetPrivileged(m.Privileged())
|
|
m.SetReadOnlyRootFilesystem(m.ReadOnlyRootFilesystem())
|
|
m.SetRunAsNonRoot(m.RunAsNonRoot())
|
|
m.SetRunAsUser(m.RunAsUser())
|
|
m.SetSELinuxOptions(m.SELinuxOptions())
|
|
if !reflect.DeepEqual(sc, originalSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, sc, originalSC)
|
|
}
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), originalSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, m.ContainerSecurityContext(), originalSC)
|
|
}
|
|
}
|
|
|
|
// AllowPrivilegeEscalation
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
b := true
|
|
modifiedSC.AllowPrivilegeEscalation = &b
|
|
m.SetAllowPrivilegeEscalation(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Capabilities
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
modifiedSC.Capabilities = &api.Capabilities{Drop: []api.Capability{"test2"}}
|
|
m.SetCapabilities(&api.Capabilities{Drop: []api.Capability{"test2"}})
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Privileged
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
b := true
|
|
modifiedSC.Privileged = &b
|
|
m.SetPrivileged(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// ReadOnlyRootFilesystem
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
b := true
|
|
modifiedSC.ReadOnlyRootFilesystem = &b
|
|
m.SetReadOnlyRootFilesystem(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsNonRoot
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
b := true
|
|
modifiedSC.RunAsNonRoot = &b
|
|
m.SetRunAsNonRoot(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsUser
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
i := int64(1123)
|
|
modifiedSC.RunAsUser = &i
|
|
m.SetRunAsUser(&i)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// SELinuxOptions
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewContainerSecurityContextMutator(tc.newSC())
|
|
modifiedSC.SELinuxOptions = &api.SELinuxOptions{User: "bob"}
|
|
m.SetSELinuxOptions(&api.SELinuxOptions{User: "bob"})
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEffectiveContainerSecurityContextAccessor(t *testing.T) {
|
|
privileged := true
|
|
runAsUser := int64(1)
|
|
runAsUserPod := int64(12)
|
|
runAsGroup := int64(1)
|
|
runAsGroupPod := int64(12)
|
|
runAsNonRoot := true
|
|
runAsNonRootPod := false
|
|
readOnlyRootFilesystem := true
|
|
allowPrivilegeEscalation := true
|
|
|
|
testcases := []struct {
|
|
PodSC *api.PodSecurityContext
|
|
SC *api.SecurityContext
|
|
Effective *api.SecurityContext
|
|
}{
|
|
{
|
|
PodSC: nil,
|
|
SC: nil,
|
|
Effective: nil,
|
|
},
|
|
{
|
|
PodSC: &api.PodSecurityContext{},
|
|
SC: &api.SecurityContext{},
|
|
Effective: &api.SecurityContext{},
|
|
},
|
|
{
|
|
PodSC: &api.PodSecurityContext{
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
RunAsUser: &runAsUser,
|
|
RunAsNonRoot: &runAsNonRoot,
|
|
},
|
|
SC: nil,
|
|
Effective: &api.SecurityContext{
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
RunAsUser: &runAsUser,
|
|
RunAsNonRoot: &runAsNonRoot,
|
|
},
|
|
},
|
|
{
|
|
PodSC: &api.PodSecurityContext{
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
RunAsUser: &runAsUserPod,
|
|
RunAsNonRoot: &runAsNonRootPod,
|
|
},
|
|
SC: &api.SecurityContext{},
|
|
Effective: &api.SecurityContext{
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
RunAsUser: &runAsUserPod,
|
|
RunAsNonRoot: &runAsNonRootPod,
|
|
},
|
|
},
|
|
{
|
|
PodSC: &api.PodSecurityContext{
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
RunAsUser: &runAsUserPod,
|
|
RunAsNonRoot: &runAsNonRootPod,
|
|
},
|
|
SC: &api.SecurityContext{
|
|
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
|
Capabilities: &api.Capabilities{Drop: []api.Capability{"test"}},
|
|
Privileged: &privileged,
|
|
ReadOnlyRootFilesystem: &readOnlyRootFilesystem,
|
|
RunAsUser: &runAsUser,
|
|
RunAsNonRoot: &runAsNonRoot,
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
},
|
|
Effective: &api.SecurityContext{
|
|
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
|
Capabilities: &api.Capabilities{Drop: []api.Capability{"test"}},
|
|
Privileged: &privileged,
|
|
ReadOnlyRootFilesystem: &readOnlyRootFilesystem,
|
|
RunAsUser: &runAsUser,
|
|
RunAsNonRoot: &runAsNonRoot,
|
|
SELinuxOptions: &api.SELinuxOptions{User: "bob"},
|
|
},
|
|
},
|
|
{
|
|
PodSC: &api.PodSecurityContext{
|
|
RunAsGroup: &runAsGroup,
|
|
},
|
|
SC: nil,
|
|
Effective: &api.SecurityContext{
|
|
RunAsGroup: &runAsGroup,
|
|
},
|
|
},
|
|
{
|
|
PodSC: &api.PodSecurityContext{
|
|
RunAsGroup: &runAsGroupPod,
|
|
},
|
|
SC: &api.SecurityContext{
|
|
RunAsGroup: &runAsGroup,
|
|
},
|
|
Effective: &api.SecurityContext{
|
|
RunAsGroup: &runAsGroup,
|
|
},
|
|
},
|
|
}
|
|
|
|
for i, tc := range testcases {
|
|
expected := tc.Effective
|
|
if expected == nil {
|
|
expected = &api.SecurityContext{}
|
|
}
|
|
|
|
a := NewEffectiveContainerSecurityContextAccessor(
|
|
NewPodSecurityContextAccessor(tc.PodSC),
|
|
NewContainerSecurityContextMutator(tc.SC),
|
|
)
|
|
|
|
if v := a.Capabilities(); !reflect.DeepEqual(expected.Capabilities, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.Capabilities, v)
|
|
}
|
|
if v := a.Privileged(); !reflect.DeepEqual(expected.Privileged, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.Privileged, v)
|
|
}
|
|
if v := a.RunAsNonRoot(); !reflect.DeepEqual(expected.RunAsNonRoot, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsNonRoot, v)
|
|
}
|
|
if v := a.RunAsUser(); !reflect.DeepEqual(expected.RunAsUser, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.RunAsUser, v)
|
|
}
|
|
if v := a.SELinuxOptions(); !reflect.DeepEqual(expected.SELinuxOptions, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.SELinuxOptions, v)
|
|
}
|
|
if v := a.ReadOnlyRootFilesystem(); !reflect.DeepEqual(expected.ReadOnlyRootFilesystem, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.ReadOnlyRootFilesystem, v)
|
|
}
|
|
if v := a.AllowPrivilegeEscalation(); !reflect.DeepEqual(expected.AllowPrivilegeEscalation, v) {
|
|
t.Errorf("%d: expected %#v, got %#v", i, expected.AllowPrivilegeEscalation, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEffectiveContainerSecurityContextMutator(t *testing.T) {
|
|
runAsNonRootPod := false
|
|
runAsUserPod := int64(12)
|
|
|
|
testcases := map[string]struct {
|
|
newPodSC func() *api.PodSecurityContext
|
|
newSC func() *api.SecurityContext
|
|
}{
|
|
"nil": {
|
|
newPodSC: func() *api.PodSecurityContext { return nil },
|
|
newSC: func() *api.SecurityContext { return nil },
|
|
},
|
|
"zero": {
|
|
newPodSC: func() *api.PodSecurityContext { return &api.PodSecurityContext{} },
|
|
newSC: func() *api.SecurityContext { return &api.SecurityContext{} },
|
|
},
|
|
"populated pod sc": {
|
|
newPodSC: func() *api.PodSecurityContext {
|
|
return &api.PodSecurityContext{
|
|
SELinuxOptions: &api.SELinuxOptions{User: "poduser"},
|
|
RunAsNonRoot: &runAsNonRootPod,
|
|
RunAsUser: &runAsUserPod,
|
|
}
|
|
},
|
|
newSC: func() *api.SecurityContext {
|
|
return &api.SecurityContext{}
|
|
},
|
|
},
|
|
"populated sc": {
|
|
newPodSC: func() *api.PodSecurityContext { return nil },
|
|
newSC: func() *api.SecurityContext {
|
|
return &api.SecurityContext{
|
|
Capabilities: &api.Capabilities{Drop: []api.Capability{"test"}},
|
|
SELinuxOptions: &api.SELinuxOptions{},
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
nonNilSC := func(sc *api.SecurityContext) *api.SecurityContext {
|
|
if sc == nil {
|
|
return &api.SecurityContext{}
|
|
}
|
|
return sc
|
|
}
|
|
|
|
for k, tc := range testcases {
|
|
{
|
|
podSC := tc.newPodSC()
|
|
sc := tc.newSC()
|
|
originalPodSC := tc.newPodSC()
|
|
originalSC := tc.newSC()
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(podSC),
|
|
NewContainerSecurityContextMutator(sc),
|
|
)
|
|
|
|
// no-op sets should not modify the object
|
|
m.SetAllowPrivilegeEscalation(m.AllowPrivilegeEscalation())
|
|
m.SetCapabilities(m.Capabilities())
|
|
m.SetPrivileged(m.Privileged())
|
|
m.SetReadOnlyRootFilesystem(m.ReadOnlyRootFilesystem())
|
|
m.SetRunAsNonRoot(m.RunAsNonRoot())
|
|
m.SetRunAsUser(m.RunAsUser())
|
|
m.SetSELinuxOptions(m.SELinuxOptions())
|
|
if !reflect.DeepEqual(podSC, originalPodSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, podSC, originalPodSC)
|
|
}
|
|
if !reflect.DeepEqual(sc, originalSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, sc, originalSC)
|
|
}
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), originalSC) {
|
|
t.Errorf("%s: unexpected mutation: %#v, %#v", k, m.ContainerSecurityContext(), originalSC)
|
|
}
|
|
}
|
|
|
|
// AllowPrivilegeEscalation
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
b := true
|
|
modifiedSC.AllowPrivilegeEscalation = &b
|
|
m.SetAllowPrivilegeEscalation(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Capabilities
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
modifiedSC.Capabilities = &api.Capabilities{Drop: []api.Capability{"test2"}}
|
|
m.SetCapabilities(&api.Capabilities{Drop: []api.Capability{"test2"}})
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Privileged
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
b := true
|
|
modifiedSC.Privileged = &b
|
|
m.SetPrivileged(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// ReadOnlyRootFilesystem
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
b := true
|
|
modifiedSC.ReadOnlyRootFilesystem = &b
|
|
m.SetReadOnlyRootFilesystem(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsNonRoot
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
b := true
|
|
modifiedSC.RunAsNonRoot = &b
|
|
m.SetRunAsNonRoot(&b)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// RunAsUser
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
i := int64(1123)
|
|
modifiedSC.RunAsUser = &i
|
|
m.SetRunAsUser(&i)
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// SELinuxOptions
|
|
{
|
|
modifiedSC := nonNilSC(tc.newSC())
|
|
m := NewEffectiveContainerSecurityContextMutator(
|
|
NewPodSecurityContextAccessor(tc.newPodSC()),
|
|
NewContainerSecurityContextMutator(tc.newSC()),
|
|
)
|
|
modifiedSC.SELinuxOptions = &api.SELinuxOptions{User: "bob"}
|
|
m.SetSELinuxOptions(&api.SELinuxOptions{User: "bob"})
|
|
if !reflect.DeepEqual(m.ContainerSecurityContext(), modifiedSC) {
|
|
t.Errorf("%s: unexpected object:\n%s", k, diff.ObjectGoPrintSideBySide(modifiedSC, m.ContainerSecurityContext()))
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|