1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Extend Docker authorization with TLS user information

Currently Docker authorization framework does not use any user
information, which already available in the Docker context for TLS
connection.
The purpose of this CR is to complete the existing authz work by adding
the basic client certificate details (SUBJECT_NAME) and authentication
method (TLS) to the authz request.

We think this should be the default behavior when no extended
authorization module is specified (currently WIP under #20883).

Signed-off-by: Liron Levin <liron@twistlock.com>
This commit is contained in:
Liron Levin 2016-03-27 15:53:37 +03:00
parent 6f9872180c
commit 3c157713b3
2 changed files with 54 additions and 3 deletions

View file

@ -13,11 +13,19 @@ import (
func NewAuthorizationMiddleware(plugins []authorization.Plugin) Middleware { func NewAuthorizationMiddleware(plugins []authorization.Plugin) Middleware {
return func(handler httputils.APIFunc) httputils.APIFunc { return func(handler httputils.APIFunc) httputils.APIFunc {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 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 := "" user := ""
userAuthNMethod := "" 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) authCtx := authorization.NewCtx(plugins, user, userAuthNMethod, r.Method, r.RequestURI)
if err := authCtx.AuthZRequest(w, r); err != nil { if err := authCtx.AuthZRequest(w, r); err != nil {

View file

@ -53,6 +53,8 @@ type authorizationController struct {
psRequestCnt int // psRequestCnt counts the number of calls to list container request api 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 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 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) { func (s *DockerAuthzSuite) SetUpTest(c *check.C) {
@ -104,6 +106,7 @@ func (s *DockerAuthzSuite) SetUpSuite(c *check.C) {
} }
b, err := json.Marshal(reqRes) b, err := json.Marshal(reqRes)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
s.ctrl.reqUser = authReq.User
w.Write(b) w.Write(b)
}) })
@ -131,6 +134,7 @@ func (s *DockerAuthzSuite) SetUpSuite(c *check.C) {
} }
b, err := json.Marshal(resRes) b, err := json.Marshal(resRes)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)
s.ctrl.resUser = authReq.User
w.Write(b) w.Write(b)
}) })
@ -213,6 +217,45 @@ func (s *DockerAuthzSuite) TestAuthZPluginAllowRequest(c *check.C) {
c.Assert(s.ctrl.psResponseCnt, check.Equals, 1) 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) { func (s *DockerAuthzSuite) TestAuthZPluginDenyRequest(c *check.C) {
err := s.d.Start("--authorization-plugin=" + testAuthZPlugin) err := s.d.Start("--authorization-plugin=" + testAuthZPlugin)
c.Assert(err, check.IsNil) c.Assert(err, check.IsNil)