зеркало из https://github.com/microsoft/docker.git
Update authz plugin list on failure.
When daemon fails to load an authz plugin, it should be removed from the plugin list. Else the plugin is retried on every request and response, resulting in undesired behavior (eg. daemon panic) Signed-off-by: Anusha Ragunathan <anusha@docker.com>
This commit is contained in:
Родитель
ff6db320f8
Коммит
fae904af02
|
@ -52,6 +52,8 @@ type Ctx struct {
|
|||
}
|
||||
|
||||
// AuthZRequest authorized the request to the docker daemon using authZ plugins
|
||||
// Side effect: If the authz plugin is invalid, then update ctx.plugins, so that
|
||||
// the caller(middleware) can update its list and stop retrying with invalid plugins.
|
||||
func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error {
|
||||
var body []byte
|
||||
if sendBody(ctx.requestURI, r.Header) && r.ContentLength > 0 && r.ContentLength < maxBodySize {
|
||||
|
@ -76,11 +78,14 @@ func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error {
|
|||
RequestHeaders: headers(r.Header),
|
||||
}
|
||||
|
||||
for _, plugin := range ctx.plugins {
|
||||
for i, plugin := range ctx.plugins {
|
||||
logrus.Debugf("AuthZ request using plugin %s", plugin.Name())
|
||||
|
||||
authRes, err := plugin.AuthZRequest(ctx.authReq)
|
||||
if err != nil {
|
||||
if err == ErrInvalidPlugin {
|
||||
ctx.plugins = append(ctx.plugins[:i], ctx.plugins[i+1:]...)
|
||||
}
|
||||
return fmt.Errorf("plugin %s failed with error: %s", plugin.Name(), err)
|
||||
}
|
||||
|
||||
|
@ -93,6 +98,8 @@ func (ctx *Ctx) AuthZRequest(w http.ResponseWriter, r *http.Request) error {
|
|||
}
|
||||
|
||||
// AuthZResponse authorized and manipulates the response from docker daemon using authZ plugins
|
||||
// Side effect: If the authz plugin is invalid, then update ctx.plugins, so that
|
||||
// the caller(middleware) can update its list and stop retrying with invalid plugins.
|
||||
func (ctx *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error {
|
||||
ctx.authReq.ResponseStatusCode = rm.StatusCode()
|
||||
ctx.authReq.ResponseHeaders = headers(rm.Header())
|
||||
|
@ -101,11 +108,14 @@ func (ctx *Ctx) AuthZResponse(rm ResponseModifier, r *http.Request) error {
|
|||
ctx.authReq.ResponseBody = rm.RawBody()
|
||||
}
|
||||
|
||||
for _, plugin := range ctx.plugins {
|
||||
for i, plugin := range ctx.plugins {
|
||||
logrus.Debugf("AuthZ response using plugin %s", plugin.Name())
|
||||
|
||||
authRes, err := plugin.AuthZResponse(ctx.authReq)
|
||||
if err != nil {
|
||||
if err == ErrInvalidPlugin {
|
||||
ctx.plugins = append(ctx.plugins[:i], ctx.plugins[i+1:]...)
|
||||
}
|
||||
return fmt.Errorf("plugin %s failed with error: %s", plugin.Name(), err)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package authorization
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
|
@ -59,6 +60,11 @@ func (m *Middleware) WrapHandler(handler func(ctx context.Context, w http.Respon
|
|||
|
||||
if err := authCtx.AuthZRequest(w, r); err != nil {
|
||||
logrus.Errorf("AuthZRequest for %s %s returned error: %s", r.Method, r.RequestURI, err)
|
||||
if strings.Contains(err.Error(), ErrInvalidPlugin.Error()) {
|
||||
m.mu.Lock()
|
||||
m.plugins = authCtx.plugins
|
||||
m.mu.Unlock()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -72,6 +78,11 @@ func (m *Middleware) WrapHandler(handler func(ctx context.Context, w http.Respon
|
|||
|
||||
if err := authCtx.AuthZResponse(rw, r); errD == nil && err != nil {
|
||||
logrus.Errorf("AuthZResponse for %s %s returned error: %s", r.Method, r.RequestURI, err)
|
||||
if strings.Contains(err.Error(), ErrInvalidPlugin.Error()) {
|
||||
m.mu.Lock()
|
||||
m.plugins = authCtx.plugins
|
||||
m.mu.Unlock()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
package authorization
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/docker/pkg/plugingetter"
|
||||
"github.com/docker/docker/pkg/plugins"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidPlugin indicates that the plugin cannot be used. This is
|
||||
// because the plugin was not found or does not implement necessary
|
||||
// functionality
|
||||
ErrInvalidPlugin = errors.New("invalid plugin")
|
||||
)
|
||||
|
||||
// Plugin allows third party plugins to authorize requests and responses
|
||||
// in the context of docker API
|
||||
type Plugin interface {
|
||||
|
@ -102,7 +110,7 @@ func (a *authorizationPlugin) initPlugin() error {
|
|||
plugin, e = plugins.Get(a.name, AuthZApiImplements)
|
||||
}
|
||||
if e != nil {
|
||||
err = e
|
||||
err = ErrInvalidPlugin
|
||||
return
|
||||
}
|
||||
a.plugin = plugin.Client()
|
||||
|
|
Загрузка…
Ссылка в новой задаче