Skip to content

Commit

Permalink
Merge branch 'main' into docs/mfa-login-totp
Browse files Browse the repository at this point in the history
  • Loading branch information
mister-ken authored Dec 12, 2024
2 parents d100907 + e8ccd6e commit 40bae67
Show file tree
Hide file tree
Showing 19 changed files with 306 additions and 117 deletions.
19 changes: 19 additions & 0 deletions builtin/logical/database/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,20 @@ func (b *databaseBackend) StaticRole(ctx context.Context, s logical.Storage, rol
return b.roleAtPath(ctx, s, roleName, databaseStaticRolePath)
}

func (b *databaseBackend) StoreStaticRole(ctx context.Context, s logical.Storage, r *roleEntry) error {
logger := b.Logger().With("role", r.Name, "database", r.DBName)
entry, err := logical.StorageEntryJSON(databaseStaticRolePath+r.Name, r)
if err != nil {
logger.Error("unable to encode entry for storage", "error", err)
return err
}
if err := s.Put(ctx, entry); err != nil {
logger.Error("unable to write to storage", "error", err)
return err
}
return nil
}

func (b *databaseBackend) roleAtPath(ctx context.Context, s logical.Storage, roleName string, pathPrefix string) (*roleEntry, error) {
entry, err := s.Get(ctx, pathPrefix+roleName)
if err != nil {
Expand All @@ -247,6 +261,11 @@ func (b *databaseBackend) roleAtPath(ctx context.Context, s logical.Storage, rol
return nil, err
}

// handle upgrade for new field Name
if result.Name == "" {
result.Name = roleName
}

switch {
case upgradeCh.Statements != nil:
var stmts v4.Statements
Expand Down
7 changes: 6 additions & 1 deletion builtin/logical/database/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func TestBackend_RoleUpgrade(t *testing.T) {
backend := &databaseBackend{}

roleExpected := &roleEntry{
Name: "test",
Statements: v4.Statements{
CreationStatements: "test",
Creation: []string{"test"},
Expand Down Expand Up @@ -211,6 +212,7 @@ func TestBackend_config_connection(t *testing.T) {
"password_policy": "",
"plugin_version": "",
"verify_connection": false,
"skip_static_role_import_rotation": false,
}
configReq.Operation = logical.ReadOperation
resp, err = b.HandleRequest(namespace.RootContext(nil), configReq)
Expand Down Expand Up @@ -266,6 +268,7 @@ func TestBackend_config_connection(t *testing.T) {
"password_policy": "",
"plugin_version": "",
"verify_connection": false,
"skip_static_role_import_rotation": false,
}
configReq.Operation = logical.ReadOperation
resp, err = b.HandleRequest(namespace.RootContext(nil), configReq)
Expand Down Expand Up @@ -310,6 +313,7 @@ func TestBackend_config_connection(t *testing.T) {
"password_policy": "",
"plugin_version": "",
"verify_connection": false,
"skip_static_role_import_rotation": false,
}
configReq.Operation = logical.ReadOperation
resp, err = b.HandleRequest(namespace.RootContext(nil), configReq)
Expand Down Expand Up @@ -417,7 +421,7 @@ func TestBackend_basic(t *testing.T) {
defer b.Cleanup(context.Background())

cleanup, connURL := postgreshelper.PrepareTestContainer(t)
defer cleanup()
t.Cleanup(cleanup)

// Configure a connection
data := map[string]interface{}{
Expand Down Expand Up @@ -768,6 +772,7 @@ func TestBackend_connectionCrud(t *testing.T) {
"password_policy": "",
"plugin_version": "",
"verify_connection": false,
"skip_static_role_import_rotation": false,
}
resp, err = client.Read("database/config/plugin-test")
if err != nil {
Expand Down
87 changes: 51 additions & 36 deletions builtin/logical/database/path_config_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ type DatabaseConfig struct {

PasswordPolicy string `json:"password_policy" structs:"password_policy" mapstructure:"password_policy"`
VerifyConnection bool `json:"verify_connection" structs:"verify_connection" mapstructure:"verify_connection"`

// SkipStaticRoleImportRotation is a flag to toggle wether or not a given
// static account's password should be rotated on creation of the static
// roles associated with this DB config. This can be overridden at the
// role-level by the role's skip_import_rotation field. The default is
// false. Enterprise only.
SkipStaticRoleImportRotation bool `json:"skip_static_role_import_rotation" structs:"skip_static_role_import_rotation" mapstructure:"skip_static_role_import_rotation"`
}

func (c *DatabaseConfig) SupportsCredentialType(credentialType v5.CredentialType) bool {
Expand Down Expand Up @@ -205,57 +212,60 @@ func (b *databaseBackend) reloadPlugin() framework.OperationFunc {
// pathConfigurePluginConnection returns a configured framework.Path setup to
// operate on plugins.
func pathConfigurePluginConnection(b *databaseBackend) *framework.Path {
return &framework.Path{
Pattern: fmt.Sprintf("config/%s", framework.GenericNameRegex("name")),

DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: operationPrefixDatabase,
fields := map[string]*framework.FieldSchema{
"name": {
Type: framework.TypeString,
Description: "Name of this database connection",
},

Fields: map[string]*framework.FieldSchema{
"name": {
Type: framework.TypeString,
Description: "Name of this database connection",
},

"plugin_name": {
Type: framework.TypeString,
Description: `The name of a builtin or previously registered
"plugin_name": {
Type: framework.TypeString,
Description: `The name of a builtin or previously registered
plugin known to vault. This endpoint will create an instance of
that plugin type.`,
},
},

"plugin_version": {
Type: framework.TypeString,
Description: `The version of the plugin to use.`,
},
"plugin_version": {
Type: framework.TypeString,
Description: `The version of the plugin to use.`,
},

"verify_connection": {
Type: framework.TypeBool,
Default: true,
Description: `If true, the connection details are verified by
"verify_connection": {
Type: framework.TypeBool,
Default: true,
Description: `If true, the connection details are verified by
actually connecting to the database. Defaults to true.`,
},
},

"allowed_roles": {
Type: framework.TypeCommaStringSlice,
Description: `Comma separated string or array of the role names
"allowed_roles": {
Type: framework.TypeCommaStringSlice,
Description: `Comma separated string or array of the role names
allowed to get creds from this database connection. If empty no
roles are allowed. If "*" all roles are allowed.`,
},
},

"root_rotation_statements": {
Type: framework.TypeStringSlice,
Description: `Specifies the database statements to be executed
"root_rotation_statements": {
Type: framework.TypeStringSlice,
Description: `Specifies the database statements to be executed
to rotate the root user's credentials. See the plugin's API
page for more information on support and formatting for this
parameter.`,
},
"password_policy": {
Type: framework.TypeString,
Description: `Password policy to use when generating passwords.`,
},
},
"password_policy": {
Type: framework.TypeString,
Description: `Password policy to use when generating passwords.`,
},
}
AddConnectionFieldsEnt(fields)

return &framework.Path{
Pattern: fmt.Sprintf("config/%s", framework.GenericNameRegex("name")),

DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: operationPrefixDatabase,
},

Fields: fields,

ExistenceCheck: b.connectionExistenceCheck(),

Expand Down Expand Up @@ -480,6 +490,10 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc {
config.PasswordPolicy = passwordPolicyRaw.(string)
}

if skipImportRotationRaw, ok := data.GetOk("skip_static_role_import_rotation"); ok {
config.SkipStaticRoleImportRotation = skipImportRotationRaw.(bool)
}

// Remove these entries from the data before we store it keyed under
// ConnectionDetails.
delete(data.Raw, "name")
Expand All @@ -489,6 +503,7 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc {
delete(data.Raw, "verify_connection")
delete(data.Raw, "root_rotation_statements")
delete(data.Raw, "password_policy")
delete(data.Raw, "skip_static_role_import_rotation")

id, err := uuid.GenerateUUID()
if err != nil {
Expand Down
13 changes: 13 additions & 0 deletions builtin/logical/database/path_config_connection_ce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

//go:build !enterprise

package database

import "github.com/hashicorp/vault/sdk/framework"

// AddConnectionFieldsEnt is a no-op for community edition
func AddConnectionFieldsEnt(fields map[string]*framework.FieldSchema) {
// no-op
}
Loading

0 comments on commit 40bae67

Please sign in to comment.