@@ -842,6 +842,100 @@ 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
+ defaultMapping = []* runtimeapi.IDMapping {{
850
+ ContainerId : 0 ,
851
+ HostId : 1000 ,
852
+ Length : 100000 ,
853
+ }}
854
+ )
855
+
856
+ BeforeEach (func () {
857
+ podName = "user-namespaces-pod-" + framework .NewUUID ()
858
+ })
859
+
860
+ It ("runtime should support NamespaceMode_POD" , func () {
861
+ namespaceOption := & runtimeapi.NamespaceOption {
862
+ UsernsOptions : & runtimeapi.UserNamespace {
863
+ Mode : runtimeapi .NamespaceMode_POD ,
864
+ Uids : defaultMapping ,
865
+ Gids : defaultMapping ,
866
+ },
867
+ }
868
+
869
+ hostLogPath , podLogPath := createLogTempDir (podName )
870
+ defer os .RemoveAll (hostLogPath )
871
+ podID , podConfig = createNamespacePodSandbox (rc , namespaceOption , podName , podLogPath )
872
+ containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
873
+
874
+ matchContainerOutputRe (podConfig , containerName , `\s+0\s+1000\s+100000\n` )
875
+ })
876
+
877
+ It ("runtime should support NamespaceMode_NODE" , func () {
878
+ namespaceOption := & runtimeapi.NamespaceOption {
879
+ UsernsOptions : & runtimeapi.UserNamespace {
880
+ Mode : runtimeapi .NamespaceMode_NODE ,
881
+ },
882
+ }
883
+
884
+ hostLogPath , podLogPath := createLogTempDir (podName )
885
+ defer os .RemoveAll (hostLogPath )
886
+ podID , podConfig = createNamespacePodSandbox (rc , namespaceOption , podName , podLogPath )
887
+ containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
888
+
889
+ // 4294967295 means that the entire range is available
890
+ matchContainerOutputRe (podConfig , containerName , `\s+0\s+0\s+4294967295\n` )
891
+ })
892
+
893
+ It ("runtime should fail if more than one mapping provided" , func () {
894
+ wrongMapping := []* runtimeapi.IDMapping {{
895
+ ContainerId : 0 ,
896
+ HostId : 1000 ,
897
+ Length : 100000 ,
898
+ }, {
899
+ ContainerId : 0 ,
900
+ HostId : 2000 ,
901
+ Length : 100000 ,
902
+ }}
903
+ usernsOptions := & runtimeapi.UserNamespace {
904
+ Mode : runtimeapi .NamespaceMode_POD ,
905
+ Uids : wrongMapping ,
906
+ Gids : wrongMapping ,
907
+ }
908
+
909
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
910
+ })
911
+
912
+ It ("runtime should fail if container ID 0 is not mapped" , func () {
913
+ mapping := []* runtimeapi.IDMapping {{
914
+ ContainerId : 1 ,
915
+ HostId : 1000 ,
916
+ Length : 100000 ,
917
+ }}
918
+ usernsOptions := & runtimeapi.UserNamespace {
919
+ Mode : runtimeapi .NamespaceMode_POD ,
920
+ Uids : mapping ,
921
+ Gids : mapping ,
922
+ }
923
+
924
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
925
+ })
926
+
927
+ It ("runtime should fail with NamespaceMode_CONTAINER" , func () {
928
+ usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_CONTAINER }
929
+
930
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
931
+ })
932
+
933
+ It ("runtime should fail with NamespaceMode_TARGET" , func () {
934
+ usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_TARGET }
935
+
936
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
937
+ })
938
+ })
845
939
})
846
940
847
941
// matchContainerOutput matches log line in container logs.
@@ -850,6 +944,12 @@ func matchContainerOutput(podConfig *runtimeapi.PodSandboxConfig, name, output s
850
944
verifyLogContents (podConfig , fmt .Sprintf ("%s.log" , name ), output , stdoutType )
851
945
}
852
946
947
+ // matchContainerOutputRe matches log line in container logs using the provided regular expression pattern.
948
+ func matchContainerOutputRe (podConfig * runtimeapi.PodSandboxConfig , name , pattern string ) {
949
+ By ("check container output" )
950
+ verifyLogContentsRe (podConfig , fmt .Sprintf ("%s.log" , name ), pattern , stdoutType )
951
+ }
952
+
853
953
// createRunAsUserContainer creates the container with specified RunAsUser in ContainerConfig.
854
954
func createRunAsUserContainer (rc internalapi.RuntimeService , ic internalapi.ImageManagerService , podID string , podConfig * runtimeapi.PodSandboxConfig , prefix string ) (string , string ) {
855
955
By ("create RunAsUser container" )
@@ -946,7 +1046,8 @@ func createNamespacePodSandbox(rc internalapi.RuntimeService, podSandboxNamespac
946
1046
uid := framework .DefaultUIDPrefix + framework .NewUUID ()
947
1047
namespace := framework .DefaultNamespacePrefix + framework .NewUUID ()
948
1048
config := & runtimeapi.PodSandboxConfig {
949
- Metadata : framework .BuildPodSandboxMetadata (podSandboxName , uid , namespace , framework .DefaultAttempt ),
1049
+ Metadata : framework .BuildPodSandboxMetadata (podSandboxName , uid , namespace , framework .DefaultAttempt ),
1050
+ DnsConfig : & runtimeapi.DNSConfig {},
950
1051
Linux : & runtimeapi.LinuxPodSandboxConfig {
951
1052
SecurityContext : & runtimeapi.LinuxSandboxSecurityContext {
952
1053
NamespaceOptions : podSandboxNamespace ,
@@ -1281,3 +1382,58 @@ func checkSetHostname(rc internalapi.RuntimeService, containerID string, setable
1281
1382
Expect (err ).To (HaveOccurred (), msg )
1282
1383
}
1283
1384
}
1385
+
1386
+ func runUserNamespaceContainer (
1387
+ rc internalapi.RuntimeService ,
1388
+ ic internalapi.ImageManagerService ,
1389
+ podID string ,
1390
+ podConfig * runtimeapi.PodSandboxConfig ,
1391
+ ) string {
1392
+ By ("create user namespaces container" )
1393
+ containerName := "user-namespaces-container-" + framework .NewUUID ()
1394
+ containerConfig := & runtimeapi.ContainerConfig {
1395
+ Metadata : framework .BuildContainerMetadata (containerName , framework .DefaultAttempt ),
1396
+ Image : & runtimeapi.ImageSpec {
1397
+ Image : framework .TestContext .TestImageList .DefaultTestContainerImage ,
1398
+ UserSpecifiedImage : framework .TestContext .TestImageList .DefaultTestContainerImage ,
1399
+ },
1400
+ Command : []string {"cat" , "/proc/self/uid_map" },
1401
+ LogPath : fmt .Sprintf ("%s.log" , containerName ),
1402
+ Linux : & runtimeapi.LinuxContainerConfig {
1403
+ SecurityContext : & runtimeapi.LinuxContainerSecurityContext {
1404
+ NamespaceOptions : podConfig .Linux .SecurityContext .NamespaceOptions ,
1405
+ },
1406
+ },
1407
+ }
1408
+
1409
+ containerID := createContainerWithExpectation (rc , ic , containerConfig , podID , podConfig , true )
1410
+ startContainer (rc , containerID )
1411
+
1412
+ Eventually (func () runtimeapi.ContainerState {
1413
+ return getContainerStatus (rc , containerID ).State
1414
+ }, time .Minute , time .Second * 4 ).Should (Equal (runtimeapi .ContainerState_CONTAINER_EXITED ))
1415
+
1416
+ return containerName
1417
+ }
1418
+
1419
+ func runUserNamespacePodWithError (
1420
+ rc internalapi.RuntimeService ,
1421
+ podName string ,
1422
+ usernsOptions * runtimeapi.UserNamespace ,
1423
+ ) {
1424
+ uid := framework .DefaultUIDPrefix + framework .NewUUID ()
1425
+ namespace := framework .DefaultNamespacePrefix + framework .NewUUID ()
1426
+ config := & runtimeapi.PodSandboxConfig {
1427
+ Metadata : framework .BuildPodSandboxMetadata (podName , uid , namespace , framework .DefaultAttempt ),
1428
+ Linux : & runtimeapi.LinuxPodSandboxConfig {
1429
+ SecurityContext : & runtimeapi.LinuxSandboxSecurityContext {
1430
+ NamespaceOptions : & runtimeapi.NamespaceOption {
1431
+ UsernsOptions : usernsOptions ,
1432
+ },
1433
+ },
1434
+ },
1435
+ Labels : framework .DefaultPodLabels ,
1436
+ }
1437
+
1438
+ framework .RunPodSandboxError (rc , config )
1439
+ }
0 commit comments