github.com/containers/podman/v4@v4.9.4/test/e2e/login_logout_test.go (about) 1 package integration 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strconv" 9 "strings" 10 11 . "github.com/containers/podman/v4/test/utils" 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("Podman login and logout", func() { 17 var ( 18 err error 19 authPath string 20 certPath string 21 certDirPath string 22 server string 23 testImg string 24 registriesConfWithSearch []byte 25 ) 26 27 BeforeEach(func() { 28 authPath = filepath.Join(podmanTest.TempDir, "auth") 29 err := os.Mkdir(authPath, os.ModePerm) 30 Expect(err).ToNot(HaveOccurred()) 31 32 htpasswd := SystemExec("htpasswd", []string{"-Bbn", "podmantest", "test"}) 33 htpasswd.WaitWithDefaultTimeout() 34 Expect(htpasswd).Should(ExitCleanly()) 35 36 f, err := os.Create(filepath.Join(authPath, "htpasswd")) 37 Expect(err).ToNot(HaveOccurred()) 38 defer f.Close() 39 40 _, err = f.WriteString(htpasswd.OutputToString()) 41 Expect(err).ToNot(HaveOccurred()) 42 err = f.Sync() 43 Expect(err).ToNot(HaveOccurred()) 44 port := GetPort() 45 server = strings.Join([]string{"localhost", strconv.Itoa(port)}, ":") 46 47 registriesConfWithSearch = []byte(fmt.Sprintf("[registries.search]\nregistries = ['%s']", server)) 48 49 testImg = strings.Join([]string{server, "test-alpine"}, "/") 50 51 certDirPath = filepath.Join(os.Getenv("HOME"), ".config/containers/certs.d", server) 52 err = os.MkdirAll(certDirPath, os.ModePerm) 53 Expect(err).ToNot(HaveOccurred()) 54 cwd, _ := os.Getwd() 55 certPath = filepath.Join(cwd, "../", "certs") 56 57 setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), filepath.Join(certDirPath, "ca.crt")}) 58 setup.WaitWithDefaultTimeout() 59 60 session := podmanTest.Podman([]string{"run", "-d", "-p", strings.Join([]string{strconv.Itoa(port), strconv.Itoa(port)}, ":"), 61 "-e", strings.Join([]string{"REGISTRY_HTTP_ADDR=0.0.0.0", strconv.Itoa(port)}, ":"), "--name", "registry", "-v", 62 strings.Join([]string{authPath, "/auth:Z"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e", 63 "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", 64 "-v", strings.Join([]string{certPath, "/certs:Z"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", 65 "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", REGISTRY_IMAGE}) 66 session.WaitWithDefaultTimeout() 67 Expect(session).Should(ExitCleanly()) 68 69 if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) { 70 Skip("Cannot start docker registry.") 71 } 72 73 // collision protection: each test uses a unique authfile 74 os.Setenv("REGISTRY_AUTH_FILE", filepath.Join(podmanTest.TempDir, "default-auth.json")) 75 }) 76 77 AfterEach(func() { 78 os.Unsetenv("REGISTRY_AUTH_FILE") 79 os.RemoveAll(authPath) 80 os.RemoveAll(certDirPath) 81 }) 82 83 readAuthInfo := func(filePath string) map[string]interface{} { 84 authBytes, err := os.ReadFile(filePath) 85 Expect(err).ToNot(HaveOccurred()) 86 87 var authInfo map[string]interface{} 88 err = json.Unmarshal(authBytes, &authInfo) 89 Expect(err).ToNot(HaveOccurred()) 90 GinkgoWriter.Println(authInfo) 91 92 const authsKey = "auths" 93 Expect(authInfo).To(HaveKey(authsKey)) 94 95 auths, ok := authInfo[authsKey].(map[string]interface{}) 96 Expect(ok).To(BeTrue(), "authInfo[%s]", authsKey) 97 98 return auths 99 } 100 101 It("podman login and logout", func() { 102 authFile := os.Getenv("REGISTRY_AUTH_FILE") 103 Expect(authFile).NotTo(BeEmpty(), "$REGISTRY_AUTH_FILE") 104 105 session := podmanTest.Podman([]string{"login", "-u", "podmantest", "-p", "test", server}) 106 session.WaitWithDefaultTimeout() 107 Expect(session).Should(ExitCleanly()) 108 109 // Confirm that file was created, with the desired credentials 110 auths := readAuthInfo(authFile) 111 Expect(auths).To(HaveKey(server)) 112 // base64-encoded "podmantest:test" 113 Expect(auths[server]).To(HaveKeyWithValue("auth", "cG9kbWFudGVzdDp0ZXN0")) 114 115 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 116 session.WaitWithDefaultTimeout() 117 Expect(session).Should(ExitCleanly()) 118 119 session = podmanTest.Podman([]string{"logout", server}) 120 session.WaitWithDefaultTimeout() 121 Expect(session).Should(ExitCleanly()) 122 123 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 124 session.WaitWithDefaultTimeout() 125 Expect(session).To(ExitWithError()) 126 Expect(session.ErrorToString()).To(ContainSubstring(": authentication required")) 127 }) 128 129 It("podman login and logout without registry parameter", func() { 130 registriesConf, err := os.CreateTemp("", "TestLoginWithoutParameter") 131 Expect(err).ToNot(HaveOccurred()) 132 defer registriesConf.Close() 133 defer os.Remove(registriesConf.Name()) 134 135 err = os.WriteFile(registriesConf.Name(), registriesConfWithSearch, os.ModePerm) 136 Expect(err).ToNot(HaveOccurred()) 137 138 // Environment is per-process, so this looks very unsafe; actually it seems fine because tests are not 139 // run in parallel unless they opt in by calling t.Parallel(). So don’t do that. 140 oldRCP, hasRCP := os.LookupEnv("CONTAINERS_REGISTRIES_CONF") 141 defer func() { 142 if hasRCP { 143 os.Setenv("CONTAINERS_REGISTRIES_CONF", oldRCP) 144 } else { 145 os.Unsetenv("CONTAINERS_REGISTRIES_CONF") 146 } 147 }() 148 os.Setenv("CONTAINERS_REGISTRIES_CONF", registriesConf.Name()) 149 150 session := podmanTest.Podman([]string{"login", "-u", "podmantest", "-p", "test"}) 151 session.WaitWithDefaultTimeout() 152 Expect(session).Should(ExitCleanly()) 153 154 session = podmanTest.Podman([]string{"logout"}) 155 session.WaitWithDefaultTimeout() 156 Expect(session).Should(ExitCleanly()) 157 }) 158 159 It("podman login and logout with flag --authfile", func() { 160 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 161 session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--authfile", authFile, server}) 162 session.WaitWithDefaultTimeout() 163 Expect(session).Should(ExitCleanly()) 164 165 readAuthInfo(authFile) 166 167 // push should fail with nonexistent authfile 168 session = podmanTest.Podman([]string{"push", "-q", "--authfile", "/tmp/nonexistent", ALPINE, testImg}) 169 session.WaitWithDefaultTimeout() 170 Expect(session).To(ExitWithError()) 171 Expect(session.ErrorToString()).To(Equal("Error: credential file is not accessible: stat /tmp/nonexistent: no such file or directory")) 172 173 session = podmanTest.Podman([]string{"push", "-q", "--authfile", authFile, ALPINE, testImg}) 174 session.WaitWithDefaultTimeout() 175 Expect(session).Should(ExitCleanly()) 176 177 session = podmanTest.Podman([]string{"run", "-q", "--authfile", authFile, testImg}) 178 session.WaitWithDefaultTimeout() 179 Expect(session).Should(ExitCleanly()) 180 181 // logout should fail with nonexistent authfile 182 session = podmanTest.Podman([]string{"logout", "--authfile", "/tmp/nonexistent", server}) 183 session.WaitWithDefaultTimeout() 184 Expect(session).To(ExitWithError()) 185 Expect(session.ErrorToString()).To(Equal("Error: credential file is not accessible: stat /tmp/nonexistent: no such file or directory")) 186 187 session = podmanTest.Podman([]string{"logout", "--authfile", authFile, server}) 188 session.WaitWithDefaultTimeout() 189 Expect(session).Should(ExitCleanly()) 190 }) 191 192 It("podman login and logout --compat-auth-file flag handling", func() { 193 // A minimal smoke test 194 compatAuthFile := filepath.Join(podmanTest.TempDir, "config.json") 195 session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--compat-auth-file", compatAuthFile, server}) 196 session.WaitWithDefaultTimeout() 197 Expect(session).Should(ExitCleanly()) 198 199 readAuthInfo(compatAuthFile) 200 201 session = podmanTest.Podman([]string{"logout", "--compat-auth-file", compatAuthFile, server}) 202 session.WaitWithDefaultTimeout() 203 Expect(session).Should(ExitCleanly()) 204 205 // logout should fail with nonexistent authfile 206 session = podmanTest.Podman([]string{"logout", "--compat-auth-file", "/tmp/nonexistent", server}) 207 session.WaitWithDefaultTimeout() 208 Expect(session).To(ExitWithError()) 209 Expect(session.ErrorToString()).To(Equal("Error: credential file is not accessible: stat /tmp/nonexistent: no such file or directory")) 210 211 // inconsistent command line flags are rejected 212 // Pre-create the files to make sure we are not hitting the “file not found” path 213 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 214 err := os.WriteFile(authFile, []byte("{}"), 0o700) 215 Expect(err).ToNot(HaveOccurred()) 216 err = os.WriteFile(compatAuthFile, []byte("{}"), 0o700) 217 Expect(err).ToNot(HaveOccurred()) 218 219 session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", 220 "--authfile", authFile, "--compat-auth-file", compatAuthFile, server}) 221 session.WaitWithDefaultTimeout() 222 Expect(session).To(ExitWithError()) 223 Expect(session.ErrorToString()).To(Equal("Error: options for paths to the credential file and to the Docker-compatible credential file can not be set simultaneously")) 224 225 session = podmanTest.Podman([]string{"logout", "--authfile", authFile, "--compat-auth-file", compatAuthFile, server}) 226 session.WaitWithDefaultTimeout() 227 Expect(session).To(ExitWithError()) 228 Expect(session.ErrorToString()).To(Equal("Error: options for paths to the credential file and to the Docker-compatible credential file can not be set simultaneously")) 229 }) 230 231 It("podman manifest with --authfile", func() { 232 os.Unsetenv("REGISTRY_AUTH_FILE") 233 234 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 235 session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--authfile", authFile, server}) 236 session.WaitWithDefaultTimeout() 237 Expect(session).Should(ExitCleanly()) 238 239 readAuthInfo(authFile) 240 241 session = podmanTest.Podman([]string{"manifest", "create", testImg}) 242 session.WaitWithDefaultTimeout() 243 Expect(session).Should(ExitCleanly()) 244 245 session = podmanTest.Podman([]string{"manifest", "push", "-q", testImg}) 246 session.WaitWithDefaultTimeout() 247 Expect(session).To(ExitWithError()) 248 Expect(session.ErrorToString()).To(ContainSubstring(": authentication required")) 249 250 session = podmanTest.Podman([]string{"manifest", "push", "-q", "--authfile", authFile, testImg}) 251 session.WaitWithDefaultTimeout() 252 Expect(session).Should(ExitCleanly()) 253 254 // Now remove the local manifest to trigger remote inspection 255 session = podmanTest.Podman([]string{"manifest", "rm", testImg}) 256 session.WaitWithDefaultTimeout() 257 Expect(session).Should(ExitCleanly()) 258 259 session = podmanTest.Podman([]string{"manifest", "inspect", testImg}) 260 session.WaitWithDefaultTimeout() 261 Expect(session).To(ExitWithError()) 262 Expect(session.ErrorToString()).To(ContainSubstring(": authentication required")) 263 264 session = podmanTest.Podman([]string{"manifest", "inspect", "--authfile", authFile, testImg}) 265 session.WaitWithDefaultTimeout() 266 Expect(session).Should(ExitCleanly()) 267 }) 268 269 It("podman login and logout with --tls-verify", func() { 270 session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--tls-verify=false", server}) 271 session.WaitWithDefaultTimeout() 272 Expect(session).Should(ExitCleanly()) 273 274 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 275 session.WaitWithDefaultTimeout() 276 Expect(session).Should(ExitCleanly()) 277 278 session = podmanTest.Podman([]string{"logout", server}) 279 session.WaitWithDefaultTimeout() 280 Expect(session).Should(ExitCleanly()) 281 }) 282 It("podman login and logout with --cert-dir", func() { 283 certDir := filepath.Join(podmanTest.TempDir, "certs") 284 err := os.MkdirAll(certDir, os.ModePerm) 285 Expect(err).ToNot(HaveOccurred()) 286 287 setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), filepath.Join(certDir, "ca.crt")}) 288 setup.WaitWithDefaultTimeout() 289 290 session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--cert-dir", certDir, server}) 291 session.WaitWithDefaultTimeout() 292 Expect(session).Should(ExitCleanly()) 293 294 session = podmanTest.Podman([]string{"push", "-q", "--cert-dir", certDir, ALPINE, testImg}) 295 session.WaitWithDefaultTimeout() 296 Expect(session).Should(ExitCleanly()) 297 298 session = podmanTest.Podman([]string{"logout", server}) 299 session.WaitWithDefaultTimeout() 300 Expect(session).Should(ExitCleanly()) 301 }) 302 It("podman login and logout with multi registry", func() { 303 certDir := filepath.Join(os.Getenv("HOME"), ".config/containers/certs.d", "localhost:9001") 304 err = os.MkdirAll(certDir, os.ModePerm) 305 Expect(err).ToNot(HaveOccurred()) 306 307 cwd, _ := os.Getwd() 308 certPath = filepath.Join(cwd, "../", "certs") 309 310 setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), filepath.Join(certDir, "ca.crt")}) 311 setup.WaitWithDefaultTimeout() 312 defer os.RemoveAll(certDir) 313 314 // N/B: This second registry container shares the same auth and cert dirs 315 // as the registry started from BeforeEach(). Since this one starts 316 // second, re-labeling the volumes should keep SELinux happy. 317 session := podmanTest.Podman([]string{"run", "-d", "-p", "9001:9001", "-e", "REGISTRY_HTTP_ADDR=0.0.0.0:9001", "--name", "registry1", "-v", 318 strings.Join([]string{authPath, "/auth:z"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e", 319 "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd", 320 "-v", strings.Join([]string{certPath, "/certs:z"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt", 321 "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", REGISTRY_IMAGE}) 322 session.WaitWithDefaultTimeout() 323 Expect(session).Should(ExitCleanly()) 324 325 if !WaitContainerReady(podmanTest, "registry1", "listening on", 20, 1) { 326 Skip("Cannot start docker registry.") 327 } 328 329 session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", server}) 330 session.WaitWithDefaultTimeout() 331 Expect(session).Should(ExitCleanly()) 332 333 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 334 session.WaitWithDefaultTimeout() 335 Expect(session).Should(ExitCleanly()) 336 337 session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"}) 338 session.WaitWithDefaultTimeout() 339 Expect(session).To(ExitWithError()) 340 Expect(session.ErrorToString()).To(ContainSubstring("/test-alpine: authentication required")) 341 342 session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "localhost:9001"}) 343 session.WaitWithDefaultTimeout() 344 Expect(session).Should(ExitCleanly()) 345 346 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 347 session.WaitWithDefaultTimeout() 348 Expect(session).Should(ExitCleanly()) 349 350 session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"}) 351 session.WaitWithDefaultTimeout() 352 Expect(session).Should(ExitCleanly()) 353 354 session = podmanTest.Podman([]string{"logout", server}) 355 session.WaitWithDefaultTimeout() 356 Expect(session).Should(ExitCleanly()) 357 358 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 359 session.WaitWithDefaultTimeout() 360 Expect(session).To(ExitWithError()) 361 Expect(session.ErrorToString()).To(ContainSubstring("/test-alpine: authentication required")) 362 363 session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"}) 364 session.WaitWithDefaultTimeout() 365 Expect(session).Should(ExitCleanly()) 366 367 session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "localhost:9001"}) 368 session.WaitWithDefaultTimeout() 369 Expect(session).Should(ExitCleanly()) 370 371 session = podmanTest.Podman([]string{"logout", "-a"}) 372 session.WaitWithDefaultTimeout() 373 Expect(session).Should(ExitCleanly()) 374 375 session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg}) 376 session.WaitWithDefaultTimeout() 377 Expect(session).To(ExitWithError()) 378 Expect(session.ErrorToString()).To(ContainSubstring("/test-alpine: authentication required")) 379 380 session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"}) 381 session.WaitWithDefaultTimeout() 382 Expect(session).To(ExitWithError()) 383 Expect(session.ErrorToString()).To(ContainSubstring("/test-alpine: authentication required")) 384 }) 385 386 It("podman login and logout with repository", func() { 387 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 388 389 testRepository := server + "/podmantest" 390 session := podmanTest.Podman([]string{ 391 "login", 392 "-u", "podmantest", 393 "-p", "test", 394 "--authfile", authFile, 395 testRepository, 396 }) 397 session.WaitWithDefaultTimeout() 398 Expect(session).Should(ExitCleanly()) 399 400 authInfo := readAuthInfo(authFile) 401 Expect(authInfo).To(HaveKey(testRepository)) 402 403 session = podmanTest.Podman([]string{ 404 "logout", 405 "--authfile", authFile, 406 testRepository, 407 }) 408 session.WaitWithDefaultTimeout() 409 Expect(session).Should(ExitCleanly()) 410 411 authInfo = readAuthInfo(authFile) 412 Expect(authInfo).NotTo(HaveKey(testRepository)) 413 }) 414 415 It("podman login and logout with repository and specified image", func() { 416 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 417 418 testTarget := server + "/podmantest/test-alpine" 419 session := podmanTest.Podman([]string{ 420 "login", 421 "-u", "podmantest", 422 "-p", "test", 423 "--authfile", authFile, 424 testTarget, 425 }) 426 session.WaitWithDefaultTimeout() 427 Expect(session).Should(ExitCleanly()) 428 429 authInfo := readAuthInfo(authFile) 430 Expect(authInfo).To(HaveKey(testTarget)) 431 432 session = podmanTest.Podman([]string{ 433 "push", "-q", 434 "--authfile", authFile, 435 ALPINE, testTarget, 436 }) 437 session.WaitWithDefaultTimeout() 438 Expect(session).Should(ExitCleanly()) 439 440 }) 441 442 It("podman login and logout with repository with fallback", func() { 443 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 444 445 testRepos := []string{ 446 server + "/podmantest", 447 server, 448 } 449 for _, testRepo := range testRepos { 450 session := podmanTest.Podman([]string{ 451 "login", 452 "-u", "podmantest", 453 "-p", "test", 454 "--authfile", authFile, 455 testRepo, 456 }) 457 session.WaitWithDefaultTimeout() 458 Expect(session).Should(ExitCleanly()) 459 } 460 461 authInfo := readAuthInfo(authFile) 462 Expect(authInfo).To(HaveKey(testRepos[0])) 463 Expect(authInfo).To(HaveKey(testRepos[1])) 464 465 session := podmanTest.Podman([]string{ 466 "push", "-q", 467 "--authfile", authFile, 468 ALPINE, testRepos[0] + "/test-image-alpine", 469 }) 470 session.WaitWithDefaultTimeout() 471 Expect(session).Should(ExitCleanly()) 472 473 session = podmanTest.Podman([]string{ 474 "logout", 475 "--authfile", authFile, 476 testRepos[0], 477 }) 478 session.WaitWithDefaultTimeout() 479 Expect(session).Should(ExitCleanly()) 480 481 session = podmanTest.Podman([]string{ 482 "push", "-q", 483 "--authfile", authFile, 484 ALPINE, testRepos[0] + "/test-image-alpine", 485 }) 486 session.WaitWithDefaultTimeout() 487 Expect(session).Should(ExitCleanly()) 488 489 session = podmanTest.Podman([]string{ 490 "logout", 491 "--authfile", authFile, 492 testRepos[1], 493 }) 494 session.WaitWithDefaultTimeout() 495 Expect(session).Should(ExitCleanly()) 496 497 authInfo = readAuthInfo(authFile) 498 Expect(authInfo).NotTo(HaveKey(testRepos[0])) 499 Expect(authInfo).NotTo(HaveKey(testRepos[1])) 500 }) 501 502 It("podman login with http{s} prefix", func() { 503 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 504 505 for _, invalidArg := range []string{ 506 "https://" + server + "/podmantest", 507 "http://" + server + "/podmantest/image:latest", 508 } { 509 session := podmanTest.Podman([]string{ 510 "login", 511 "-u", "podmantest", 512 "-p", "test", 513 "--authfile", authFile, 514 invalidArg, 515 }) 516 session.WaitWithDefaultTimeout() 517 Expect(session).To(ExitCleanly()) 518 } 519 }) 520 521 It("podman login and logout with repository push with invalid auth.json credentials", func() { 522 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 523 // only `server` contains the correct login data 524 err := os.WriteFile(authFile, []byte(fmt.Sprintf(`{"auths": { 525 "%s/podmantest": { "auth": "cG9kbWFudGVzdDp3cm9uZw==" }, 526 "%s": { "auth": "cG9kbWFudGVzdDp0ZXN0" } 527 }}`, server, server)), 0644) 528 Expect(err).ToNot(HaveOccurred()) 529 530 session := podmanTest.Podman([]string{ 531 "push", "-q", 532 "--authfile", authFile, 533 ALPINE, server + "/podmantest/test-image", 534 }) 535 session.WaitWithDefaultTimeout() 536 Expect(session).To(ExitWithError()) 537 Expect(session.ErrorToString()).To(ContainSubstring("/test-image: authentication required")) 538 539 session = podmanTest.Podman([]string{ 540 "push", "-q", 541 "--authfile", authFile, 542 ALPINE, server + "/test-image", 543 }) 544 session.WaitWithDefaultTimeout() 545 Expect(session).To(ExitCleanly()) 546 }) 547 548 It("podman login and logout with repository pull with wrong auth.json credentials", func() { 549 authFile := filepath.Join(podmanTest.TempDir, "auth.json") 550 551 testTarget := server + "/podmantest/test-alpine" 552 session := podmanTest.Podman([]string{ 553 "login", 554 "-u", "podmantest", 555 "-p", "test", 556 "--authfile", authFile, 557 testTarget, 558 }) 559 session.WaitWithDefaultTimeout() 560 Expect(session).Should(ExitCleanly()) 561 562 session = podmanTest.Podman([]string{ 563 "push", "-q", 564 "--authfile", authFile, 565 ALPINE, testTarget, 566 }) 567 session.WaitWithDefaultTimeout() 568 Expect(session).Should(ExitCleanly()) 569 570 // only `server + /podmantest` and `server` have the correct login data 571 err := os.WriteFile(authFile, []byte(fmt.Sprintf(`{"auths": { 572 "%s/podmantest/test-alpine": { "auth": "cG9kbWFudGVzdDp3cm9uZw==" }, 573 "%s/podmantest": { "auth": "cG9kbWFudGVzdDp0ZXN0" }, 574 "%s": { "auth": "cG9kbWFudGVzdDp0ZXN0" } 575 }}`, server, server, server)), 0644) 576 Expect(err).ToNot(HaveOccurred()) 577 578 session = podmanTest.Podman([]string{ 579 "pull", "-q", 580 "--authfile", authFile, 581 server + "/podmantest/test-alpine", 582 }) 583 session.WaitWithDefaultTimeout() 584 Expect(session).To(ExitWithError()) 585 Expect(session.ErrorToString()).To(ContainSubstring("/test-alpine: authentication required")) 586 }) 587 })