浏览代码

integration-cli: add suite for testing registries with auth

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
Antonio Murdaca 9 年之前
父节点
当前提交
011b4f01f4
共有 4 个文件被更改,包括 92 次插入16 次删除
  1. 33 3
      integration-cli/check_test.go
  2. 9 0
      integration-cli/docker_cli_login_test.go
  3. 2 2
      integration-cli/docker_utils.go
  4. 48 11
      integration-cli/registry.go

+ 33 - 3
integration-cli/check_test.go

@@ -49,7 +49,7 @@ type DockerRegistrySuite struct {
 
 
 func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
 func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	s.reg = setupRegistry(c, false)
+	s.reg = setupRegistry(c, false, false)
 	s.d = NewDaemon(c)
 	s.d = NewDaemon(c)
 }
 }
 
 
@@ -77,7 +77,7 @@ type DockerSchema1RegistrySuite struct {
 
 
 func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
 func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
 	testRequires(c, DaemonIsLinux)
 	testRequires(c, DaemonIsLinux)
-	s.reg = setupRegistry(c, true)
+	s.reg = setupRegistry(c, true, false)
 	s.d = NewDaemon(c)
 	s.d = NewDaemon(c)
 }
 }
 
 
@@ -91,6 +91,36 @@ func (s *DockerSchema1RegistrySuite) TearDownTest(c *check.C) {
 	s.ds.TearDownTest(c)
 	s.ds.TearDownTest(c)
 }
 }
 
 
+func init() {
+	check.Suite(&DockerRegistryAuthSuite{
+		ds: &DockerSuite{},
+	})
+}
+
+type DockerRegistryAuthSuite struct {
+	ds  *DockerSuite
+	reg *testRegistryV2
+	d   *Daemon
+}
+
+func (s *DockerRegistryAuthSuite) SetUpTest(c *check.C) {
+	testRequires(c, DaemonIsLinux)
+	s.reg = setupRegistry(c, false, true)
+	s.d = NewDaemon(c)
+}
+
+func (s *DockerRegistryAuthSuite) TearDownTest(c *check.C) {
+	if s.reg != nil {
+		out, err := s.d.Cmd("logout", privateRegistryURL)
+		c.Assert(err, check.IsNil, check.Commentf(out))
+		s.reg.Close()
+	}
+	if s.d != nil {
+		s.d.Stop()
+	}
+	s.ds.TearDownTest(c)
+}
+
 func init() {
 func init() {
 	check.Suite(&DockerDaemonSuite{
 	check.Suite(&DockerDaemonSuite{
 		ds: &DockerSuite{},
 		ds: &DockerSuite{},
@@ -128,7 +158,7 @@ type DockerTrustSuite struct {
 }
 }
 
 
 func (s *DockerTrustSuite) SetUpTest(c *check.C) {
 func (s *DockerTrustSuite) SetUpTest(c *check.C) {
-	s.reg = setupRegistry(c, false)
+	s.reg = setupRegistry(c, false, false)
 	s.not = setupNotary(c)
 	s.not = setupNotary(c)
 }
 }
 
 

+ 9 - 0
integration-cli/docker_cli_login_test.go

@@ -17,5 +17,14 @@ func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
 	// run the command and block until it's done
 	// run the command and block until it's done
 	err := cmd.Run()
 	err := cmd.Run()
 	c.Assert(err, checker.NotNil) //"Expected non nil err when loginning in & TTY not available"
 	c.Assert(err, checker.NotNil) //"Expected non nil err when loginning in & TTY not available"
+}
+
+func (s *DockerRegistryAuthSuite) TestLoginToPrivateRegistry(c *check.C) {
+	// wrong credentials
+	out, _, err := dockerCmdWithError("login", "-u", s.reg.username, "-p", "WRONGPASSWORD", "-e", s.reg.email, privateRegistryURL)
+	c.Assert(err, checker.NotNil, check.Commentf(out))
+	c.Assert(out, checker.Contains, "401 Unauthorized")
 
 
+	// now it's fine
+	dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL)
 }
 }

+ 2 - 2
integration-cli/docker_utils.go

@@ -1554,9 +1554,9 @@ func daemonTime(c *check.C) time.Time {
 	return dt
 	return dt
 }
 }
 
 
-func setupRegistry(c *check.C, schema1 bool) *testRegistryV2 {
+func setupRegistry(c *check.C, schema1, auth bool) *testRegistryV2 {
 	testRequires(c, RegistryHosting)
 	testRequires(c, RegistryHosting)
-	reg, err := newTestRegistryV2(c, schema1)
+	reg, err := newTestRegistryV2(c, schema1, auth)
 	c.Assert(err, check.IsNil)
 	c.Assert(err, check.IsNil)
 
 
 	// Wait for registry to be ready to serve requests.
 	// Wait for registry to be ready to serve requests.

+ 48 - 11
integration-cli/registry.go

@@ -18,28 +18,55 @@ const (
 )
 )
 
 
 type testRegistryV2 struct {
 type testRegistryV2 struct {
-	cmd *exec.Cmd
-	dir string
+	cmd      *exec.Cmd
+	dir      string
+	username string
+	password string
+	email    string
 }
 }
 
 
-func newTestRegistryV2(c *check.C, schema1 bool) (*testRegistryV2, error) {
+func newTestRegistryV2(c *check.C, schema1, auth bool) (*testRegistryV2, error) {
+	tmp, err := ioutil.TempDir("", "registry-test-")
+	if err != nil {
+		return nil, err
+	}
 	template := `version: 0.1
 	template := `version: 0.1
 loglevel: debug
 loglevel: debug
 storage:
 storage:
     filesystem:
     filesystem:
         rootdirectory: %s
         rootdirectory: %s
 http:
 http:
-    addr: %s`
-	tmp, err := ioutil.TempDir("", "registry-test-")
-	if err != nil {
-		return nil, err
+    addr: %s
+%s`
+	var (
+		htpasswd string
+		username string
+		password string
+		email    string
+	)
+	if auth {
+		htpasswdPath := filepath.Join(tmp, "htpasswd")
+		// generated with: htpasswd -Bbn testuser testpassword
+		userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m"
+		username = "testuser"
+		password = "testpassword"
+		email = "test@test.org"
+		if err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644)); err != nil {
+			return nil, err
+		}
+		htpasswd = fmt.Sprintf(`auth:
+    htpasswd:
+        realm: basic-realm
+        path: %s
+`, htpasswdPath)
 	}
 	}
+
 	confPath := filepath.Join(tmp, "config.yaml")
 	confPath := filepath.Join(tmp, "config.yaml")
 	config, err := os.Create(confPath)
 	config, err := os.Create(confPath)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL); err != nil {
+	if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL, htpasswd); err != nil {
 		os.RemoveAll(tmp)
 		os.RemoveAll(tmp)
 		return nil, err
 		return nil, err
 	}
 	}
@@ -57,8 +84,11 @@ http:
 		return nil, err
 		return nil, err
 	}
 	}
 	return &testRegistryV2{
 	return &testRegistryV2{
-		cmd: cmd,
-		dir: tmp,
+		cmd:      cmd,
+		dir:      tmp,
+		username: username,
+		password: password,
+		email:    email,
 	}, nil
 	}, nil
 }
 }
 
 
@@ -68,7 +98,14 @@ func (t *testRegistryV2) Ping() error {
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	if resp.StatusCode != http.StatusOK {
+	resp.Body.Close()
+
+	fail := resp.StatusCode != http.StatusOK
+	if t.username != "" {
+		// unauthorized is a _good_ status when pinging v2/ and it needs auth
+		fail = fail && resp.StatusCode != http.StatusUnauthorized
+	}
+	if fail {
 		return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
 		return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
 	}
 	}
 	return nil
 	return nil