@@ -842,6 +842,125 @@ var _ = framework.KubeDescribe("Security Context", func() {
842
842
matchContainerOutput (podConfig , containerName , "Effective uid: 0\n " )
843
843
})
844
844
})
845
+
846
+ Context ("UserNamespaces" , func () {
847
+ var (
848
+ podName string
849
+ runtimeHandler string
850
+ defaultMapping = []* runtimeapi.IDMapping {{
851
+ ContainerId : 0 ,
852
+ HostId : 1000 ,
853
+ Length : 100000 ,
854
+ }}
855
+ )
856
+
857
+ BeforeEach (func () {
858
+ podName = "user-namespaces-pod-" + framework .NewUUID ()
859
+
860
+ // Find a working runtime handler if none provided
861
+ if framework .TestContext .RuntimeHandler == "" {
862
+ By ("searching for runtime handler which supports user namespaces" )
863
+ ctx , cancel := context .WithTimeout (context .Background (), time .Minute )
864
+ defer cancel ()
865
+ resp , err := rc .Status (ctx , false )
866
+ framework .ExpectNoError (err , "failed to get runtime config: %v" , err )
867
+
868
+ for _ , rh := range resp .GetRuntimeHandlers () {
869
+ if rh .GetFeatures ().GetUserNamespaces () {
870
+ runtimeHandler = rh .GetName ()
871
+ break
872
+ }
873
+ }
874
+ } else {
875
+ runtimeHandler = framework .TestContext .RuntimeHandler
876
+ }
877
+
878
+ if runtimeHandler == "" {
879
+ Skip ("no runtime handler found which supports user namespaces" )
880
+ }
881
+
882
+ By (fmt .Sprintf ("using runtime handler: %s" , runtimeHandler ))
883
+ })
884
+
885
+ It ("runtime should support NamespaceMode_POD" , func () {
886
+ namespaceOption := & runtimeapi.NamespaceOption {
887
+ UsernsOptions : & runtimeapi.UserNamespace {
888
+ Mode : runtimeapi .NamespaceMode_POD ,
889
+ Uids : defaultMapping ,
890
+ Gids : defaultMapping ,
891
+ },
892
+ }
893
+
894
+ hostLogPath , podLogPath := createLogTempDir (podName )
895
+ defer os .RemoveAll (hostLogPath )
896
+ podID , podConfig = createNamespacePodSandboxWithRuntimeHandler (rc , namespaceOption , podName , podLogPath , runtimeHandler )
897
+ containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
898
+
899
+ matchContainerOutputRe (podConfig , containerName , `\s+0\s+1000\s+100000\n` )
900
+ })
901
+
902
+ It ("runtime should support NamespaceMode_NODE" , func () {
903
+ namespaceOption := & runtimeapi.NamespaceOption {
904
+ UsernsOptions : & runtimeapi.UserNamespace {
905
+ Mode : runtimeapi .NamespaceMode_NODE ,
906
+ },
907
+ }
908
+
909
+ hostLogPath , podLogPath := createLogTempDir (podName )
910
+ defer os .RemoveAll (hostLogPath )
911
+ podID , podConfig = createNamespacePodSandboxWithRuntimeHandler (rc , namespaceOption , podName , podLogPath , runtimeHandler )
912
+ containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
913
+
914
+ // 4294967295 means that the entire range is available
915
+ matchContainerOutputRe (podConfig , containerName , `\s+0\s+0\s+4294967295\n` )
916
+ })
917
+
918
+ It ("runtime should fail if more than one mapping provided" , func () {
919
+ wrongMapping := []* runtimeapi.IDMapping {{
920
+ ContainerId : 0 ,
921
+ HostId : 1000 ,
922
+ Length : 100000 ,
923
+ }, {
924
+ ContainerId : 0 ,
925
+ HostId : 2000 ,
926
+ Length : 100000 ,
927
+ }}
928
+ usernsOptions := & runtimeapi.UserNamespace {
929
+ Mode : runtimeapi .NamespaceMode_POD ,
930
+ Uids : wrongMapping ,
931
+ Gids : wrongMapping ,
932
+ }
933
+
934
+ runUserNamespacePodWithError (rc , podName , usernsOptions , runtimeHandler )
935
+ })
936
+
937
+ It ("runtime should fail if container ID 0 is not mapped" , func () {
938
+ mapping := []* runtimeapi.IDMapping {{
939
+ ContainerId : 1 ,
940
+ HostId : 1000 ,
941
+ Length : 100000 ,
942
+ }}
943
+ usernsOptions := & runtimeapi.UserNamespace {
944
+ Mode : runtimeapi .NamespaceMode_POD ,
945
+ Uids : mapping ,
946
+ Gids : mapping ,
947
+ }
948
+
949
+ runUserNamespacePodWithError (rc , podName , usernsOptions , runtimeHandler )
950
+ })
951
+
952
+ It ("runtime should fail with NamespaceMode_CONTAINER" , func () {
953
+ usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_CONTAINER }
954
+
955
+ runUserNamespacePodWithError (rc , podName , usernsOptions , runtimeHandler )
956
+ })
957
+
958
+ It ("runtime should fail with NamespaceMode_TARGET" , func () {
959
+ usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_TARGET }
960
+
961
+ runUserNamespacePodWithError (rc , podName , usernsOptions , runtimeHandler )
962
+ })
963
+ })
845
964
})
846
965
847
966
// matchContainerOutput matches log line in container logs.
@@ -850,6 +969,12 @@ func matchContainerOutput(podConfig *runtimeapi.PodSandboxConfig, name, output s
850
969
verifyLogContents (podConfig , fmt .Sprintf ("%s.log" , name ), output , stdoutType )
851
970
}
852
971
972
+ // matchContainerOutputRe matches log line in container logs using the provided regular expression pattern.
973
+ func matchContainerOutputRe (podConfig * runtimeapi.PodSandboxConfig , name , pattern string ) {
974
+ By ("check container output" )
975
+ verifyLogContentsRe (podConfig , fmt .Sprintf ("%s.log" , name ), pattern , stdoutType )
976
+ }
977
+
853
978
// createRunAsUserContainer creates the container with specified RunAsUser in ContainerConfig.
854
979
func createRunAsUserContainer (rc internalapi.RuntimeService , ic internalapi.ImageManagerService , podID string , podConfig * runtimeapi.PodSandboxConfig , prefix string ) (string , string ) {
855
980
By ("create RunAsUser container" )
@@ -942,11 +1067,23 @@ func createInvalidRunAsGroupContainer(rc internalapi.RuntimeService, ic internal
942
1067
943
1068
// createNamespacePodSandbox creates a PodSandbox with different NamespaceOption config for creating containers.
944
1069
func createNamespacePodSandbox (rc internalapi.RuntimeService , podSandboxNamespace * runtimeapi.NamespaceOption , podSandboxName string , podLogPath string ) (string , * runtimeapi.PodSandboxConfig ) {
1070
+ return createNamespacePodSandboxWithRuntimeHandler (rc , podSandboxNamespace , podSandboxName , podLogPath , framework .TestContext .RuntimeHandler )
1071
+ }
1072
+
1073
+ // createNamespacePodSandboxWithRuntimeHandler creates a PodSandbox with
1074
+ // different NamespaceOption config for creating containers by using a custom
1075
+ // runtime handler.
1076
+ func createNamespacePodSandboxWithRuntimeHandler (
1077
+ rc internalapi.RuntimeService ,
1078
+ podSandboxNamespace * runtimeapi.NamespaceOption ,
1079
+ podSandboxName , podLogPath , runtimeHandler string ,
1080
+ ) (string , * runtimeapi.PodSandboxConfig ) {
945
1081
By ("create NamespaceOption podSandbox" )
946
1082
uid := framework .DefaultUIDPrefix + framework .NewUUID ()
947
1083
namespace := framework .DefaultNamespacePrefix + framework .NewUUID ()
948
1084
config := & runtimeapi.PodSandboxConfig {
949
- Metadata : framework .BuildPodSandboxMetadata (podSandboxName , uid , namespace , framework .DefaultAttempt ),
1085
+ Metadata : framework .BuildPodSandboxMetadata (podSandboxName , uid , namespace , framework .DefaultAttempt ),
1086
+ DnsConfig : & runtimeapi.DNSConfig {},
950
1087
Linux : & runtimeapi.LinuxPodSandboxConfig {
951
1088
SecurityContext : & runtimeapi.LinuxSandboxSecurityContext {
952
1089
NamespaceOptions : podSandboxNamespace ,
@@ -957,7 +1094,7 @@ func createNamespacePodSandbox(rc internalapi.RuntimeService, podSandboxNamespac
957
1094
Labels : framework .DefaultPodLabels ,
958
1095
}
959
1096
960
- return framework .RunPodSandbox (rc , config ), config
1097
+ return framework .RunPodSandboxWithRuntimeHandler (rc , config , runtimeHandler ), config
961
1098
}
962
1099
963
1100
// createNamespaceContainer creates container with different NamespaceOption config.
@@ -1281,3 +1418,59 @@ func checkSetHostname(rc internalapi.RuntimeService, containerID string, setable
1281
1418
Expect (err ).To (HaveOccurred (), msg )
1282
1419
}
1283
1420
}
1421
+
1422
+ func runUserNamespaceContainer (
1423
+ rc internalapi.RuntimeService ,
1424
+ ic internalapi.ImageManagerService ,
1425
+ podID string ,
1426
+ podConfig * runtimeapi.PodSandboxConfig ,
1427
+ ) string {
1428
+ By ("create user namespaces container" )
1429
+ containerName := "user-namespaces-container-" + framework .NewUUID ()
1430
+ containerConfig := & runtimeapi.ContainerConfig {
1431
+ Metadata : framework .BuildContainerMetadata (containerName , framework .DefaultAttempt ),
1432
+ Image : & runtimeapi.ImageSpec {
1433
+ Image : framework .TestContext .TestImageList .DefaultTestContainerImage ,
1434
+ UserSpecifiedImage : framework .TestContext .TestImageList .DefaultTestContainerImage ,
1435
+ },
1436
+ Command : []string {"cat" , "/proc/self/uid_map" },
1437
+ LogPath : fmt .Sprintf ("%s.log" , containerName ),
1438
+ Linux : & runtimeapi.LinuxContainerConfig {
1439
+ SecurityContext : & runtimeapi.LinuxContainerSecurityContext {
1440
+ NamespaceOptions : podConfig .Linux .SecurityContext .NamespaceOptions ,
1441
+ },
1442
+ },
1443
+ }
1444
+
1445
+ containerID := createContainerWithExpectation (rc , ic , containerConfig , podID , podConfig , true )
1446
+ startContainer (rc , containerID )
1447
+
1448
+ Eventually (func () runtimeapi.ContainerState {
1449
+ return getContainerStatus (rc , containerID ).State
1450
+ }, time .Minute , time .Second * 4 ).Should (Equal (runtimeapi .ContainerState_CONTAINER_EXITED ))
1451
+
1452
+ return containerName
1453
+ }
1454
+
1455
+ func runUserNamespacePodWithError (
1456
+ rc internalapi.RuntimeService ,
1457
+ podName string ,
1458
+ usernsOptions * runtimeapi.UserNamespace ,
1459
+ runtimeHandler string ,
1460
+ ) {
1461
+ uid := framework .DefaultUIDPrefix + framework .NewUUID ()
1462
+ namespace := framework .DefaultNamespacePrefix + framework .NewUUID ()
1463
+ config := & runtimeapi.PodSandboxConfig {
1464
+ Metadata : framework .BuildPodSandboxMetadata (podName , uid , namespace , framework .DefaultAttempt ),
1465
+ Linux : & runtimeapi.LinuxPodSandboxConfig {
1466
+ SecurityContext : & runtimeapi.LinuxSandboxSecurityContext {
1467
+ NamespaceOptions : & runtimeapi.NamespaceOption {
1468
+ UsernsOptions : usernsOptions ,
1469
+ },
1470
+ },
1471
+ },
1472
+ Labels : framework .DefaultPodLabels ,
1473
+ }
1474
+
1475
+ framework .RunPodSandboxErrorWithRuntimeHandler (rc , config , runtimeHandler )
1476
+ }
0 commit comments