diff --git a/test/e2e/internal/utils/exec.go b/test/e2e/internal/utils/exec.go index b827ba019..8e26d75dc 100644 --- a/test/e2e/internal/utils/exec.go +++ b/test/e2e/internal/utils/exec.go @@ -34,10 +34,9 @@ const ( orasBinary = "oras" // customize your own basic auth file via `htpasswd -cBb ` - Username = "hello" - Password = "oras-test" - AuthConfigPath = "test.config" - DefaultTimeout = 10 * time.Second + Username = "hello" + Password = "oras-test" + DefaultTimeout = 10 * time.Second // If the command hasn't exited yet, ginkgo session ExitCode is -1 notResponding = -1 ) diff --git a/test/e2e/internal/utils/testdata.go b/test/e2e/internal/utils/testdata.go index 400164387..e3f3d37fd 100644 --- a/test/e2e/internal/utils/testdata.go +++ b/test/e2e/internal/utils/testdata.go @@ -16,13 +16,14 @@ limitations under the License. package utils const ( - PreviewDesc = "** This command is in preview and under development. **" - ExampleDesc = "\nExample - " - ImageRepo = "command/images" - BlobRepo = "command/blobs" - ArtifactRepo = "command/artifacts" - Namespace = "command" - InvalidRepo = "INVALID" + PreviewDesc = "** This command is in preview and under development. **" + ExampleDesc = "\nExample - " + ImageRepo = "command/images" + BlobRepo = "command/blobs" + ArtifactRepo = "command/artifacts" + Namespace = "command" + InvalidRepo = "INVALID" + LegacyConfigName = "legacy.config" // env RegHostKey = "ORAS_REGISTRY_HOST" FallbackRegHostKey = "ORAS_REGISTRY_FALLBACK_HOST" diff --git a/test/e2e/suite/auth/auth.go b/test/e2e/suite/auth/auth.go index 7852c7873..1d21b7fc4 100644 --- a/test/e2e/suite/auth/auth.go +++ b/test/e2e/suite/auth/auth.go @@ -17,49 +17,47 @@ package scenario import ( "fmt" + "path/filepath" "strings" "time" . "github.com/onsi/ginkgo/v2" + "oras.land/oras-go/v2" + "oras.land/oras/test/e2e/internal/testdata/foobar" . "oras.land/oras/test/e2e/internal/utils" ) -var _ = Describe("Common registry user", Ordered, func() { - When("logging out", Ordered, func() { - It("should use logout command to logout", func() { - ORAS("logout", ZOTHost, "--registry-config", AuthConfigPath).Exec() - }) - +var _ = Describe("Common registry user", func() { + When("not logged in", func() { It("should run commands without logging in", func() { - RunWithoutLogin("attach", ZOTHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example") - ORAS("copy", ZOTHost+"/repo:from", ZOTHost+"/repo:to", "--from-registry-config", AuthConfigPath, "--to-registry-config", AuthConfigPath). - ExpectFailure(). - MatchErrKeyWords("Error:", "credential required"). - WithDescription("fail without logging in").Exec() - RunWithoutLogin("discover", ZOTHost+"/repo:tag") - RunWithoutLogin("push", "-a", "key=value", ZOTHost+"/repo:tag") - RunWithoutLogin("pull", ZOTHost+"/repo:tag") - RunWithoutLogin("manifest", "fetch", ZOTHost+"/repo:tag") - RunWithoutLogin("blob", "delete", ZOTHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - RunWithoutLogin("blob", "push", ZOTHost+"/repo", WriteTempFile("blob", "test")) - RunWithoutLogin("tag", ZOTHost+"/repo:tag", "tag1") - RunWithoutLogin("resolve", ZOTHost+"/repo:tag") - RunWithoutLogin("repo", "ls", ZOTHost) - RunWithoutLogin("repo", "tags", RegistryRef(ZOTHost, "repo", "")) - RunWithoutLogin("manifest", "fetch-config", ZOTHost+"/repo:tag") + authConfigPath := filepath.Join(GinkgoT().TempDir(), "auth.config") + RunWithoutLogin("attach", ZOTHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example", "--registry-config", authConfigPath) + RunWithoutLogin("copy", ZOTHost+"/repo:from", ZOTHost+"/repo:to", "--from-registry-config", authConfigPath, "--to-registry-config", authConfigPath) + RunWithoutLogin("discover", ZOTHost+"/repo:tag", "--registry-config", authConfigPath) + RunWithoutLogin("push", "-a", "key=value", ZOTHost+"/repo:tag", "--registry-config", authConfigPath) + RunWithoutLogin("pull", ZOTHost+"/repo:tag", "--registry-config", authConfigPath) + RunWithoutLogin("manifest", "fetch", ZOTHost+"/repo:tag", "--registry-config", authConfigPath) + RunWithoutLogin("blob", "delete", ZOTHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "--registry-config", authConfigPath) + RunWithoutLogin("blob", "push", ZOTHost+"/repo", WriteTempFile("blob", "test"), "--registry-config", authConfigPath) + RunWithoutLogin("tag", ZOTHost+"/repo:tag", "tag1", "--registry-config", authConfigPath) + RunWithoutLogin("resolve", ZOTHost+"/repo:tag", "--registry-config", authConfigPath) + RunWithoutLogin("repo", "ls", ZOTHost, "--registry-config", authConfigPath) + RunWithoutLogin("repo", "tags", RegistryRef(ZOTHost, "repo", ""), "--registry-config", authConfigPath) + RunWithoutLogin("manifest", "fetch-config", ZOTHost+"/repo:tag", "--registry-config", authConfigPath) }) }) When("logging in", func() { - It("should use basic auth", func() { - ORAS("login", ZOTHost, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath). + tmpConfigName := "test.config" + It("should succeed to use basic auth", func() { + ORAS("login", ZOTHost, "-u", Username, "-p", Password, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20*time.Second). MatchContent("Login Succeeded\n"). MatchErrKeyWords("WARNING", "Using --password via the CLI is insecure", "Use --password-stdin").Exec() }) It("should fail if no username input", func() { - ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20 * time.Second). WithInput(strings.NewReader("")). MatchKeyWords("username:"). @@ -68,14 +66,14 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should fail if no password input", func() { - ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Password: "). WithInput(strings.NewReader(fmt.Sprintf("%s\n", Username))).ExpectFailure().Exec() }) It("should fail if password is empty", func() { - ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Password: "). MatchErrKeyWords("Error: password required"). @@ -83,32 +81,41 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should fail if no token input", func() { - ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Token: "). WithInput(strings.NewReader("\n")).ExpectFailure().Exec() }) It("should fail if token is empty", func() { - ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Token: "). MatchErrKeyWords("Error: token required"). WithInput(strings.NewReader("\n\n")).ExpectFailure().Exec() }) - It("should use prompted input", func() { - ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). + It("should succeed to use prompted input", func() { + ORAS("login", ZOTHost, "--registry-config", filepath.Join(GinkgoT().TempDir(), tmpConfigName)). WithTimeOut(20*time.Second). WithInput(strings.NewReader(fmt.Sprintf("%s\n%s\n", Username, Password))). MatchKeyWords("Username: ", "Password: ", "Login Succeeded\n").Exec() }) }) + + When("using legacy config", func() { + var LegacyConfigPath = filepath.Join(TestDataRoot, LegacyConfigName) + It("should succeed to copy", func() { + src := RegistryRef(ZOTHost, ArtifactRepo, foobar.Tag) + dst := RegistryRef(ZOTHost, fmt.Sprintf("command/auth/%d/copy", GinkgoRandomSeed()), foobar.Tag) + foobarStates := append(foobar.ImageLayerStateKeys, foobar.ManifestStateKey, foobar.ImageConfigStateKey(oras.MediaTypeUnknownConfig)) + ORAS("cp", src, dst, "-v", "--from-registry-config", LegacyConfigPath, "--to-registry-config", LegacyConfigPath).MatchStatus(foobarStates, true, len(foobarStates)).Exec() + }) + }) }) func RunWithoutLogin(args ...string) { - ORAS(append(args, "--registry-config", AuthConfigPath)...). - ExpectFailure(). + ORAS(args...).ExpectFailure(). MatchErrKeyWords("Error:", "credential required"). WithDescription("fail without logging in").Exec() } diff --git a/test/e2e/suite/command/custom_header.go b/test/e2e/suite/command/custom_header.go index 1920ef14d..c8972fc64 100644 --- a/test/e2e/suite/command/custom_header.go +++ b/test/e2e/suite/command/custom_header.go @@ -17,6 +17,7 @@ package command import ( "fmt" + "path/filepath" . "github.com/onsi/ginkgo/v2" "oras.land/oras/test/e2e/internal/testdata/foobar" @@ -80,7 +81,7 @@ var _ = Describe("1.1 registry users:", func() { MatchRequestHeaders(FoobarHeader, AbHeader).Exec() }) It("login", func() { - ORAS("login", Host, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath, + ORAS("login", Host, "-u", Username, "-p", Password, "--registry-config", filepath.Join(GinkgoT().TempDir(), "test.config"), "-H", FoobarHeaderInput, "-H", AbHeaderInput). MatchRequestHeaders(FoobarHeader, AbHeader).Exec() }) diff --git a/test/e2e/testdata/legacy.config b/test/e2e/testdata/legacy.config new file mode 100644 index 000000000..42b6ba17e --- /dev/null +++ b/test/e2e/testdata/legacy.config @@ -0,0 +1,7 @@ +{ + "auths": { + "http://localhost:7000/": { + "auth": "aGVsbG86b3Jhcy10ZXN0" + } + } +} \ No newline at end of file