diff --git a/builtin/logical/database/dbplugin/client.go b/builtin/logical/database/dbplugin/client.go index d9095a0fd667..6df39489fea0 100644 --- a/builtin/logical/database/dbplugin/client.go +++ b/builtin/logical/database/dbplugin/client.go @@ -36,7 +36,7 @@ func newPluginClient(sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginR "database": new(DatabasePlugin), } - client, err := pluginRunner.Run(sys, pluginMap, handshakeConfig, []string{}, logger, false) + client, err := pluginRunner.Run(sys, pluginMap, handshakeConfig, []string{}, logger) if err != nil { return nil, err } diff --git a/helper/pluginutil/runner.go b/helper/pluginutil/runner.go index f35ffa9530b3..c6d46f301411 100644 --- a/helper/pluginutil/runner.go +++ b/helper/pluginutil/runner.go @@ -48,7 +48,7 @@ type PluginRunner struct { // Run takes a wrapper RunnerUtil instance along with the go-plugin paramaters and // returns a configured plugin.Client with TLS Configured and a wrapping token set // on PluginUnwrapTokenEnv for plugin process consumption. -func (r *PluginRunner) Run(wrapper RunnerUtil, pluginMap map[string]plugin.Plugin, hs plugin.HandshakeConfig, env []string, logger log.Logger, isMetadataMode bool) (*plugin.Client, error) { +func (r *PluginRunner) Run(wrapper RunnerUtil, pluginMap map[string]plugin.Plugin, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) { // Get a CA TLS Certificate certBytes, key, err := generateCert() if err != nil { @@ -72,6 +72,8 @@ func (r *PluginRunner) Run(wrapper RunnerUtil, pluginMap map[string]plugin.Plugi cmd.Env = append(cmd.Env, env...) // Add the response wrap token to the ENV of the plugin cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, wrapToken)) + // Add the metadata mode ENV and set it to false + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadaModeEnv, "false")) // Add the mlock setting to the ENV of the plugin if wrapper.MlockEnabled() { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true")) @@ -88,23 +90,49 @@ func (r *PluginRunner) Run(wrapper RunnerUtil, pluginMap map[string]plugin.Plugi } namedLogger := clogger.ResetNamed("plugin") - // Handle case where plugin is being ran in metadata-mode - if isMetadataMode { - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadaModeEnv, "true")) - namedLogger = clogger.ResetNamed("plugin.metadata") - clientTLSConfig = nil + client := plugin.NewClient(&plugin.ClientConfig{ + HandshakeConfig: hs, + Plugins: pluginMap, + Cmd: cmd, + TLSConfig: clientTLSConfig, + SecureConfig: secureConfig, + Logger: namedLogger, + }) + + return client, nil +} + +func (r *PluginRunner) RunMetadataMode(wrapper RunnerUtil, pluginMap map[string]plugin.Plugin, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) { + cmd := exec.Command(r.Command, r.Args...) + cmd.Env = append(cmd.Env, env...) + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadaModeEnv, "true")) + + // Add the mlock setting to the ENV of the plugin + if wrapper.MlockEnabled() { + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true")) + } + + secureConfig := &plugin.SecureConfig{ + Checksum: r.Sha256, + Hash: sha256.New(), } + // Create logger for the plugin client + clogger := &hclogFaker{ + logger: logger, + } + namedLogger := clogger.ResetNamed("plugin.metadata") + client := plugin.NewClient(&plugin.ClientConfig{ HandshakeConfig: hs, Plugins: pluginMap, Cmd: cmd, - TLSConfig: clientTLSConfig, SecureConfig: secureConfig, Logger: namedLogger, }) return client, nil + } type APIClientMeta struct { diff --git a/helper/pluginutil/tls.go b/helper/pluginutil/tls.go index 738f162e9816..97effb256790 100644 --- a/helper/pluginutil/tls.go +++ b/helper/pluginutil/tls.go @@ -128,7 +128,7 @@ func wrapServerConfig(sys RunnerUtil, certBytes []byte, key *ecdsa.PrivateKey) ( // VaultPluginTLSProvider is run inside a plugin and retrives the response // wrapped TLS certificate from vault. It returns a configured TLS Config. func VaultPluginTLSProvider(apiTLSConfig *api.TLSConfig) func() (*tls.Config, error) { - if os.Getenv(PluginMetadaModeEnv) != "" { + if os.Getenv(PluginMetadaModeEnv) == "true" { return nil } diff --git a/logical/plugin/backend.go b/logical/plugin/backend.go index 8a80be0298bb..081922c9bd3e 100644 --- a/logical/plugin/backend.go +++ b/logical/plugin/backend.go @@ -9,7 +9,8 @@ import ( // BackendPlugin is the plugin.Plugin implementation type BackendPlugin struct { - Factory func(*logical.BackendConfig) (logical.Backend, error) + Factory func(*logical.BackendConfig) (logical.Backend, error) + metadataMode bool } // Server gets called when on plugin.Serve() @@ -19,5 +20,5 @@ func (b *BackendPlugin) Server(broker *plugin.MuxBroker) (interface{}, error) { // Client gets called on plugin.NewClient() func (b BackendPlugin) Client(broker *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { - return &backendPluginClient{client: c, broker: broker}, nil + return &backendPluginClient{client: c, broker: broker, metadataMode: b.metadataMode}, nil } diff --git a/logical/plugin/backend_client.go b/logical/plugin/backend_client.go index f18564b134a7..6c9e317afdb6 100644 --- a/logical/plugin/backend_client.go +++ b/logical/plugin/backend_client.go @@ -11,8 +11,9 @@ import ( // backendPluginClient implements logical.Backend and is the // go-plugin client. type backendPluginClient struct { - broker *plugin.MuxBroker - client *rpc.Client + broker *plugin.MuxBroker + client *rpc.Client + metadataMode bool system logical.SystemView logger log.Logger @@ -182,21 +183,33 @@ func (b *backendPluginClient) InvalidateKey(key string) { func (b *backendPluginClient) Setup(config *logical.BackendConfig) error { // Shim logical.Storage + storageImpl := config.StorageView + if b.metadataMode { + storageImpl = &NOOPStorage{} + } storageID := b.broker.NextId() go b.broker.AcceptAndServe(storageID, &StorageServer{ - impl: config.StorageView, + impl: storageImpl, }) // Shim log.Logger + loggerImpl := config.Logger + if b.metadataMode { + loggerImpl = log.NullLog + } loggerID := b.broker.NextId() go b.broker.AcceptAndServe(loggerID, &LoggerServer{ - logger: config.Logger, + logger: loggerImpl, }) // Shim logical.SystemView + sysViewImpl := config.System + if b.metadataMode { + sysViewImpl = &logical.StaticSystemView{} + } sysViewID := b.broker.NextId() go b.broker.AcceptAndServe(sysViewID, &SystemViewServer{ - impl: config.System, + impl: sysViewImpl, }) args := &SetupArgs{ diff --git a/logical/plugin/plugin.go b/logical/plugin/plugin.go index b80b2b9f38b8..c5017e8538c8 100644 --- a/logical/plugin/plugin.go +++ b/logical/plugin/plugin.go @@ -78,10 +78,18 @@ func NewBackend(pluginName string, sys pluginutil.LookRunnerUtil, logger log.Log func newPluginClient(sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger, isMetadataMode bool) (logical.Backend, error) { // pluginMap is the map of plugins we can dispense. pluginMap := map[string]plugin.Plugin{ - "backend": &BackendPlugin{}, + "backend": &BackendPlugin{ + metadataMode: isMetadataMode, + }, } - client, err := pluginRunner.Run(sys, pluginMap, handshakeConfig, []string{}, logger, isMetadataMode) + var client *plugin.Client + var err error + if isMetadataMode { + client, err = pluginRunner.RunMetadataMode(sys, pluginMap, handshakeConfig, []string{}, logger) + } else { + client, err = pluginRunner.Run(sys, pluginMap, handshakeConfig, []string{}, logger) + } if err != nil { return nil, err } diff --git a/logical/plugin/storage.go b/logical/plugin/storage.go index 55cea8449bf8..99c21f6461d0 100644 --- a/logical/plugin/storage.go +++ b/logical/plugin/storage.go @@ -117,3 +117,23 @@ type StoragePutReply struct { type StorageDeleteReply struct { Error *plugin.BasicError } + +// NOOPStorage is used to deny access to the storage interface while running a +// backend plugin in metadata mode. +type NOOPStorage struct{} + +func (s *NOOPStorage) List(prefix string) ([]string, error) { + return []string{}, nil +} + +func (s *NOOPStorage) Get(key string) (*logical.StorageEntry, error) { + return nil, nil +} + +func (s *NOOPStorage) Put(entry *logical.StorageEntry) error { + return nil +} + +func (s *NOOPStorage) Delete(key string) error { + return nil +}