Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
package plugin
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/rpc"
|
|
|
|
|
|
|
|
"github.com/hashicorp/go-plugin"
|
|
|
|
"github.com/hashicorp/vault/logical"
|
|
|
|
log "github.com/mgutz/logxi/v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
// backendPluginClient implements logical.Backend and is the
|
|
|
|
// go-plugin client.
|
|
|
|
type backendPluginClient struct {
|
|
|
|
broker *plugin.MuxBroker
|
|
|
|
client *rpc.Client
|
|
|
|
pluginClient *plugin.Client
|
|
|
|
|
|
|
|
system logical.SystemView
|
|
|
|
logger log.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleRequestArgs is the args for HandleRequest method.
|
|
|
|
type HandleRequestArgs struct {
|
|
|
|
StorageID uint32
|
|
|
|
Request *logical.Request
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleRequestReply is the reply for HandleRequest method.
|
|
|
|
type HandleRequestReply struct {
|
|
|
|
Response *logical.Response
|
|
|
|
Error *plugin.BasicError
|
|
|
|
}
|
|
|
|
|
|
|
|
// SpecialPathsReply is the reply for SpecialPaths method.
|
|
|
|
type SpecialPathsReply struct {
|
|
|
|
Paths *logical.Paths
|
|
|
|
}
|
|
|
|
|
|
|
|
// SystemReply is the reply for System method.
|
|
|
|
type SystemReply struct {
|
|
|
|
SystemView logical.SystemView
|
|
|
|
Error *plugin.BasicError
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleExistenceCheckArgs is the args for HandleExistenceCheck method.
|
|
|
|
type HandleExistenceCheckArgs struct {
|
|
|
|
StorageID uint32
|
|
|
|
Request *logical.Request
|
|
|
|
}
|
|
|
|
|
|
|
|
// HandleExistenceCheckReply is the reply for HandleExistenceCheck method.
|
|
|
|
type HandleExistenceCheckReply struct {
|
|
|
|
CheckFound bool
|
|
|
|
Exists bool
|
|
|
|
Error *plugin.BasicError
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetupArgs is the args for Setup method.
|
|
|
|
type SetupArgs struct {
|
|
|
|
StorageID uint32
|
|
|
|
LoggerID uint32
|
|
|
|
SysViewID uint32
|
|
|
|
Config map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetupReply is the reply for Setup method.
|
|
|
|
type SetupReply struct {
|
|
|
|
Error *plugin.BasicError
|
|
|
|
}
|
|
|
|
|
|
|
|
// TypeReply is the reply for the Type method.
|
|
|
|
type TypeReply struct {
|
|
|
|
Type logical.BackendType
|
|
|
|
}
|
|
|
|
|
|
|
|
// RegisterLicenseArgs is the args for the RegisterLicense method.
|
|
|
|
type RegisterLicenseArgs struct {
|
|
|
|
License interface{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// RegisterLicenseReply is the reply for the RegisterLicense method.
|
|
|
|
type RegisterLicenseReply struct {
|
|
|
|
Error *plugin.BasicError
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) HandleRequest(req *logical.Request) (*logical.Response, error) {
|
2017-07-25 20:57:26 +00:00
|
|
|
// Do not send the storage, since go-plugin cannot serialize
|
|
|
|
// interfaces. The server will pick up the storage from the shim.
|
|
|
|
req.Storage = nil
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
args := &HandleRequestArgs{
|
|
|
|
Request: req,
|
|
|
|
}
|
|
|
|
var reply HandleRequestReply
|
|
|
|
|
|
|
|
err := b.client.Call("Plugin.HandleRequest", args, &reply)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if reply.Error != nil {
|
|
|
|
if reply.Error.Error() == logical.ErrUnsupportedOperation.Error() {
|
|
|
|
return nil, logical.ErrUnsupportedOperation
|
|
|
|
}
|
|
|
|
return nil, reply.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.Response, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) SpecialPaths() *logical.Paths {
|
|
|
|
var reply SpecialPathsReply
|
|
|
|
err := b.client.Call("Plugin.SpecialPaths", new(interface{}), &reply)
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.Paths
|
|
|
|
}
|
|
|
|
|
|
|
|
// System returns vault's system view. The backend client stores the view during
|
|
|
|
// Setup, so there is no need to shim the system just to get it back.
|
|
|
|
func (b *backendPluginClient) System() logical.SystemView {
|
|
|
|
return b.system
|
|
|
|
}
|
|
|
|
|
|
|
|
// Logger returns vault's logger. The backend client stores the logger during
|
|
|
|
// Setup, so there is no need to shim the logger just to get it back.
|
|
|
|
func (b *backendPluginClient) Logger() log.Logger {
|
|
|
|
return b.logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) HandleExistenceCheck(req *logical.Request) (bool, bool, error) {
|
2017-07-25 20:57:26 +00:00
|
|
|
// Do not send the storage, since go-plugin cannot serialize
|
|
|
|
// interfaces. The server will pick up the storage from the shim.
|
|
|
|
req.Storage = nil
|
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
|
|
|
args := &HandleExistenceCheckArgs{
|
|
|
|
Request: req,
|
|
|
|
}
|
|
|
|
var reply HandleExistenceCheckReply
|
|
|
|
|
|
|
|
err := b.client.Call("Plugin.HandleExistenceCheck", args, &reply)
|
|
|
|
if err != nil {
|
|
|
|
return false, false, err
|
|
|
|
}
|
|
|
|
if reply.Error != nil {
|
|
|
|
// THINKING: Should be be a switch on all error types?
|
|
|
|
if reply.Error.Error() == logical.ErrUnsupportedPath.Error() {
|
|
|
|
return false, false, logical.ErrUnsupportedPath
|
|
|
|
}
|
|
|
|
return false, false, reply.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.CheckFound, reply.Exists, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) Cleanup() {
|
|
|
|
b.client.Call("Plugin.Cleanup", new(interface{}), &struct{}{})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) Initialize() error {
|
|
|
|
err := b.client.Call("Plugin.Initialize", new(interface{}), &struct{}{})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) InvalidateKey(key string) {
|
|
|
|
b.client.Call("Plugin.InvalidateKey", key, &struct{}{})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) Setup(config *logical.BackendConfig) error {
|
|
|
|
// Shim logical.Storage
|
|
|
|
storageID := b.broker.NextId()
|
|
|
|
go b.broker.AcceptAndServe(storageID, &StorageServer{
|
|
|
|
impl: config.StorageView,
|
|
|
|
})
|
|
|
|
|
|
|
|
// Shim log.Logger
|
|
|
|
loggerID := b.broker.NextId()
|
|
|
|
go b.broker.AcceptAndServe(loggerID, &LoggerServer{
|
|
|
|
logger: config.Logger,
|
|
|
|
})
|
|
|
|
|
|
|
|
// Shim logical.SystemView
|
|
|
|
sysViewID := b.broker.NextId()
|
|
|
|
go b.broker.AcceptAndServe(sysViewID, &SystemViewServer{
|
|
|
|
impl: config.System,
|
|
|
|
})
|
|
|
|
|
|
|
|
args := &SetupArgs{
|
|
|
|
StorageID: storageID,
|
|
|
|
LoggerID: loggerID,
|
|
|
|
SysViewID: sysViewID,
|
|
|
|
Config: config.Config,
|
|
|
|
}
|
|
|
|
var reply SetupReply
|
|
|
|
|
|
|
|
err := b.client.Call("Plugin.Setup", args, &reply)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if reply.Error != nil {
|
|
|
|
return reply.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set system and logger for getter methods
|
|
|
|
b.system = config.System
|
|
|
|
b.logger = config.Logger
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) Type() logical.BackendType {
|
|
|
|
var reply TypeReply
|
|
|
|
err := b.client.Call("Plugin.Type", new(interface{}), &reply)
|
|
|
|
if err != nil {
|
|
|
|
return logical.TypeUnknown
|
|
|
|
}
|
|
|
|
|
|
|
|
return logical.BackendType(reply.Type)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *backendPluginClient) RegisterLicense(license interface{}) error {
|
|
|
|
var reply RegisterLicenseReply
|
|
|
|
args := RegisterLicenseArgs{
|
|
|
|
License: license,
|
|
|
|
}
|
|
|
|
err := b.client.Call("Plugin.RegisterLicense", args, &reply)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if reply.Error != nil {
|
|
|
|
return reply.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|