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>
This commit is contained in:
Liron Levin 2016-05-16 21:12:48 +03:00 committed by liron
parent ee355e017d
commit 4192fe9c06
5 changed files with 29 additions and 14 deletions

View File

@ -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)
}

View File

@ -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 plugins 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,...

View File

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

View File

@ -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 := ""

View File

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