Browse code

integration-cli: add suite for testing registries with auth

Signed-off-by: Antonio Murdaca <runcom@redhat.com>

Antonio Murdaca authored on 2016/01/24 03:45:01
Showing 4 changed files
... ...
@@ -49,7 +49,7 @@ type DockerRegistrySuite struct {
49 49
 
50 50
 func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
51 51
 	testRequires(c, DaemonIsLinux)
52
-	s.reg = setupRegistry(c, false)
52
+	s.reg = setupRegistry(c, false, false)
53 53
 	s.d = NewDaemon(c)
54 54
 }
55 55
 
... ...
@@ -77,7 +77,7 @@ type DockerSchema1RegistrySuite struct {
77 77
 
78 78
 func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) {
79 79
 	testRequires(c, DaemonIsLinux)
80
-	s.reg = setupRegistry(c, true)
80
+	s.reg = setupRegistry(c, true, false)
81 81
 	s.d = NewDaemon(c)
82 82
 }
83 83
 
... ...
@@ -92,6 +92,36 @@ func (s *DockerSchema1RegistrySuite) TearDownTest(c *check.C) {
92 92
 }
93 93
 
94 94
 func init() {
95
+	check.Suite(&DockerRegistryAuthSuite{
96
+		ds: &DockerSuite{},
97
+	})
98
+}
99
+
100
+type DockerRegistryAuthSuite struct {
101
+	ds  *DockerSuite
102
+	reg *testRegistryV2
103
+	d   *Daemon
104
+}
105
+
106
+func (s *DockerRegistryAuthSuite) SetUpTest(c *check.C) {
107
+	testRequires(c, DaemonIsLinux)
108
+	s.reg = setupRegistry(c, false, true)
109
+	s.d = NewDaemon(c)
110
+}
111
+
112
+func (s *DockerRegistryAuthSuite) TearDownTest(c *check.C) {
113
+	if s.reg != nil {
114
+		out, err := s.d.Cmd("logout", privateRegistryURL)
115
+		c.Assert(err, check.IsNil, check.Commentf(out))
116
+		s.reg.Close()
117
+	}
118
+	if s.d != nil {
119
+		s.d.Stop()
120
+	}
121
+	s.ds.TearDownTest(c)
122
+}
123
+
124
+func init() {
95 125
 	check.Suite(&DockerDaemonSuite{
96 126
 		ds: &DockerSuite{},
97 127
 	})
... ...
@@ -128,7 +158,7 @@ type DockerTrustSuite struct {
128 128
 }
129 129
 
130 130
 func (s *DockerTrustSuite) SetUpTest(c *check.C) {
131
-	s.reg = setupRegistry(c, false)
131
+	s.reg = setupRegistry(c, false, false)
132 132
 	s.not = setupNotary(c)
133 133
 }
134 134
 
... ...
@@ -17,5 +17,14 @@ func (s *DockerSuite) TestLoginWithoutTTY(c *check.C) {
17 17
 	// run the command and block until it's done
18 18
 	err := cmd.Run()
19 19
 	c.Assert(err, checker.NotNil) //"Expected non nil err when loginning in & TTY not available"
20
+}
21
+
22
+func (s *DockerRegistryAuthSuite) TestLoginToPrivateRegistry(c *check.C) {
23
+	// wrong credentials
24
+	out, _, err := dockerCmdWithError("login", "-u", s.reg.username, "-p", "WRONGPASSWORD", "-e", s.reg.email, privateRegistryURL)
25
+	c.Assert(err, checker.NotNil, check.Commentf(out))
26
+	c.Assert(out, checker.Contains, "401 Unauthorized")
20 27
 
28
+	// now it's fine
29
+	dockerCmd(c, "login", "-u", s.reg.username, "-p", s.reg.password, "-e", s.reg.email, privateRegistryURL)
21 30
 }
... ...
@@ -1554,9 +1554,9 @@ func daemonTime(c *check.C) time.Time {
1554 1554
 	return dt
1555 1555
 }
1556 1556
 
1557
-func setupRegistry(c *check.C, schema1 bool) *testRegistryV2 {
1557
+func setupRegistry(c *check.C, schema1, auth bool) *testRegistryV2 {
1558 1558
 	testRequires(c, RegistryHosting)
1559
-	reg, err := newTestRegistryV2(c, schema1)
1559
+	reg, err := newTestRegistryV2(c, schema1, auth)
1560 1560
 	c.Assert(err, check.IsNil)
1561 1561
 
1562 1562
 	// Wait for registry to be ready to serve requests.
... ...
@@ -18,28 +18,55 @@ const (
18 18
 )
19 19
 
20 20
 type testRegistryV2 struct {
21
-	cmd *exec.Cmd
22
-	dir string
21
+	cmd      *exec.Cmd
22
+	dir      string
23
+	username string
24
+	password string
25
+	email    string
23 26
 }
24 27
 
25
-func newTestRegistryV2(c *check.C, schema1 bool) (*testRegistryV2, error) {
28
+func newTestRegistryV2(c *check.C, schema1, auth bool) (*testRegistryV2, error) {
29
+	tmp, err := ioutil.TempDir("", "registry-test-")
30
+	if err != nil {
31
+		return nil, err
32
+	}
26 33
 	template := `version: 0.1
27 34
 loglevel: debug
28 35
 storage:
29 36
     filesystem:
30 37
         rootdirectory: %s
31 38
 http:
32
-    addr: %s`
33
-	tmp, err := ioutil.TempDir("", "registry-test-")
34
-	if err != nil {
35
-		return nil, err
39
+    addr: %s
40
+%s`
41
+	var (
42
+		htpasswd string
43
+		username string
44
+		password string
45
+		email    string
46
+	)
47
+	if auth {
48
+		htpasswdPath := filepath.Join(tmp, "htpasswd")
49
+		// generated with: htpasswd -Bbn testuser testpassword
50
+		userpasswd := "testuser:$2y$05$sBsSqk0OpSD1uTZkHXc4FeJ0Z70wLQdAX/82UiHuQOKbNbBrzs63m"
51
+		username = "testuser"
52
+		password = "testpassword"
53
+		email = "test@test.org"
54
+		if err := ioutil.WriteFile(htpasswdPath, []byte(userpasswd), os.FileMode(0644)); err != nil {
55
+			return nil, err
56
+		}
57
+		htpasswd = fmt.Sprintf(`auth:
58
+    htpasswd:
59
+        realm: basic-realm
60
+        path: %s
61
+`, htpasswdPath)
36 62
 	}
63
+
37 64
 	confPath := filepath.Join(tmp, "config.yaml")
38 65
 	config, err := os.Create(confPath)
39 66
 	if err != nil {
40 67
 		return nil, err
41 68
 	}
42
-	if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL); err != nil {
69
+	if _, err := fmt.Fprintf(config, template, tmp, privateRegistryURL, htpasswd); err != nil {
43 70
 		os.RemoveAll(tmp)
44 71
 		return nil, err
45 72
 	}
... ...
@@ -57,8 +84,11 @@ http:
57 57
 		return nil, err
58 58
 	}
59 59
 	return &testRegistryV2{
60
-		cmd: cmd,
61
-		dir: tmp,
60
+		cmd:      cmd,
61
+		dir:      tmp,
62
+		username: username,
63
+		password: password,
64
+		email:    email,
62 65
 	}, nil
63 66
 }
64 67
 
... ...
@@ -68,7 +98,14 @@ func (t *testRegistryV2) Ping() error {
68 68
 	if err != nil {
69 69
 		return err
70 70
 	}
71
-	if resp.StatusCode != http.StatusOK {
71
+	resp.Body.Close()
72
+
73
+	fail := resp.StatusCode != http.StatusOK
74
+	if t.username != "" {
75
+		// unauthorized is a _good_ status when pinging v2/ and it needs auth
76
+		fail = fail && resp.StatusCode != http.StatusUnauthorized
77
+	}
78
+	if fail {
72 79
 		return fmt.Errorf("registry ping replied with an unexpected status code %d", resp.StatusCode)
73 80
 	}
74 81
 	return nil