mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 11:38:02 +00:00
[DBPW 5/X] Use AutoMTLS with DB plugins (#10008)
This commit is contained in:
@@ -6,7 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
"github.com/hashicorp/vault/api"
|
|
||||||
"github.com/hashicorp/vault/sdk/database/newdbplugin"
|
"github.com/hashicorp/vault/sdk/database/newdbplugin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,13 +25,13 @@ func New() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run instantiates a MongoDB object, and runs the RPC server for the plugin
|
// Run instantiates a MongoDB object, and runs the RPC server for the plugin
|
||||||
func RunV5(apiTLSConfig *api.TLSConfig) error {
|
func RunV5() error {
|
||||||
dbType, err := New()
|
dbType, err := New()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
|
newdbplugin.Serve(dbType.(newdbplugin.Database))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ func TestBackend_PluginMain_MockV5(t *testing.T) {
|
|||||||
flags := apiClientMeta.FlagSet()
|
flags := apiClientMeta.FlagSet()
|
||||||
flags.Parse(args)
|
flags.Parse(args)
|
||||||
|
|
||||||
RunV5(apiClientMeta.GetTLSConfig())
|
RunV5()
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertNoRespData(t *testing.T, resp *logical.Response) {
|
func assertNoRespData(t *testing.T, resp *logical.Response) {
|
||||||
|
|||||||
@@ -39,13 +39,14 @@ func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunne
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var client *plugin.Client
|
client, err := pluginRunner.RunConfig(ctx,
|
||||||
var err error
|
pluginutil.Runner(sys),
|
||||||
if isMetadataMode {
|
pluginutil.PluginSets(pluginSets),
|
||||||
client, err = pluginRunner.RunMetadataMode(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
pluginutil.HandshakeConfig(handshakeConfig),
|
||||||
} else {
|
pluginutil.Logger(logger),
|
||||||
client, err = pluginRunner.Run(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
pluginutil.MetadataMode(isMetadataMode),
|
||||||
}
|
pluginutil.AutoMTLS(true),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package newdbplugin
|
package newdbplugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
@@ -11,11 +10,11 @@ import (
|
|||||||
// Serve is called from within a plugin and wraps the provided
|
// Serve is called from within a plugin and wraps the provided
|
||||||
// Database implementation in a databasePluginRPCServer object and starts a
|
// Database implementation in a databasePluginRPCServer object and starts a
|
||||||
// RPC server.
|
// RPC server.
|
||||||
func Serve(db Database, tlsProvider func() (*tls.Config, error)) {
|
func Serve(db Database) {
|
||||||
plugin.Serve(ServeConfig(db, tlsProvider))
|
plugin.Serve(ServeConfig(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServeConfig(db Database, tlsProvider func() (*tls.Config, error)) *plugin.ServeConfig {
|
func ServeConfig(db Database) *plugin.ServeConfig {
|
||||||
err := pluginutil.OptionallyEnableMlock()
|
err := pluginutil.OptionallyEnableMlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -34,7 +33,6 @@ func ServeConfig(db Database, tlsProvider func() (*tls.Config, error)) *plugin.S
|
|||||||
conf := &plugin.ServeConfig{
|
conf := &plugin.ServeConfig{
|
||||||
HandshakeConfig: handshakeConfig,
|
HandshakeConfig: handshakeConfig,
|
||||||
VersionedPlugins: pluginSets,
|
VersionedPlugins: pluginSets,
|
||||||
TLSProvider: tlsProvider,
|
|
||||||
GRPCServer: plugin.DefaultGRPCServer,
|
GRPCServer: plugin.DefaultGRPCServer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
161
sdk/helper/pluginutil/run_config.go
Normal file
161
sdk/helper/pluginutil/run_config.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
package pluginutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
log "github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vault/sdk/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type runConfig struct {
|
||||||
|
// Provided by PluginRunner
|
||||||
|
command string
|
||||||
|
args []string
|
||||||
|
sha256 []byte
|
||||||
|
|
||||||
|
// Initialized with what's in PluginRunner.Env, but can be added to
|
||||||
|
env []string
|
||||||
|
|
||||||
|
wrapper RunnerUtil
|
||||||
|
pluginSets map[int]plugin.PluginSet
|
||||||
|
hs plugin.HandshakeConfig
|
||||||
|
logger log.Logger
|
||||||
|
isMetadataMode bool
|
||||||
|
autoMTLS bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc runConfig) makeConfig(ctx context.Context) (*plugin.ClientConfig, error) {
|
||||||
|
cmd := exec.Command(rc.command, rc.args...)
|
||||||
|
cmd.Env = append(cmd.Env, rc.env...)
|
||||||
|
|
||||||
|
// Add the mlock setting to the ENV of the plugin
|
||||||
|
if rc.wrapper != nil && rc.wrapper.MlockEnabled() {
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true"))
|
||||||
|
}
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version))
|
||||||
|
|
||||||
|
if rc.isMetadataMode {
|
||||||
|
rc.logger = rc.logger.With("metadata", "true")
|
||||||
|
}
|
||||||
|
metadataEnv := fmt.Sprintf("%s=%t", PluginMetadataModeEnv, rc.isMetadataMode)
|
||||||
|
cmd.Env = append(cmd.Env, metadataEnv)
|
||||||
|
|
||||||
|
var clientTLSConfig *tls.Config
|
||||||
|
if !rc.autoMTLS && !rc.isMetadataMode {
|
||||||
|
// Get a CA TLS Certificate
|
||||||
|
certBytes, key, err := generateCert()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use CA to sign a client cert and return a configured TLS config
|
||||||
|
clientTLSConfig, err = createClientTLSConfig(certBytes, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use CA to sign a server cert and wrap the values in a response wrapped
|
||||||
|
// token.
|
||||||
|
wrapToken, err := wrapServerConfig(ctx, rc.wrapper, certBytes, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the response wrap token to the ENV of the plugin
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, wrapToken))
|
||||||
|
}
|
||||||
|
|
||||||
|
secureConfig := &plugin.SecureConfig{
|
||||||
|
Checksum: rc.sha256,
|
||||||
|
Hash: sha256.New(),
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig := &plugin.ClientConfig{
|
||||||
|
HandshakeConfig: rc.hs,
|
||||||
|
VersionedPlugins: rc.pluginSets,
|
||||||
|
Cmd: cmd,
|
||||||
|
SecureConfig: secureConfig,
|
||||||
|
TLSConfig: clientTLSConfig,
|
||||||
|
Logger: rc.logger,
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolNetRPC,
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
AutoMTLS: rc.autoMTLS,
|
||||||
|
}
|
||||||
|
return clientConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc runConfig) run(ctx context.Context) (*plugin.Client, error) {
|
||||||
|
clientConfig, err := rc.makeConfig(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := plugin.NewClient(clientConfig)
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunOpt func(*runConfig)
|
||||||
|
|
||||||
|
func Env(env ...string) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.env = append(rc.env, env...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Runner(wrapper RunnerUtil) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.wrapper = wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PluginSets(pluginSets map[int]plugin.PluginSet) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.pluginSets = pluginSets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandshakeConfig(hs plugin.HandshakeConfig) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.hs = hs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Logger(logger log.Logger) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.logger = logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MetadataMode(isMetadataMode bool) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.isMetadataMode = isMetadataMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AutoMTLS(autoMTLS bool) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.autoMTLS = autoMTLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PluginRunner) RunConfig(ctx context.Context, opts ...RunOpt) (*plugin.Client, error) {
|
||||||
|
rc := runConfig{
|
||||||
|
command: r.Command,
|
||||||
|
args: r.Args,
|
||||||
|
sha256: r.Sha256,
|
||||||
|
env: r.Env,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc.run(ctx)
|
||||||
|
}
|
||||||
341
sdk/helper/pluginutil/run_config_test.go
Normal file
341
sdk/helper/pluginutil/run_config_test.go
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
package pluginutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/sdk/version"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vault/sdk/helper/wrapping"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNameMakeConfig(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
rc runConfig
|
||||||
|
|
||||||
|
responseWrapInfo *wrapping.ResponseWrapInfo
|
||||||
|
responseWrapInfoErr error
|
||||||
|
responseWrapInfoTimes int
|
||||||
|
|
||||||
|
mlockEnabled bool
|
||||||
|
mlockEnabledTimes int
|
||||||
|
|
||||||
|
expectedConfig *plugin.ClientConfig
|
||||||
|
expectTLSConfig bool
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := map[string]testCase{
|
||||||
|
"metadata mode, not-AutoMTLS": {
|
||||||
|
rc: runConfig{
|
||||||
|
command: "echo",
|
||||||
|
args: []string{"foo", "bar"},
|
||||||
|
sha256: []byte("some_sha256"),
|
||||||
|
env: []string{"initial=true"},
|
||||||
|
pluginSets: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hs: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
logger: hclog.NewNullLogger(),
|
||||||
|
isMetadataMode: true,
|
||||||
|
autoMTLS: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
responseWrapInfoTimes: 0,
|
||||||
|
|
||||||
|
mlockEnabled: false,
|
||||||
|
mlockEnabledTimes: 1,
|
||||||
|
|
||||||
|
expectedConfig: &plugin.ClientConfig{
|
||||||
|
HandshakeConfig: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
VersionedPlugins: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Cmd: commandWithEnv(
|
||||||
|
"echo",
|
||||||
|
[]string{"foo", "bar"},
|
||||||
|
[]string{
|
||||||
|
"initial=true",
|
||||||
|
fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version),
|
||||||
|
fmt.Sprintf("%s=%t", PluginMetadataModeEnv, true),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SecureConfig: &plugin.SecureConfig{
|
||||||
|
Checksum: []byte("some_sha256"),
|
||||||
|
// Hash is generated
|
||||||
|
},
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolNetRPC,
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
Logger: hclog.NewNullLogger(),
|
||||||
|
AutoMTLS: false,
|
||||||
|
},
|
||||||
|
expectTLSConfig: false,
|
||||||
|
},
|
||||||
|
"non-metadata mode, not-AutoMTLS": {
|
||||||
|
rc: runConfig{
|
||||||
|
command: "echo",
|
||||||
|
args: []string{"foo", "bar"},
|
||||||
|
sha256: []byte("some_sha256"),
|
||||||
|
env: []string{"initial=true"},
|
||||||
|
pluginSets: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hs: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
logger: hclog.NewNullLogger(),
|
||||||
|
isMetadataMode: false,
|
||||||
|
autoMTLS: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
responseWrapInfo: &wrapping.ResponseWrapInfo{
|
||||||
|
Token: "testtoken",
|
||||||
|
},
|
||||||
|
responseWrapInfoTimes: 1,
|
||||||
|
|
||||||
|
mlockEnabled: true,
|
||||||
|
mlockEnabledTimes: 1,
|
||||||
|
|
||||||
|
expectedConfig: &plugin.ClientConfig{
|
||||||
|
HandshakeConfig: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
VersionedPlugins: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Cmd: commandWithEnv(
|
||||||
|
"echo",
|
||||||
|
[]string{"foo", "bar"},
|
||||||
|
[]string{
|
||||||
|
"initial=true",
|
||||||
|
fmt.Sprintf("%s=%t", PluginMlockEnabled, true),
|
||||||
|
fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version),
|
||||||
|
fmt.Sprintf("%s=%t", PluginMetadataModeEnv, false),
|
||||||
|
fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, "testtoken"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SecureConfig: &plugin.SecureConfig{
|
||||||
|
Checksum: []byte("some_sha256"),
|
||||||
|
// Hash is generated
|
||||||
|
},
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolNetRPC,
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
Logger: hclog.NewNullLogger(),
|
||||||
|
AutoMTLS: false,
|
||||||
|
},
|
||||||
|
expectTLSConfig: true,
|
||||||
|
},
|
||||||
|
"metadata mode, AutoMTLS": {
|
||||||
|
rc: runConfig{
|
||||||
|
command: "echo",
|
||||||
|
args: []string{"foo", "bar"},
|
||||||
|
sha256: []byte("some_sha256"),
|
||||||
|
env: []string{"initial=true"},
|
||||||
|
pluginSets: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hs: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
logger: hclog.NewNullLogger(),
|
||||||
|
isMetadataMode: true,
|
||||||
|
autoMTLS: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
responseWrapInfoTimes: 0,
|
||||||
|
|
||||||
|
mlockEnabled: false,
|
||||||
|
mlockEnabledTimes: 1,
|
||||||
|
|
||||||
|
expectedConfig: &plugin.ClientConfig{
|
||||||
|
HandshakeConfig: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
VersionedPlugins: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Cmd: commandWithEnv(
|
||||||
|
"echo",
|
||||||
|
[]string{"foo", "bar"},
|
||||||
|
[]string{
|
||||||
|
"initial=true",
|
||||||
|
fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version),
|
||||||
|
fmt.Sprintf("%s=%t", PluginMetadataModeEnv, true),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SecureConfig: &plugin.SecureConfig{
|
||||||
|
Checksum: []byte("some_sha256"),
|
||||||
|
// Hash is generated
|
||||||
|
},
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolNetRPC,
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
Logger: hclog.NewNullLogger(),
|
||||||
|
AutoMTLS: true,
|
||||||
|
},
|
||||||
|
expectTLSConfig: false,
|
||||||
|
},
|
||||||
|
"not-metadata mode, AutoMTLS": {
|
||||||
|
rc: runConfig{
|
||||||
|
command: "echo",
|
||||||
|
args: []string{"foo", "bar"},
|
||||||
|
sha256: []byte("some_sha256"),
|
||||||
|
env: []string{"initial=true"},
|
||||||
|
pluginSets: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
hs: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
logger: hclog.NewNullLogger(),
|
||||||
|
isMetadataMode: false,
|
||||||
|
autoMTLS: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
responseWrapInfoTimes: 0,
|
||||||
|
|
||||||
|
mlockEnabled: false,
|
||||||
|
mlockEnabledTimes: 1,
|
||||||
|
|
||||||
|
expectedConfig: &plugin.ClientConfig{
|
||||||
|
HandshakeConfig: plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "magic_cookie_key",
|
||||||
|
MagicCookieValue: "magic_cookie_value",
|
||||||
|
},
|
||||||
|
VersionedPlugins: map[int]plugin.PluginSet{
|
||||||
|
1: plugin.PluginSet{
|
||||||
|
"bogus": nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Cmd: commandWithEnv(
|
||||||
|
"echo",
|
||||||
|
[]string{"foo", "bar"},
|
||||||
|
[]string{
|
||||||
|
"initial=true",
|
||||||
|
fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version),
|
||||||
|
fmt.Sprintf("%s=%t", PluginMetadataModeEnv, false),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SecureConfig: &plugin.SecureConfig{
|
||||||
|
Checksum: []byte("some_sha256"),
|
||||||
|
// Hash is generated
|
||||||
|
},
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolNetRPC,
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
Logger: hclog.NewNullLogger(),
|
||||||
|
AutoMTLS: true,
|
||||||
|
},
|
||||||
|
expectTLSConfig: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, test := range tests {
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
mockWrapper := new(mockRunnerUtil)
|
||||||
|
mockWrapper.On("ResponseWrapData", mock.Anything, mock.Anything, mock.Anything, mock.Anything).
|
||||||
|
Return(test.responseWrapInfo, test.responseWrapInfoErr)
|
||||||
|
mockWrapper.On("MlockEnabled").
|
||||||
|
Return(test.mlockEnabled)
|
||||||
|
test.rc.wrapper = mockWrapper
|
||||||
|
defer mockWrapper.AssertNumberOfCalls(t, "ResponseWrapData", test.responseWrapInfoTimes)
|
||||||
|
defer mockWrapper.AssertNumberOfCalls(t, "MlockEnabled", test.mlockEnabledTimes)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
config, err := test.rc.makeConfig(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("no error expected, got: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Certain fields will need to be checked for existence, not specific value
|
||||||
|
// The following fields are generated, so we just need to check for existence, not specific value
|
||||||
|
// The value must be nilled out before performing a DeepEqual check
|
||||||
|
hsh := config.SecureConfig.Hash
|
||||||
|
if hsh == nil {
|
||||||
|
t.Fatalf("Missing SecureConfig.Hash")
|
||||||
|
}
|
||||||
|
config.SecureConfig.Hash = nil
|
||||||
|
|
||||||
|
if test.expectTLSConfig && config.TLSConfig == nil {
|
||||||
|
t.Fatalf("TLS config expected, got nil")
|
||||||
|
}
|
||||||
|
if !test.expectTLSConfig && config.TLSConfig != nil {
|
||||||
|
t.Fatalf("no TLS config expected, got: %#v", config.TLSConfig)
|
||||||
|
}
|
||||||
|
config.TLSConfig = nil
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(config, test.expectedConfig) {
|
||||||
|
t.Fatalf("Actual config: %#v\nExpected config: %#v", config, test.expectedConfig)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandWithEnv(cmd string, args []string, env []string) *exec.Cmd {
|
||||||
|
c := exec.Command(cmd, args...)
|
||||||
|
c.Env = env
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ RunnerUtil = &mockRunnerUtil{}
|
||||||
|
|
||||||
|
type mockRunnerUtil struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRunnerUtil) ResponseWrapData(ctx context.Context, data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) {
|
||||||
|
args := m.Called(ctx, data, ttl, jwt)
|
||||||
|
return args.Get(0).(*wrapping.ResponseWrapInfo), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockRunnerUtil) MlockEnabled() bool {
|
||||||
|
args := m.Called()
|
||||||
|
return args.Bool(0)
|
||||||
|
}
|
||||||
@@ -2,17 +2,12 @@ package pluginutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||||
"github.com/hashicorp/vault/sdk/helper/wrapping"
|
"github.com/hashicorp/vault/sdk/helper/wrapping"
|
||||||
"github.com/hashicorp/vault/sdk/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Looker defines the plugin Lookup function that looks into the plugin catalog
|
// Looker defines the plugin Lookup function that looks into the plugin catalog
|
||||||
@@ -53,83 +48,28 @@ type PluginRunner struct {
|
|||||||
// returns a configured plugin.Client with TLS Configured and a wrapping token set
|
// returns a configured plugin.Client with TLS Configured and a wrapping token set
|
||||||
// on PluginUnwrapTokenEnv for plugin process consumption.
|
// on PluginUnwrapTokenEnv for plugin process consumption.
|
||||||
func (r *PluginRunner) Run(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
func (r *PluginRunner) Run(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
||||||
return r.runCommon(ctx, wrapper, pluginSets, hs, env, logger, false)
|
return r.RunConfig(ctx,
|
||||||
|
Runner(wrapper),
|
||||||
|
PluginSets(pluginSets),
|
||||||
|
HandshakeConfig(hs),
|
||||||
|
Env(env...),
|
||||||
|
Logger(logger),
|
||||||
|
MetadataMode(false),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunMetadataMode returns a configured plugin.Client that will dispense a plugin
|
// RunMetadataMode returns a configured plugin.Client that will dispense a plugin
|
||||||
// in metadata mode. The PluginMetadataModeEnv is passed in as part of the Cmd to
|
// in metadata mode. The PluginMetadataModeEnv is passed in as part of the Cmd to
|
||||||
// plugin.Client, and consumed by the plugin process on api.VaultPluginTLSProvider.
|
// plugin.Client, and consumed by the plugin process on api.VaultPluginTLSProvider.
|
||||||
func (r *PluginRunner) RunMetadataMode(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
func (r *PluginRunner) RunMetadataMode(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
||||||
return r.runCommon(ctx, wrapper, pluginSets, hs, env, logger, true)
|
return r.RunConfig(ctx,
|
||||||
|
Runner(wrapper),
|
||||||
}
|
PluginSets(pluginSets),
|
||||||
|
HandshakeConfig(hs),
|
||||||
func (r *PluginRunner) runCommon(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger, isMetadataMode bool) (*plugin.Client, error) {
|
Env(env...),
|
||||||
cmd := exec.Command(r.Command, r.Args...)
|
Logger(logger),
|
||||||
|
MetadataMode(true),
|
||||||
// `env` should always go last to avoid overwriting internal values that might
|
)
|
||||||
// have been provided externally.
|
|
||||||
cmd.Env = append(cmd.Env, r.Env...)
|
|
||||||
cmd.Env = append(cmd.Env, env...)
|
|
||||||
|
|
||||||
// Add the mlock setting to the ENV of the plugin
|
|
||||||
if wrapper != nil && wrapper.MlockEnabled() {
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true"))
|
|
||||||
}
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version))
|
|
||||||
|
|
||||||
var clientTLSConfig *tls.Config
|
|
||||||
if !isMetadataMode {
|
|
||||||
// Add the metadata mode ENV and set it to false
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadataModeEnv, "false"))
|
|
||||||
|
|
||||||
// Get a CA TLS Certificate
|
|
||||||
certBytes, key, err := generateCert()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use CA to sign a client cert and return a configured TLS config
|
|
||||||
clientTLSConfig, err = createClientTLSConfig(certBytes, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use CA to sign a server cert and wrap the values in a response wrapped
|
|
||||||
// token.
|
|
||||||
wrapToken, err := wrapServerConfig(ctx, wrapper, certBytes, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the response wrap token to the ENV of the plugin
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, wrapToken))
|
|
||||||
} else {
|
|
||||||
logger = logger.With("metadata", "true")
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadataModeEnv, "true"))
|
|
||||||
}
|
|
||||||
|
|
||||||
secureConfig := &plugin.SecureConfig{
|
|
||||||
Checksum: r.Sha256,
|
|
||||||
Hash: sha256.New(),
|
|
||||||
}
|
|
||||||
|
|
||||||
clientConfig := &plugin.ClientConfig{
|
|
||||||
HandshakeConfig: hs,
|
|
||||||
VersionedPlugins: pluginSets,
|
|
||||||
Cmd: cmd,
|
|
||||||
SecureConfig: secureConfig,
|
|
||||||
TLSConfig: clientTLSConfig,
|
|
||||||
Logger: logger,
|
|
||||||
AllowedProtocols: []plugin.Protocol{
|
|
||||||
plugin.ProtocolNetRPC,
|
|
||||||
plugin.ProtocolGRPC,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
client := plugin.NewClient(clientConfig)
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CtxCancelIfCanceled takes a context cancel func and a context. If the context is
|
// CtxCancelIfCanceled takes a context cancel func and a context. If the context is
|
||||||
|
|||||||
15
vendor/github.com/hashicorp/vault/sdk/database/newdbplugin/plugin_client.go
generated
vendored
15
vendor/github.com/hashicorp/vault/sdk/database/newdbplugin/plugin_client.go
generated
vendored
@@ -39,13 +39,14 @@ func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunne
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var client *plugin.Client
|
client, err := pluginRunner.RunConfig(ctx,
|
||||||
var err error
|
pluginutil.Runner(sys),
|
||||||
if isMetadataMode {
|
pluginutil.PluginSets(pluginSets),
|
||||||
client, err = pluginRunner.RunMetadataMode(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
pluginutil.HandshakeConfig(handshakeConfig),
|
||||||
} else {
|
pluginutil.Logger(logger),
|
||||||
client, err = pluginRunner.Run(ctx, sys, pluginSets, handshakeConfig, []string{}, logger)
|
pluginutil.MetadataMode(isMetadataMode),
|
||||||
}
|
pluginutil.AutoMTLS(true),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
8
vendor/github.com/hashicorp/vault/sdk/database/newdbplugin/plugin_server.go
generated
vendored
8
vendor/github.com/hashicorp/vault/sdk/database/newdbplugin/plugin_server.go
generated
vendored
@@ -1,7 +1,6 @@
|
|||||||
package newdbplugin
|
package newdbplugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/go-plugin"
|
"github.com/hashicorp/go-plugin"
|
||||||
@@ -11,11 +10,11 @@ import (
|
|||||||
// Serve is called from within a plugin and wraps the provided
|
// Serve is called from within a plugin and wraps the provided
|
||||||
// Database implementation in a databasePluginRPCServer object and starts a
|
// Database implementation in a databasePluginRPCServer object and starts a
|
||||||
// RPC server.
|
// RPC server.
|
||||||
func Serve(db Database, tlsProvider func() (*tls.Config, error)) {
|
func Serve(db Database) {
|
||||||
plugin.Serve(ServeConfig(db, tlsProvider))
|
plugin.Serve(ServeConfig(db))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServeConfig(db Database, tlsProvider func() (*tls.Config, error)) *plugin.ServeConfig {
|
func ServeConfig(db Database) *plugin.ServeConfig {
|
||||||
err := pluginutil.OptionallyEnableMlock()
|
err := pluginutil.OptionallyEnableMlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -34,7 +33,6 @@ func ServeConfig(db Database, tlsProvider func() (*tls.Config, error)) *plugin.S
|
|||||||
conf := &plugin.ServeConfig{
|
conf := &plugin.ServeConfig{
|
||||||
HandshakeConfig: handshakeConfig,
|
HandshakeConfig: handshakeConfig,
|
||||||
VersionedPlugins: pluginSets,
|
VersionedPlugins: pluginSets,
|
||||||
TLSProvider: tlsProvider,
|
|
||||||
GRPCServer: plugin.DefaultGRPCServer,
|
GRPCServer: plugin.DefaultGRPCServer,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
154
vendor/github.com/hashicorp/vault/sdk/helper/pluginutil/run_config.go
generated
vendored
Normal file
154
vendor/github.com/hashicorp/vault/sdk/helper/pluginutil/run_config.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package pluginutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
log "github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vault/sdk/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type runConfig struct {
|
||||||
|
// Provided by PluginRunner
|
||||||
|
command string
|
||||||
|
args []string
|
||||||
|
sha256 []byte
|
||||||
|
|
||||||
|
// Initialized with what's in PluginRunner.Env, but can be added to
|
||||||
|
env []string
|
||||||
|
|
||||||
|
wrapper RunnerUtil
|
||||||
|
pluginSets map[int]plugin.PluginSet
|
||||||
|
hs plugin.HandshakeConfig
|
||||||
|
logger log.Logger
|
||||||
|
isMetadataMode bool
|
||||||
|
autoMTLS bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc runConfig) run(ctx context.Context) (*plugin.Client, error) {
|
||||||
|
cmd := exec.Command(rc.command, rc.args...)
|
||||||
|
cmd.Env = append(cmd.Env, rc.env...)
|
||||||
|
|
||||||
|
// Add the mlock setting to the ENV of the plugin
|
||||||
|
if rc.wrapper != nil && rc.wrapper.MlockEnabled() {
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true"))
|
||||||
|
}
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version))
|
||||||
|
|
||||||
|
var clientTLSConfig *tls.Config
|
||||||
|
if !rc.isMetadataMode {
|
||||||
|
// Add the metadata mode ENV and set it to false
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadataModeEnv, "false"))
|
||||||
|
|
||||||
|
// Get a CA TLS Certificate
|
||||||
|
certBytes, key, err := generateCert()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use CA to sign a client cert and return a configured TLS config
|
||||||
|
clientTLSConfig, err = createClientTLSConfig(certBytes, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use CA to sign a server cert and wrap the values in a response wrapped
|
||||||
|
// token.
|
||||||
|
wrapToken, err := wrapServerConfig(ctx, rc.wrapper, certBytes, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the response wrap token to the ENV of the plugin
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, wrapToken))
|
||||||
|
} else {
|
||||||
|
rc.logger = rc.logger.With("metadata", "true")
|
||||||
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadataModeEnv, "true"))
|
||||||
|
}
|
||||||
|
|
||||||
|
secureConfig := &plugin.SecureConfig{
|
||||||
|
Checksum: rc.sha256,
|
||||||
|
Hash: sha256.New(),
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig := &plugin.ClientConfig{
|
||||||
|
HandshakeConfig: rc.hs,
|
||||||
|
VersionedPlugins: rc.pluginSets,
|
||||||
|
Cmd: cmd,
|
||||||
|
SecureConfig: secureConfig,
|
||||||
|
TLSConfig: clientTLSConfig,
|
||||||
|
Logger: rc.logger,
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolNetRPC,
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
AutoMTLS: rc.autoMTLS,
|
||||||
|
}
|
||||||
|
|
||||||
|
client := plugin.NewClient(clientConfig)
|
||||||
|
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type RunOpt func(*runConfig)
|
||||||
|
|
||||||
|
func Env(env ...string) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.env = append(rc.env, env...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Runner(wrapper RunnerUtil) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.wrapper = wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PluginSets(pluginSets map[int]plugin.PluginSet) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.pluginSets = pluginSets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandshakeConfig(hs plugin.HandshakeConfig) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.hs = hs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Logger(logger log.Logger) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.logger = logger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MetadataMode(isMetadataMode bool) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.isMetadataMode = isMetadataMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AutoMTLS(autoMTLS bool) RunOpt {
|
||||||
|
return func(rc *runConfig) {
|
||||||
|
rc.autoMTLS = autoMTLS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PluginRunner) RunConfig(ctx context.Context, opts ...RunOpt) (*plugin.Client, error) {
|
||||||
|
rc := runConfig{
|
||||||
|
command: r.Command,
|
||||||
|
args: r.Args,
|
||||||
|
sha256: r.Sha256,
|
||||||
|
env: r.Env,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc.run(ctx)
|
||||||
|
}
|
||||||
92
vendor/github.com/hashicorp/vault/sdk/helper/pluginutil/runner.go
generated
vendored
92
vendor/github.com/hashicorp/vault/sdk/helper/pluginutil/runner.go
generated
vendored
@@ -2,17 +2,12 @@ package pluginutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/hashicorp/go-hclog"
|
log "github.com/hashicorp/go-hclog"
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||||
"github.com/hashicorp/vault/sdk/helper/wrapping"
|
"github.com/hashicorp/vault/sdk/helper/wrapping"
|
||||||
"github.com/hashicorp/vault/sdk/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Looker defines the plugin Lookup function that looks into the plugin catalog
|
// Looker defines the plugin Lookup function that looks into the plugin catalog
|
||||||
@@ -53,83 +48,28 @@ type PluginRunner struct {
|
|||||||
// returns a configured plugin.Client with TLS Configured and a wrapping token set
|
// returns a configured plugin.Client with TLS Configured and a wrapping token set
|
||||||
// on PluginUnwrapTokenEnv for plugin process consumption.
|
// on PluginUnwrapTokenEnv for plugin process consumption.
|
||||||
func (r *PluginRunner) Run(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
func (r *PluginRunner) Run(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
||||||
return r.runCommon(ctx, wrapper, pluginSets, hs, env, logger, false)
|
return r.RunConfig(ctx,
|
||||||
|
Runner(wrapper),
|
||||||
|
PluginSets(pluginSets),
|
||||||
|
HandshakeConfig(hs),
|
||||||
|
Env(env...),
|
||||||
|
Logger(logger),
|
||||||
|
MetadataMode(false),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunMetadataMode returns a configured plugin.Client that will dispense a plugin
|
// RunMetadataMode returns a configured plugin.Client that will dispense a plugin
|
||||||
// in metadata mode. The PluginMetadataModeEnv is passed in as part of the Cmd to
|
// in metadata mode. The PluginMetadataModeEnv is passed in as part of the Cmd to
|
||||||
// plugin.Client, and consumed by the plugin process on api.VaultPluginTLSProvider.
|
// plugin.Client, and consumed by the plugin process on api.VaultPluginTLSProvider.
|
||||||
func (r *PluginRunner) RunMetadataMode(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
func (r *PluginRunner) RunMetadataMode(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger) (*plugin.Client, error) {
|
||||||
return r.runCommon(ctx, wrapper, pluginSets, hs, env, logger, true)
|
return r.RunConfig(ctx,
|
||||||
|
Runner(wrapper),
|
||||||
}
|
PluginSets(pluginSets),
|
||||||
|
HandshakeConfig(hs),
|
||||||
func (r *PluginRunner) runCommon(ctx context.Context, wrapper RunnerUtil, pluginSets map[int]plugin.PluginSet, hs plugin.HandshakeConfig, env []string, logger log.Logger, isMetadataMode bool) (*plugin.Client, error) {
|
Env(env...),
|
||||||
cmd := exec.Command(r.Command, r.Args...)
|
Logger(logger),
|
||||||
|
MetadataMode(true),
|
||||||
// `env` should always go last to avoid overwriting internal values that might
|
)
|
||||||
// have been provided externally.
|
|
||||||
cmd.Env = append(cmd.Env, r.Env...)
|
|
||||||
cmd.Env = append(cmd.Env, env...)
|
|
||||||
|
|
||||||
// Add the mlock setting to the ENV of the plugin
|
|
||||||
if wrapper != nil && wrapper.MlockEnabled() {
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true"))
|
|
||||||
}
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version))
|
|
||||||
|
|
||||||
var clientTLSConfig *tls.Config
|
|
||||||
if !isMetadataMode {
|
|
||||||
// Add the metadata mode ENV and set it to false
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadataModeEnv, "false"))
|
|
||||||
|
|
||||||
// Get a CA TLS Certificate
|
|
||||||
certBytes, key, err := generateCert()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use CA to sign a client cert and return a configured TLS config
|
|
||||||
clientTLSConfig, err = createClientTLSConfig(certBytes, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use CA to sign a server cert and wrap the values in a response wrapped
|
|
||||||
// token.
|
|
||||||
wrapToken, err := wrapServerConfig(ctx, wrapper, certBytes, key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the response wrap token to the ENV of the plugin
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, wrapToken))
|
|
||||||
} else {
|
|
||||||
logger = logger.With("metadata", "true")
|
|
||||||
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMetadataModeEnv, "true"))
|
|
||||||
}
|
|
||||||
|
|
||||||
secureConfig := &plugin.SecureConfig{
|
|
||||||
Checksum: r.Sha256,
|
|
||||||
Hash: sha256.New(),
|
|
||||||
}
|
|
||||||
|
|
||||||
clientConfig := &plugin.ClientConfig{
|
|
||||||
HandshakeConfig: hs,
|
|
||||||
VersionedPlugins: pluginSets,
|
|
||||||
Cmd: cmd,
|
|
||||||
SecureConfig: secureConfig,
|
|
||||||
TLSConfig: clientTLSConfig,
|
|
||||||
Logger: logger,
|
|
||||||
AllowedProtocols: []plugin.Protocol{
|
|
||||||
plugin.ProtocolNetRPC,
|
|
||||||
plugin.ProtocolGRPC,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
client := plugin.NewClient(clientConfig)
|
|
||||||
|
|
||||||
return client, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CtxCancelIfCanceled takes a context cancel func and a context. If the context is
|
// CtxCancelIfCanceled takes a context cancel func and a context. If the context is
|
||||||
|
|||||||
2
vendor/github.com/kr/pretty/formatter.go
generated
vendored
2
vendor/github.com/kr/pretty/formatter.go
generated
vendored
@@ -37,7 +37,7 @@ func (fo formatter) passThrough(f fmt.State, c rune) {
|
|||||||
s := "%"
|
s := "%"
|
||||||
for i := 0; i < 128; i++ {
|
for i := 0; i < 128; i++ {
|
||||||
if f.Flag(i) {
|
if f.Flag(i) {
|
||||||
s += string(i)
|
s += string(rune(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if w, ok := f.Width(); ok {
|
if w, ok := f.Width(); ok {
|
||||||
|
|||||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -657,7 +657,7 @@ github.com/keybase/go-crypto/openpgp/s2k
|
|||||||
github.com/keybase/go-crypto/rsa
|
github.com/keybase/go-crypto/rsa
|
||||||
# github.com/konsorten/go-windows-terminal-sequences v1.0.3
|
# github.com/konsorten/go-windows-terminal-sequences v1.0.3
|
||||||
github.com/konsorten/go-windows-terminal-sequences
|
github.com/konsorten/go-windows-terminal-sequences
|
||||||
# github.com/kr/pretty v0.2.0
|
# github.com/kr/pretty v0.2.1
|
||||||
github.com/kr/pretty
|
github.com/kr/pretty
|
||||||
# github.com/kr/text v0.2.0
|
# github.com/kr/text v0.2.0
|
||||||
github.com/kr/text
|
github.com/kr/text
|
||||||
|
|||||||
Reference in New Issue
Block a user