Просмотр исходного кода

Merge pull request #21556 from twistlock/basic_authn_client_cert

Extend Docker authorization with TLS user information
David Calavera 9 лет назад
Родитель
Сommit
dd757deae0

+ 11 - 3
api/server/middleware/authorization.go

@@ -13,11 +13,19 @@ import (
 func NewAuthorizationMiddleware(plugins []authorization.Plugin) Middleware {
 	return func(handler httputils.APIFunc) httputils.APIFunc {
 		return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
-			// FIXME: fill when authN gets in
-			// User and UserAuthNMethod are taken from AuthN plugins
-			// Currently tracked in https://github.com/docker/docker/pull/13994
+
 			user := ""
 			userAuthNMethod := ""
+
+			// Default authorization using existing TLS connection credentials
+			// FIXME: Non trivial authorization mechanisms (such as advanced certificate validations, kerberos support
+			// and ldap) will be extracted using AuthN feature, which is tracked under:
+			// https://github.com/docker/docker/pull/20883
+			if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
+				user = r.TLS.PeerCertificates[0].Subject.CommonName
+				userAuthNMethod = "TLS"
+			}
+
 			authCtx := authorization.NewCtx(plugins, user, userAuthNMethod, r.Method, r.RequestURI)
 
 			if err := authCtx.AuthZRequest(w, r); err != nil {

+ 43 - 0
integration-cli/docker_cli_authz_unix_test.go

@@ -53,6 +53,8 @@ type authorizationController struct {
 	psRequestCnt  int                    // psRequestCnt counts the number of calls to list container request api
 	psResponseCnt int                    // psResponseCnt counts the number of calls to list containers response API
 	requestsURIs  []string               // requestsURIs stores all request URIs that are sent to the authorization controller
+	reqUser       string
+	resUser       string
 }
 
 func (s *DockerAuthzSuite) SetUpTest(c *check.C) {
@@ -104,6 +106,7 @@ func (s *DockerAuthzSuite) SetUpSuite(c *check.C) {
 		}
 		b, err := json.Marshal(reqRes)
 		c.Assert(err, check.IsNil)
+		s.ctrl.reqUser = authReq.User
 		w.Write(b)
 	})
 
@@ -131,6 +134,7 @@ func (s *DockerAuthzSuite) SetUpSuite(c *check.C) {
 		}
 		b, err := json.Marshal(resRes)
 		c.Assert(err, check.IsNil)
+		s.ctrl.resUser = authReq.User
 		w.Write(b)
 	})
 
@@ -213,6 +217,45 @@ func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) {
 	c.Assert(s.ctrl.psResponseCnt, check.Equals, 1)
 }
 
+func (s *DockerAuthzSuite) TestAuthZPluginTls(c *check.C) {
+
+	const testDaemonHTTPSAddr = "tcp://localhost:4271"
+	// start the daemon and load busybox, --net=none build fails otherwise
+	// cause it needs to pull busybox
+	if err := s.d.Start(
+		"--authorization-plugin="+testAuthZPlugin,
+		"--tlsverify",
+		"--tlscacert",
+		"fixtures/https/ca.pem",
+		"--tlscert",
+		"fixtures/https/server-cert.pem",
+		"--tlskey",
+		"fixtures/https/server-key.pem",
+		"-H", testDaemonHTTPSAddr); err != nil {
+		c.Fatalf("Could not start daemon with busybox: %v", err)
+	}
+
+	s.ctrl.reqRes.Allow = true
+	s.ctrl.resRes.Allow = true
+
+	out, _ := dockerCmd(
+		c,
+		"--tlsverify",
+		"--tlscacert", "fixtures/https/ca.pem",
+		"--tlscert", "fixtures/https/client-cert.pem",
+		"--tlskey", "fixtures/https/client-key.pem",
+		"-H",
+		testDaemonHTTPSAddr,
+		"version",
+	)
+	if !strings.Contains(out, "Server") {
+		c.Fatalf("docker version should return information of server side")
+	}
+
+	c.Assert(s.ctrl.reqUser, check.Equals, "client")
+	c.Assert(s.ctrl.resUser, check.Equals, "client")
+}
+
 func (s *DockerAuthzSuite) TestAuthZPluginDenyRequest(c *check.C) {
 	err := s.d.Start("--authorization-plugin=" + testAuthZPlugin)
 	c.Assert(err, check.IsNil)