github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/test/e2e/run_userns_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/user"
     8  	"strings"
     9  
    10  	. "github.com/containers/podman/v2/test/utils"
    11  	. "github.com/onsi/ginkgo"
    12  	. "github.com/onsi/gomega"
    13  )
    14  
    15  var _ = Describe("Podman UserNS support", func() {
    16  	var (
    17  		tempdir    string
    18  		err        error
    19  		podmanTest *PodmanTestIntegration
    20  	)
    21  
    22  	BeforeEach(func() {
    23  		if os.Getenv("SKIP_USERNS") != "" {
    24  			Skip("Skip userns tests.")
    25  		}
    26  		if _, err := os.Stat("/proc/self/uid_map"); err != nil {
    27  			Skip("User namespaces not supported.")
    28  		}
    29  		tempdir, err = CreateTempDirInTempDir()
    30  		if err != nil {
    31  			os.Exit(1)
    32  		}
    33  		podmanTest = PodmanTestCreate(tempdir)
    34  		podmanTest.Setup()
    35  		podmanTest.SeedImages()
    36  	})
    37  
    38  	AfterEach(func() {
    39  		podmanTest.Cleanup()
    40  		f := CurrentGinkgoTestDescription()
    41  		processTestResult(f)
    42  
    43  	})
    44  
    45  	It("podman uidmapping and gidmapping", func() {
    46  		session := podmanTest.Podman([]string{"run", "--uidmap=0:100:5000", "--gidmap=0:200:5000", "alpine", "echo", "hello"})
    47  		session.WaitWithDefaultTimeout()
    48  		Expect(session.ExitCode()).To(Equal(0))
    49  		ok, _ := session.GrepString("hello")
    50  		Expect(ok).To(BeTrue())
    51  	})
    52  
    53  	// It essentially repeats the test above but with the `-it` short option
    54  	// that broke execution at:
    55  	//     https://github.com/containers/podman/pull/1066#issuecomment-403562116
    56  	// To avoid a potential future regression, use this as a test.
    57  	It("podman uidmapping and gidmapping with short-opts", func() {
    58  		session := podmanTest.Podman([]string{"run", "--uidmap=0:1:5000", "--gidmap=0:200:5000", "-it", "alpine", "echo", "hello"})
    59  		session.WaitWithDefaultTimeout()
    60  		Expect(session.ExitCode()).To(Equal(0))
    61  		ok, _ := session.GrepString("hello")
    62  		Expect(ok).To(BeTrue())
    63  	})
    64  
    65  	It("podman uidmapping and gidmapping with a volume", func() {
    66  		session := podmanTest.Podman([]string{"run", "--uidmap=0:1:500", "--gidmap=0:200:5000", "-v", "my-foo-volume:/foo:Z", "alpine", "echo", "hello"})
    67  		session.WaitWithDefaultTimeout()
    68  		Expect(session.ExitCode()).To(Equal(0))
    69  		ok, _ := session.GrepString("hello")
    70  		Expect(ok).To(BeTrue())
    71  	})
    72  
    73  	It("podman uidmapping and gidmapping --net=host", func() {
    74  		session := podmanTest.Podman([]string{"run", "--net=host", "--uidmap=0:1:5000", "--gidmap=0:200:5000", "alpine", "echo", "hello"})
    75  		session.WaitWithDefaultTimeout()
    76  		Expect(session.ExitCode()).To(Equal(0))
    77  		ok, _ := session.GrepString("hello")
    78  		Expect(ok).To(BeTrue())
    79  	})
    80  
    81  	It("podman --userns=keep-id", func() {
    82  		session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "id", "-u"})
    83  		session.WaitWithDefaultTimeout()
    84  		Expect(session.ExitCode()).To(Equal(0))
    85  		uid := fmt.Sprintf("%d", os.Geteuid())
    86  		ok, _ := session.GrepString(uid)
    87  		Expect(ok).To(BeTrue())
    88  	})
    89  
    90  	It("podman --userns=keep-id check passwd", func() {
    91  		session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "id", "-un"})
    92  		session.WaitWithDefaultTimeout()
    93  		Expect(session.ExitCode()).To(Equal(0))
    94  		u, err := user.Current()
    95  		Expect(err).To(BeNil())
    96  		ok, _ := session.GrepString(u.Name)
    97  		Expect(ok).To(BeTrue())
    98  	})
    99  
   100  	It("podman --userns=keep-id root owns /usr", func() {
   101  		session := podmanTest.Podman([]string{"run", "--userns=keep-id", "alpine", "stat", "-c%u", "/usr"})
   102  		session.WaitWithDefaultTimeout()
   103  		Expect(session.ExitCode()).To(Equal(0))
   104  		Expect(session.OutputToString()).To(Equal("0"))
   105  	})
   106  
   107  	It("podman --userns=keep-id --user root:root", func() {
   108  		session := podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", "alpine", "id", "-u"})
   109  		session.WaitWithDefaultTimeout()
   110  		Expect(session.ExitCode()).To(Equal(0))
   111  		Expect(session.OutputToString()).To(Equal("0"))
   112  	})
   113  
   114  	It("podman run --userns=keep-id can add users", func() {
   115  		if os.Geteuid() == 0 {
   116  			Skip("Test only runs without root")
   117  		}
   118  
   119  		userName := os.Getenv("USER")
   120  		if userName == "" {
   121  			Skip("Can't complete test if no username available")
   122  		}
   123  
   124  		ctrName := "ctr-name"
   125  		session := podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", "-d", "--stop-signal", "9", "--name", ctrName, fedoraMinimal, "sleep", "600"})
   126  		session.WaitWithDefaultTimeout()
   127  		Expect(session.ExitCode()).To(Equal(0))
   128  
   129  		exec1 := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "cat", "/etc/passwd"})
   130  		exec1.WaitWithDefaultTimeout()
   131  		Expect(exec1.ExitCode()).To(Equal(0))
   132  		Expect(exec1.OutputToString()).To(ContainSubstring(userName))
   133  
   134  		exec2 := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "useradd", "testuser"})
   135  		exec2.WaitWithDefaultTimeout()
   136  		Expect(exec2.ExitCode()).To(Equal(0))
   137  	})
   138  
   139  	It("podman --userns=auto", func() {
   140  		u, err := user.Current()
   141  		Expect(err).To(BeNil())
   142  		name := u.Name
   143  		if name == "root" {
   144  			name = "containers"
   145  		}
   146  
   147  		content, err := ioutil.ReadFile("/etc/subuid")
   148  		if err != nil {
   149  			Skip("cannot read /etc/subuid")
   150  		}
   151  		if !strings.Contains(string(content), name) {
   152  			Skip("cannot find mappings for the current user")
   153  		}
   154  
   155  		m := make(map[string]string)
   156  		for i := 0; i < 5; i++ {
   157  			session := podmanTest.Podman([]string{"run", "--userns=auto", "alpine", "cat", "/proc/self/uid_map"})
   158  			session.WaitWithDefaultTimeout()
   159  			Expect(session.ExitCode()).To(Equal(0))
   160  			l := session.OutputToString()
   161  			Expect(strings.Contains(l, "1024")).To(BeTrue())
   162  			m[l] = l
   163  		}
   164  		// check for no duplicates
   165  		Expect(len(m)).To(Equal(5))
   166  	})
   167  
   168  	It("podman --userns=auto:size=%d", func() {
   169  		u, err := user.Current()
   170  		Expect(err).To(BeNil())
   171  
   172  		name := u.Name
   173  		if name == "root" {
   174  			name = "containers"
   175  		}
   176  
   177  		content, err := ioutil.ReadFile("/etc/subuid")
   178  		if err != nil {
   179  			Skip("cannot read /etc/subuid")
   180  		}
   181  		if !strings.Contains(string(content), name) {
   182  			Skip("cannot find mappings for the current user")
   183  		}
   184  
   185  		session := podmanTest.Podman([]string{"run", "--userns=auto:size=500", "alpine", "cat", "/proc/self/uid_map"})
   186  		session.WaitWithDefaultTimeout()
   187  		Expect(session.ExitCode()).To(Equal(0))
   188  		ok, _ := session.GrepString("500")
   189  
   190  		session = podmanTest.Podman([]string{"run", "--userns=auto:size=3000", "alpine", "cat", "/proc/self/uid_map"})
   191  		session.WaitWithDefaultTimeout()
   192  		Expect(session.ExitCode()).To(Equal(0))
   193  		ok, _ = session.GrepString("3000")
   194  
   195  		session = podmanTest.Podman([]string{"run", "--userns=auto", "--user=2000:3000", "alpine", "cat", "/proc/self/uid_map"})
   196  		session.WaitWithDefaultTimeout()
   197  		Expect(session.ExitCode()).To(Equal(0))
   198  		ok, _ = session.GrepString("3001")
   199  
   200  		session = podmanTest.Podman([]string{"run", "--userns=auto", "--user=4000:1000", "alpine", "cat", "/proc/self/uid_map"})
   201  		session.WaitWithDefaultTimeout()
   202  		Expect(session.ExitCode()).To(Equal(0))
   203  		ok, _ = session.GrepString("4001")
   204  		Expect(ok).To(BeTrue())
   205  	})
   206  
   207  	It("podman --userns=auto:uidmapping=", func() {
   208  		u, err := user.Current()
   209  		Expect(err).To(BeNil())
   210  
   211  		name := u.Name
   212  		if name == "root" {
   213  			name = "containers"
   214  		}
   215  
   216  		content, err := ioutil.ReadFile("/etc/subuid")
   217  		if err != nil {
   218  			Skip("cannot read /etc/subuid")
   219  		}
   220  		if !strings.Contains(string(content), name) {
   221  			Skip("cannot find mappings for the current user")
   222  		}
   223  
   224  		session := podmanTest.Podman([]string{"run", "--userns=auto:uidmapping=0:0:1", "alpine", "cat", "/proc/self/uid_map"})
   225  		session.WaitWithDefaultTimeout()
   226  		Expect(session.ExitCode()).To(Equal(0))
   227  		output := session.OutputToString()
   228  		Expect(output).To(MatchRegexp("\\s0\\s0\\s1"))
   229  
   230  		session = podmanTest.Podman([]string{"run", "--userns=auto:size=8192,uidmapping=0:0:1", "alpine", "cat", "/proc/self/uid_map"})
   231  		session.WaitWithDefaultTimeout()
   232  		Expect(session.ExitCode()).To(Equal(0))
   233  		ok, _ := session.GrepString("8191")
   234  		Expect(ok).To(BeTrue())
   235  	})
   236  
   237  	It("podman --userns=auto:gidmapping=", func() {
   238  		u, err := user.Current()
   239  		Expect(err).To(BeNil())
   240  
   241  		name := u.Name
   242  		if name == "root" {
   243  			name = "containers"
   244  		}
   245  
   246  		content, err := ioutil.ReadFile("/etc/subuid")
   247  		if err != nil {
   248  			Skip("cannot read /etc/subuid")
   249  		}
   250  		if !strings.Contains(string(content), name) {
   251  			Skip("cannot find mappings for the current user")
   252  		}
   253  
   254  		session := podmanTest.Podman([]string{"run", "--userns=auto:gidmapping=0:0:1", "alpine", "cat", "/proc/self/gid_map"})
   255  		session.WaitWithDefaultTimeout()
   256  		Expect(session.ExitCode()).To(Equal(0))
   257  		output := session.OutputToString()
   258  		Expect(output).To(MatchRegexp("\\s0\\s0\\s1"))
   259  
   260  		session = podmanTest.Podman([]string{"run", "--userns=auto:size=8192,gidmapping=0:0:1", "alpine", "cat", "/proc/self/gid_map"})
   261  		session.WaitWithDefaultTimeout()
   262  		Expect(session.ExitCode()).To(Equal(0))
   263  		ok, _ := session.GrepString("8191")
   264  		Expect(ok).To(BeTrue())
   265  	})
   266  
   267  	It("podman --userns=container:CTR", func() {
   268  		ctrName := "userns-ctr"
   269  		session := podmanTest.Podman([]string{"run", "-d", "--uidmap=0:0:1", "--uidmap=1:1:4998", "--name", ctrName, "alpine", "top"})
   270  		session.WaitWithDefaultTimeout()
   271  		Expect(session.ExitCode()).To(Equal(0))
   272  
   273  		// runc has an issue and we also need to join the IPC namespace.
   274  		session = podmanTest.Podman([]string{"run", "--rm", "--userns=container:" + ctrName, "--ipc=container:" + ctrName, "alpine", "cat", "/proc/self/uid_map"})
   275  		session.WaitWithDefaultTimeout()
   276  		Expect(session.ExitCode()).To(Equal(0))
   277  
   278  		ok, _ := session.GrepString("4998")
   279  		Expect(ok).To(BeTrue())
   280  
   281  		session = podmanTest.Podman([]string{"run", "--rm", "--userns=container:" + ctrName, "--net=container:" + ctrName, "alpine", "cat", "/proc/self/uid_map"})
   282  		session.WaitWithDefaultTimeout()
   283  		Expect(session.ExitCode()).To(Equal(0))
   284  
   285  		ok, _ = session.GrepString("4998")
   286  		Expect(ok).To(BeTrue())
   287  	})
   288  
   289  	It("podman --user with volume", func() {
   290  		tests := []struct {
   291  			uid, gid, arg, vol string
   292  		}{
   293  			{"0", "0", "0:0", "vol-0"},
   294  			{"1000", "0", "1000", "vol-1"},
   295  			{"1000", "1000", "1000:1000", "vol-2"},
   296  		}
   297  
   298  		for _, tt := range tests {
   299  			session := podmanTest.Podman([]string{"run", "-d", "--user", tt.arg, "--mount", "type=volume,src=" + tt.vol + ",dst=/home/user", "alpine", "top"})
   300  			session.WaitWithDefaultTimeout()
   301  			Expect(session.ExitCode()).To(Equal(0))
   302  
   303  			inspectUID := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .UID }}", tt.vol})
   304  			inspectUID.WaitWithDefaultTimeout()
   305  			Expect(inspectUID.ExitCode()).To(Equal(0))
   306  			Expect(inspectUID.OutputToString()).To(Equal(tt.uid))
   307  
   308  			// Make sure we're defaulting to 0.
   309  			inspectGID := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .GID }}", tt.vol})
   310  			inspectGID.WaitWithDefaultTimeout()
   311  			Expect(inspectGID.ExitCode()).To(Equal(0))
   312  			Expect(inspectGID.OutputToString()).To(Equal(tt.gid))
   313  		}
   314  	})
   315  })