github.com/kim0/docker@v0.6.2-0.20161130212042-4addda3f07e7/pkg/authorization/middleware.go (about) 1 package authorization 2 3 import ( 4 "net/http" 5 "strings" 6 "sync" 7 8 "github.com/Sirupsen/logrus" 9 "github.com/docker/docker/pkg/plugingetter" 10 "golang.org/x/net/context" 11 ) 12 13 // Middleware uses a list of plugins to 14 // handle authorization in the API requests. 15 type Middleware struct { 16 mu sync.Mutex 17 plugins []Plugin 18 } 19 20 // NewMiddleware creates a new Middleware 21 // with a slice of plugins names. 22 func NewMiddleware(names []string, pg plugingetter.PluginGetter) *Middleware { 23 SetPluginGetter(pg) 24 return &Middleware{ 25 plugins: newPlugins(names), 26 } 27 } 28 29 // SetPlugins sets the plugin used for authorization 30 func (m *Middleware) SetPlugins(names []string) { 31 m.mu.Lock() 32 m.plugins = newPlugins(names) 33 m.mu.Unlock() 34 } 35 36 // WrapHandler returns a new handler function wrapping the previous one in the request chain. 37 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 { 38 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 39 40 m.mu.Lock() 41 plugins := m.plugins 42 m.mu.Unlock() 43 if len(plugins) == 0 { 44 return handler(ctx, w, r, vars) 45 } 46 47 user := "" 48 userAuthNMethod := "" 49 50 // Default authorization using existing TLS connection credentials 51 // FIXME: Non trivial authorization mechanisms (such as advanced certificate validations, kerberos support 52 // and ldap) will be extracted using AuthN feature, which is tracked under: 53 // https://github.com/docker/docker/pull/20883 54 if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 { 55 user = r.TLS.PeerCertificates[0].Subject.CommonName 56 userAuthNMethod = "TLS" 57 } 58 59 authCtx := NewCtx(plugins, user, userAuthNMethod, r.Method, r.RequestURI) 60 61 if err := authCtx.AuthZRequest(w, r); err != nil { 62 logrus.Errorf("AuthZRequest for %s %s returned error: %s", r.Method, r.RequestURI, err) 63 if strings.Contains(err.Error(), ErrInvalidPlugin.Error()) { 64 m.mu.Lock() 65 m.plugins = authCtx.plugins 66 m.mu.Unlock() 67 } 68 return err 69 } 70 71 rw := NewResponseModifier(w) 72 73 var errD error 74 75 if errD = handler(ctx, rw, r, vars); errD != nil { 76 logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.RequestURI, errD) 77 } 78 79 if err := authCtx.AuthZResponse(rw, r); errD == nil && err != nil { 80 logrus.Errorf("AuthZResponse for %s %s returned error: %s", r.Method, r.RequestURI, err) 81 if strings.Contains(err.Error(), ErrInvalidPlugin.Error()) { 82 m.mu.Lock() 83 m.plugins = authCtx.plugins 84 m.mu.Unlock() 85 } 86 return err 87 } 88 89 if errD != nil { 90 return errD 91 } 92 93 return nil 94 } 95 }