Execute builtin plugins

This commit is contained in:
Brian Kassouf
2017-04-04 14:43:39 -07:00
parent 73a2cdf6a5
commit f6b45bdcfb
3 changed files with 88 additions and 35 deletions

View File

@@ -1,8 +1,10 @@
package command
import (
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"net"
"net/http"
"net/url"
@@ -131,6 +133,33 @@ func (c *ServerCommand) Run(args []string) int {
dev = true
}
// Record the vault binary's location and SHA-256 checksum for use in
// builtin plugins.
ex, err := os.Executable()
if err != nil {
c.Ui.Output(fmt.Sprintf(
"Error looking up vault binary: %s", err))
return 1
}
file, err := os.Open(ex)
if err != nil {
c.Ui.Output(fmt.Sprintf(
"Error loading vault binary: %s", err))
return 1
}
defer file.Close()
hash := sha256.New()
_, err = io.Copy(hash, file)
if err != nil {
c.Ui.Output(fmt.Sprintf(
"Error checksumming vault binary: %s", err))
return 1
}
sha256Value := hash.Sum(nil)
// Validation
if !dev {
switch {
@@ -225,21 +254,23 @@ func (c *ServerCommand) Run(args []string) int {
}
coreConfig := &vault.CoreConfig{
Physical: backend,
RedirectAddr: config.Backend.RedirectAddr,
HAPhysical: nil,
Seal: seal,
AuditBackends: c.AuditBackends,
CredentialBackends: c.CredentialBackends,
LogicalBackends: c.LogicalBackends,
Logger: c.logger,
DisableCache: config.DisableCache,
DisableMlock: config.DisableMlock,
MaxLeaseTTL: config.MaxLeaseTTL,
DefaultLeaseTTL: config.DefaultLeaseTTL,
ClusterName: config.ClusterName,
CacheSize: config.CacheSize,
PluginDirectory: config.PluginDirectory,
Physical: backend,
RedirectAddr: config.Backend.RedirectAddr,
HAPhysical: nil,
Seal: seal,
AuditBackends: c.AuditBackends,
CredentialBackends: c.CredentialBackends,
LogicalBackends: c.LogicalBackends,
Logger: c.logger,
DisableCache: config.DisableCache,
DisableMlock: config.DisableMlock,
MaxLeaseTTL: config.MaxLeaseTTL,
DefaultLeaseTTL: config.DefaultLeaseTTL,
ClusterName: config.ClusterName,
CacheSize: config.CacheSize,
PluginDirectory: config.PluginDirectory,
VaultBinaryLocation: ex,
VaultBinarySHA256: sha256Value,
}
if dev {
coreConfig.DevToken = devRootTokenID
@@ -252,7 +283,7 @@ func (c *ServerCommand) Run(args []string) int {
"Error getting user's home directory: %v", err))
return 1
}
coreConfig.PluginDirectory = filepath.Join(homePath, "/vault-plugins/")
coreConfig.PluginDirectory = filepath.Join(homePath, "/.vault-plugins/")
}
var disableClustering bool

View File

@@ -335,6 +335,12 @@ type Core struct {
// pluginDirectory is the location vault will look for plugins
pluginDirectory string
// vaultBinaryLocation is used to run builtin plugins in secure mode
vaultBinaryLocation string
// vaultBinarySHA256 is used to run builtin plugins in secure mode
vaultBinarySHA256 []byte
// pluginCatalog is used to manage plugin configurations
pluginCatalog *PluginCatalog
}
@@ -381,7 +387,9 @@ type CoreConfig struct {
EnableUI bool `json:"ui" structs:"ui" mapstructure:"ui"`
PluginDirectory string `json:"plugin_directory" structs:"plugin_directory" mapstructure:"plugin_directory"`
PluginDirectory string `json:"plugin_directory" structs:"plugin_directory" mapstructure:"plugin_directory"`
VaultBinaryLocation string `json:"vault_binary_location" structs:"vault_binary_location" mapstructure:"vault_binary_location"`
VaultBinarySHA256 []byte `json:"vault_binary_sha256" structs:"vault_binary_sha256" mapstructure:"vault_binary_sha256"`
ReloadFuncs *map[string][]ReloadFunc
ReloadFuncsLock *sync.RWMutex
@@ -439,6 +447,8 @@ func NewCore(conf *CoreConfig) (*Core, error) {
clusterName: conf.ClusterName,
clusterListenerShutdownCh: make(chan struct{}),
clusterListenerShutdownSuccessCh: make(chan struct{}),
vaultBinaryLocation: conf.VaultBinaryLocation,
vaultBinarySHA256: conf.VaultBinarySHA256,
}
// Wrap the physical backend in a cache layer if enabled and not already wrapped

View File

@@ -10,50 +10,62 @@ import (
"github.com/hashicorp/vault/helper/jsonutil"
"github.com/hashicorp/vault/helper/pluginutil"
"github.com/hashicorp/vault/helper/strutil"
"github.com/hashicorp/vault/logical"
)
var (
pluginCatalogPrefix = "plugin-catalog/"
builtinPlugins = []string{"mysql-database-plugin", "postgres-database-plugin"}
)
type PluginCatalog struct {
catalogView *BarrierView
directory string
catalogView *BarrierView
directory string
vaultCommand string
vaultSHA256 []byte
lock sync.RWMutex
builtin map[string]*pluginutil.PluginRunner
}
func NewPluginCatalog(view *BarrierView, directory string) *PluginCatalog {
return &PluginCatalog{
catalogView: view.SubView(pluginCatalogPrefix),
directory: directory,
}
}
func (c *Core) setupPluginCatalog() error {
catalog := NewPluginCatalog(c.systemBarrierView, c.pluginDirectory)
c.pluginCatalog = catalog
c.pluginCatalog = &PluginCatalog{
catalogView: c.systemBarrierView.SubView(pluginCatalogPrefix),
directory: c.pluginDirectory,
vaultCommand: c.vaultBinaryLocation,
vaultSHA256: c.vaultBinarySHA256,
}
return nil
}
func (c *PluginCatalog) Get(name string) (*pluginutil.PluginRunner, error) {
// 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 {
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
}
// Look for builtin plugins
if !strutil.StrListContains(builtinPlugins, name) {
return nil, fmt.Errorf("no plugin found with name: %s", name)
}
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 &pluginutil.PluginRunner{
Name: name,
Command: c.vaultCommand,
Args: []string{"plugin-exec", name},
Sha256: c.vaultSHA256,
}, nil
}
func (c *PluginCatalog) Set(name, command string, sha256 []byte) error {