github.com/gdevillele/moby@v1.13.0/pkg/authorization/middleware.go (about)

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