github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/pkg/authorization/plugin.go (about)

     1  package authorization // import "github.com/demonoid81/moby/pkg/authorization"
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/demonoid81/moby/pkg/plugingetter"
     7  	"github.com/demonoid81/moby/pkg/plugins"
     8  )
     9  
    10  // Plugin allows third party plugins to authorize requests and responses
    11  // in the context of docker API
    12  type Plugin interface {
    13  	// Name returns the registered plugin name
    14  	Name() string
    15  
    16  	// AuthZRequest authorizes the request from the client to the daemon
    17  	AuthZRequest(*Request) (*Response, error)
    18  
    19  	// AuthZResponse authorizes the response from the daemon to the client
    20  	AuthZResponse(*Request) (*Response, error)
    21  }
    22  
    23  // newPlugins constructs and initializes the authorization plugins based on plugin names
    24  func newPlugins(names []string) []Plugin {
    25  	plugins := []Plugin{}
    26  	pluginsMap := make(map[string]struct{})
    27  	for _, name := range names {
    28  		if _, ok := pluginsMap[name]; ok {
    29  			continue
    30  		}
    31  		pluginsMap[name] = struct{}{}
    32  		plugins = append(plugins, newAuthorizationPlugin(name))
    33  	}
    34  	return plugins
    35  }
    36  
    37  var getter plugingetter.PluginGetter
    38  
    39  // SetPluginGetter sets the plugingetter
    40  func SetPluginGetter(pg plugingetter.PluginGetter) {
    41  	getter = pg
    42  }
    43  
    44  // GetPluginGetter gets the plugingetter
    45  func GetPluginGetter() plugingetter.PluginGetter {
    46  	return getter
    47  }
    48  
    49  // authorizationPlugin is an internal adapter to docker plugin system
    50  type authorizationPlugin struct {
    51  	initErr error
    52  	plugin  *plugins.Client
    53  	name    string
    54  	once    sync.Once
    55  }
    56  
    57  func newAuthorizationPlugin(name string) Plugin {
    58  	return &authorizationPlugin{name: name}
    59  }
    60  
    61  func (a *authorizationPlugin) Name() string {
    62  	return a.name
    63  }
    64  
    65  // Set the remote for an authz pluginv2
    66  func (a *authorizationPlugin) SetName(remote string) {
    67  	a.name = remote
    68  }
    69  
    70  func (a *authorizationPlugin) AuthZRequest(authReq *Request) (*Response, error) {
    71  	if err := a.initPlugin(); err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	authRes := &Response{}
    76  	if err := a.plugin.Call(AuthZApiRequest, authReq, authRes); err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	return authRes, nil
    81  }
    82  
    83  func (a *authorizationPlugin) AuthZResponse(authReq *Request) (*Response, error) {
    84  	if err := a.initPlugin(); err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	authRes := &Response{}
    89  	if err := a.plugin.Call(AuthZApiResponse, authReq, authRes); err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	return authRes, nil
    94  }
    95  
    96  // initPlugin initializes the authorization plugin if needed
    97  func (a *authorizationPlugin) initPlugin() error {
    98  	// Lazy loading of plugins
    99  	a.once.Do(func() {
   100  		if a.plugin == nil {
   101  			var plugin plugingetter.CompatPlugin
   102  			var e error
   103  
   104  			if pg := GetPluginGetter(); pg != nil {
   105  				plugin, e = pg.Get(a.name, AuthZApiImplements, plugingetter.Lookup)
   106  				a.SetName(plugin.Name())
   107  			} else {
   108  				plugin, e = plugins.Get(a.name, AuthZApiImplements)
   109  			}
   110  			if e != nil {
   111  				a.initErr = e
   112  				return
   113  			}
   114  			a.plugin = plugin.Client()
   115  		}
   116  	})
   117  	return a.initErr
   118  }