github.com/containers/podman/v5@v5.1.0-rc1/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/v5/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(125, ": authentication required"))
   126  	})
   127  
   128  	It("podman login and logout without registry parameter", func() {
   129  		registriesConf, err := os.CreateTemp("", "TestLoginWithoutParameter")
   130  		Expect(err).ToNot(HaveOccurred())
   131  		defer registriesConf.Close()
   132  		defer os.Remove(registriesConf.Name())
   133  
   134  		err = os.WriteFile(registriesConf.Name(), registriesConfWithSearch, os.ModePerm)
   135  		Expect(err).ToNot(HaveOccurred())
   136  
   137  		// Environment is per-process, so this looks very unsafe; actually it seems fine because tests are not
   138  		// run in parallel unless they opt in by calling t.Parallel().  So don’t do that.
   139  		oldRCP, hasRCP := os.LookupEnv("CONTAINERS_REGISTRIES_CONF")
   140  		defer func() {
   141  			if hasRCP {
   142  				os.Setenv("CONTAINERS_REGISTRIES_CONF", oldRCP)
   143  			} else {
   144  				os.Unsetenv("CONTAINERS_REGISTRIES_CONF")
   145  			}
   146  		}()
   147  		os.Setenv("CONTAINERS_REGISTRIES_CONF", registriesConf.Name())
   148  
   149  		session := podmanTest.Podman([]string{"login", "-u", "podmantest", "-p", "test"})
   150  		session.WaitWithDefaultTimeout()
   151  		Expect(session).Should(ExitCleanly())
   152  
   153  		session = podmanTest.Podman([]string{"logout"})
   154  		session.WaitWithDefaultTimeout()
   155  		Expect(session).Should(ExitCleanly())
   156  	})
   157  
   158  	It("podman login and logout with flag --authfile", func() {
   159  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   160  		session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--authfile", authFile, server})
   161  		session.WaitWithDefaultTimeout()
   162  		Expect(session).Should(ExitCleanly())
   163  
   164  		readAuthInfo(authFile)
   165  
   166  		// push should fail with nonexistent authfile
   167  		session = podmanTest.Podman([]string{"push", "-q", "--authfile", "/tmp/nonexistent", ALPINE, testImg})
   168  		session.WaitWithDefaultTimeout()
   169  		Expect(session).To(ExitWithError(125, "credential file is not accessible: faccessat /tmp/nonexistent: no such file or directory"))
   170  
   171  		session = podmanTest.Podman([]string{"push", "-q", "--authfile", authFile, ALPINE, testImg})
   172  		session.WaitWithDefaultTimeout()
   173  		Expect(session).Should(ExitCleanly())
   174  
   175  		session = podmanTest.Podman([]string{"run", "-q", "--authfile", authFile, testImg})
   176  		session.WaitWithDefaultTimeout()
   177  		Expect(session).Should(ExitCleanly())
   178  
   179  		// logout should fail with nonexistent authfile
   180  		session = podmanTest.Podman([]string{"logout", "--authfile", "/tmp/nonexistent", server})
   181  		session.WaitWithDefaultTimeout()
   182  		Expect(session).To(ExitWithError(125, "credential file is not accessible: faccessat /tmp/nonexistent: no such file or directory"))
   183  
   184  		session = podmanTest.Podman([]string{"logout", "--authfile", authFile, server})
   185  		session.WaitWithDefaultTimeout()
   186  		Expect(session).Should(ExitCleanly())
   187  	})
   188  
   189  	It("podman login and logout --compat-auth-file flag handling", func() {
   190  		// A minimal smoke test
   191  		compatAuthFile := filepath.Join(podmanTest.TempDir, "config.json")
   192  		session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--compat-auth-file", compatAuthFile, server})
   193  		session.WaitWithDefaultTimeout()
   194  		Expect(session).Should(ExitCleanly())
   195  
   196  		readAuthInfo(compatAuthFile)
   197  
   198  		session = podmanTest.Podman([]string{"logout", "--compat-auth-file", compatAuthFile, server})
   199  		session.WaitWithDefaultTimeout()
   200  		Expect(session).Should(ExitCleanly())
   201  
   202  		// logout should fail with nonexistent authfile
   203  		session = podmanTest.Podman([]string{"logout", "--compat-auth-file", "/tmp/nonexistent", server})
   204  		session.WaitWithDefaultTimeout()
   205  		Expect(session).To(ExitWithError(125, "credential file is not accessible: faccessat /tmp/nonexistent: no such file or directory"))
   206  
   207  		// inconsistent command line flags are rejected
   208  		// Pre-create the files to make sure we are not hitting the “file not found” path
   209  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   210  		err := os.WriteFile(authFile, []byte("{}"), 0o700)
   211  		Expect(err).ToNot(HaveOccurred())
   212  		err = os.WriteFile(compatAuthFile, []byte("{}"), 0o700)
   213  		Expect(err).ToNot(HaveOccurred())
   214  
   215  		session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test",
   216  			"--authfile", authFile, "--compat-auth-file", compatAuthFile, server})
   217  		session.WaitWithDefaultTimeout()
   218  		Expect(session).To(ExitWithError(125, "options for paths to the credential file and to the Docker-compatible credential file can not be set simultaneously"))
   219  
   220  		session = podmanTest.Podman([]string{"logout", "--authfile", authFile, "--compat-auth-file", compatAuthFile, server})
   221  		session.WaitWithDefaultTimeout()
   222  		Expect(session).To(ExitWithError(125, "options for paths to the credential file and to the Docker-compatible credential file can not be set simultaneously"))
   223  	})
   224  
   225  	It("podman manifest with --authfile", func() {
   226  		os.Unsetenv("REGISTRY_AUTH_FILE")
   227  
   228  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   229  		session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--authfile", authFile, server})
   230  		session.WaitWithDefaultTimeout()
   231  		Expect(session).Should(ExitCleanly())
   232  
   233  		readAuthInfo(authFile)
   234  
   235  		session = podmanTest.Podman([]string{"manifest", "create", testImg})
   236  		session.WaitWithDefaultTimeout()
   237  		Expect(session).Should(ExitCleanly())
   238  
   239  		session = podmanTest.Podman([]string{"manifest", "push", "-q", testImg})
   240  		session.WaitWithDefaultTimeout()
   241  		Expect(session).To(ExitWithError(125, ": authentication required"))
   242  
   243  		session = podmanTest.Podman([]string{"manifest", "push", "-q", "--authfile", authFile, testImg})
   244  		session.WaitWithDefaultTimeout()
   245  		Expect(session).Should(ExitCleanly())
   246  
   247  		// Now remove the local manifest to trigger remote inspection
   248  		session = podmanTest.Podman([]string{"manifest", "rm", testImg})
   249  		session.WaitWithDefaultTimeout()
   250  		Expect(session).Should(ExitCleanly())
   251  
   252  		session = podmanTest.Podman([]string{"manifest", "inspect", testImg})
   253  		session.WaitWithDefaultTimeout()
   254  		Expect(session).To(ExitWithError(125, ": authentication required"))
   255  
   256  		session = podmanTest.Podman([]string{"manifest", "inspect", "--authfile", authFile, testImg})
   257  		session.WaitWithDefaultTimeout()
   258  		Expect(session).Should(ExitCleanly())
   259  	})
   260  
   261  	It("podman login and logout with --tls-verify", func() {
   262  		session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--tls-verify=false", server})
   263  		session.WaitWithDefaultTimeout()
   264  		Expect(session).Should(ExitCleanly())
   265  
   266  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg})
   267  		session.WaitWithDefaultTimeout()
   268  		Expect(session).Should(ExitCleanly())
   269  
   270  		session = podmanTest.Podman([]string{"logout", server})
   271  		session.WaitWithDefaultTimeout()
   272  		Expect(session).Should(ExitCleanly())
   273  	})
   274  	It("podman login and logout with --cert-dir", func() {
   275  		certDir := filepath.Join(podmanTest.TempDir, "certs")
   276  		err := os.MkdirAll(certDir, os.ModePerm)
   277  		Expect(err).ToNot(HaveOccurred())
   278  
   279  		setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), filepath.Join(certDir, "ca.crt")})
   280  		setup.WaitWithDefaultTimeout()
   281  
   282  		session := podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "--cert-dir", certDir, server})
   283  		session.WaitWithDefaultTimeout()
   284  		Expect(session).Should(ExitCleanly())
   285  
   286  		session = podmanTest.Podman([]string{"push", "-q", "--cert-dir", certDir, ALPINE, testImg})
   287  		session.WaitWithDefaultTimeout()
   288  		Expect(session).Should(ExitCleanly())
   289  
   290  		session = podmanTest.Podman([]string{"logout", server})
   291  		session.WaitWithDefaultTimeout()
   292  		Expect(session).Should(ExitCleanly())
   293  	})
   294  	It("podman login and logout with multi registry", func() {
   295  		certDir := filepath.Join(os.Getenv("HOME"), ".config/containers/certs.d", "localhost:9001")
   296  		err = os.MkdirAll(certDir, os.ModePerm)
   297  		Expect(err).ToNot(HaveOccurred())
   298  
   299  		cwd, _ := os.Getwd()
   300  		certPath = filepath.Join(cwd, "../", "certs")
   301  
   302  		setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), filepath.Join(certDir, "ca.crt")})
   303  		setup.WaitWithDefaultTimeout()
   304  		defer os.RemoveAll(certDir)
   305  
   306  		// N/B: This second registry container shares the same auth and cert dirs
   307  		//      as the registry started from BeforeEach().  Since this one starts
   308  		//      second, re-labeling the volumes should keep SELinux happy.
   309  		session := podmanTest.Podman([]string{"run", "-d", "-p", "9001:9001", "-e", "REGISTRY_HTTP_ADDR=0.0.0.0:9001", "--name", "registry1", "-v",
   310  			strings.Join([]string{authPath, "/auth:z"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e",
   311  			"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
   312  			"-v", strings.Join([]string{certPath, "/certs:z"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt",
   313  			"-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", REGISTRY_IMAGE})
   314  		session.WaitWithDefaultTimeout()
   315  		Expect(session).Should(ExitCleanly())
   316  
   317  		if !WaitContainerReady(podmanTest, "registry1", "listening on", 20, 1) {
   318  			Skip("Cannot start docker registry.")
   319  		}
   320  
   321  		session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", server})
   322  		session.WaitWithDefaultTimeout()
   323  		Expect(session).Should(ExitCleanly())
   324  
   325  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg})
   326  		session.WaitWithDefaultTimeout()
   327  		Expect(session).Should(ExitCleanly())
   328  
   329  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"})
   330  		session.WaitWithDefaultTimeout()
   331  		Expect(session).To(ExitWithError(125, "/test-alpine: authentication required"))
   332  
   333  		session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "localhost:9001"})
   334  		session.WaitWithDefaultTimeout()
   335  		Expect(session).Should(ExitCleanly())
   336  
   337  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg})
   338  		session.WaitWithDefaultTimeout()
   339  		Expect(session).Should(ExitCleanly())
   340  
   341  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"})
   342  		session.WaitWithDefaultTimeout()
   343  		Expect(session).Should(ExitCleanly())
   344  
   345  		session = podmanTest.Podman([]string{"logout", server})
   346  		session.WaitWithDefaultTimeout()
   347  		Expect(session).Should(ExitCleanly())
   348  
   349  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg})
   350  		session.WaitWithDefaultTimeout()
   351  		Expect(session).To(ExitWithError(125, "/test-alpine: authentication required"))
   352  
   353  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"})
   354  		session.WaitWithDefaultTimeout()
   355  		Expect(session).Should(ExitCleanly())
   356  
   357  		session = podmanTest.Podman([]string{"login", "--username", "podmantest", "--password", "test", "localhost:9001"})
   358  		session.WaitWithDefaultTimeout()
   359  		Expect(session).Should(ExitCleanly())
   360  
   361  		session = podmanTest.Podman([]string{"logout", "-a"})
   362  		session.WaitWithDefaultTimeout()
   363  		Expect(session).Should(ExitCleanly())
   364  
   365  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, testImg})
   366  		session.WaitWithDefaultTimeout()
   367  		Expect(session).To(ExitWithError(125, "/test-alpine: authentication required"))
   368  
   369  		session = podmanTest.Podman([]string{"push", "-q", ALPINE, "localhost:9001/test-alpine"})
   370  		session.WaitWithDefaultTimeout()
   371  		Expect(session).To(ExitWithError(125, "/test-alpine: authentication required"))
   372  	})
   373  
   374  	It("podman login and logout with repository", func() {
   375  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   376  
   377  		testRepository := server + "/podmantest"
   378  		session := podmanTest.Podman([]string{
   379  			"login",
   380  			"-u", "podmantest",
   381  			"-p", "test",
   382  			"--authfile", authFile,
   383  			testRepository,
   384  		})
   385  		session.WaitWithDefaultTimeout()
   386  		Expect(session).Should(ExitCleanly())
   387  
   388  		authInfo := readAuthInfo(authFile)
   389  		Expect(authInfo).To(HaveKey(testRepository))
   390  
   391  		session = podmanTest.Podman([]string{
   392  			"logout",
   393  			"--authfile", authFile,
   394  			testRepository,
   395  		})
   396  		session.WaitWithDefaultTimeout()
   397  		Expect(session).Should(ExitCleanly())
   398  
   399  		authInfo = readAuthInfo(authFile)
   400  		Expect(authInfo).NotTo(HaveKey(testRepository))
   401  	})
   402  
   403  	It("podman login and logout with repository and specified image", func() {
   404  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   405  
   406  		testTarget := server + "/podmantest/test-alpine"
   407  		session := podmanTest.Podman([]string{
   408  			"login",
   409  			"-u", "podmantest",
   410  			"-p", "test",
   411  			"--authfile", authFile,
   412  			testTarget,
   413  		})
   414  		session.WaitWithDefaultTimeout()
   415  		Expect(session).Should(ExitCleanly())
   416  
   417  		authInfo := readAuthInfo(authFile)
   418  		Expect(authInfo).To(HaveKey(testTarget))
   419  
   420  		session = podmanTest.Podman([]string{
   421  			"push", "-q",
   422  			"--authfile", authFile,
   423  			ALPINE, testTarget,
   424  		})
   425  		session.WaitWithDefaultTimeout()
   426  		Expect(session).Should(ExitCleanly())
   427  
   428  	})
   429  
   430  	It("podman login and logout with repository with fallback", func() {
   431  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   432  
   433  		testRepos := []string{
   434  			server + "/podmantest",
   435  			server,
   436  		}
   437  		for _, testRepo := range testRepos {
   438  			session := podmanTest.Podman([]string{
   439  				"login",
   440  				"-u", "podmantest",
   441  				"-p", "test",
   442  				"--authfile", authFile,
   443  				testRepo,
   444  			})
   445  			session.WaitWithDefaultTimeout()
   446  			Expect(session).Should(ExitCleanly())
   447  		}
   448  
   449  		authInfo := readAuthInfo(authFile)
   450  		Expect(authInfo).To(HaveKey(testRepos[0]))
   451  		Expect(authInfo).To(HaveKey(testRepos[1]))
   452  
   453  		session := podmanTest.Podman([]string{
   454  			"push", "-q",
   455  			"--authfile", authFile,
   456  			ALPINE, testRepos[0] + "/test-image-alpine",
   457  		})
   458  		session.WaitWithDefaultTimeout()
   459  		Expect(session).Should(ExitCleanly())
   460  
   461  		session = podmanTest.Podman([]string{
   462  			"logout",
   463  			"--authfile", authFile,
   464  			testRepos[0],
   465  		})
   466  		session.WaitWithDefaultTimeout()
   467  		Expect(session).Should(ExitCleanly())
   468  
   469  		session = podmanTest.Podman([]string{
   470  			"push", "-q",
   471  			"--authfile", authFile,
   472  			ALPINE, testRepos[0] + "/test-image-alpine",
   473  		})
   474  		session.WaitWithDefaultTimeout()
   475  		Expect(session).Should(ExitCleanly())
   476  
   477  		session = podmanTest.Podman([]string{
   478  			"logout",
   479  			"--authfile", authFile,
   480  			testRepos[1],
   481  		})
   482  		session.WaitWithDefaultTimeout()
   483  		Expect(session).Should(ExitCleanly())
   484  
   485  		authInfo = readAuthInfo(authFile)
   486  		Expect(authInfo).NotTo(HaveKey(testRepos[0]))
   487  		Expect(authInfo).NotTo(HaveKey(testRepos[1]))
   488  	})
   489  
   490  	It("podman login with http{s} prefix", func() {
   491  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   492  
   493  		for _, invalidArg := range []string{
   494  			"https://" + server + "/podmantest",
   495  			"http://" + server + "/podmantest/image:latest",
   496  		} {
   497  			session := podmanTest.Podman([]string{
   498  				"login",
   499  				"-u", "podmantest",
   500  				"-p", "test",
   501  				"--authfile", authFile,
   502  				invalidArg,
   503  			})
   504  			session.WaitWithDefaultTimeout()
   505  			Expect(session).To(ExitCleanly())
   506  		}
   507  	})
   508  
   509  	It("podman login and logout with repository push with invalid auth.json credentials", func() {
   510  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   511  		// only `server` contains the correct login data
   512  		err := os.WriteFile(authFile, []byte(fmt.Sprintf(`{"auths": {
   513  			"%s/podmantest": { "auth": "cG9kbWFudGVzdDp3cm9uZw==" },
   514  			"%s": { "auth": "cG9kbWFudGVzdDp0ZXN0" }
   515  		}}`, server, server)), 0644)
   516  		Expect(err).ToNot(HaveOccurred())
   517  
   518  		session := podmanTest.Podman([]string{
   519  			"push", "-q",
   520  			"--authfile", authFile,
   521  			ALPINE, server + "/podmantest/test-image",
   522  		})
   523  		session.WaitWithDefaultTimeout()
   524  		Expect(session).To(ExitWithError(125, "/test-image: authentication required"))
   525  
   526  		session = podmanTest.Podman([]string{
   527  			"push", "-q",
   528  			"--authfile", authFile,
   529  			ALPINE, server + "/test-image",
   530  		})
   531  		session.WaitWithDefaultTimeout()
   532  		Expect(session).To(ExitCleanly())
   533  	})
   534  
   535  	It("podman login and logout with repository pull with wrong auth.json credentials", func() {
   536  		authFile := filepath.Join(podmanTest.TempDir, "auth.json")
   537  
   538  		testTarget := server + "/podmantest/test-alpine"
   539  		session := podmanTest.Podman([]string{
   540  			"login",
   541  			"-u", "podmantest",
   542  			"-p", "test",
   543  			"--authfile", authFile,
   544  			testTarget,
   545  		})
   546  		session.WaitWithDefaultTimeout()
   547  		Expect(session).Should(ExitCleanly())
   548  
   549  		session = podmanTest.Podman([]string{
   550  			"push", "-q",
   551  			"--authfile", authFile,
   552  			ALPINE, testTarget,
   553  		})
   554  		session.WaitWithDefaultTimeout()
   555  		Expect(session).Should(ExitCleanly())
   556  
   557  		// only `server + /podmantest` and `server` have the correct login data
   558  		err := os.WriteFile(authFile, []byte(fmt.Sprintf(`{"auths": {
   559  			"%s/podmantest/test-alpine": { "auth": "cG9kbWFudGVzdDp3cm9uZw==" },
   560  			"%s/podmantest": { "auth": "cG9kbWFudGVzdDp0ZXN0" },
   561  			"%s": { "auth": "cG9kbWFudGVzdDp0ZXN0" }
   562  		}}`, server, server, server)), 0644)
   563  		Expect(err).ToNot(HaveOccurred())
   564  
   565  		session = podmanTest.Podman([]string{
   566  			"pull", "-q",
   567  			"--authfile", authFile,
   568  			server + "/podmantest/test-alpine",
   569  		})
   570  		session.WaitWithDefaultTimeout()
   571  		Expect(session).To(ExitWithError(125, "/test-alpine: authentication required"))
   572  	})
   573  })