From aad74443f63aed7357feedce715d028f67b1355c Mon Sep 17 00:00:00 2001 From: Ismail / David Date: Mon, 25 Jul 2022 14:20:40 -0500 Subject: [PATCH 1/3] allow running plugin in multiplexing mode --- .gitignore | 3 ++ cloudsql.go | 1 + cmd/vault-plugin-database-cloudsql/serve.go | 36 ++++++++++++++----- .../serve_test.go | 2 +- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 359c01c..aa5b2fd 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ build/ # fake google application default credentials for testing fake-creds.json + +# IDE +.vscode diff --git a/cloudsql.go b/cloudsql.go index df4a346..547de73 100644 --- a/cloudsql.go +++ b/cloudsql.go @@ -110,6 +110,7 @@ func newPostgresDatabase(dbType DBType, connProducer *connutil.SQLConnectionProd // // attribute 'sslmode=disable' is required. even though the sslmode parameter is set to disable, // the Cloud SQL Auth proxy does provide an encrypted connection. + // See: https://cloud.google.com/sql/docs/postgres/connect-admin-proxy#connect-to-proxy cleanup, err := pgxv4.RegisterDriver(dbType.String(), cloudsqlconn.WithIAMAuthN()) if err != nil { return nil, nil, nil, errors.Wrap(err, "failed to register 'postgres' driver with 'cloud-sql-go-connector'") diff --git a/cmd/vault-plugin-database-cloudsql/serve.go b/cmd/vault-plugin-database-cloudsql/serve.go index e32a12e..6894dfc 100644 --- a/cmd/vault-plugin-database-cloudsql/serve.go +++ b/cmd/vault-plugin-database-cloudsql/serve.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/go-plugin" "github.com/hashicorp/vault/api" dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5" + "github.com/pkg/errors" ) // Serve launches the plugin @@ -22,8 +23,10 @@ func Serve(ctx context.Context, testServerChan chan *plugin.ReattachConfig) { flags := apiClientMeta.FlagSet() var flagDBType string var flagLogLevel string + var flagMultiplex bool flags.StringVar(&flagDBType, "db-type", cloudsql.Postgres.String(), "can be: 'cloudsql-postgres'") flags.StringVar(&flagLogLevel, "log-level", "info", "can be: 'trace', 'debug', 'info', 'warn', 'error', 'off'") + flags.BoolVar(&flagMultiplex, "multiplex", true, "Whether to enable plugin multiplexing. can be: 'true' or 'false'") err := flags.Parse(os.Args[1:]) if err != nil { fmt.Printf("unable to parse plugin arguments: %s", err) @@ -35,20 +38,36 @@ func Serve(ctx context.Context, testServerChan chan *plugin.ReattachConfig) { Level: hclog.LevelFromString(flagLogLevel), }) - // initialize "cloudsql" database plugin - cloudsqlDatabase, err := cloudsql.New(cloudsql.DBType(flagDBType)) - if err != nil { - logger.Error("failed to initialize cloudsql database plugin. aborting now.", err) - os.Exit(1) + // provide factory to initialize a "cloudsql" database plugin + pluginFactory := func() (interface{}, error) { + cloudsqlDatabase, err := cloudsql.New(cloudsql.DBType(flagDBType)) + if err != nil { + return nil, errors.Wrap(err, "failed to get new instance of cloudsql database plugin") + } + return cloudsqlDatabase, nil } // Vault communicates to plugins over RPC // start RPC server to which vault will connect to // See: https://www.vaultproject.io/docs/secrets/databases/custom#serving-a-plugin - // TODO determine whether ServeMultiplex is required - // See: https://www.vaultproject.io/docs/plugins/plugin-architecture#plugin-multiplexing - serveConfig := dbplugin.ServeConfig(cloudsqlDatabase.(dbplugin.Database)) + var serveConfig *plugin.ServeConfig + if flagMultiplex { + // See: https://www.vaultproject.io/docs/plugins/plugin-architecture#plugin-multiplexing + serveConfig = dbplugin.ServeConfigMultiplex(pluginFactory) + } else { + dbPlugin, err := pluginFactory() + if err != nil { + logger.Error("failed to initialize database plugin. aborting now.", err) + os.Exit(1) + } + serveConfig = dbplugin.ServeConfig(dbPlugin.(dbplugin.Database)) + } + if serveConfig == nil { + logger.Error("failed to initialize server config for plugin. aborting now.") + os.Exit(1) + } if testServerChan != nil { + // if running in test mode, use channel to pry into the plugin's lifecycle serveConfig.Test = &plugin.ServeTestConfig{ Context: ctx, ReattachConfigCh: testServerChan, @@ -58,6 +77,5 @@ func Serve(ctx context.Context, testServerChan chan *plugin.ReattachConfig) { } else { serveConfig.Logger = logger } - plugin.Serve(serveConfig) } diff --git a/cmd/vault-plugin-database-cloudsql/serve_test.go b/cmd/vault-plugin-database-cloudsql/serve_test.go index 648a814..192a30e 100644 --- a/cmd/vault-plugin-database-cloudsql/serve_test.go +++ b/cmd/vault-plugin-database-cloudsql/serve_test.go @@ -12,7 +12,7 @@ import ( ) func TestServe(t *testing.T) { - os.Args = []string{"my-plugin"} + os.Args = []string{"my-plugin", "-multiplex=true"} ctx := context.Background() reattachConfigCh := make(chan *plugin.ReattachConfig) From 54d00cccbfb2b5480cdd9bccb20ecb497f6e2c4b Mon Sep 17 00:00:00 2001 From: Ismail / David Date: Mon, 25 Jul 2022 14:32:28 -0500 Subject: [PATCH 2/3] refactor server config initialization logic --- cmd/vault-plugin-database-cloudsql/serve.go | 40 ++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/cmd/vault-plugin-database-cloudsql/serve.go b/cmd/vault-plugin-database-cloudsql/serve.go index 6894dfc..a676f33 100644 --- a/cmd/vault-plugin-database-cloudsql/serve.go +++ b/cmd/vault-plugin-database-cloudsql/serve.go @@ -47,9 +47,30 @@ func Serve(ctx context.Context, testServerChan chan *plugin.ReattachConfig) { return cloudsqlDatabase, nil } + serveConfig, err := initServeConfig(flagMultiplex, pluginFactory, logger) + if err != nil { + logger.Error("failed to initialize database plugin. aborting now.", err) + os.Exit(1) + } + if testServerChan != nil { + // if running in test mode, use channel to pry into the plugin's lifecycle + serveConfig.Test = &plugin.ServeTestConfig{ + Context: ctx, + ReattachConfigCh: testServerChan, + CloseCh: nil, + } + serveConfig.Logger = hclog.NewNullLogger() + } else { + serveConfig.Logger = logger + } // Vault communicates to plugins over RPC // start RPC server to which vault will connect to // See: https://www.vaultproject.io/docs/secrets/databases/custom#serving-a-plugin + plugin.Serve(serveConfig) +} + +func initServeConfig(flagMultiplex bool, pluginFactory dbplugin.Factory, logger hclog.Logger) (*plugin.ServeConfig, error) { + logger.Debug("initializing cloudsql plugin with multiplexing=%t", flagMultiplex) var serveConfig *plugin.ServeConfig if flagMultiplex { // See: https://www.vaultproject.io/docs/plugins/plugin-architecture#plugin-multiplexing @@ -57,25 +78,12 @@ func Serve(ctx context.Context, testServerChan chan *plugin.ReattachConfig) { } else { dbPlugin, err := pluginFactory() if err != nil { - logger.Error("failed to initialize database plugin. aborting now.", err) - os.Exit(1) + return nil, errors.Wrap(err, "failed to create new plugin instance") } serveConfig = dbplugin.ServeConfig(dbPlugin.(dbplugin.Database)) } if serveConfig == nil { - logger.Error("failed to initialize server config for plugin. aborting now.") - os.Exit(1) + return nil, errors.New("failed to initialize server config for plugin") } - if testServerChan != nil { - // if running in test mode, use channel to pry into the plugin's lifecycle - serveConfig.Test = &plugin.ServeTestConfig{ - Context: ctx, - ReattachConfigCh: testServerChan, - CloseCh: nil, - } - serveConfig.Logger = hclog.NewNullLogger() - } else { - serveConfig.Logger = logger - } - plugin.Serve(serveConfig) + return serveConfig, nil } From 93040ccadf8b7bc5c04c31bc79ad079d79476170 Mon Sep 17 00:00:00 2001 From: Ismail Ahmad Date: Tue, 26 Jul 2022 11:26:45 -0400 Subject: [PATCH 3/3] chore: refactor variable name --- README.md | 1 + cmd/vault-plugin-database-cloudsql/serve.go | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 08e51ff..3046bb5 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ The following plugin arguments are supported: * `-db-type`, defaults to `cloudsql-postgres`. This is currently the only supported database type. * `-log-level`, defaults to `info` +* `multiplex`, defaults to `true` ## Getting Started diff --git a/cmd/vault-plugin-database-cloudsql/serve.go b/cmd/vault-plugin-database-cloudsql/serve.go index a676f33..06c453e 100644 --- a/cmd/vault-plugin-database-cloudsql/serve.go +++ b/cmd/vault-plugin-database-cloudsql/serve.go @@ -69,10 +69,10 @@ func Serve(ctx context.Context, testServerChan chan *plugin.ReattachConfig) { plugin.Serve(serveConfig) } -func initServeConfig(flagMultiplex bool, pluginFactory dbplugin.Factory, logger hclog.Logger) (*plugin.ServeConfig, error) { - logger.Debug("initializing cloudsql plugin with multiplexing=%t", flagMultiplex) +func initServeConfig(multiplex bool, pluginFactory dbplugin.Factory, logger hclog.Logger) (*plugin.ServeConfig, error) { + logger.Debug("initializing cloudsql plugin with multiplexing=%t", multiplex) var serveConfig *plugin.ServeConfig - if flagMultiplex { + if multiplex { // See: https://www.vaultproject.io/docs/plugins/plugin-architecture#plugin-multiplexing serveConfig = dbplugin.ServeConfigMultiplex(pluginFactory) } else {