pkg/cri/sbserver: sub-test uses array and capture range var

Using array to build sub-tests is to avoid random pick. The shuffle
thing should be handled by go-test framework. And we should capture
range var before runing sub-test.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
This commit is contained in:
Wei Fu
2023-04-15 21:53:01 +08:00
parent ffc70c45c4
commit 8bcfdda39b
27 changed files with 973 additions and 493 deletions

View File

@@ -198,12 +198,14 @@ func TestContainerCapabilities(t *testing.T) {
testContainerName := "container-name"
testPid := uint32(1234)
allCaps := cap.Known()
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
capability *runtime.Capability
includes []string
excludes []string
}{
"should be able to add/drop capabilities": {
{
desc: "should be able to add/drop capabilities",
capability: &runtime.Capability{
AddCapabilities: []string{"SYS_ADMIN"},
DropCapabilities: []string{"CHOWN"},
@@ -211,19 +213,22 @@ func TestContainerCapabilities(t *testing.T) {
includes: []string{"CAP_SYS_ADMIN"},
excludes: []string{"CAP_CHOWN"},
},
"should be able to add all capabilities": {
{
desc: "should be able to add all capabilities",
capability: &runtime.Capability{
AddCapabilities: []string{"ALL"},
},
includes: allCaps,
},
"should be able to drop all capabilities": {
{
desc: "should be able to drop all capabilities",
capability: &runtime.Capability{
DropCapabilities: []string{"ALL"},
},
excludes: allCaps,
},
"should be able to drop capabilities with add all": {
{
desc: "should be able to drop capabilities with add all",
capability: &runtime.Capability{
AddCapabilities: []string{"ALL"},
DropCapabilities: []string{"CHOWN"},
@@ -231,7 +236,8 @@ func TestContainerCapabilities(t *testing.T) {
includes: util.SubtractStringSlice(allCaps, "CAP_CHOWN"),
excludes: []string{"CAP_CHOWN"},
},
"should be able to add capabilities with drop all": {
{
desc: "should be able to add capabilities with drop all",
capability: &runtime.Capability{
AddCapabilities: []string{"SYS_ADMIN"},
DropCapabilities: []string{"ALL"},
@@ -240,7 +246,8 @@ func TestContainerCapabilities(t *testing.T) {
excludes: util.SubtractStringSlice(allCaps, "CAP_SYS_ADMIN"),
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
containerConfig, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
ociRuntime := config.Runtime{}
c := newTestCRIService()
@@ -390,33 +397,39 @@ func TestContainerAndSandboxPrivileged(t *testing.T) {
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
ociRuntime := config.Runtime{}
c := newTestCRIService()
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
containerPrivileged bool
sandboxPrivileged bool
expectError bool
}{
"privileged container in non-privileged sandbox should fail": {
{
desc: "privileged container in non-privileged sandbox should fail",
containerPrivileged: true,
sandboxPrivileged: false,
expectError: true,
},
"privileged container in privileged sandbox should be fine": {
{
desc: "privileged container in privileged sandbox should be fine",
containerPrivileged: true,
sandboxPrivileged: true,
expectError: false,
},
"non-privileged container in privileged sandbox should be fine": {
{
desc: "non-privileged container in privileged sandbox should be fine",
containerPrivileged: false,
sandboxPrivileged: true,
expectError: false,
},
"non-privileged container in non-privileged sandbox should be fine": {
{
desc: "non-privileged container in non-privileged sandbox should be fine",
containerPrivileged: false,
sandboxPrivileged: false,
expectError: false,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
containerConfig.Linux.SecurityContext.Privileged = test.containerPrivileged
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
Privileged: test.sandboxPrivileged,
@@ -439,22 +452,26 @@ func TestPrivilegedBindMount(t *testing.T) {
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
ociRuntime := config.Runtime{}
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
privileged bool
expectedSysFSRO bool
expectedCgroupFSRO bool
}{
"sysfs and cgroupfs should mount as 'ro' by default": {
{
desc: "sysfs and cgroupfs should mount as 'ro' by default",
expectedSysFSRO: true,
expectedCgroupFSRO: true,
},
"sysfs and cgroupfs should not mount as 'ro' if privileged": {
{
desc: "sysfs and cgroupfs should not mount as 'ro' if privileged",
privileged: true,
expectedSysFSRO: false,
expectedCgroupFSRO: false,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
containerConfig.Linux.SecurityContext.Privileged = test.privileged
sandboxConfig.Linux.SecurityContext.Privileged = test.privileged
@@ -498,13 +515,15 @@ func TestMountPropagation(t *testing.T) {
}, nil
}
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
criMount *runtime.Mount
fakeLookupMountFn func(string) (mount.Info, error)
optionsCheck []string
expectErr bool
}{
"HostPath should mount as 'rprivate' if propagation is MountPropagation_PROPAGATION_PRIVATE": {
{
desc: "HostPath should mount as 'rprivate' if propagation is MountPropagation_PROPAGATION_PRIVATE",
criMount: &runtime.Mount{
ContainerPath: "container-path",
HostPath: "host-path",
@@ -514,7 +533,8 @@ func TestMountPropagation(t *testing.T) {
optionsCheck: []string{"rbind", "rprivate"},
expectErr: false,
},
"HostPath should mount as 'rslave' if propagation is MountPropagation_PROPAGATION_HOST_TO_CONTAINER": {
{
desc: "HostPath should mount as 'rslave' if propagation is MountPropagation_PROPAGATION_HOST_TO_CONTAINER",
criMount: &runtime.Mount{
ContainerPath: "container-path",
HostPath: "host-path",
@@ -524,7 +544,8 @@ func TestMountPropagation(t *testing.T) {
optionsCheck: []string{"rbind", "rslave"},
expectErr: false,
},
"HostPath should mount as 'rshared' if propagation is MountPropagation_PROPAGATION_BIDIRECTIONAL": {
{
desc: "HostPath should mount as 'rshared' if propagation is MountPropagation_PROPAGATION_BIDIRECTIONAL",
criMount: &runtime.Mount{
ContainerPath: "container-path",
HostPath: "host-path",
@@ -534,7 +555,8 @@ func TestMountPropagation(t *testing.T) {
optionsCheck: []string{"rbind", "rshared"},
expectErr: false,
},
"HostPath should mount as 'rprivate' if propagation is illegal": {
{
desc: "HostPath should mount as 'rprivate' if propagation is illegal",
criMount: &runtime.Mount{
ContainerPath: "container-path",
HostPath: "host-path",
@@ -544,7 +566,8 @@ func TestMountPropagation(t *testing.T) {
optionsCheck: []string{"rbind", "rprivate"},
expectErr: false,
},
"Expect an error if HostPath isn't shared and mount propagation is MountPropagation_PROPAGATION_BIDIRECTIONAL": {
{
desc: "Expect an error if HostPath isn't shared and mount propagation is MountPropagation_PROPAGATION_BIDIRECTIONAL",
criMount: &runtime.Mount{
ContainerPath: "container-path",
HostPath: "host-path",
@@ -553,7 +576,8 @@ func TestMountPropagation(t *testing.T) {
fakeLookupMountFn: slaveLookupMountFn,
expectErr: true,
},
"Expect an error if HostPath isn't slave or shared and mount propagation is MountPropagation_PROPAGATION_HOST_TO_CONTAINER": {
{
desc: "Expect an error if HostPath isn't slave or shared and mount propagation is MountPropagation_PROPAGATION_HOST_TO_CONTAINER",
criMount: &runtime.Mount{
ContainerPath: "container-path",
HostPath: "host-path",
@@ -563,7 +587,8 @@ func TestMountPropagation(t *testing.T) {
expectErr: true,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c := newTestCRIService()
c.os.(*ostesting.FakeOS).LookupMountFn = test.fakeLookupMountFn
config, _, _, _ := getCreateContainerTestData()
@@ -590,24 +615,28 @@ func TestPidNamespace(t *testing.T) {
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
ociRuntime := config.Runtime{}
c := newTestCRIService()
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
pidNS runtime.NamespaceMode
expected runtimespec.LinuxNamespace
}{
"node namespace mode": {
{
desc: "node namespace mode",
pidNS: runtime.NamespaceMode_NODE,
expected: runtimespec.LinuxNamespace{
Type: runtimespec.PIDNamespace,
Path: opts.GetPIDNamespace(testPid),
},
},
"container namespace mode": {
{
desc: "container namespace mode",
pidNS: runtime.NamespaceMode_CONTAINER,
expected: runtimespec.LinuxNamespace{
Type: runtimespec.PIDNamespace,
},
},
"pod namespace mode": {
{
desc: "pod namespace mode",
pidNS: runtime.NamespaceMode_POD,
expected: runtimespec.LinuxNamespace{
Type: runtimespec.PIDNamespace,
@@ -615,7 +644,8 @@ func TestPidNamespace(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
containerConfig.Linux.SecurityContext.NamespaceOptions = &runtime.NamespaceOption{Pid: test.pidNS}
spec, err := c.buildContainerSpec(currentPlatform, testID, testSandboxID, testPid, "", testContainerName, testImageName, containerConfig, sandboxConfig, imageConfig, nil, ociRuntime)
require.NoError(t, err)
@@ -647,7 +677,9 @@ func TestUserNamespace(t *testing.T) {
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
ociRuntime := config.Runtime{}
c := newTestCRIService()
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
userNS *runtime.UserNamespace
sandboxUserNS *runtime.UserNamespace
expNS *runtimespec.LinuxNamespace
@@ -656,7 +688,8 @@ func TestUserNamespace(t *testing.T) {
expGIDMapping []runtimespec.LinuxIDMapping
err bool
}{
"node namespace mode": {
{
desc: "node namespace mode",
userNS: &runtime.UserNamespace{Mode: runtime.NamespaceMode_NODE},
// Expect userns to NOT be present.
expNotNS: &runtimespec.LinuxNamespace{
@@ -664,7 +697,8 @@ func TestUserNamespace(t *testing.T) {
Path: opts.GetUserNamespace(testPid),
},
},
"node namespace mode with mappings": {
{
desc: "node namespace mode with mappings",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_NODE,
Uids: []*runtime.IDMapping{&idMap},
@@ -672,19 +706,23 @@ func TestUserNamespace(t *testing.T) {
},
err: true,
},
"container namespace mode": {
{
desc: "container namespace mode",
userNS: &runtime.UserNamespace{Mode: runtime.NamespaceMode_CONTAINER},
err: true,
},
"target namespace mode": {
{
desc: "target namespace mode",
userNS: &runtime.UserNamespace{Mode: runtime.NamespaceMode_TARGET},
err: true,
},
"unknown namespace mode": {
{
desc: "unknown namespace mode",
userNS: &runtime.UserNamespace{Mode: runtime.NamespaceMode(100)},
err: true,
},
"pod namespace mode": {
{
desc: "pod namespace mode",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap},
@@ -697,7 +735,8 @@ func TestUserNamespace(t *testing.T) {
expUIDMapping: []runtimespec.LinuxIDMapping{expIDMap},
expGIDMapping: []runtimespec.LinuxIDMapping{expIDMap},
},
"pod namespace mode with inconsistent sandbox config (different GIDs)": {
{
desc: "pod namespace mode with inconsistent sandbox config (different GIDs)",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap},
@@ -710,7 +749,8 @@ func TestUserNamespace(t *testing.T) {
},
err: true,
},
"pod namespace mode with inconsistent sandbox config (different UIDs)": {
{
desc: "pod namespace mode with inconsistent sandbox config (different UIDs)",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap},
@@ -723,7 +763,8 @@ func TestUserNamespace(t *testing.T) {
},
err: true,
},
"pod namespace mode with inconsistent sandbox config (different len)": {
{
desc: "pod namespace mode with inconsistent sandbox config (different len)",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap},
@@ -736,7 +777,8 @@ func TestUserNamespace(t *testing.T) {
},
err: true,
},
"pod namespace mode with inconsistent sandbox config (different mode)": {
{
desc: "pod namespace mode with inconsistent sandbox config (different mode)",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap},
@@ -749,7 +791,8 @@ func TestUserNamespace(t *testing.T) {
},
err: true,
},
"pod namespace mode with several mappings": {
{
desc: "pod namespace mode with several mappings",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap, &idMap},
@@ -757,7 +800,8 @@ func TestUserNamespace(t *testing.T) {
},
err: true,
},
"pod namespace mode with uneven mappings": {
{
desc: "pod namespace mode with uneven mappings",
userNS: &runtime.UserNamespace{
Mode: runtime.NamespaceMode_POD,
Uids: []*runtime.IDMapping{&idMap, &idMap},
@@ -766,9 +810,8 @@ func TestUserNamespace(t *testing.T) {
err: true,
},
} {
desc := desc
test := test
t.Run(desc, func(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
containerConfig.Linux.SecurityContext.NamespaceOptions = &runtime.NamespaceOption{UsernsOptions: test.userNS}
// By default, set sandbox and container config to the same (this is
// required by containerSpec). However, if the test wants to test for what
@@ -817,7 +860,8 @@ func TestNoDefaultRunMount(t *testing.T) {
}
func TestGenerateSeccompSecurityProfileSpecOpts(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
profile string
privileged bool
disable bool
@@ -826,98 +870,119 @@ func TestGenerateSeccompSecurityProfileSpecOpts(t *testing.T) {
defaultProfile string
sp *runtime.SecurityProfile
}{
"should return error if seccomp is specified when seccomp is not supported": {
{
desc: "should return error if seccomp is specified when seccomp is not supported",
profile: runtimeDefault,
disable: true,
expectErr: true,
},
"should not return error if seccomp is not specified when seccomp is not supported": {
{
desc: "should not return error if seccomp is not specified when seccomp is not supported",
profile: "",
disable: true,
},
"should not return error if seccomp is unconfined when seccomp is not supported": {
{
desc: "should not return error if seccomp is unconfined when seccomp is not supported",
profile: unconfinedProfile,
disable: true,
},
"should not set seccomp when privileged is true": {
{
desc: "should not set seccomp when privileged is true",
profile: seccompDefaultProfile,
privileged: true,
},
"should not set seccomp when seccomp is unconfined": {
{
desc: "should not set seccomp when seccomp is unconfined",
profile: unconfinedProfile,
},
"should not set seccomp when seccomp is not specified": {
{
desc: "should not set seccomp when seccomp is not specified",
profile: "",
},
"should set default seccomp when seccomp is runtime/default": {
{
desc: "should set default seccomp when seccomp is runtime/default",
profile: runtimeDefault,
specOpts: seccomp.WithDefaultProfile(),
},
"should set default seccomp when seccomp is docker/default": {
{
desc: "should set default seccomp when seccomp is docker/default",
profile: dockerDefault,
specOpts: seccomp.WithDefaultProfile(),
},
"should set specified profile when local profile is specified": {
{
desc: "should set specified profile when local profile is specified",
profile: profileNamePrefix + "test-profile",
specOpts: seccomp.WithProfile("test-profile"),
},
"should use default profile when seccomp is empty": {
{
desc: "should use default profile when seccomp is empty",
defaultProfile: profileNamePrefix + "test-profile",
specOpts: seccomp.WithProfile("test-profile"),
},
"should fallback to docker/default when seccomp is empty and default is runtime/default": {
{
desc: "should fallback to docker/default when seccomp is empty and default is runtime/default",
defaultProfile: runtimeDefault,
specOpts: seccomp.WithDefaultProfile(),
},
//-----------------------------------------------
// now buckets for the SecurityProfile variants
//-----------------------------------------------
"sp should return error if seccomp is specified when seccomp is not supported": {
{
desc: "sp should return error if seccomp is specified when seccomp is not supported",
disable: true,
expectErr: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
},
},
"sp should not return error if seccomp is unconfined when seccomp is not supported": {
{
desc: "sp should not return error if seccomp is unconfined when seccomp is not supported",
disable: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Unconfined,
},
},
"sp should not set seccomp when privileged is true": {
{
desc: "sp should not set seccomp when privileged is true",
privileged: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
},
},
"sp should not set seccomp when seccomp is unconfined": {
{
desc: "sp should not set seccomp when seccomp is unconfined",
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Unconfined,
},
},
"sp should not set seccomp when seccomp is not specified": {},
"sp should set default seccomp when seccomp is runtime/default": {
{
desc: "sp should not set seccomp when seccomp is not specified",
},
{
desc: "sp should set default seccomp when seccomp is runtime/default",
specOpts: seccomp.WithDefaultProfile(),
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
},
},
"sp should set specified profile when local profile is specified": {
{
desc: "sp should set specified profile when local profile is specified",
specOpts: seccomp.WithProfile("test-profile"),
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Localhost,
LocalhostRef: profileNamePrefix + "test-profile",
},
},
"sp should set specified profile when local profile is specified even without prefix": {
{
desc: "sp should set specified profile when local profile is specified even without prefix",
specOpts: seccomp.WithProfile("test-profile"),
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Localhost,
LocalhostRef: "test-profile",
},
},
"sp should return error if specified profile is invalid": {
{
desc: "sp should return error if specified profile is invalid",
expectErr: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
@@ -925,7 +990,8 @@ func TestGenerateSeccompSecurityProfileSpecOpts(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
cri := &criService{}
cri.config.UnsetSeccompProfile = test.defaultProfile
ssp := test.sp
@@ -957,7 +1023,8 @@ func TestGenerateSeccompSecurityProfileSpecOpts(t *testing.T) {
}
func TestGenerateApparmorSpecOpts(t *testing.T) {
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
profile string
privileged bool
disable bool
@@ -965,103 +1032,123 @@ func TestGenerateApparmorSpecOpts(t *testing.T) {
expectErr bool
sp *runtime.SecurityProfile
}{
"should return error if apparmor is specified when apparmor is not supported": {
{
desc: "should return error if apparmor is specified when apparmor is not supported",
profile: runtimeDefault,
disable: true,
expectErr: true,
},
"should not return error if apparmor is not specified when apparmor is not supported": {
{
desc: "should not return error if apparmor is not specified when apparmor is not supported",
profile: "",
disable: true,
},
"should set default apparmor when apparmor is not specified": {
{
desc: "should set default apparmor when apparmor is not specified",
profile: "",
specOpts: apparmor.WithDefaultProfile(appArmorDefaultProfileName),
},
"should not apparmor when apparmor is not specified and privileged is true": {
{
desc: "should not apparmor when apparmor is not specified and privileged is true",
profile: "",
privileged: true,
},
"should not return error if apparmor is unconfined when apparmor is not supported": {
{
desc: "should not return error if apparmor is unconfined when apparmor is not supported",
profile: unconfinedProfile,
disable: true,
},
"should not apparmor when apparmor is unconfined": {
{
desc: "should not apparmor when apparmor is unconfined",
profile: unconfinedProfile,
},
"should not apparmor when apparmor is unconfined and privileged is true": {
{
desc: "should not apparmor when apparmor is unconfined and privileged is true",
profile: unconfinedProfile,
privileged: true,
},
"should set default apparmor when apparmor is runtime/default": {
{
desc: "should set default apparmor when apparmor is runtime/default",
profile: runtimeDefault,
specOpts: apparmor.WithDefaultProfile(appArmorDefaultProfileName),
},
"should not apparmor when apparmor is default and privileged is true": {
{
desc: "should not apparmor when apparmor is default and privileged is true",
profile: runtimeDefault,
privileged: true,
},
// TODO (mikebrow) add success with existing defined profile tests
"should return error when undefined local profile is specified": {
{
desc: "should return error when undefined local profile is specified",
profile: profileNamePrefix + "test-profile",
expectErr: true,
},
"should return error when undefined local profile is specified and privileged is true": {
{
desc: "should return error when undefined local profile is specified and privileged is true",
profile: profileNamePrefix + "test-profile",
privileged: true,
expectErr: true,
},
"should return error if specified profile is invalid": {
{
desc: "should return error if specified profile is invalid",
profile: "test-profile",
expectErr: true,
},
//--------------------------------------
// buckets for SecurityProfile struct
//--------------------------------------
"sp should return error if apparmor is specified when apparmor is not supported": {
{
desc: "sp should return error if apparmor is specified when apparmor is not supported",
disable: true,
expectErr: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
},
},
"sp should not return error if apparmor is unconfined when apparmor is not supported": {
{
desc: "sp should not return error if apparmor is unconfined when apparmor is not supported",
disable: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Unconfined,
},
},
"sp should not apparmor when apparmor is unconfined": {
{
desc: "sp should not apparmor when apparmor is unconfined",
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Unconfined,
},
},
"sp should not apparmor when apparmor is unconfined and privileged is true": {
{
desc: "sp should not apparmor when apparmor is unconfined and privileged is true",
privileged: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Unconfined,
},
},
"sp should set default apparmor when apparmor is runtime/default": {
{
desc: "sp should set default apparmor when apparmor is runtime/default",
specOpts: apparmor.WithDefaultProfile(appArmorDefaultProfileName),
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
},
},
"sp should not apparmor when apparmor is default and privileged is true": {
{
desc: "sp should not apparmor when apparmor is default and privileged is true",
privileged: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_RuntimeDefault,
},
},
"sp should return error when undefined local profile is specified": {
{
desc: "sp should return error when undefined local profile is specified",
expectErr: true,
sp: &runtime.SecurityProfile{
ProfileType: runtime.SecurityProfile_Localhost,
LocalhostRef: profileNamePrefix + "test-profile",
},
},
"sp should return error when undefined local profile is specified even without prefix": {
{
desc: "sp should return error when undefined local profile is specified even without prefix",
profile: profileNamePrefix + "test-profile",
expectErr: true,
sp: &runtime.SecurityProfile{
@@ -1069,7 +1156,8 @@ func TestGenerateApparmorSpecOpts(t *testing.T) {
LocalhostRef: "test-profile",
},
},
"sp should return error when undefined local profile is specified and privileged is true": {
{
desc: "sp should return error when undefined local profile is specified and privileged is true",
privileged: true,
expectErr: true,
sp: &runtime.SecurityProfile{
@@ -1078,7 +1166,8 @@ func TestGenerateApparmorSpecOpts(t *testing.T) {
},
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
asp := test.sp
csp, err := generateApparmorSecurityProfile(test.profile)
if err != nil {
@@ -1117,7 +1206,8 @@ func TestMaskedAndReadonlyPaths(t *testing.T) {
defaultSpec, err := oci.GenerateSpec(ctrdutil.NamespacedContext(), nil, &containers.Container{ID: testID})
require.NoError(t, err)
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
disableProcMount bool
masked []string
readonly []string
@@ -1125,7 +1215,8 @@ func TestMaskedAndReadonlyPaths(t *testing.T) {
expectedReadonly []string
privileged bool
}{
"should apply default if not specified when disable_proc_mount = true": {
{
desc: "should apply default if not specified when disable_proc_mount = true",
disableProcMount: true,
masked: nil,
readonly: nil,
@@ -1133,7 +1224,8 @@ func TestMaskedAndReadonlyPaths(t *testing.T) {
expectedReadonly: defaultSpec.Linux.ReadonlyPaths,
privileged: false,
},
"should apply default if not specified when disable_proc_mount = false": {
{
desc: "should apply default if not specified when disable_proc_mount = false",
disableProcMount: false,
masked: nil,
readonly: nil,
@@ -1141,33 +1233,38 @@ func TestMaskedAndReadonlyPaths(t *testing.T) {
expectedReadonly: []string{},
privileged: false,
},
"should be able to specify empty paths": {
{
desc: "should be able to specify empty paths",
masked: []string{},
readonly: []string{},
expectedMasked: []string{},
expectedReadonly: []string{},
privileged: false,
},
"should apply CRI specified paths": {
{
desc: "should apply CRI specified paths",
masked: []string{"/proc"},
readonly: []string{"/sys"},
expectedMasked: []string{"/proc"},
expectedReadonly: []string{"/sys"},
privileged: false,
},
"default should be nil for privileged": {
{
desc: "default should be nil for privileged",
expectedMasked: nil,
expectedReadonly: nil,
privileged: true,
},
"should be able to specify empty paths, esp. if privileged": {
{
desc: "should be able to specify empty paths, esp. if privileged",
masked: []string{},
readonly: []string{},
expectedMasked: nil,
expectedReadonly: nil,
privileged: true,
},
"should not apply CRI specified paths if privileged": {
{
desc: "should not apply CRI specified paths if privileged",
masked: []string{"/proc"},
readonly: []string{"/sys"},
expectedMasked: nil,
@@ -1175,7 +1272,8 @@ func TestMaskedAndReadonlyPaths(t *testing.T) {
privileged: true,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c.config.DisableProcMount = test.disableProcMount
containerConfig.Linux.SecurityContext.MaskedPaths = test.masked
containerConfig.Linux.SecurityContext.ReadonlyPaths = test.readonly
@@ -1205,28 +1303,33 @@ func TestHostname(t *testing.T) {
c.os.(*ostesting.FakeOS).HostnameFn = func() (string, error) {
return "real-hostname", nil
}
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
hostname string
networkNs runtime.NamespaceMode
expectedEnv string
}{
"should add HOSTNAME=sandbox.Hostname for pod network namespace": {
{
desc: "should add HOSTNAME=sandbox.Hostname for pod network namespace",
hostname: "test-hostname",
networkNs: runtime.NamespaceMode_POD,
expectedEnv: "HOSTNAME=test-hostname",
},
"should add HOSTNAME=sandbox.Hostname for host network namespace": {
{
desc: "should add HOSTNAME=sandbox.Hostname for host network namespace",
hostname: "test-hostname",
networkNs: runtime.NamespaceMode_NODE,
expectedEnv: "HOSTNAME=test-hostname",
},
"should add HOSTNAME=os.Hostname for host network namespace if sandbox.Hostname is not set": {
{
desc: "should add HOSTNAME=os.Hostname for host network namespace if sandbox.Hostname is not set",
hostname: "",
networkNs: runtime.NamespaceMode_NODE,
expectedEnv: "HOSTNAME=real-hostname",
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
sandboxConfig.Hostname = test.hostname
sandboxConfig.Linux.SecurityContext = &runtime.LinuxSandboxSecurityContext{
NamespaceOptions: &runtime.NamespaceOption{Network: test.networkNs},
@@ -1357,12 +1460,14 @@ additional-group-for-root:x:22222:root
os.WriteFile(filepath.Join(tempRootDir, "etc", "group"), []byte(etcGroup), 0644),
)
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
imageConfigUser string
securityContext *runtime.LinuxContainerSecurityContext
expected runtimespec.User
}{
"Only SecurityContext was set, SecurityContext defines User": {
{
desc: "Only SecurityContext was set, SecurityContext defines User",
securityContext: &runtime.LinuxContainerSecurityContext{
RunAsUser: &runtime.Int64Value{Value: 1000},
RunAsGroup: &runtime.Int64Value{Value: 2000},
@@ -1370,12 +1475,14 @@ additional-group-for-root:x:22222:root
},
expected: runtimespec.User{UID: 1000, GID: 2000, AdditionalGids: []uint32{2000, 3333, 11111}},
},
"Only imageConfig.User was set, imageConfig.User defines User": {
{
desc: "Only imageConfig.User was set, imageConfig.User defines User",
imageConfigUser: "1000",
securityContext: nil,
expected: runtimespec.User{UID: 1000, GID: 1000, AdditionalGids: []uint32{1000, 11111}},
},
"Both SecurityContext and ImageConfig.User was set, SecurityContext defines User": {
{
desc: "Both SecurityContext and ImageConfig.User was set, SecurityContext defines User",
imageConfigUser: "0",
securityContext: &runtime.LinuxContainerSecurityContext{
RunAsUser: &runtime.Int64Value{Value: 1000},
@@ -1384,12 +1491,13 @@ additional-group-for-root:x:22222:root
},
expected: runtimespec.User{UID: 1000, GID: 2000, AdditionalGids: []uint32{2000, 3333, 11111}},
},
"No SecurityContext nor ImageConfig.User were set, runtime default defines User": {
{
desc: "No SecurityContext nor ImageConfig.User were set, runtime default defines User",
expected: runtimespec.User{UID: 0, GID: 0, AdditionalGids: []uint32{0, 22222}},
},
} {
desc := desc
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
containerConfig.Linux.SecurityContext = test.securityContext
imageConfig.User = test.imageConfigUser
@@ -1419,32 +1527,37 @@ func TestNonRootUserAndDevices(t *testing.T) {
testDevice := hostDevicesRaw[0]
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
uid, gid *runtime.Int64Value
deviceOwnershipFromSecurityContext bool
expectedDeviceUID uint32
expectedDeviceGID uint32
}{
"expect non-root container's Devices Uid/Gid to be the same as the device Uid/Gid on the host when deviceOwnershipFromSecurityContext is disabled": {
{
desc: "expect non-root container's Devices Uid/Gid to be the same as the device Uid/Gid on the host when deviceOwnershipFromSecurityContext is disabled",
uid: &runtime.Int64Value{Value: 1},
gid: &runtime.Int64Value{Value: 10},
expectedDeviceUID: *testDevice.UID,
expectedDeviceGID: *testDevice.GID,
},
"expect root container's Devices Uid/Gid to be the same as the device Uid/Gid on the host when deviceOwnershipFromSecurityContext is disabled": {
{
desc: "expect root container's Devices Uid/Gid to be the same as the device Uid/Gid on the host when deviceOwnershipFromSecurityContext is disabled",
uid: &runtime.Int64Value{Value: 0},
gid: &runtime.Int64Value{Value: 0},
expectedDeviceUID: *testDevice.UID,
expectedDeviceGID: *testDevice.GID,
},
"expect non-root container's Devices Uid/Gid to be the same as RunAsUser/RunAsGroup when deviceOwnershipFromSecurityContext is enabled": {
{
desc: "expect non-root container's Devices Uid/Gid to be the same as RunAsUser/RunAsGroup when deviceOwnershipFromSecurityContext is enabled",
uid: &runtime.Int64Value{Value: 1},
gid: &runtime.Int64Value{Value: 10},
deviceOwnershipFromSecurityContext: true,
expectedDeviceUID: 1,
expectedDeviceGID: 10,
},
"expect root container's Devices Uid/Gid to be the same as the device Uid/Gid on the host when deviceOwnershipFromSecurityContext is enabled": {
{
desc: "expect root container's Devices Uid/Gid to be the same as the device Uid/Gid on the host when deviceOwnershipFromSecurityContext is enabled",
uid: &runtime.Int64Value{Value: 0},
gid: &runtime.Int64Value{Value: 0},
deviceOwnershipFromSecurityContext: true,
@@ -1452,7 +1565,8 @@ func TestNonRootUserAndDevices(t *testing.T) {
expectedDeviceGID: *testDevice.GID,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
c.config.DeviceOwnershipFromSecurityContext = test.deviceOwnershipFromSecurityContext
containerConfig.Linux.SecurityContext.RunAsUser = test.uid
containerConfig.Linux.SecurityContext.RunAsGroup = test.gid
@@ -1480,42 +1594,48 @@ func TestPrivilegedDevices(t *testing.T) {
testContainerName := "container-name"
containerConfig, sandboxConfig, imageConfig, _ := getCreateContainerTestData()
for desc, test := range map[string]struct {
for _, test := range []struct {
desc string
privileged bool
privilegedWithoutHostDevices bool
privilegedWithoutHostDevicesAllDevicesAllowed bool
expectHostDevices bool
expectAllDevicesAllowed bool
}{
"expect no host devices when privileged is false": {
{
desc: "expect no host devices when privileged is false",
privileged: false,
privilegedWithoutHostDevices: false,
privilegedWithoutHostDevicesAllDevicesAllowed: false,
expectHostDevices: false,
expectAllDevicesAllowed: false,
},
"expect no host devices when privileged is false and privilegedWithoutHostDevices is true": {
{
desc: "expect no host devices when privileged is false and privilegedWithoutHostDevices is true",
privileged: false,
privilegedWithoutHostDevices: true,
privilegedWithoutHostDevicesAllDevicesAllowed: false,
expectHostDevices: false,
expectAllDevicesAllowed: false,
},
"expect host devices and all device allowlist when privileged is true": {
{
desc: "expect host devices and all device allowlist when privileged is true",
privileged: true,
privilegedWithoutHostDevices: false,
privilegedWithoutHostDevicesAllDevicesAllowed: false,
expectHostDevices: true,
expectAllDevicesAllowed: true,
},
"expect no host devices when privileged is true and privilegedWithoutHostDevices is true": {
{
desc: "expect no host devices when privileged is true and privilegedWithoutHostDevices is true",
privileged: true,
privilegedWithoutHostDevices: true,
privilegedWithoutHostDevicesAllDevicesAllowed: false,
expectHostDevices: false,
expectAllDevicesAllowed: false,
},
"expect host devices and all devices allowlist when privileged is true and privilegedWithoutHostDevices is true and privilegedWithoutHostDevicesAllDevicesAllowed is true": {
{
desc: "expect host devices and all devices allowlist when privileged is true and privilegedWithoutHostDevices is true and privilegedWithoutHostDevicesAllDevicesAllowed is true",
privileged: true,
privilegedWithoutHostDevices: true,
privilegedWithoutHostDevicesAllDevicesAllowed: true,
@@ -1523,7 +1643,8 @@ func TestPrivilegedDevices(t *testing.T) {
expectAllDevicesAllowed: true,
},
} {
t.Run(desc, func(t *testing.T) {
test := test
t.Run(test.desc, func(t *testing.T) {
containerConfig.Linux.SecurityContext.Privileged = test.privileged
sandboxConfig.Linux.SecurityContext.Privileged = test.privileged