123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- package authorization
- import (
- "net/http"
- "sync"
- "github.com/Sirupsen/logrus"
- "github.com/docker/docker/pkg/plugingetter"
- "golang.org/x/net/context"
- )
- // Middleware uses a list of plugins to
- // handle authorization in the API requests.
- type Middleware struct {
- mu sync.Mutex
- plugins []Plugin
- }
- // NewMiddleware creates a new Middleware
- // with a slice of plugins names.
- func NewMiddleware(names []string, pg plugingetter.PluginGetter) *Middleware {
- SetPluginGetter(pg)
- return &Middleware{
- plugins: newPlugins(names),
- }
- }
- // GetAuthzPlugins gets authorization plugins
- func (m *Middleware) GetAuthzPlugins() []Plugin {
- m.mu.Lock()
- defer m.mu.Unlock()
- return m.plugins
- }
- // SetAuthzPlugins sets authorization plugins
- func (m *Middleware) SetAuthzPlugins(plugins []Plugin) {
- m.mu.Lock()
- m.plugins = plugins
- m.mu.Unlock()
- }
- // SetPlugins sets the plugin used for authorization
- func (m *Middleware) SetPlugins(names []string) {
- m.mu.Lock()
- m.plugins = newPlugins(names)
- m.mu.Unlock()
- }
- // 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 {
- return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
- plugins := m.GetAuthzPlugins()
- if len(plugins) == 0 {
- return handler(ctx, w, r, vars)
- }
- user := ""
- userAuthNMethod := ""
- // Default authorization using existing TLS connection credentials
- // FIXME: Non trivial authorization mechanisms (such as advanced certificate validations, kerberos support
- // and ldap) will be extracted using AuthN feature, which is tracked under:
- // https://github.com/docker/docker/pull/20883
- if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
- user = r.TLS.PeerCertificates[0].Subject.CommonName
- userAuthNMethod = "TLS"
- }
- authCtx := NewCtx(plugins, user, userAuthNMethod, r.Method, r.RequestURI)
- if err := authCtx.AuthZRequest(w, r); err != nil {
- logrus.Errorf("AuthZRequest for %s %s returned error: %s", r.Method, r.RequestURI, err)
- return err
- }
- rw := NewResponseModifier(w)
- var errD error
- if errD = handler(ctx, rw, r, vars); errD != nil {
- logrus.Errorf("Handler for %s %s returned error: %s", r.Method, r.RequestURI, errD)
- }
- // There's a chance that the authCtx.plugins was updated. One of the reasons
- // this can happen is when an authzplugin is disabled.
- plugins = m.GetAuthzPlugins()
- if len(plugins) == 0 {
- logrus.Debug("There are no authz plugins in the chain")
- return nil
- }
- authCtx.plugins = plugins
- if err := authCtx.AuthZResponse(rw, r); errD == nil && err != nil {
- logrus.Errorf("AuthZResponse for %s %s returned error: %s", r.Method, r.RequestURI, err)
- return err
- }
- if errD != nil {
- return errD
- }
- return nil
- }
- }
|