allow specifiying more extra owner roles
This commit is contained in:
parent
89801ef30a
commit
78eaae2efc
|
|
@ -130,7 +130,10 @@ spec:
|
||||||
users:
|
users:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
cron_admin_username:
|
additional_owner_roles:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
enable_password_rotation:
|
enable_password_rotation:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
@ -502,6 +505,7 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
default:
|
default:
|
||||||
- admin
|
- admin
|
||||||
|
- cron_admin
|
||||||
role_deletion_suffix:
|
role_deletion_suffix:
|
||||||
type: string
|
type: string
|
||||||
default: "_deleted"
|
default: "_deleted"
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,10 @@ configGeneral:
|
||||||
|
|
||||||
# parameters describing Postgres users
|
# parameters describing Postgres users
|
||||||
configUsers:
|
configUsers:
|
||||||
# username used to grant rights to set up and maintain cron jobs to database owners
|
# roles to be granted to database owners
|
||||||
cron_admin_username: cron_admin
|
# additional_owner_roles:
|
||||||
|
# - cron_admin
|
||||||
|
|
||||||
# enable password rotation for app users that are not database owners
|
# enable password rotation for app users that are not database owners
|
||||||
enable_password_rotation: false
|
enable_password_rotation: false
|
||||||
# rotation interval for updating credentials in K8s secrets of app users
|
# rotation interval for updating credentials in K8s secrets of app users
|
||||||
|
|
@ -346,6 +348,7 @@ configTeamsApi:
|
||||||
# List of roles that cannot be overwritten by an application, team or infrastructure role
|
# List of roles that cannot be overwritten by an application, team or infrastructure role
|
||||||
protected_role_names:
|
protected_role_names:
|
||||||
- admin
|
- admin
|
||||||
|
- cron_admin
|
||||||
# Suffix to add if members are removed from TeamsAPI or PostgresTeam CRD
|
# Suffix to add if members are removed from TeamsAPI or PostgresTeam CRD
|
||||||
role_deletion_suffix: "_deleted"
|
role_deletion_suffix: "_deleted"
|
||||||
# role name to grant to team members created from the Teams API
|
# role name to grant to team members created from the Teams API
|
||||||
|
|
|
||||||
|
|
@ -177,12 +177,14 @@ under the `users` key.
|
||||||
Postgres username used for replication between instances. The default is
|
Postgres username used for replication between instances. The default is
|
||||||
`standby`.
|
`standby`.
|
||||||
|
|
||||||
* **cron_admin_username**
|
* **additional_owner_roles**
|
||||||
Specifies the role that owns rights to set up cron jobs with `pg_cron`
|
Specifies database roles that will become members of all database owners.
|
||||||
extension inside the `postgres` database. The must be pre-configured in the
|
Then owners can use `SET ROLE` to obtain privileges of these roles to e.g.
|
||||||
docker image. In Spilo this role is called `cron_admin`. This role will
|
create/update functionality from extensions as part of a migration script.
|
||||||
become a member of all database owners so that they can set up cron jobs
|
Note, that roles listed here should be preconfigured in the docker image
|
||||||
e.g. as part of a migration script. Default is `empty`.
|
and already exist in the database cluster on startup. One such role can be
|
||||||
|
`cron_admin` which is provided by the Spilo docker image to set up cron
|
||||||
|
jobs inside the `postgres` database. Default is `empty`.
|
||||||
|
|
||||||
* **enable_password_rotation**
|
* **enable_password_rotation**
|
||||||
For all `LOGIN` roles that are not database owners the operator can rotate
|
For all `LOGIN` roles that are not database owners the operator can rotate
|
||||||
|
|
@ -755,7 +757,7 @@ key.
|
||||||
|
|
||||||
* **protected_role_names**
|
* **protected_role_names**
|
||||||
List of roles that cannot be overwritten by an application, team or
|
List of roles that cannot be overwritten by an application, team or
|
||||||
infrastructure role. The default is `admin`.
|
infrastructure role. The default list is `admin` and `cron_admin`.
|
||||||
|
|
||||||
* **postgres_superuser_teams**
|
* **postgres_superuser_teams**
|
||||||
List of teams which members need the superuser role in each PG database
|
List of teams which members need the superuser role in each PG database
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: postgres-operator
|
name: postgres-operator
|
||||||
data:
|
data:
|
||||||
|
# additional_owner_roles: "cron_admin"
|
||||||
# additional_pod_capabilities: "SYS_NICE"
|
# additional_pod_capabilities: "SYS_NICE"
|
||||||
# additional_secret_mount: "some-secret-name"
|
# additional_secret_mount: "some-secret-name"
|
||||||
# additional_secret_mount_path: "/some/dir"
|
# additional_secret_mount_path: "/some/dir"
|
||||||
|
|
@ -23,7 +24,6 @@ data:
|
||||||
# connection_pooler_schema: "pooler"
|
# connection_pooler_schema: "pooler"
|
||||||
# connection_pooler_user: "pooler"
|
# connection_pooler_user: "pooler"
|
||||||
crd_categories: "all"
|
crd_categories: "all"
|
||||||
# cron_admin_username: "cron_admin"
|
|
||||||
# custom_service_annotations: "keyx:valuez,keya:valuea"
|
# custom_service_annotations: "keyx:valuez,keya:valuea"
|
||||||
# custom_pod_annotations: "keya:valuea,keyb:valueb"
|
# custom_pod_annotations: "keya:valuea,keyb:valueb"
|
||||||
db_hosted_zone: db.example.com
|
db_hosted_zone: db.example.com
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,10 @@ spec:
|
||||||
users:
|
users:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
cron_admin_username:
|
additional_owner_roles:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
enable_password_rotation:
|
enable_password_rotation:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
@ -500,6 +503,7 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
default:
|
default:
|
||||||
- admin
|
- admin
|
||||||
|
- cron_admin
|
||||||
role_deletion_suffix:
|
role_deletion_suffix:
|
||||||
type: string
|
type: string
|
||||||
default: "_deleted"
|
default: "_deleted"
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,13 @@ configuration:
|
||||||
# protocol: TCP
|
# protocol: TCP
|
||||||
workers: 8
|
workers: 8
|
||||||
users:
|
users:
|
||||||
|
# additional_owner_roles:
|
||||||
|
# - cron_admin
|
||||||
enable_password_rotation: false
|
enable_password_rotation: false
|
||||||
password_rotation_interval: 90
|
password_rotation_interval: 90
|
||||||
password_rotation_user_retention: 180
|
password_rotation_user_retention: 180
|
||||||
replication_username: standby
|
replication_username: standby
|
||||||
super_username: postgres
|
super_username: postgres
|
||||||
# cron_admin_username: cron_admin
|
|
||||||
major_version_upgrade:
|
major_version_upgrade:
|
||||||
major_version_upgrade_mode: "off"
|
major_version_upgrade_mode: "off"
|
||||||
# major_version_upgrade_team_allow_list:
|
# major_version_upgrade_team_allow_list:
|
||||||
|
|
|
||||||
|
|
@ -1142,9 +1142,15 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
|
||||||
"users": {
|
"users": {
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Properties: map[string]apiextv1.JSONSchemaProps{
|
Properties: map[string]apiextv1.JSONSchemaProps{
|
||||||
"cron_admin_username": {
|
"additional_owner_roles": {
|
||||||
|
Type: "array",
|
||||||
|
Nullable: true,
|
||||||
|
Items: &apiextv1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1.JSONSchemaProps{
|
||||||
Type: "string",
|
Type: "string",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
"enable_password_rotation": {
|
"enable_password_rotation": {
|
||||||
Type: "boolean",
|
Type: "boolean",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ type OperatorConfigurationList struct {
|
||||||
type PostgresUsersConfiguration struct {
|
type PostgresUsersConfiguration struct {
|
||||||
SuperUsername string `json:"super_username,omitempty"`
|
SuperUsername string `json:"super_username,omitempty"`
|
||||||
ReplicationUsername string `json:"replication_username,omitempty"`
|
ReplicationUsername string `json:"replication_username,omitempty"`
|
||||||
CronAdminUsername string `json:"cron_admin_username,omitempty"`
|
AddtionalOwnerRoles []string `json:"additional_owner_roles,omitempty"`
|
||||||
EnablePasswordRotation bool `json:"enable_password_rotation,omitempty"`
|
EnablePasswordRotation bool `json:"enable_password_rotation,omitempty"`
|
||||||
PasswordRotationInterval uint32 `json:"password_rotation_interval,omitempty"`
|
PasswordRotationInterval uint32 `json:"password_rotation_interval,omitempty"`
|
||||||
PasswordRotationUserRetention uint32 `json:"password_rotation_user_retention,omitempty"`
|
PasswordRotationUserRetention uint32 `json:"password_rotation_user_retention,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -401,7 +401,7 @@ func (in *OperatorConfigurationData) DeepCopyInto(out *OperatorConfigurationData
|
||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.PostgresUsersConfiguration = in.PostgresUsersConfiguration
|
in.PostgresUsersConfiguration.DeepCopyInto(&out.PostgresUsersConfiguration)
|
||||||
in.MajorVersionUpgrade.DeepCopyInto(&out.MajorVersionUpgrade)
|
in.MajorVersionUpgrade.DeepCopyInto(&out.MajorVersionUpgrade)
|
||||||
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
|
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
|
||||||
out.PostgresPodResources = in.PostgresPodResources
|
out.PostgresPodResources = in.PostgresPodResources
|
||||||
|
|
@ -916,6 +916,11 @@ func (in *PostgresTeamSpec) DeepCopy() *PostgresTeamSpec {
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *PostgresUsersConfiguration) DeepCopyInto(out *PostgresUsersConfiguration) {
|
func (in *PostgresUsersConfiguration) DeepCopyInto(out *PostgresUsersConfiguration) {
|
||||||
*out = *in
|
*out = *in
|
||||||
|
if in.AddtionalOwnerRoles != nil {
|
||||||
|
in, out := &in.AddtionalOwnerRoles, &out.AddtionalOwnerRoles
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ func (c *Cluster) initUsers() error {
|
||||||
return fmt.Errorf("could not init human users: %v", err)
|
return fmt.Errorf("could not init human users: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.initCronAdmin()
|
c.initAdditionalOwnerRoles()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -1299,11 +1299,9 @@ func (c *Cluster) initRobotUsers() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) initCronAdmin() {
|
func (c *Cluster) initAdditionalOwnerRoles() {
|
||||||
cronAdminName := c.OpConfig.CronAdminUsername
|
for _, additionalOwner := range c.OpConfig.AddtionalOwnerRoles {
|
||||||
if cronAdminName == "" {
|
// fetch all database owners the additional should become a member of
|
||||||
return
|
|
||||||
}
|
|
||||||
memberOf := make([]string, 0)
|
memberOf := make([]string, 0)
|
||||||
for username, pgUser := range c.pgUsers {
|
for username, pgUser := range c.pgUsers {
|
||||||
if pgUser.IsDbOwner {
|
if pgUser.IsDbOwner {
|
||||||
|
|
@ -1313,22 +1311,17 @@ func (c *Cluster) initCronAdmin() {
|
||||||
|
|
||||||
if len(memberOf) > 1 {
|
if len(memberOf) > 1 {
|
||||||
namespace := c.Namespace
|
namespace := c.Namespace
|
||||||
adminRole := ""
|
additionalOwnerPgUser := spec.PgUser{
|
||||||
if c.OpConfig.EnableAdminRoleForUsers && cronAdminName != c.OpConfig.TeamAdminRole {
|
|
||||||
adminRole = c.OpConfig.TeamAdminRole
|
|
||||||
}
|
|
||||||
cronAdmin := spec.PgUser{
|
|
||||||
Origin: spec.RoleOriginSpilo,
|
Origin: spec.RoleOriginSpilo,
|
||||||
MemberOf: memberOf,
|
MemberOf: memberOf,
|
||||||
Name: cronAdminName,
|
Name: additionalOwner,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Flags: []string{constants.RoleFlagNoLogin},
|
|
||||||
AdminRole: adminRole,
|
|
||||||
}
|
}
|
||||||
if currentRole, present := c.pgUsers[cronAdminName]; present {
|
if currentRole, present := c.pgUsers[additionalOwner]; present {
|
||||||
c.pgUsers[cronAdminName] = c.resolveNameConflict(¤tRole, &cronAdmin)
|
c.pgUsers[additionalOwner] = c.resolveNameConflict(¤tRole, &additionalOwnerPgUser)
|
||||||
} else {
|
} else {
|
||||||
c.pgUsers[cronAdminName] = cronAdmin
|
c.pgUsers[additionalOwner] = additionalOwnerPgUser
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ type Auth struct {
|
||||||
InfrastructureRolesDefs string `name:"infrastructure_roles_secrets"`
|
InfrastructureRolesDefs string `name:"infrastructure_roles_secrets"`
|
||||||
SuperUsername string `name:"super_username" default:"postgres"`
|
SuperUsername string `name:"super_username" default:"postgres"`
|
||||||
ReplicationUsername string `name:"replication_username" default:"standby"`
|
ReplicationUsername string `name:"replication_username" default:"standby"`
|
||||||
CronAdminUsername string `name:"cron_admin_username" default:""`
|
AddtionalOwnerRoles []string `name:"additional_owner_roles" default:""`
|
||||||
EnablePasswordRotation bool `name:"enable_password_rotation" default:"false"`
|
EnablePasswordRotation bool `name:"enable_password_rotation" default:"false"`
|
||||||
PasswordRotationInterval uint32 `name:"password_rotation_interval" default:"90"`
|
PasswordRotationInterval uint32 `name:"password_rotation_interval" default:"90"`
|
||||||
PasswordRotationUserRetention uint32 `name:"password_rotation_user_retention" default:"180"`
|
PasswordRotationUserRetention uint32 `name:"password_rotation_user_retention" default:"180"`
|
||||||
|
|
|
||||||
|
|
@ -53,25 +53,31 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r := spec.PgSyncUserRequest{}
|
r := spec.PgSyncUserRequest{}
|
||||||
|
r.User = dbUser
|
||||||
newMD5Password := util.NewEncryptor(strategy.PasswordEncryption).PGUserPassword(newUser)
|
newMD5Password := util.NewEncryptor(strategy.PasswordEncryption).PGUserPassword(newUser)
|
||||||
|
|
||||||
|
// do not compare for roles coming from docker image
|
||||||
|
if newUser.Origin != spec.RoleOriginSpilo {
|
||||||
if dbUser.Password != newMD5Password {
|
if dbUser.Password != newMD5Password {
|
||||||
r.User.Password = newMD5Password
|
r.User.Password = newMD5Password
|
||||||
r.Kind = spec.PGsyncUserAlter
|
r.Kind = spec.PGsyncUserAlter
|
||||||
}
|
}
|
||||||
if addNewRoles, equal := util.SubstractStringSlices(newUser.MemberOf, dbUser.MemberOf); !equal {
|
|
||||||
r.User.MemberOf = addNewRoles
|
|
||||||
r.Kind = spec.PGsyncUserAlter
|
|
||||||
}
|
|
||||||
if addNewFlags, equal := util.SubstractStringSlices(newUser.Flags, dbUser.Flags); !equal {
|
if addNewFlags, equal := util.SubstractStringSlices(newUser.Flags, dbUser.Flags); !equal {
|
||||||
r.User.Flags = addNewFlags
|
r.User.Flags = addNewFlags
|
||||||
r.Kind = spec.PGsyncUserAlter
|
r.Kind = spec.PGsyncUserAlter
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if addNewRoles, equal := util.SubstractStringSlices(newUser.MemberOf, dbUser.MemberOf); !equal {
|
||||||
|
r.User.MemberOf = addNewRoles
|
||||||
|
r.Kind = spec.PGsyncUserAlter
|
||||||
|
}
|
||||||
if r.Kind == spec.PGsyncUserAlter {
|
if r.Kind == spec.PGsyncUserAlter {
|
||||||
r.User.Name = newUser.Name
|
r.User.Name = newUser.Name
|
||||||
reqs = append(reqs, r)
|
reqs = append(reqs, r)
|
||||||
}
|
}
|
||||||
if len(newUser.Parameters) > 0 && !reflect.DeepEqual(dbUser.Parameters, newUser.Parameters) {
|
if newUser.Origin != spec.RoleOriginSpilo &&
|
||||||
|
len(newUser.Parameters) > 0 &&
|
||||||
|
!reflect.DeepEqual(dbUser.Parameters, newUser.Parameters) {
|
||||||
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncAlterSet, User: newUser})
|
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncAlterSet, User: newUser})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue