mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-02 03:27:54 +00:00
MySQL - Add username customization (#10834)
This commit is contained in:
@@ -8,11 +8,10 @@ import (
|
||||
"strings"
|
||||
|
||||
stdmysql "github.com/go-sql-driver/mysql"
|
||||
"github.com/hashicorp/errwrap"
|
||||
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
|
||||
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
|
||||
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/template"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -26,13 +25,9 @@ const (
|
||||
`
|
||||
|
||||
mySQLTypeName = "mysql"
|
||||
)
|
||||
|
||||
var (
|
||||
MetadataLen int = 10
|
||||
LegacyMetadataLen int = 4
|
||||
UsernameLen int = 32
|
||||
LegacyUsernameLen int = 16
|
||||
DefaultUserNameTemplate = `{{ printf "v-%s-%s-%s-%s" (.DisplayName | truncate 10) (.RoleName | truncate 10) (random 20) (unix_time) | truncate 32 }}`
|
||||
DefaultLegacyUserNameTemplate = `{{ printf "v-%s-%s-%s" (.RoleName | truncate 4) (random 20) | truncate 16 }}`
|
||||
)
|
||||
|
||||
var _ dbplugin.Database = (*MySQL)(nil)
|
||||
@@ -40,15 +35,17 @@ var _ dbplugin.Database = (*MySQL)(nil)
|
||||
type MySQL struct {
|
||||
*mySQLConnectionProducer
|
||||
|
||||
displayNameLen int
|
||||
roleNameLen int
|
||||
maxUsernameLen int
|
||||
usernameProducer template.StringTemplate
|
||||
defaultUsernameTemplate string
|
||||
}
|
||||
|
||||
// New implements builtinplugins.BuiltinFactory
|
||||
func New(displayNameLen int, roleNameLen int, maxUsernameLen int) func() (interface{}, error) {
|
||||
func New(defaultUsernameTemplate string) func() (interface{}, error) {
|
||||
return func() (interface{}, error) {
|
||||
db := newMySQL(displayNameLen, roleNameLen, maxUsernameLen)
|
||||
if defaultUsernameTemplate == "" {
|
||||
return nil, fmt.Errorf("missing default username template")
|
||||
}
|
||||
db := newMySQL(defaultUsernameTemplate)
|
||||
// Wrap the plugin with middleware to sanitize errors
|
||||
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.SecretValues)
|
||||
|
||||
@@ -56,14 +53,12 @@ func New(displayNameLen int, roleNameLen int, maxUsernameLen int) func() (interf
|
||||
}
|
||||
}
|
||||
|
||||
func newMySQL(displayNameLen int, roleNameLen int, maxUsernameLen int) *MySQL {
|
||||
func newMySQL(defaultUsernameTemplate string) *MySQL {
|
||||
connProducer := &mySQLConnectionProducer{}
|
||||
|
||||
return &MySQL{
|
||||
mySQLConnectionProducer: connProducer,
|
||||
displayNameLen: displayNameLen,
|
||||
roleNameLen: roleNameLen,
|
||||
maxUsernameLen: maxUsernameLen,
|
||||
defaultUsernameTemplate: defaultUsernameTemplate,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,13 +76,36 @@ func (m *MySQL) getConnection(ctx context.Context) (*sql.DB, error) {
|
||||
}
|
||||
|
||||
func (m *MySQL) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
|
||||
err := m.mySQLConnectionProducer.Initialize(ctx, req.Config, req.VerifyConnection)
|
||||
usernameTemplate, err := strutil.GetString(req.Config, "username_template")
|
||||
if err != nil {
|
||||
return dbplugin.InitializeResponse{}, err
|
||||
}
|
||||
|
||||
if usernameTemplate == "" {
|
||||
usernameTemplate = m.defaultUsernameTemplate
|
||||
}
|
||||
|
||||
up, err := template.NewTemplate(template.Template(usernameTemplate))
|
||||
if err != nil {
|
||||
return dbplugin.InitializeResponse{}, fmt.Errorf("unable to initialize username template: %w", err)
|
||||
}
|
||||
|
||||
m.usernameProducer = up
|
||||
|
||||
_, err = m.usernameProducer.Generate(dbplugin.UsernameMetadata{})
|
||||
if err != nil {
|
||||
return dbplugin.InitializeResponse{}, fmt.Errorf("invalid username template: %w", err)
|
||||
}
|
||||
|
||||
err = m.mySQLConnectionProducer.Initialize(ctx, req.Config, req.VerifyConnection)
|
||||
if err != nil {
|
||||
return dbplugin.InitializeResponse{}, err
|
||||
}
|
||||
|
||||
resp := dbplugin.InitializeResponse{
|
||||
Config: req.Config,
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -96,7 +114,7 @@ func (m *MySQL) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplu
|
||||
return dbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
|
||||
}
|
||||
|
||||
username, err := m.generateUsername(req)
|
||||
username, err := m.usernameProducer.Generate(req.UsernameConfig)
|
||||
if err != nil {
|
||||
return dbplugin.NewUserResponse{}, err
|
||||
}
|
||||
@@ -122,19 +140,6 @@ func (m *MySQL) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplu
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (m *MySQL) generateUsername(req dbplugin.NewUserRequest) (string, error) {
|
||||
username, err := credsutil.GenerateUsername(
|
||||
credsutil.DisplayName(req.UsernameConfig.DisplayName, m.displayNameLen),
|
||||
credsutil.RoleName(req.UsernameConfig.RoleName, m.roleNameLen),
|
||||
credsutil.MaxLength(m.maxUsernameLen),
|
||||
)
|
||||
if err != nil {
|
||||
return "", errwrap.Wrapf("error generating username: {{err}}", err)
|
||||
}
|
||||
|
||||
return username, nil
|
||||
}
|
||||
|
||||
func (m *MySQL) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
|
||||
// Grab the read lock
|
||||
m.Lock()
|
||||
|
||||
Reference in New Issue
Block a user