Skip to content

Commit e838daf

Browse files
authored
Merge branch 'main' into docs/secrets-seo-updates-3
2 parents 4d81df6 + c4be16c commit e838daf

26 files changed

+295
-143
lines changed

builtin/logical/database/backend.go

+19
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,20 @@ func (b *databaseBackend) StaticRole(ctx context.Context, s logical.Storage, rol
228228
return b.roleAtPath(ctx, s, roleName, databaseStaticRolePath)
229229
}
230230

231+
func (b *databaseBackend) StoreStaticRole(ctx context.Context, s logical.Storage, r *roleEntry) error {
232+
logger := b.Logger().With("role", r.Name, "database", r.DBName)
233+
entry, err := logical.StorageEntryJSON(databaseStaticRolePath+r.Name, r)
234+
if err != nil {
235+
logger.Error("unable to encode entry for storage", "error", err)
236+
return err
237+
}
238+
if err := s.Put(ctx, entry); err != nil {
239+
logger.Error("unable to write to storage", "error", err)
240+
return err
241+
}
242+
return nil
243+
}
244+
231245
func (b *databaseBackend) roleAtPath(ctx context.Context, s logical.Storage, roleName string, pathPrefix string) (*roleEntry, error) {
232246
entry, err := s.Get(ctx, pathPrefix+roleName)
233247
if err != nil {
@@ -247,6 +261,11 @@ func (b *databaseBackend) roleAtPath(ctx context.Context, s logical.Storage, rol
247261
return nil, err
248262
}
249263

264+
// handle upgrade for new field Name
265+
if result.Name == "" {
266+
result.Name = roleName
267+
}
268+
250269
switch {
251270
case upgradeCh.Statements != nil:
252271
var stmts v4.Statements

builtin/logical/database/backend_test.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func TestBackend_RoleUpgrade(t *testing.T) {
9797
backend := &databaseBackend{}
9898

9999
roleExpected := &roleEntry{
100+
Name: "test",
100101
Statements: v4.Statements{
101102
CreationStatements: "test",
102103
Creation: []string{"test"},
@@ -211,6 +212,7 @@ func TestBackend_config_connection(t *testing.T) {
211212
"password_policy": "",
212213
"plugin_version": "",
213214
"verify_connection": false,
215+
"skip_static_role_import_rotation": false,
214216
}
215217
configReq.Operation = logical.ReadOperation
216218
resp, err = b.HandleRequest(namespace.RootContext(nil), configReq)
@@ -266,6 +268,7 @@ func TestBackend_config_connection(t *testing.T) {
266268
"password_policy": "",
267269
"plugin_version": "",
268270
"verify_connection": false,
271+
"skip_static_role_import_rotation": false,
269272
}
270273
configReq.Operation = logical.ReadOperation
271274
resp, err = b.HandleRequest(namespace.RootContext(nil), configReq)
@@ -310,6 +313,7 @@ func TestBackend_config_connection(t *testing.T) {
310313
"password_policy": "",
311314
"plugin_version": "",
312315
"verify_connection": false,
316+
"skip_static_role_import_rotation": false,
313317
}
314318
configReq.Operation = logical.ReadOperation
315319
resp, err = b.HandleRequest(namespace.RootContext(nil), configReq)
@@ -417,7 +421,7 @@ func TestBackend_basic(t *testing.T) {
417421
defer b.Cleanup(context.Background())
418422

419423
cleanup, connURL := postgreshelper.PrepareTestContainer(t)
420-
defer cleanup()
424+
t.Cleanup(cleanup)
421425

422426
// Configure a connection
423427
data := map[string]interface{}{
@@ -768,6 +772,7 @@ func TestBackend_connectionCrud(t *testing.T) {
768772
"password_policy": "",
769773
"plugin_version": "",
770774
"verify_connection": false,
775+
"skip_static_role_import_rotation": false,
771776
}
772777
resp, err = client.Read("database/config/plugin-test")
773778
if err != nil {

builtin/logical/database/path_config_connection.go

+51-36
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ type DatabaseConfig struct {
4242

4343
PasswordPolicy string `json:"password_policy" structs:"password_policy" mapstructure:"password_policy"`
4444
VerifyConnection bool `json:"verify_connection" structs:"verify_connection" mapstructure:"verify_connection"`
45+
46+
// SkipStaticRoleImportRotation is a flag to toggle wether or not a given
47+
// static account's password should be rotated on creation of the static
48+
// roles associated with this DB config. This can be overridden at the
49+
// role-level by the role's skip_import_rotation field. The default is
50+
// false. Enterprise only.
51+
SkipStaticRoleImportRotation bool `json:"skip_static_role_import_rotation" structs:"skip_static_role_import_rotation" mapstructure:"skip_static_role_import_rotation"`
4552
}
4653

4754
func (c *DatabaseConfig) SupportsCredentialType(credentialType v5.CredentialType) bool {
@@ -205,57 +212,60 @@ func (b *databaseBackend) reloadPlugin() framework.OperationFunc {
205212
// pathConfigurePluginConnection returns a configured framework.Path setup to
206213
// operate on plugins.
207214
func pathConfigurePluginConnection(b *databaseBackend) *framework.Path {
208-
return &framework.Path{
209-
Pattern: fmt.Sprintf("config/%s", framework.GenericNameRegex("name")),
210-
211-
DisplayAttrs: &framework.DisplayAttributes{
212-
OperationPrefix: operationPrefixDatabase,
215+
fields := map[string]*framework.FieldSchema{
216+
"name": {
217+
Type: framework.TypeString,
218+
Description: "Name of this database connection",
213219
},
214220

215-
Fields: map[string]*framework.FieldSchema{
216-
"name": {
217-
Type: framework.TypeString,
218-
Description: "Name of this database connection",
219-
},
220-
221-
"plugin_name": {
222-
Type: framework.TypeString,
223-
Description: `The name of a builtin or previously registered
221+
"plugin_name": {
222+
Type: framework.TypeString,
223+
Description: `The name of a builtin or previously registered
224224
plugin known to vault. This endpoint will create an instance of
225225
that plugin type.`,
226-
},
226+
},
227227

228-
"plugin_version": {
229-
Type: framework.TypeString,
230-
Description: `The version of the plugin to use.`,
231-
},
228+
"plugin_version": {
229+
Type: framework.TypeString,
230+
Description: `The version of the plugin to use.`,
231+
},
232232

233-
"verify_connection": {
234-
Type: framework.TypeBool,
235-
Default: true,
236-
Description: `If true, the connection details are verified by
233+
"verify_connection": {
234+
Type: framework.TypeBool,
235+
Default: true,
236+
Description: `If true, the connection details are verified by
237237
actually connecting to the database. Defaults to true.`,
238-
},
238+
},
239239

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

247-
"root_rotation_statements": {
248-
Type: framework.TypeStringSlice,
249-
Description: `Specifies the database statements to be executed
247+
"root_rotation_statements": {
248+
Type: framework.TypeStringSlice,
249+
Description: `Specifies the database statements to be executed
250250
to rotate the root user's credentials. See the plugin's API
251251
page for more information on support and formatting for this
252252
parameter.`,
253-
},
254-
"password_policy": {
255-
Type: framework.TypeString,
256-
Description: `Password policy to use when generating passwords.`,
257-
},
258253
},
254+
"password_policy": {
255+
Type: framework.TypeString,
256+
Description: `Password policy to use when generating passwords.`,
257+
},
258+
}
259+
AddConnectionFieldsEnt(fields)
260+
261+
return &framework.Path{
262+
Pattern: fmt.Sprintf("config/%s", framework.GenericNameRegex("name")),
263+
264+
DisplayAttrs: &framework.DisplayAttributes{
265+
OperationPrefix: operationPrefixDatabase,
266+
},
267+
268+
Fields: fields,
259269

260270
ExistenceCheck: b.connectionExistenceCheck(),
261271

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

493+
if skipImportRotationRaw, ok := data.GetOk("skip_static_role_import_rotation"); ok {
494+
config.SkipStaticRoleImportRotation = skipImportRotationRaw.(bool)
495+
}
496+
483497
// Remove these entries from the data before we store it keyed under
484498
// ConnectionDetails.
485499
delete(data.Raw, "name")
@@ -489,6 +503,7 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc {
489503
delete(data.Raw, "verify_connection")
490504
delete(data.Raw, "root_rotation_statements")
491505
delete(data.Raw, "password_policy")
506+
delete(data.Raw, "skip_static_role_import_rotation")
492507

493508
id, err := uuid.GenerateUUID()
494509
if err != nil {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
//go:build !enterprise
5+
6+
package database
7+
8+
import "github.com/hashicorp/vault/sdk/framework"
9+
10+
// AddConnectionFieldsEnt is a no-op for community edition
11+
func AddConnectionFieldsEnt(fields map[string]*framework.FieldSchema) {
12+
// no-op
13+
}

0 commit comments

Comments
 (0)