@@ -32,6 +32,7 @@ import (
32
32
33
33
. "github.com/onsi/ginkgo/v2"
34
34
. "github.com/onsi/gomega"
35
+ . "github.com/onsi/gomega/gstruct"
35
36
"golang.org/x/sys/unix"
36
37
internalapi "k8s.io/cri-api/pkg/apis"
37
38
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
@@ -306,57 +307,6 @@ var _ = framework.KubeDescribe("Security Context", func() {
306
307
Expect (groups ).To (ContainElement ("5678" ))
307
308
})
308
309
309
- It ("if the container's primary UID belongs to some groups in the image, runtime should add SupplementalGroups to them" , func () {
310
- By ("create pod" )
311
- podID , podConfig , podLogDir = createPodSandboxWithLogDirectory (rc )
312
-
313
- By ("create container for security context SupplementalGroups" )
314
- supplementalGroup := int64 (1234 )
315
- containerName := "container-with-SupplementalGroups-and-predefined-group-image-test-" + framework .NewUUID ()
316
- logPath := containerName + ".log"
317
- containerConfig := & runtimeapi.ContainerConfig {
318
- Metadata : framework .BuildContainerMetadata (containerName , framework .DefaultAttempt ),
319
- Image : & runtimeapi.ImageSpec {Image : testImagePreDefinedGroup },
320
- Command : []string {"sh" , "-c" , "id -G; while :; do sleep 1; done" },
321
- Linux : & runtimeapi.LinuxContainerConfig {
322
- SecurityContext : & runtimeapi.LinuxContainerSecurityContext {
323
- RunAsUser : & runtimeapi.Int64Value {Value : imagePredefinedGroupUID },
324
- SupplementalGroups : []int64 {supplementalGroup },
325
- },
326
- },
327
- LogPath : logPath ,
328
- }
329
- containerID := framework .CreateContainer (rc , ic , containerConfig , podID , podConfig )
330
-
331
- By ("start container" )
332
- startContainer (rc , containerID )
333
- Eventually (func (g Gomega ) {
334
- g .Expect (getContainerStatus (rc , containerID ).State ).To (Equal (runtimeapi .ContainerState_CONTAINER_RUNNING ))
335
- g .Expect (parseLogLine (podConfig , logPath )).NotTo (BeEmpty ())
336
- }, time .Minute , time .Second * 4 ).Should (Succeed ())
337
-
338
- // In testImagePreDefinedGroup,
339
- // - its default user is default-user(uid=1000)
340
- // - default-user belongs to group-defined-in-image(gid=50000)
341
- //
342
- // thus, supplementary group of the container processes should be
343
- // - 1000: self
344
- // - 1234: SupplementalGroups
345
- // - 50000: groups define in the container image
346
- //
347
- // $ id -G
348
- // 1000 1234 5678 50000
349
- expectedOutput := fmt .Sprintf ("%d %d %d\n " , imagePredefinedGroupUID , supplementalGroup , imagePredefinedGroupGID )
350
-
351
- By ("verify groups for the first process of the container" )
352
- verifyLogContents (podConfig , logPath , expectedOutput , stdoutType )
353
-
354
- By ("verify groups for 'exec'-ed process of container" )
355
- command := []string {"id" , "-G" }
356
- o := execSyncContainer (rc , containerID , command )
357
- Expect (o ).To (BeEquivalentTo (expectedOutput ))
358
- })
359
-
360
310
It ("runtime should support RunAsUser" , func () {
361
311
By ("create pod" )
362
312
podID , podConfig = framework .CreatePodSandboxForContainer (rc )
@@ -639,6 +589,151 @@ var _ = framework.KubeDescribe("Security Context", func() {
639
589
})
640
590
})
641
591
592
+ Context ("SupplementalGroupsPolicy" , func () {
593
+ BeforeEach (func (ctx context.Context ) {
594
+ By ("skip if the runtime does not support SupplementalGroupsPolicy" )
595
+ statusResponse , err := rc .Status (ctx , false )
596
+ Expect (err ).NotTo (HaveOccurred ())
597
+ if ! (statusResponse .Features != nil && statusResponse .Features .SupplementalGroupsPolicy ) {
598
+ Skip ("The runtime does not support SupplementalGroupsPolicy feature" )
599
+ }
600
+ })
601
+
602
+ When ("SupplementalGroupsPolicy=Merge (Default)" , func () {
603
+ It ("if the container's primary UID belongs to some groups in the image, runtime should add SupplementalGroups to them" , func () {
604
+ By ("create pod" )
605
+ podID , podConfig , podLogDir = createPodSandboxWithLogDirectory (rc )
606
+
607
+ By ("create container for security context SupplementalGroups" )
608
+ supplementalGroup := int64 (1234 )
609
+ containerName := "container-with-SupplementalGroupsPolicyMerge-" + framework .NewUUID ()
610
+ logPath := containerName + ".log"
611
+ containerConfig := & runtimeapi.ContainerConfig {
612
+ Metadata : framework .BuildContainerMetadata (containerName , framework .DefaultAttempt ),
613
+ Image : & runtimeapi.ImageSpec {Image : testImagePreDefinedGroup },
614
+ Command : []string {"sh" , "-c" , "id -G; while :; do sleep 1; done" },
615
+ Linux : & runtimeapi.LinuxContainerConfig {
616
+ SecurityContext : & runtimeapi.LinuxContainerSecurityContext {
617
+ RunAsUser : & runtimeapi.Int64Value {Value : imagePredefinedGroupUID },
618
+ SupplementalGroups : []int64 {supplementalGroup },
619
+ // SupplementalGroupsPolicy_Merge is default(0)
620
+ // SupplementalGroupsPolicy: runtimeapi.SupplementalGroupsPolicy_Merge,
621
+ },
622
+ },
623
+ LogPath : logPath ,
624
+ }
625
+ containerID := framework .CreateContainer (rc , ic , containerConfig , podID , podConfig )
626
+
627
+ By ("start container" )
628
+ startContainer (rc , containerID )
629
+
630
+ Eventually (func (g Gomega ) {
631
+ containerStatus := getContainerStatus (rc , containerID )
632
+ g .Expect (containerStatus .State ).To (Equal (runtimeapi .ContainerState_CONTAINER_RUNNING ))
633
+ // In testImagePreDefinedGroup,
634
+ // - its default user is default-user(uid=1000)
635
+ // - default-user belongs to group-defined-in-image(gid=50000) in /etc/group
636
+ // And, SupplementalGroupsPolicy is Merge(default)
637
+ //
638
+ // Thus, firstly attached process identity of the first container processes should be
639
+ // - uid: 1000 (RunAsUser)
640
+ // - gid: 1000 (default group for uid=1000)
641
+ // - supplementary groups
642
+ // - 1000: self
643
+ // - 1234: SupplementalGroups
644
+ // - 50000: groups defined in the container image (/etc/group)
645
+ g .Expect (containerStatus .User ).To (PointTo (MatchFields (IgnoreExtras , Fields {
646
+ "Linux" : PointTo (MatchFields (IgnoreExtras , Fields {
647
+ "Uid" : Equal (imagePredefinedGroupUID ),
648
+ "Gid" : Equal (imagePredefinedGroupUID ),
649
+ // we can not assume the order of gids
650
+ "SupplementalGroups" : And (ContainElements (imagePredefinedGroupUID , supplementalGroup , imagePredefinedGroupGID ), HaveLen (3 )),
651
+ })),
652
+ })))
653
+ g .Expect (parseLogLine (podConfig , logPath )).NotTo (BeEmpty ())
654
+ }, time .Minute , time .Second * 4 ).Should (Succeed ())
655
+
656
+ // $ id -G
657
+ // 1000 1234 50000
658
+ expectedOutput := fmt .Sprintf ("%d %d %d\n " , imagePredefinedGroupUID , supplementalGroup , imagePredefinedGroupGID )
659
+
660
+ By ("verify groups for the first process of the container" )
661
+ verifyLogContents (podConfig , logPath , expectedOutput , stdoutType )
662
+
663
+ By ("verify groups for 'exec'-ed process of container" )
664
+ command := []string {"id" , "-G" }
665
+ o := execSyncContainer (rc , containerID , command )
666
+ Expect (o ).To (BeEquivalentTo (expectedOutput ))
667
+ })
668
+ })
669
+ When ("SupplementalGroupsPolicy=Strict" , func () {
670
+ It ("even if the container's primary UID belongs to some groups in the image, runtime should not add SupplementalGroups to them" , func () {
671
+ By ("create pod" )
672
+ podID , podConfig , podLogDir = createPodSandboxWithLogDirectory (rc )
673
+
674
+ By ("create container for security context SupplementalGroups" )
675
+ supplementalGroup := int64 (1234 )
676
+ containerName := "container-with-SupplementalGroupsPolicyMerge-" + framework .NewUUID ()
677
+ logPath := containerName + ".log"
678
+ containerConfig := & runtimeapi.ContainerConfig {
679
+ Metadata : framework .BuildContainerMetadata (containerName , framework .DefaultAttempt ),
680
+ Image : & runtimeapi.ImageSpec {Image : testImagePreDefinedGroup },
681
+ Command : []string {"sh" , "-c" , "id -G; while :; do sleep 1; done" },
682
+ Linux : & runtimeapi.LinuxContainerConfig {
683
+ SecurityContext : & runtimeapi.LinuxContainerSecurityContext {
684
+ RunAsUser : & runtimeapi.Int64Value {Value : imagePredefinedGroupUID },
685
+ SupplementalGroups : []int64 {supplementalGroup },
686
+ SupplementalGroupsPolicy : runtimeapi .SupplementalGroupsPolicy_Strict ,
687
+ },
688
+ },
689
+ LogPath : logPath ,
690
+ }
691
+ containerID := framework .CreateContainer (rc , ic , containerConfig , podID , podConfig )
692
+
693
+ By ("start container" )
694
+ startContainer (rc , containerID )
695
+
696
+ Eventually (func (g Gomega ) {
697
+ containerStatus := getContainerStatus (rc , containerID )
698
+ g .Expect (containerStatus .State ).To (Equal (runtimeapi .ContainerState_CONTAINER_RUNNING ))
699
+ // In testImagePreDefinedGroup,
700
+ // - its default user is default-user(uid=1000)
701
+ // - default-user belongs to group-defined-in-image(gid=50000) in /etc/group
702
+ // And, SupplementalGroupsPolicy is Strict
703
+ //
704
+ // Thus, firstly attached process identity of the first container processes should be
705
+ // (5000(defined in /etc/group) is not appended to supplementary groups)
706
+ // - uid: 1000 (RunAsUser)
707
+ // - gid: 1000 (default group for uid=1000)
708
+ // - supplementary groups
709
+ // - 1000: self
710
+ // - 1234: SupplementalGroups
711
+ g .Expect (containerStatus .User ).To (PointTo (MatchFields (IgnoreExtras , Fields {
712
+ "Linux" : PointTo (MatchFields (IgnoreExtras , Fields {
713
+ "Uid" : Equal (imagePredefinedGroupUID ),
714
+ "Gid" : Equal (imagePredefinedGroupUID ),
715
+ // we can not assume the order of gids
716
+ "SupplementalGroups" : And (ContainElements (imagePredefinedGroupUID , supplementalGroup ), HaveLen (2 )),
717
+ })),
718
+ })))
719
+ g .Expect (parseLogLine (podConfig , logPath )).NotTo (BeEmpty ())
720
+ }, time .Minute , time .Second * 4 ).Should (Succeed ())
721
+
722
+ // $ id -G
723
+ // 1000 1234
724
+ expectedOutput := fmt .Sprintf ("%d %d\n " , imagePredefinedGroupUID , supplementalGroup )
725
+
726
+ By ("verify groups for the first process of the container" )
727
+ verifyLogContents (podConfig , logPath , expectedOutput , stdoutType )
728
+
729
+ By ("verify groups for 'exec'-ed process of container" )
730
+ command := []string {"id" , "-G" }
731
+ o := execSyncContainer (rc , containerID , command )
732
+ Expect (o ).To (BeEquivalentTo (expectedOutput ))
733
+ })
734
+ })
735
+ })
736
+
642
737
// TODO(random-liu): We should set apparmor to unconfined in seccomp test to prevent
643
738
// them from interfering with each other.
644
739
Context ("SeccompProfilePath" , func () {
0 commit comments