Skip to content

Commit

Permalink
Merge branch 'main' into scc/codeowner-update
Browse files Browse the repository at this point in the history
  • Loading branch information
schavis authored Dec 17, 2024
2 parents 99babab + 2984e0f commit 84a4ee8
Show file tree
Hide file tree
Showing 208 changed files with 4,226 additions and 1,256 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
jobs:
bench:
name: Bench
if: github.base_ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
Expand Down
4 changes: 2 additions & 2 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
# UI code related to Vault's JWT/OIDC auth method and OIDC provider.
# Changes to these files often require coordination with backend code,
# so stewards of the backend code are added below for notification.
/ui/app/components/auth-jwt.js @hashicorp/vault-ecosystem
/ui/app/routes/vault/cluster/oidc-*.js @hashicorp/vault-ecosystem
/ui/app/components/auth-jwt.js @hashicorp/vault-ui @hashicorp/vault-ecosystem
/ui/app/routes/vault/cluster/oidc-*.js @hashicorp/vault-ui @hashicorp/vault-ecosystem

# Release config; service account is required for automation tooling.
/.release/ @hashicorp/github-secure-vault-core @hashicorp/quality-team
Expand Down
33 changes: 33 additions & 0 deletions builtin/logical/database/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/hashicorp/vault/sdk/helper/locksutil"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/queue"
"github.com/mitchellh/mapstructure"
)

const (
Expand Down Expand Up @@ -205,6 +206,19 @@ func (b *databaseBackend) DatabaseConfig(ctx context.Context, s logical.Storage,
return &config, nil
}

// ConnectionDetails decodes the DatabaseConfig.ConnectionDetails map into a
// struct
func (b *databaseBackend) ConnectionDetails(ctx context.Context, config *DatabaseConfig) (*ConnectionDetails, error) {
cd := &ConnectionDetails{}

err := mapstructure.WeakDecode(config.ConnectionDetails, &cd)
if err != nil {
return nil, err
}

return cd, nil
}

type upgradeStatements struct {
// This json tag has a typo in it, the new version does not. This
// necessitates this upgrade logic.
Expand All @@ -228,6 +242,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 +275,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
3 changes: 1 addition & 2 deletions builtin/logical/database/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ import (
"strings"
"time"

"github.com/hashicorp/vault/sdk/helper/cryptoutil"

"github.com/hashicorp/vault/helper/random"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/cryptoutil"
"github.com/hashicorp/vault/sdk/helper/template"
"github.com/mitchellh/mapstructure"
)
Expand Down
93 changes: 57 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,19 @@ 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"`
}

// ConnectionDetails represents the DatabaseConfig.ConnectionDetails map as a
// struct
type ConnectionDetails struct {
SelfManaged bool `json:"self_managed" structs:"self_managed" mapstructure:"self_managed"`
}

func (c *DatabaseConfig) SupportsCredentialType(credentialType v5.CredentialType) bool {
Expand Down Expand Up @@ -205,57 +218,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 +496,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 +509,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 84a4ee8

Please sign in to comment.