diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 9914333d44..bb157e468e 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -55,8 +55,9 @@ type DaemonCli struct { commonFlags *cliflags.CommonFlags configFile *string - api *apiserver.Server - d *daemon.Daemon + api *apiserver.Server + d *daemon.Daemon + authzMiddleware *authorization.Middleware // authzMiddleware enables to dynamically reload the authorization plugins } func presentInHelp(usage string) string { return usage } @@ -317,10 +318,15 @@ func (cli *DaemonCli) start() (err error) { func (cli *DaemonCli) reloadConfig() { reload := func(config *daemon.Config) { + + // Reload the authorization plugin + cli.authzMiddleware.SetPlugins(config.AuthorizationPlugins) + if err := cli.d.Reload(config); err != nil { logrus.Errorf("Error reconfiguring the daemon: %v", err) return } + if config.IsValueSet("debug") { debugEnabled := utils.IsDebugEnabled() switch { @@ -438,9 +444,6 @@ func (cli *DaemonCli) initMiddlewares(s *apiserver.Server, cfg *apiserver.Config u := middleware.NewUserAgentMiddleware(v) s.UseMiddleware(u) - if len(cli.Config.AuthorizationPlugins) > 0 { - authZPlugins := authorization.NewPlugins(cli.Config.AuthorizationPlugins) - handleAuthorization := authorization.NewMiddleware(authZPlugins) - s.UseMiddleware(handleAuthorization) - } + cli.authzMiddleware = authorization.NewMiddleware(cli.Config.AuthorizationPlugins) + s.UseMiddleware(cli.authzMiddleware) } diff --git a/docs/extend/plugins_authorization.md b/docs/extend/plugins_authorization.md index 4c11fa26ca..8630bfb761 100644 --- a/docs/extend/plugins_authorization.md +++ b/docs/extend/plugins_authorization.md @@ -104,6 +104,8 @@ support the Docker client interactions detailed in this section. Enable the authorization plugin with a dedicated command line flag in the `--authorization-plugin=PLUGIN_ID` format. The flag supplies a `PLUGIN_ID` value. This value can be the plugin’s socket or a path to a specification file. +Authorization plugins can be loaded without restarting the daemon. Refer +to the [`dockerd` documentation](../reference/commandline/dockerd.md#configuration-reloading) for more information. ```bash $ docker daemon --authorization-plugin=plugin1 --authorization-plugin=plugin2,... diff --git a/docs/reference/commandline/dockerd.md b/docs/reference/commandline/dockerd.md index f3ac7e5fb4..9c0d4b71c6 100644 --- a/docs/reference/commandline/dockerd.md +++ b/docs/reference/commandline/dockerd.md @@ -1152,6 +1152,7 @@ The list of currently supported options that can be reconfigured is this: the runtime shipped with the official docker packages. - `runtimes`: it updates the list of available OCI runtimes that can be used to run containers +- `authorization-plugin`: specifies the authorization plugins to use. Updating and reloading the cluster configurations such as `--cluster-store`, `--cluster-advertise` and `--cluster-store-opts` will take effect only if diff --git a/pkg/authorization/middleware.go b/pkg/authorization/middleware.go index 73511a8148..58734ec496 100644 --- a/pkg/authorization/middleware.go +++ b/pkg/authorization/middleware.go @@ -14,17 +14,26 @@ type Middleware struct { } // NewMiddleware creates a new Middleware -// with a slice of plugins. -func NewMiddleware(p []Plugin) Middleware { - return Middleware{ - plugins: p, +// with a slice of plugins names. +func NewMiddleware(names []string) *Middleware { + return &Middleware{ + plugins: newPlugins(names), } } +// SetPlugins sets the plugin used for authorization +func (m *Middleware) SetPlugins(names []string) { + m.plugins = newPlugins(names) +} + // WrapHandler returns a new handler function wrapping the previous one in the request chain. -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 { +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 { return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + if len(m.plugins) == 0 { + return handler(ctx, w, r, vars) + } + user := "" userAuthNMethod := "" diff --git a/pkg/authorization/plugin.go b/pkg/authorization/plugin.go index fc5c7efb4b..39dcedea2f 100644 --- a/pkg/authorization/plugin.go +++ b/pkg/authorization/plugin.go @@ -19,8 +19,8 @@ type Plugin interface { AuthZResponse(*Request) (*Response, error) } -// NewPlugins constructs and initializes the authorization plugins based on plugin names -func NewPlugins(names []string) []Plugin { +// newPlugins constructs and initializes the authorization plugins based on plugin names +func newPlugins(names []string) []Plugin { plugins := []Plugin{} pluginsMap := make(map[string]struct{}) for _, name := range names {