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 })