From 4c75326aad6b9a9a9ca1fdd4626007ab6dd4b10c Mon Sep 17 00:00:00 2001 From: Brian Kassouf Date: Wed, 12 Apr 2017 17:35:02 -0700 Subject: [PATCH] Cleanup path files --- builtin/logical/database/backend.go | 10 +-- builtin/logical/database/dbplugin/plugin.go | 9 --- .../database/path_config_connection.go | 71 +++++++++++-------- builtin/logical/database/path_roles.go | 1 + command/{plugin-exec.go => plugin_exec.go} | 0 5 files changed, 46 insertions(+), 45 deletions(-) rename command/{plugin-exec.go => plugin_exec.go} (100%) diff --git a/builtin/logical/database/backend.go b/builtin/logical/database/backend.go index c8f9ad8541..2ce7595260 100644 --- a/builtin/logical/database/backend.go +++ b/builtin/logical/database/backend.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/vault/logical/framework" ) -const databaseConfigPath = "database/dbs/" +const databaseConfigPath = "database/config/" // DatabaseConfig is used by the Factory function to configure a DatabaseType // object. @@ -32,12 +32,6 @@ func Backend(conf *logical.BackendConfig) *databaseBackend { b.Backend = &framework.Backend{ Help: strings.TrimSpace(backendHelp), - PathsSpecial: &logical.Paths{ - Root: []string{ - "dbs/plugin/*", - }, - }, - Paths: []*framework.Path{ pathConfigurePluginConnection(&b), pathListRoles(&b), @@ -90,7 +84,7 @@ func (b *databaseBackend) getOrCreateDBObj(s logical.Storage, name string) (dbpl return db, nil } - entry, err := s.Get(fmt.Sprintf("dbs/%s", name)) + entry, err := s.Get(fmt.Sprintf("config/%s", name)) if err != nil { return nil, fmt.Errorf("failed to read connection configuration with name: %s", name) } diff --git a/builtin/logical/database/dbplugin/plugin.go b/builtin/logical/database/dbplugin/plugin.go index 5e6ce939be..61de0fe8ce 100644 --- a/builtin/logical/database/dbplugin/plugin.go +++ b/builtin/logical/database/dbplugin/plugin.go @@ -1,7 +1,6 @@ package dbplugin import ( - "errors" "fmt" "net/rpc" "time" @@ -11,10 +10,6 @@ import ( log "github.com/mgutz/logxi/v1" ) -var ( - ErrEmptyPluginName = errors.New("empty plugin name") -) - // DatabaseType is the interface that all database objects must implement. type DatabaseType interface { Type() (string, error) @@ -37,10 +32,6 @@ type Statements struct { // PluginFactory is used to build plugin database types. It wraps the database // object in a logging and metrics middleware. func PluginFactory(pluginName string, sys pluginutil.LookWrapper, logger log.Logger) (DatabaseType, error) { - if pluginName == "" { - return nil, ErrEmptyPluginName - } - // Look for plugin in the plugin catalog pluginMeta, err := sys.LookupPlugin(pluginName) if err != nil { diff --git a/builtin/logical/database/path_config_connection.go b/builtin/logical/database/path_config_connection.go index 5817f53c2d..f69c7761b2 100644 --- a/builtin/logical/database/path_config_connection.go +++ b/builtin/logical/database/path_config_connection.go @@ -1,6 +1,7 @@ package database import ( + "errors" "fmt" "github.com/fatih/structs" @@ -9,6 +10,11 @@ import ( "github.com/hashicorp/vault/logical/framework" ) +var ( + respErrEmptyPluginName = logical.ErrorResponse("empty plugin name") + respErrEmptyName = logical.ErrorResponse("Empty name attribute given") +) + // pathResetConnection configures a path to reset a plugin. func pathResetConnection(b *databaseBackend) *framework.Path { return &framework.Path{ @@ -16,7 +22,7 @@ func pathResetConnection(b *databaseBackend) *framework.Path { Fields: map[string]*framework.FieldSchema{ "name": &framework.FieldSchema{ Type: framework.TypeString, - Description: "Name of this DB type", + Description: "Name of this database connection", }, }, @@ -35,15 +41,17 @@ func (b *databaseBackend) pathConnectionReset() framework.OperationFunc { return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("name").(string) if name == "" { - return logical.ErrorResponse("Empty name attribute given"), nil + return respErrEmptyName, nil } // Grab the mutex lock b.Lock() defer b.Unlock() + // Close plugin and delete the entry in the connections cache. b.clearConnection(name) + // Execute plugin again, we don't need the object so throw away. _, err := b.getOrCreateDBObj(req.Storage, name) if err != nil { return nil, err @@ -61,14 +69,7 @@ func pathConfigurePluginConnection(b *databaseBackend) *framework.Path { Fields: map[string]*framework.FieldSchema{ "name": &framework.FieldSchema{ Type: framework.TypeString, - Description: "Name of this DB type", - }, - - "verify_connection": &framework.FieldSchema{ - Type: framework.TypeBool, - Default: true, - Description: `If set, the connection details are verified by - actually connecting to the database`, + Description: "Name of this database connection", }, "plugin_name": &framework.FieldSchema{ @@ -77,6 +78,13 @@ func pathConfigurePluginConnection(b *databaseBackend) *framework.Path { plugin known to vault. This endpoint will create an instance of that plugin type.`, }, + + "verify_connection": &framework.FieldSchema{ + Type: framework.TypeBool, + Default: true, + Description: `If true, the connection details are verified by + actually connecting to the database. Defaults to true.`, + }, }, Callbacks: map[logical.Operation]framework.OperationFunc{ @@ -94,10 +102,13 @@ func pathConfigurePluginConnection(b *databaseBackend) *framework.Path { func (b *databaseBackend) connectionReadHandler() framework.OperationFunc { return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("name").(string) + if name == "" { + return respErrEmptyName, nil + } - entry, err := req.Storage.Get(fmt.Sprintf("dbs/%s", name)) + entry, err := req.Storage.Get(fmt.Sprintf("config/%s", name)) if err != nil { - return nil, fmt.Errorf("failed to read connection configuration") + return nil, errors.New("failed to read connection configuration") } if entry == nil { return nil, nil @@ -118,12 +129,12 @@ func (b *databaseBackend) connectionDeleteHandler() framework.OperationFunc { return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) { name := data.Get("name").(string) if name == "" { - return logical.ErrorResponse("Empty name attribute given"), nil + return respErrEmptyName, nil } - err := req.Storage.Delete(fmt.Sprintf("dbs/%s", name)) + err := req.Storage.Delete(fmt.Sprintf("config/%s", name)) if err != nil { - return nil, fmt.Errorf("failed to delete connection configuration") + return nil, errors.New("failed to delete connection configuration") } b.Lock() @@ -134,9 +145,9 @@ func (b *databaseBackend) connectionDeleteHandler() framework.OperationFunc { if err != nil { return nil, err } - } - delete(b.connections, name) + delete(b.connections, name) + } return nil, nil } @@ -146,22 +157,22 @@ func (b *databaseBackend) connectionDeleteHandler() framework.OperationFunc { // both builtin and plugin database types. func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc { return func(req *logical.Request, data *framework.FieldData) (*logical.Response, error) { - - config := &DatabaseConfig{ - ConnectionDetails: data.Raw, - PluginName: data.Get("plugin_name").(string), + pluginName := data.Get("plugin_name").(string) + if pluginName == "" { + return respErrEmptyPluginName, nil } name := data.Get("name").(string) if name == "" { - return logical.ErrorResponse("Empty name attribute given"), nil + return respErrEmptyName, nil } verifyConnection := data.Get("verify_connection").(bool) - // Grab the mutex lock - b.Lock() - defer b.Unlock() + config := &DatabaseConfig{ + ConnectionDetails: data.Raw, + PluginName: pluginName, + } db, err := dbplugin.PluginFactory(config.PluginName, b.System(), b.logger) if err != nil { @@ -174,6 +185,10 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc { return logical.ErrorResponse(fmt.Sprintf("Error creating database object: %s", err)), nil } + // Grab the mutex lock + b.Lock() + defer b.Unlock() + if _, ok := b.connections[name]; ok { // Close and remove the old connection err := b.connections[name].Close() @@ -189,7 +204,7 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc { b.connections[name] = db // Store it - entry, err := logical.StorageEntryJSON(fmt.Sprintf("dbs/%s", name), config) + entry, err := logical.StorageEntryJSON(fmt.Sprintf("config/%s", name), config) if err != nil { return nil, err } @@ -198,7 +213,7 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc { } resp := &logical.Response{} - resp.AddWarning("Read access to this endpoint should be controlled via ACLs as it will return the connection string or URL as it is, including passwords, if any.") + resp.AddWarning("Read access to this endpoint should be controlled via ACLs as it will return the connection details as is, including passwords, if any.") return resp, nil } @@ -221,7 +236,7 @@ accepts: plugin known to vault. This endpoint will create an instance of that plugin type. - * "verify_connection" - A boolean value denoting if the plugin should verify + * "verify_connection" (default: true) - A boolean value denoting if the plugin should verify it is able to connect to the database using the provided connection details. ` diff --git a/builtin/logical/database/path_roles.go b/builtin/logical/database/path_roles.go index 263a555e6b..b3393b1ba8 100644 --- a/builtin/logical/database/path_roles.go +++ b/builtin/logical/database/path_roles.go @@ -109,6 +109,7 @@ func (b *databaseBackend) pathRoleRead() framework.OperationFunc { return &logical.Response{ Data: map[string]interface{}{ + "db_name": role.DBName, "creation_statements": role.Statements.CreationStatements, "revocation_statements": role.Statements.RevocationStatements, "rollback_statements": role.Statements.RollbackStatements, diff --git a/command/plugin-exec.go b/command/plugin_exec.go similarity index 100% rename from command/plugin-exec.go rename to command/plugin_exec.go