set search_path for default roles

This commit is contained in:
Felix Kunde 2020-07-16 17:15:06 +02:00
parent 375963424d
commit a315c90e71
4 changed files with 54 additions and 36 deletions

View File

@ -15,7 +15,7 @@ spec:
serviceAccountName: postgres-operator serviceAccountName: postgres-operator
containers: containers:
- name: postgres-operator - name: postgres-operator
image: registry.opensource.zalan.do/acid/postgres-operator:v1.5.0 image: registry.opensource.zalan.do/acid/postgres-operator:v1.5.0-19-g37596342-dirty
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
resources: resources:
requests: requests:

View File

@ -955,32 +955,42 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
} }
for preparedDbName, preparedDB := range c.Spec.PreparedDatabases { for preparedDbName, preparedDB := range c.Spec.PreparedDatabases {
// get list of prepared schemas to set in search_path
preparedSchemas := preparedDB.PreparedSchemas
if len(preparedDB.PreparedSchemas) == 0 {
preparedSchemas = map[string]acidv1.PreparedSchema{"data": {DefaultRoles: util.True()}}
}
var searchPath strings.Builder
searchPath.WriteString(constants.DefaultSearchPath)
for preparedSchemaName := range preparedSchemas {
searchPath.WriteString(", " + preparedSchemaName)
}
// default roles per database // default roles per database
if err := c.initDefaultRoles(defaultRoles, "admin", preparedDbName); err != nil { if err := c.initDefaultRoles(defaultRoles, "admin", preparedDbName, searchPath.String()); err != nil {
return fmt.Errorf("could not initialize default roles for database %s: %v", preparedDbName, err) return fmt.Errorf("could not initialize default roles for database %s: %v", preparedDbName, err)
} }
if preparedDB.DefaultUsers { if preparedDB.DefaultUsers {
if err := c.initDefaultRoles(defaultUsers, "admin", preparedDbName); err != nil { if err := c.initDefaultRoles(defaultUsers, "admin", preparedDbName, searchPath.String()); err != nil {
return fmt.Errorf("could not initialize default roles for database %s: %v", preparedDbName, err) return fmt.Errorf("could not initialize default roles for database %s: %v", preparedDbName, err)
} }
} }
// default roles per database schema // default roles per database schema
preparedSchemas := preparedDB.PreparedSchemas
if len(preparedDB.PreparedSchemas) == 0 {
preparedSchemas = map[string]acidv1.PreparedSchema{"data": {DefaultRoles: util.True()}}
}
for preparedSchemaName, preparedSchema := range preparedSchemas { for preparedSchemaName, preparedSchema := range preparedSchemas {
if preparedSchema.DefaultRoles == nil || *preparedSchema.DefaultRoles { if preparedSchema.DefaultRoles == nil || *preparedSchema.DefaultRoles {
if err := c.initDefaultRoles(defaultRoles, if err := c.initDefaultRoles(defaultRoles,
preparedDbName+constants.OwnerRoleNameSuffix, preparedDbName+constants.OwnerRoleNameSuffix,
preparedDbName+"_"+preparedSchemaName); err != nil { preparedDbName+"_"+preparedSchemaName,
constants.DefaultSearchPath+", "+preparedSchemaName); err != nil {
return fmt.Errorf("could not initialize default roles for database schema %s: %v", preparedSchemaName, err) return fmt.Errorf("could not initialize default roles for database schema %s: %v", preparedSchemaName, err)
} }
if preparedSchema.DefaultUsers { if preparedSchema.DefaultUsers {
if err := c.initDefaultRoles(defaultUsers, if err := c.initDefaultRoles(defaultUsers,
preparedDbName+constants.OwnerRoleNameSuffix, preparedDbName+constants.OwnerRoleNameSuffix,
preparedDbName+"_"+preparedSchemaName); err != nil { preparedDbName+"_"+preparedSchemaName,
constants.DefaultSearchPath+", "+preparedSchemaName); err != nil {
return fmt.Errorf("could not initialize default users for database schema %s: %v", preparedSchemaName, err) return fmt.Errorf("could not initialize default users for database schema %s: %v", preparedSchemaName, err)
} }
} }
@ -990,7 +1000,7 @@ func (c *Cluster) initPreparedDatabaseRoles() error {
return nil return nil
} }
func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix string) error { func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix string, searchPath string) error {
for defaultRole, inherits := range defaultRoles { for defaultRole, inherits := range defaultRoles {
@ -1014,12 +1024,13 @@ func (c *Cluster) initDefaultRoles(defaultRoles map[string]string, admin, prefix
} }
newRole := spec.PgUser{ newRole := spec.PgUser{
Origin: spec.RoleOriginBootstrap, Origin: spec.RoleOriginBootstrap,
Name: roleName, Name: roleName,
Password: util.RandomPassword(constants.PasswordLength), Password: util.RandomPassword(constants.PasswordLength),
Flags: flags, Flags: flags,
MemberOf: memberOf, MemberOf: memberOf,
AdminRole: adminRole, Parameters: map[string]string{"search_path": searchPath},
AdminRole: adminRole,
} }
if currentRole, present := c.pgUsers[roleName]; present { if currentRole, present := c.pgUsers[roleName]; present {
c.pgUsers[roleName] = c.resolveNameConflict(&currentRole, &newRole) c.pgUsers[roleName] = c.resolveNameConflict(&currentRole, &newRole)

View File

@ -2,20 +2,21 @@ package constants
// Roles specific constants // Roles specific constants
const ( const (
PasswordLength = 64 PasswordLength = 64
SuperuserKeyName = "superuser" SuperuserKeyName = "superuser"
ConnectionPoolerUserKeyName = "pooler" ConnectionPoolerUserKeyName = "pooler"
ReplicationUserKeyName = "replication" ReplicationUserKeyName = "replication"
RoleFlagSuperuser = "SUPERUSER" RoleFlagSuperuser = "SUPERUSER"
RoleFlagInherit = "INHERIT" RoleFlagInherit = "INHERIT"
RoleFlagLogin = "LOGIN" RoleFlagLogin = "LOGIN"
RoleFlagNoLogin = "NOLOGIN" RoleFlagNoLogin = "NOLOGIN"
RoleFlagCreateRole = "CREATEROLE" RoleFlagCreateRole = "CREATEROLE"
RoleFlagCreateDB = "CREATEDB" RoleFlagCreateDB = "CREATEDB"
RoleFlagReplication = "REPLICATION" RoleFlagReplication = "REPLICATION"
RoleFlagByPassRLS = "BYPASSRLS" RoleFlagByPassRLS = "BYPASSRLS"
OwnerRoleNameSuffix = "_owner" OwnerRoleNameSuffix = "_owner"
ReaderRoleNameSuffix = "_reader" ReaderRoleNameSuffix = "_reader"
WriterRoleNameSuffix = "_writer" WriterRoleNameSuffix = "_writer"
UserRoleNameSuffix = "_user" UserRoleNameSuffix = "_user"
DefaultSearchPath = "\"$user\""
) )

View File

@ -113,14 +113,14 @@ func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(requests []spec.PgSy
return nil return nil
} }
func (strategy DefaultUserSyncStrategy) alterPgUserSet(user spec.PgUser, db *sql.DB) (err error) {
func (strategy DefaultUserSyncStrategy) alterPgUserSet(user spec.PgUser, db *sql.DB) error {
queries := produceAlterRoleSetStmts(user) queries := produceAlterRoleSetStmts(user)
query := fmt.Sprintf(doBlockStmt, strings.Join(queries, ";")) query := fmt.Sprintf(doBlockStmt, strings.Join(queries, ";"))
if _, err = db.Exec(query); err != nil { if _, err := db.Exec(query); err != nil {
err = fmt.Errorf("dB error: %v, query: %s", err, query) return fmt.Errorf("dB error: %v, query: %s", err, query)
return
} }
return return nil
} }
func (strategy DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) error { func (strategy DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) error {
@ -148,6 +148,12 @@ func (strategy DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.D
return fmt.Errorf("dB error: %v, query: %s", err, query) return fmt.Errorf("dB error: %v, query: %s", err, query)
} }
if len(user.Parameters) > 0 {
if err := strategy.alterPgUserSet(user, db); err != nil {
return fmt.Errorf("incomplete setup for user %s: %v", user.Name, err)
}
}
return nil return nil
} }