rename db roles that are removed from manifests

This commit is contained in:
Felix Kunde
2021-04-14 12:09:05 +02:00
parent 6b73ac4282
commit d97743e7ec
6 changed files with 37 additions and 20 deletions
-4
View File
@@ -957,10 +957,6 @@ func (c *Cluster) initSystemUsers() {
Password: util.RandomPassword(constants.PasswordLength), Password: util.RandomPassword(constants.PasswordLength),
} }
if _, exists := c.pgUsers[username]; !exists {
c.pgUsers[username] = connectionPoolerUser
}
if _, exists := c.systemUsers[constants.ConnectionPoolerUserKeyName]; !exists { if _, exists := c.systemUsers[constants.ConnectionPoolerUserKeyName]; !exists {
c.systemUsers[constants.ConnectionPoolerUserKeyName] = connectionPoolerUser c.systemUsers[constants.ConnectionPoolerUserKeyName] = connectionPoolerUser
} }
+2 -1
View File
@@ -24,7 +24,8 @@ const (
JOIN pg_catalog.pg_authid b ON (m.roleid = b.oid) JOIN pg_catalog.pg_authid b ON (m.roleid = b.oid)
WHERE m.member = a.oid) as memberof WHERE m.member = a.oid) as memberof
FROM pg_catalog.pg_authid a LEFT JOIN pg_db_role_setting s ON (a.oid = s.setrole AND s.setdatabase = 0::oid) FROM pg_catalog.pg_authid a LEFT JOIN pg_db_role_setting s ON (a.oid = s.setrole AND s.setdatabase = 0::oid)
WHERE a.rolname = ANY($1) WHERE a.rolname != ALL($1)
AND (rolcanlogin OR (NOT rolcanlogin AND rolpassword IS NOT NULL))
ORDER BY 1;` ORDER BY 1;`
getDatabasesSQL = `SELECT datname, pg_get_userbyid(datdba) AS owner FROM pg_database;` getDatabasesSQL = `SELECT datname, pg_get_userbyid(datdba) AS owner FROM pg_database;`
+8 -14
View File
@@ -528,6 +528,9 @@ func (c *Cluster) syncSecrets() error {
} else if secretUsername == c.systemUsers[constants.ReplicationUserKeyName].Name { } else if secretUsername == c.systemUsers[constants.ReplicationUserKeyName].Name {
secretUsername = constants.ReplicationUserKeyName secretUsername = constants.ReplicationUserKeyName
userMap = c.systemUsers userMap = c.systemUsers
} else if secretUsername == c.systemUsers[constants.ConnectionPoolerUserName].Name {
secretUsername = constants.ConnectionPoolerUserName
userMap = c.systemUsers
} else { } else {
userMap = c.pgUsers userMap = c.pgUsers
} }
@@ -557,8 +560,8 @@ func (c *Cluster) syncRoles() (err error) {
c.setProcessName("syncing roles") c.setProcessName("syncing roles")
var ( var (
dbUsers spec.PgUserMap dbUsers spec.PgUserMap
userNames []string systemUserNames []string
) )
err = c.initDbConn() err = c.initDbConn()
@@ -576,20 +579,11 @@ func (c *Cluster) syncRoles() (err error) {
} }
}() }()
for _, u := range c.pgUsers { for _, u := range c.systemUsers {
userNames = append(userNames, u.Name) systemUserNames = append(systemUserNames, u.Name)
} }
if needMasterConnectionPooler(&c.Spec) || needReplicaConnectionPooler(&c.Spec) { dbUsers, err = c.readPgUsersFromDatabase(systemUserNames)
connectionPoolerUser := c.systemUsers[constants.ConnectionPoolerUserKeyName]
userNames = append(userNames, connectionPoolerUser.Name)
if _, exists := c.pgUsers[connectionPoolerUser.Name]; !exists {
c.pgUsers[connectionPoolerUser.Name] = connectionPoolerUser
}
}
dbUsers, err = c.readPgUsersFromDatabase(userNames)
if err != nil { if err != nil {
return fmt.Errorf("error getting users from the database: %v", err) return fmt.Errorf("error getting users from the database: %v", err)
} }
+1
View File
@@ -42,6 +42,7 @@ const (
PGSyncUserAdd = iota PGSyncUserAdd = iota
PGsyncUserAlter PGsyncUserAlter
PGSyncAlterSet // handle ALTER ROLE SET parameter = value PGSyncAlterSet // handle ALTER ROLE SET parameter = value
PGSyncUserRename
) )
// PgUser contains information about a single user. // PgUser contains information about a single user.
+1
View File
@@ -18,5 +18,6 @@ const (
ReaderRoleNameSuffix = "_reader" ReaderRoleNameSuffix = "_reader"
WriterRoleNameSuffix = "_writer" WriterRoleNameSuffix = "_writer"
UserRoleNameSuffix = "_user" UserRoleNameSuffix = "_user"
RoleRenameSuffix = "_delete_me"
DefaultSearchPath = "\"$user\"" DefaultSearchPath = "\"$user\""
) )
+25 -1
View File
@@ -9,11 +9,13 @@ import (
"github.com/zalando/postgres-operator/pkg/spec" "github.com/zalando/postgres-operator/pkg/spec"
"github.com/zalando/postgres-operator/pkg/util" "github.com/zalando/postgres-operator/pkg/util"
"github.com/zalando/postgres-operator/pkg/util/constants"
) )
const ( const (
createUserSQL = `SET LOCAL synchronous_commit = 'local'; CREATE ROLE "%s" %s %s;` createUserSQL = `SET LOCAL synchronous_commit = 'local'; CREATE ROLE "%s" %s %s;`
alterUserSQL = `ALTER ROLE "%s" %s` alterUserSQL = `ALTER ROLE "%s" %s`
alterUserRenameSQL = `ALTER ROLE "%s" RENAME TO "%s%s"`
alterRoleResetAllSQL = `ALTER ROLE "%s" RESET ALL` alterRoleResetAllSQL = `ALTER ROLE "%s" RESET ALL`
alterRoleSetSQL = `ALTER ROLE "%s" SET %s TO %s` alterRoleSetSQL = `ALTER ROLE "%s" SET %s TO %s`
grantToUserSQL = `GRANT %s TO "%s"` grantToUserSQL = `GRANT %s TO "%s"`
@@ -36,7 +38,6 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
newUsers spec.PgUserMap) []spec.PgSyncUserRequest { newUsers spec.PgUserMap) []spec.PgSyncUserRequest {
var reqs []spec.PgSyncUserRequest var reqs []spec.PgSyncUserRequest
// No existing roles are deleted or stripped of role memebership/flags
for name, newUser := range newUsers { for name, newUser := range newUsers {
dbUser, exists := dbUsers[name] dbUser, exists := dbUsers[name]
if !exists { if !exists {
@@ -70,6 +71,16 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
} }
} }
// No existing roles are deleted or stripped of role memebership/flags
// but they will be renamed acting as a simple blocker
for name, dbUser := range dbUsers {
_, exists := newUsers[name]
nameSuffixDiff := len(name) - len(constants.RoleRenameSuffix)
if !exists && (nameSuffixDiff <= 0 || (nameSuffixDiff > 0 && name[nameSuffixDiff:] != constants.RoleRenameSuffix)) {
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserRename, User: dbUser})
}
}
return reqs return reqs
} }
@@ -94,6 +105,11 @@ func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(requests []spec.PgSy
reqretries = append(reqretries, request) reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not set custom user %q parameters: %v", request.User.Name, err)) errors = append(errors, fmt.Sprintf("could not set custom user %q parameters: %v", request.User.Name, err))
} }
case spec.PGSyncUserRename:
if err := strategy.alterPgUserRename(request.User, db); err != nil {
reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not rename custom user %q: %v", request.User.Name, err))
}
default: default:
return fmt.Errorf("unrecognized operation: %v", request.Kind) return fmt.Errorf("unrecognized operation: %v", request.Kind)
} }
@@ -124,6 +140,14 @@ func (strategy DefaultUserSyncStrategy) alterPgUserSet(user spec.PgUser, db *sql
return nil return nil
} }
func (strategy DefaultUserSyncStrategy) alterPgUserRename(user spec.PgUser, db *sql.DB) error {
query := fmt.Sprintf(alterUserRenameSQL, user.Name, user.Name, constants.RoleRenameSuffix)
if _, err := db.Exec(query); err != nil {
return err
}
return nil
}
func (strategy DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) error { func (strategy DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) error {
var userFlags []string var userFlags []string
var userPassword string var userPassword string