mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-16 15:01:13 +01:00
Update the builtin keys; move catalog to core; protect against unset plugin directory
This commit is contained in:
parent
3ceb7b69e1
commit
f4ef3df4bd
@ -8,7 +8,6 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -21,7 +20,6 @@ import (
|
|||||||
|
|
||||||
colorable "github.com/mattn/go-colorable"
|
colorable "github.com/mattn/go-colorable"
|
||||||
log "github.com/mgutz/logxi/v1"
|
log "github.com/mgutz/logxi/v1"
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
|
||||||
|
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
|
||||||
@ -245,23 +243,6 @@ func (c *ServerCommand) Run(args []string) int {
|
|||||||
coreConfig.DevToken = devRootTokenID
|
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
|
var disableClustering bool
|
||||||
|
|
||||||
// Initialize the separate HA storage backend, if it exists
|
// Initialize the separate HA storage backend, if it exists
|
||||||
|
|||||||
@ -7,29 +7,21 @@ import (
|
|||||||
|
|
||||||
type BuiltinFactory func() (interface{}, error)
|
type BuiltinFactory func() (interface{}, error)
|
||||||
|
|
||||||
var BuiltinPlugins *builtinPlugins = &builtinPlugins{
|
var plugins map[string]BuiltinFactory = map[string]BuiltinFactory{
|
||||||
plugins: map[string]BuiltinFactory{
|
"mysql-database-plugin": mysql.New,
|
||||||
"mysql-database-plugin": mysql.New,
|
"postgresql-database-plugin": postgresql.New,
|
||||||
"postgresql-database-plugin": postgresql.New,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The list of builtin plugins should not be changed by any other package, so we
|
func Get(name string) (BuiltinFactory, bool) {
|
||||||
// store them in an unexported variable in this unexported struct.
|
f, ok := plugins[name]
|
||||||
type builtinPlugins struct {
|
|
||||||
plugins map[string]BuiltinFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *builtinPlugins) Get(name string) (BuiltinFactory, bool) {
|
|
||||||
f, ok := b.plugins[name]
|
|
||||||
return f, ok
|
return f, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *builtinPlugins) Keys() []string {
|
func Keys() []string {
|
||||||
keys := make([]string, len(b.plugins))
|
keys := make([]string, len(plugins))
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
for k := range b.plugins {
|
for k := range plugins {
|
||||||
keys[i] = k
|
keys[i] = k
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,8 +12,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// PluginUnwrapTokenEnv is the ENV name used to pass unwrap tokens to the
|
// PluginUnwrapTokenEnv is the ENV name used to pass the configuration for
|
||||||
// plugin.
|
// enabling mlock
|
||||||
PluginMlockEnabled = "VAULT_PLUGIN_MLOCK_ENABLED"
|
PluginMlockEnabled = "VAULT_PLUGIN_MLOCK_ENABLED"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -710,13 +710,19 @@ func NewSystemBackend(core *Core, config *logical.BackendConfig) (logical.Backen
|
|||||||
|
|
||||||
Fields: map[string]*framework.FieldSchema{
|
Fields: map[string]*framework.FieldSchema{
|
||||||
"name": &framework.FieldSchema{
|
"name": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
|
Description: "The name of the plugin",
|
||||||
},
|
},
|
||||||
"sha_256": &framework.FieldSchema{
|
"sha_256": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
Type: framework.TypeString,
|
||||||
|
Description: `The SHA256 sum of the executable used in the
|
||||||
|
command field. This should be HEX encoded.`,
|
||||||
},
|
},
|
||||||
"command": &framework.FieldSchema{
|
"command": &framework.FieldSchema{
|
||||||
Type: framework.TypeString,
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := logical.ListResponse(plugins)
|
return logical.ListResponse(plugins), nil
|
||||||
return resp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *SystemBackend) handlePluginCatalogUpdate(req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
|
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`,
|
`Configures the plugins known to vault`,
|
||||||
`
|
`
|
||||||
This path responds to the following HTTP methods.
|
This path responds to the following HTTP methods.
|
||||||
GET /
|
LIST /
|
||||||
Returns a list of names of configured plugins.
|
Returns a list of names of configured plugins.
|
||||||
|
|
||||||
GET /<name>
|
GET /<name>
|
||||||
|
|||||||
@ -1129,8 +1129,8 @@ func TestSystemBackend_PluginCatalog_CRUD(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if 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.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")
|
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",
|
Name: "mysql-database-plugin",
|
||||||
Builtin: true,
|
Builtin: true,
|
||||||
}
|
}
|
||||||
expectedBuiltin.BuiltinFactory, _ = builtinplugins.BuiltinPlugins.Get("mysql-database-plugin")
|
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin")
|
||||||
|
|
||||||
p := resp.Data["plugin"].(*pluginutil.PluginRunner)
|
p := resp.Data["plugin"].(*pluginutil.PluginRunner)
|
||||||
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
||||||
|
|||||||
@ -16,7 +16,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
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
|
// PluginCatalog keeps a record of plugins known to vault. External plugins need
|
||||||
@ -31,7 +32,7 @@ type PluginCatalog struct {
|
|||||||
|
|
||||||
func (c *Core) setupPluginCatalog() error {
|
func (c *Core) setupPluginCatalog() error {
|
||||||
c.pluginCatalog = &PluginCatalog{
|
c.pluginCatalog = &PluginCatalog{
|
||||||
catalogView: c.systemBarrierView.SubView(pluginCatalogPrefix),
|
catalogView: NewBarrierView(c.barrier, pluginCatalogPath),
|
||||||
directory: c.pluginDirectory,
|
directory: c.pluginDirectory,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,22 +46,24 @@ func (c *PluginCatalog) Get(name string) (*pluginutil.PluginRunner, error) {
|
|||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
defer c.lock.RUnlock()
|
defer c.lock.RUnlock()
|
||||||
|
|
||||||
// Look for external plugins in the barrier
|
// If the directory isn't set only look for builtin plugins.
|
||||||
out, err := c.catalogView.Get(name)
|
if c.directory != "" {
|
||||||
if err != nil {
|
// Look for external plugins in the barrier
|
||||||
return nil, fmt.Errorf("failed to retrieve plugin \"%s\": %v", name, err)
|
out, err := c.catalogView.Get(name)
|
||||||
}
|
if err != nil {
|
||||||
if out != nil {
|
return nil, fmt.Errorf("failed to retrieve plugin \"%s\": %v", name, err)
|
||||||
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 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
|
// Look for builtin plugins
|
||||||
if factory, ok := builtinplugins.BuiltinPlugins.Get(name); ok {
|
if factory, ok := builtinplugins.Get(name); ok {
|
||||||
return &pluginutil.PluginRunner{
|
return &pluginutil.PluginRunner{
|
||||||
Name: name,
|
Name: name,
|
||||||
Builtin: true,
|
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
|
// 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.
|
// external plugin. It takes the name, command and SHA256 of the plugin.
|
||||||
func (c *PluginCatalog) Set(name, command string, sha256 []byte) error {
|
func (c *PluginCatalog) Set(name, command string, sha256 []byte) error {
|
||||||
|
if c.directory == "" {
|
||||||
|
return ErrDirectoryNotConfigured
|
||||||
|
}
|
||||||
|
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
|
|
||||||
@ -143,7 +150,7 @@ func (c *PluginCatalog) List() ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the keys for builtin plugins
|
// Get the keys for builtin plugins
|
||||||
builtinKeys := builtinplugins.BuiltinPlugins.Keys()
|
builtinKeys := builtinplugins.Keys()
|
||||||
|
|
||||||
// Use a map to unique the two lists
|
// Use a map to unique the two lists
|
||||||
mapKeys := make(map[string]bool)
|
mapKeys := make(map[string]bool)
|
||||||
|
|||||||
@ -32,7 +32,7 @@ func TestPluginCatalog_CRUD(t *testing.T) {
|
|||||||
Name: "mysql-database-plugin",
|
Name: "mysql-database-plugin",
|
||||||
Builtin: true,
|
Builtin: true,
|
||||||
}
|
}
|
||||||
expectedBuiltin.BuiltinFactory, _ = builtinplugins.BuiltinPlugins.Get("mysql-database-plugin")
|
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin")
|
||||||
|
|
||||||
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
||||||
t.Fatal("expected BuiltinFactory did not match actual")
|
t.Fatal("expected BuiltinFactory did not match actual")
|
||||||
@ -90,7 +90,7 @@ func TestPluginCatalog_CRUD(t *testing.T) {
|
|||||||
Name: "mysql-database-plugin",
|
Name: "mysql-database-plugin",
|
||||||
Builtin: true,
|
Builtin: true,
|
||||||
}
|
}
|
||||||
expectedBuiltin.BuiltinFactory, _ = builtinplugins.BuiltinPlugins.Get("mysql-database-plugin")
|
expectedBuiltin.BuiltinFactory, _ = builtinplugins.Get("mysql-database-plugin")
|
||||||
|
|
||||||
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
if &(p.BuiltinFactory) == &(expectedBuiltin.BuiltinFactory) {
|
||||||
t.Fatal("expected BuiltinFactory did not match actual")
|
t.Fatal("expected BuiltinFactory did not match actual")
|
||||||
@ -113,7 +113,7 @@ func TestPluginCatalog_List(t *testing.T) {
|
|||||||
core.pluginCatalog.directory = sym
|
core.pluginCatalog.directory = sym
|
||||||
|
|
||||||
// Get builtin plugins and sort them
|
// Get builtin plugins and sort them
|
||||||
builtinKeys := builtinplugins.BuiltinPlugins.Keys()
|
builtinKeys := builtinplugins.Keys()
|
||||||
sort.Strings(builtinKeys)
|
sort.Strings(builtinKeys)
|
||||||
|
|
||||||
// List only builtin plugins
|
// List only builtin plugins
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user