Browse code

Enable to dynamically reload authorization plugins via daemon.config

Following #22729, enable to dynamically reload/remove the daemon
authorization plugins (via standard reloading mechanism).
https://docs.docker.com/engine/reference/commandline/daemon/#daemon-
configuration-file

Daemon must store a reference to the authorization middleware to refresh
the plugin on configuration changes.

Signed-off-by: Liron Levin <liron@twistlock.com>

Liron Levin authored on 2016/05/17 03:12:48
Showing 5 changed files
... ...
@@ -55,8 +55,9 @@ type DaemonCli struct {
55 55
 	commonFlags *cliflags.CommonFlags
56 56
 	configFile  *string
57 57
 
58
-	api *apiserver.Server
59
-	d   *daemon.Daemon
58
+	api             *apiserver.Server
59
+	d               *daemon.Daemon
60
+	authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins
60 61
 }
61 62
 
62 63
 func presentInHelp(usage string) string { return usage }
... ...
@@ -317,10 +318,15 @@ func (cli *DaemonCli) start() (err error) {
317 317
 
318 318
 func (cli *DaemonCli) reloadConfig() {
319 319
 	reload := func(config *daemon.Config) {
320
+
321
+		// Reload the authorization plugin
322
+		cli.authzMiddleware.SetPlugins(config.AuthorizationPlugins)
323
+
320 324
 		if err := cli.d.Reload(config); err != nil {
321 325
 			logrus.Errorf("Error reconfiguring the daemon: %v", err)
322 326
 			return
323 327
 		}
328
+
324 329
 		if config.IsValueSet("debug") {
325 330
 			debugEnabled := utils.IsDebugEnabled()
326 331
 			switch {
... ...
@@ -438,9 +444,6 @@ func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config
438 438
 	u := middleware.NewUserAgentMiddleware(v)
439 439
 	s.UseMiddleware(u)
440 440
 
441
-	if len(cli.Config.AuthorizationPlugins) > 0 {
442
-		authZPlugins := authorization.NewPlugins(cli.Config.AuthorizationPlugins)
443
-		handleAuthorization := authorization.NewMiddleware(authZPlugins)
444
-		s.UseMiddleware(handleAuthorization)
445
-	}
441
+	cli.authzMiddleware = authorization.NewMiddleware(cli.Config.AuthorizationPlugins)
442
+	s.UseMiddleware(cli.authzMiddleware)
446 443
 }
... ...
@@ -104,6 +104,8 @@ support the Docker client interactions detailed in this section.
104 104
 Enable the authorization plugin with a dedicated command line flag in the
105 105
 `--authorization-plugin=PLUGIN_ID` format. The flag supplies a `PLUGIN_ID`
106 106
 value. This value can be the plugin’s socket or a path to a specification file.
107
+Authorization plugins can be loaded without restarting the daemon. Refer
108
+to the [`dockerd` documentation](../reference/commandline/dockerd.md#configuration-reloading) for more information.
107 109
 
108 110
 ```bash
109 111
 $ docker daemon --authorization-plugin=plugin1 --authorization-plugin=plugin2,...
... ...
@@ -1152,6 +1152,7 @@ The list of currently supported options that can be reconfigured is this:
1152 1152
   the runtime shipped with the official docker packages.
1153 1153
 - `runtimes`: it updates the list of available OCI runtimes that can
1154 1154
   be used to run containers
1155
+- `authorization-plugin`: specifies the authorization plugins to use.
1155 1156
 
1156 1157
 Updating and reloading the cluster configurations such as `--cluster-store`,
1157 1158
 `--cluster-advertise` and `--cluster-store-opts` will take effect only if
... ...
@@ -14,17 +14,26 @@ type Middleware struct {
14 14
 }
15 15
 
16 16
 // NewMiddleware creates a new Middleware
17
-// with a slice of plugins.
18
-func NewMiddleware(p []Plugin) Middleware {
19
-	return Middleware{
20
-		plugins: p,
17
+// with a slice of plugins names.
18
+func NewMiddleware(names []string) *Middleware {
19
+	return &Middleware{
20
+		plugins: newPlugins(names),
21 21
 	}
22 22
 }
23 23
 
24
+// SetPlugins sets the plugin used for authorization
25
+func (m *Middleware) SetPlugins(names []string) {
26
+	m.plugins = newPlugins(names)
27
+}
28
+
24 29
 // WrapHandler returns a new handler function wrapping the previous one in the request chain.
25
-func (m Middleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
30
+func (m *Middleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
26 31
 	return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
27 32
 
33
+		if len(m.plugins) == 0 {
34
+			return handler(ctx, w, r, vars)
35
+		}
36
+
28 37
 		user := ""
29 38
 		userAuthNMethod := ""
30 39
 
... ...
@@ -19,8 +19,8 @@ type Plugin interface {
19 19
 	AuthZResponse(*Request) (*Response, error)
20 20
 }
21 21
 
22
-// NewPlugins constructs and initializes the authorization plugins based on plugin names
23
-func NewPlugins(names []string) []Plugin {
22
+// newPlugins constructs and initializes the authorization plugins based on plugin names
23
+func newPlugins(names []string) []Plugin {
24 24
 	plugins := []Plugin{}
25 25
 	pluginsMap := make(map[string]struct{})
26 26
 	for _, name := range names {