diff --git a/command/server.go b/command/server.go index ef9e3e3a0c..9697c1dc85 100644 --- a/command/server.go +++ b/command/server.go @@ -8,7 +8,6 @@ import ( "net/url" "os" "os/signal" - "path/filepath" "runtime" "sort" "strconv" @@ -21,7 +20,6 @@ import ( colorable "github.com/mattn/go-colorable" log "github.com/mgutz/logxi/v1" - homedir "github.com/mitchellh/go-homedir" "google.golang.org/grpc/grpclog" @@ -245,23 +243,6 @@ func (c *ServerCommand) Run(args []string) int { coreConfig.DevToken = devRootTokenID } - if config.PluginDirectory == "" { - homePath, err := homedir.Dir() - if err != nil { - c.Ui.Output(fmt.Sprintf( - "Error getting user's home directory: %v", err)) - return 1 - } - coreConfig.PluginDirectory = filepath.Join(homePath, "/.vault-plugins/") - err = os.Mkdir(coreConfig.PluginDirectory, 0700) - if err != nil && !os.IsExist(err) { - c.Ui.Output(fmt.Sprintf( - "Error making default plugin directory: %v", err)) - return 1 - } - - } - var disableClustering bool // Initialize the separate HA storage backend, if it exists diff --git a/helper/builtinplugins/builtin.go b/helper/builtinplugins/builtin.go index 9c51ae4789..b61a51710d 100644 --- a/helper/builtinplugins/builtin.go +++ b/helper/builtinplugins/builtin.go @@ -7,29 +7,21 @@ import ( type BuiltinFactory func() (interface{}, error) -var BuiltinPlugins *builtinPlugins = &builtinPlugins{ - plugins: map[string]BuiltinFactory{ - "mysql-database-plugin": mysql.New, - "postgresql-database-plugin": postgresql.New, - }, +var plugins map[string]BuiltinFactory = map[string]BuiltinFactory{ + "mysql-database-plugin": mysql.New, + "postgresql-database-plugin": postgresql.New, } -// The list of builtin plugins should not be changed by any other package, so we -// store them in an unexported variable in this unexported struct. -type builtinPlugins struct { - plugins map[string]BuiltinFactory -} - -func (b *builtinPlugins) Get(name string) (BuiltinFactory, bool) { - f, ok := b.plugins[name] +func Get(name string) (BuiltinFactory, bool) { + f, ok := plugins[name] return f, ok } -func (b *builtinPlugins) Keys() []string { - keys := make([]string, len(b.plugins)) +func Keys() []string { + keys := make([]string, len(plugins)) i := 0 - for k := range b.plugins { + for k := range plugins { keys[i] = k i++ } diff --git a/helper/pluginutil/runner.go b/helper/pluginutil/runner.go index 95de96a5a8..9963704e54 100644 --- a/helper/pluginutil/runner.go +++ b/helper/pluginutil/runner.go @@ -12,8 +12,8 @@ import ( ) var ( - // PluginUnwrapTokenEnv is the ENV name used to pass unwrap tokens to the - // plugin. + // PluginUnwrapTokenEnv is the ENV name used to pass the configuration for + // enabling mlock PluginMlockEnabled = "VAULT_PLUGIN_MLOCK_ENABLED" ) diff --git a/vault/logical_system.go b/vault/logical_system.go index f43de9ef67..cd7113aa30 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -710,13 +710,19 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen Fields: map[string]*framework.FieldSchema{ "name": &framework.FieldSchema{ - Type: framework.TypeString, + Type: framework.TypeString, + Description: "The name of the plugin", }, "sha_256": &framework.FieldSchema{ Type: framework.TypeString, + Description: `The SHA256 sum of the executable used in the + command field. This should be HEX encoded.`, }, "command": &framework.FieldSchema{ Type: framework.TypeString, + Description: `The command used to start the plugin. The + executable defined in this command must exist in vault's + plugin directory.`, }, }, @@ -767,8 +773,7 @@ func (b *SystemBackend) handlePluginCatalogList(req *logical.Request, d *framewo return nil, err } - resp := logical.ListResponse(plugins) - return resp, nil + return logical.ListResponse(plugins), nil } func (b *SystemBackend) handlePluginCatalogUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) { @@ -2524,7 +2529,7 @@ This path responds to the following HTTP methods. `Configures the plugins known to vault`, ` This path responds to the following HTTP methods. - GET / + LIST / Returns a list of names of configured plugins. GET / diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index e9836946c3..ea940d540d 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -1129,8 +1129,8 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) { t.Fatalf("err: %v", err) } - if len(resp.Data["keys"].([]string)) != len(builtinplugins.BuiltinPlugins.Keys()) { - t.Fatalf("Wrong number of plugins, got %d, expected %d", len(resp.Data["keys"].([]string)), len(builtinplugins.BuiltinPlugins.Keys())) + if len(resp.Data["keys"].([]string)) != len(builtinplugins.Keys()) { + t.Fatalf("Wrong number of plugins, got %d, expected %d", len(resp.Data["keys"].([]string)), len(builtinplugins.Keys())) } req = logical.TestRequest(t, logical.ReadOperation, "plugin-catalog/mysql-database-plugin") @@ -1143,7 +1143,7 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) { Name: "mysql-database-plugin", Builtin: true, } - expectedBuiltin.BuiltinFactory, _ = builtinplugins.BuiltinPlugins.Get("mysql-database-plugin") + expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin") p := resp.Data["plugin"].(*pluginutil.PluginRunner) if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) { diff --git a/vault/plugin_catalog.go b/vault/plugin_catalog.go index 598a16fac5..5d88873b31 100644 --- a/vault/plugin_catalog.go +++ b/vault/plugin_catalog.go @@ -16,7 +16,8 @@ import ( ) var ( - pluginCatalogPrefix = "plugin-catalog/" + pluginCatalogPath = "core/plugin-catalog/" + ErrDirectoryNotConfigured = errors.New("could not set plugin, plugin directory is not configured") ) // PluginCatalog keeps a record of plugins known to vault. External plugins need @@ -31,7 +32,7 @@ type PluginCatalog struct { func (c *Core) setupPluginCatalog() error { c.pluginCatalog = &PluginCatalog{ - catalogView: c.systemBarrierView.SubView(pluginCatalogPrefix), + catalogView: NewBarrierView(c.barrier, pluginCatalogPath), directory: c.pluginDirectory, } @@ -45,22 +46,24 @@ func (c *PluginCatalog) Get(name string) (*pluginutil.PluginRunner, error) { c.lock.RLock() defer c.lock.RUnlock() - // Look for external plugins in the barrier - out, err := c.catalogView.Get(name) - if err != nil { - return nil, fmt.Errorf("failed to retrieve plugin \"%s\": %v", name, err) - } - if out != nil { - entry := new(pluginutil.PluginRunner) - if err := jsonutil.DecodeJSON(out.Value, entry); err != nil { - return nil, fmt.Errorf("failed to decode plugin entry: %v", err) + // If the directory isn't set only look for builtin plugins. + if c.directory != "" { + // Look for external plugins in the barrier + out, err := c.catalogView.Get(name) + if err != nil { + return nil, fmt.Errorf("failed to retrieve plugin \"%s\": %v", name, err) } + if out != nil { + entry := new(pluginutil.PluginRunner) + if err := jsonutil.DecodeJSON(out.Value, entry); err != nil { + return nil, fmt.Errorf("failed to decode plugin entry: %v", err) + } - return entry, nil + return entry, nil + } } - // Look for builtin plugins - if factory, ok := builtinplugins.BuiltinPlugins.Get(name); ok { + if factory, ok := builtinplugins.Get(name); ok { return &pluginutil.PluginRunner{ Name: name, Builtin: true, @@ -74,6 +77,10 @@ func (c *PluginCatalog) Get(name string) (*pluginutil.PluginRunner, error) { // Set registers a new external plugin with the catalog, or updates an existing // external plugin. It takes the name, command and SHA256 of the plugin. func (c *PluginCatalog) Set(name, command string, sha256 []byte) error { + if c.directory == "" { + return ErrDirectoryNotConfigured + } + c.lock.Lock() defer c.lock.Unlock() @@ -143,7 +150,7 @@ func (c *PluginCatalog) List() ([]string, error) { } // Get the keys for builtin plugins - builtinKeys := builtinplugins.BuiltinPlugins.Keys() + builtinKeys := builtinplugins.Keys() // Use a map to unique the two lists mapKeys := make(map[string]bool) diff --git a/vault/plugin_catalog_test.go b/vault/plugin_catalog_test.go index 57e864892b..6cfacda7e5 100644 --- a/vault/plugin_catalog_test.go +++ b/vault/plugin_catalog_test.go @@ -32,7 +32,7 @@ func TestPluginCatalog_CRUD(t *testing.T) { Name: "mysql-database-plugin", Builtin: true, } - expectedBuiltin.BuiltinFactory, _ = builtinplugins.BuiltinPlugins.Get("mysql-database-plugin") + expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin") if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) { t.Fatal("expected BuiltinFactory did not match actual") @@ -90,7 +90,7 @@ func TestPluginCatalog_CRUD(t *testing.T) { Name: "mysql-database-plugin", Builtin: true, } - expectedBuiltin.BuiltinFactory, _ = builtinplugins.BuiltinPlugins.Get("mysql-database-plugin") + expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin") if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) { t.Fatal("expected BuiltinFactory did not match actual") @@ -113,7 +113,7 @@ func TestPluginCatalog_List(t *testing.T) { core.pluginCatalog.directory = sym // Get builtin plugins and sort them - builtinKeys := builtinplugins.BuiltinPlugins.Keys() + builtinKeys := builtinplugins.Keys() sort.Strings(builtinKeys) // List only builtin plugins