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>
| ... | ... |
@@ -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 {
|