grant db owners to cron_admin (#1805)
* grant db owners to cron_admin * allow specifiying more extra owner roles * add unit test for InitAdditionalOwnerRoles * add e2e test
This commit is contained in:
parent
6ba05fee22
commit
2719d411c3
|
|
@ -130,6 +130,11 @@ spec:
|
||||||
users:
|
users:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
additional_owner_roles:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
enable_password_rotation:
|
enable_password_rotation:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
@ -514,6 +519,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,6 +59,16 @@ configGeneral:
|
||||||
|
|
||||||
# parameters describing Postgres users
|
# parameters describing Postgres users
|
||||||
configUsers:
|
configUsers:
|
||||||
|
# roles to be granted to database owners
|
||||||
|
# additional_owner_roles:
|
||||||
|
# - cron_admin
|
||||||
|
|
||||||
|
# enable password rotation for app users that are not database owners
|
||||||
|
enable_password_rotation: false
|
||||||
|
# rotation interval for updating credentials in K8s secrets of app users
|
||||||
|
password_rotation_interval: 90
|
||||||
|
# retention interval to keep rotation users
|
||||||
|
password_rotation_user_retention: 180
|
||||||
# postgres username used for replication between instances
|
# postgres username used for replication between instances
|
||||||
replication_username: standby
|
replication_username: standby
|
||||||
# postgres superuser name to be created by initdb
|
# postgres superuser name to be created by initdb
|
||||||
|
|
@ -348,6 +358,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,6 +177,15 @@ 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`.
|
||||||
|
|
||||||
|
* **additional_owner_roles**
|
||||||
|
Specifies database roles that will become members of all database owners.
|
||||||
|
Then owners can use `SET ROLE` to obtain privileges of these roles to e.g.
|
||||||
|
create/update functionality from extensions as part of a migration script.
|
||||||
|
Note, that roles listed here should be preconfigured in the docker image
|
||||||
|
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
|
||||||
credentials in the corresponding K8s secrets by replacing the username and
|
credentials in the corresponding K8s secrets by replacing the username and
|
||||||
|
|
@ -770,7 +779,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
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,37 @@ class EndToEndTestCase(unittest.TestCase):
|
||||||
print('Operator log: {}'.format(k8s.get_operator_log()))
|
print('Operator log: {}'.format(k8s.get_operator_log()))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@timeout_decorator.timeout(TEST_TIMEOUT_SEC)
|
||||||
|
def test_additional_owner_roles(self):
|
||||||
|
'''
|
||||||
|
Test adding additional member roles to existing database owner roles
|
||||||
|
'''
|
||||||
|
k8s = self.k8s
|
||||||
|
|
||||||
|
# enable PostgresTeam CRD and lower resync
|
||||||
|
owner_roles = {
|
||||||
|
"data": {
|
||||||
|
"additional_owner_roles": "cron_admin",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
k8s.update_config(owner_roles)
|
||||||
|
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"},
|
||||||
|
"Operator does not get in sync")
|
||||||
|
|
||||||
|
leader = k8s.get_cluster_leader_pod()
|
||||||
|
owner_query = """
|
||||||
|
SELECT a2.rolname
|
||||||
|
FROM pg_catalog.pg_authid a
|
||||||
|
JOIN pg_catalog.pg_auth_members am
|
||||||
|
ON a.oid = am.member
|
||||||
|
AND a.rolname = 'cron_admin'
|
||||||
|
JOIN pg_catalog.pg_authid a2
|
||||||
|
ON a2.oid = am.roleid
|
||||||
|
WHERE a2.rolname IN ('zalando', 'bar_owner', 'bar_data_owner');
|
||||||
|
"""
|
||||||
|
self.eventuallyEqual(lambda: len(self.query_database(leader.metadata.name, "postgres", owner_query)), 3,
|
||||||
|
"Not all additional users found in database", 10, 5)
|
||||||
|
|
||||||
@timeout_decorator.timeout(TEST_TIMEOUT_SEC)
|
@timeout_decorator.timeout(TEST_TIMEOUT_SEC)
|
||||||
def test_additional_pod_capabilities(self):
|
def test_additional_pod_capabilities(self):
|
||||||
'''
|
'''
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
@ -114,7 +115,7 @@ data:
|
||||||
# pod_service_account_role_binding_definition: ""
|
# pod_service_account_role_binding_definition: ""
|
||||||
pod_terminate_grace_period: 5m
|
pod_terminate_grace_period: 5m
|
||||||
# postgres_superuser_teams: "postgres_superusers"
|
# postgres_superuser_teams: "postgres_superusers"
|
||||||
# protected_role_names: "admin"
|
# protected_role_names: "admin,cron_admin"
|
||||||
ready_wait_interval: 3s
|
ready_wait_interval: 3s
|
||||||
ready_wait_timeout: 30s
|
ready_wait_timeout: 30s
|
||||||
repair_period: 5m
|
repair_period: 5m
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,11 @@ spec:
|
||||||
users:
|
users:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
additional_owner_roles:
|
||||||
|
type: array
|
||||||
|
nullable: true
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
enable_password_rotation:
|
enable_password_rotation:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
@ -512,6 +517,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,6 +26,8 @@ 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
|
||||||
|
|
@ -168,6 +170,7 @@ configuration:
|
||||||
# - postgres_superusers
|
# - postgres_superusers
|
||||||
protected_role_names:
|
protected_role_names:
|
||||||
- admin
|
- admin
|
||||||
|
- cron_admin
|
||||||
role_deletion_suffix: "_deleted"
|
role_deletion_suffix: "_deleted"
|
||||||
team_admin_role: admin
|
team_admin_role: admin
|
||||||
team_api_role_configuration:
|
team_api_role_configuration:
|
||||||
|
|
|
||||||
|
|
@ -1148,6 +1148,24 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
|
||||||
"users": {
|
"users": {
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Properties: map[string]apiextv1.JSONSchemaProps{
|
Properties: map[string]apiextv1.JSONSchemaProps{
|
||||||
|
"additional_owner_roles": {
|
||||||
|
Type: "array",
|
||||||
|
Nullable: true,
|
||||||
|
Items: &apiextv1.JSONSchemaPropsOrArray{
|
||||||
|
Schema: &apiextv1.JSONSchemaProps{
|
||||||
|
Type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"enable_password_rotation": {
|
||||||
|
Type: "boolean",
|
||||||
|
},
|
||||||
|
"password_rotation_interval": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
|
"password_rotation_user_retention": {
|
||||||
|
Type: "integer",
|
||||||
|
},
|
||||||
"replication_username": {
|
"replication_username": {
|
||||||
Type: "string",
|
Type: "string",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,12 @@ type OperatorConfigurationList struct {
|
||||||
|
|
||||||
// PostgresUsersConfiguration defines the system users of Postgres.
|
// PostgresUsersConfiguration defines the system users of Postgres.
|
||||||
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"`
|
||||||
EnablePasswordRotation bool `json:"enable_password_rotation,omitempty"`
|
AdditionalOwnerRoles []string `json:"additional_owner_roles,omitempty"`
|
||||||
PasswordRotationInterval uint32 `json:"password_rotation_interval,omitempty"`
|
EnablePasswordRotation bool `json:"enable_password_rotation,omitempty"`
|
||||||
PasswordRotationUserRetention uint32 `json:"password_rotation_user_retention,omitempty"`
|
PasswordRotationInterval uint32 `json:"password_rotation_interval,omitempty"`
|
||||||
|
PasswordRotationUserRetention uint32 `json:"password_rotation_user_retention,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MajorVersionUpgradeConfiguration defines how to execute major version upgrades of Postgres.
|
// MajorVersionUpgradeConfiguration defines how to execute major version upgrades of Postgres.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -926,6 +926,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.AdditionalOwnerRoles != nil {
|
||||||
|
in, out := &in.AdditionalOwnerRoles, &out.AdditionalOwnerRoles
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,8 @@ 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.initAdditionalOwnerRoles()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1297,6 +1299,33 @@ func (c *Cluster) initRobotUsers() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) initAdditionalOwnerRoles() {
|
||||||
|
for _, additionalOwner := range c.OpConfig.AdditionalOwnerRoles {
|
||||||
|
// fetch all database owners the additional should become a member of
|
||||||
|
memberOf := make([]string, 0)
|
||||||
|
for username, pgUser := range c.pgUsers {
|
||||||
|
if pgUser.IsDbOwner {
|
||||||
|
memberOf = append(memberOf, username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(memberOf) > 1 {
|
||||||
|
namespace := c.Namespace
|
||||||
|
additionalOwnerPgUser := spec.PgUser{
|
||||||
|
Origin: spec.RoleOriginSpilo,
|
||||||
|
MemberOf: memberOf,
|
||||||
|
Name: additionalOwner,
|
||||||
|
Namespace: namespace,
|
||||||
|
}
|
||||||
|
if currentRole, present := c.pgUsers[additionalOwner]; present {
|
||||||
|
c.pgUsers[additionalOwner] = c.resolveNameConflict(¤tRole, &additionalOwnerPgUser)
|
||||||
|
} else {
|
||||||
|
c.pgUsers[additionalOwner] = additionalOwnerPgUser
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cluster) initTeamMembers(teamID string, isPostgresSuperuserTeam bool) error {
|
func (c *Cluster) initTeamMembers(teamID string, isPostgresSuperuserTeam bool) error {
|
||||||
teamMembers, err := c.getTeamMembers(teamID)
|
teamMembers, err := c.getTeamMembers(teamID)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,11 @@ var cl = New(
|
||||||
Config{
|
Config{
|
||||||
OpConfig: config.Config{
|
OpConfig: config.Config{
|
||||||
PodManagementPolicy: "ordered_ready",
|
PodManagementPolicy: "ordered_ready",
|
||||||
ProtectedRoles: []string{"admin"},
|
ProtectedRoles: []string{"admin", "cron_admin", "part_man"},
|
||||||
Auth: config.Auth{
|
Auth: config.Auth{
|
||||||
SuperUsername: superUserName,
|
SuperUsername: superUserName,
|
||||||
ReplicationUsername: replicationUserName,
|
ReplicationUsername: replicationUserName,
|
||||||
|
AdditionalOwnerRoles: []string{"cron_admin", "part_man"},
|
||||||
},
|
},
|
||||||
Resources: config.Resources{
|
Resources: config.Resources{
|
||||||
DownscalerAnnotations: []string{"downscaler/*"},
|
DownscalerAnnotations: []string{"downscaler/*"},
|
||||||
|
|
@ -44,7 +45,13 @@ var cl = New(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
k8sutil.NewMockKubernetesClient(),
|
k8sutil.NewMockKubernetesClient(),
|
||||||
acidv1.Postgresql{ObjectMeta: metav1.ObjectMeta{Name: "acid-test", Namespace: "test", Annotations: map[string]string{"downscaler/downtime_replicas": "0"}}},
|
acidv1.Postgresql{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "acid-test",
|
||||||
|
Namespace: "test",
|
||||||
|
Annotations: map[string]string{"downscaler/downtime_replicas": "0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
logger,
|
logger,
|
||||||
eventRecorder,
|
eventRecorder,
|
||||||
)
|
)
|
||||||
|
|
@ -132,6 +139,39 @@ func TestInitRobotUsers(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInitAdditionalOwnerRoles(t *testing.T) {
|
||||||
|
testName := "TestInitAdditionalOwnerRoles"
|
||||||
|
|
||||||
|
manifestUsers := map[string]acidv1.UserFlags{"foo_owner": {}, "bar_owner": {}, "app_user": {}}
|
||||||
|
expectedUsers := map[string]spec.PgUser{
|
||||||
|
"foo_owner": {Origin: spec.RoleOriginManifest, Name: "foo_owner", Namespace: cl.Namespace, Password: "f123", Flags: []string{"LOGIN"}, IsDbOwner: true},
|
||||||
|
"bar_owner": {Origin: spec.RoleOriginManifest, Name: "bar_owner", Namespace: cl.Namespace, Password: "b123", Flags: []string{"LOGIN"}, IsDbOwner: true},
|
||||||
|
"app_user": {Origin: spec.RoleOriginManifest, Name: "app_user", Namespace: cl.Namespace, Password: "a123", Flags: []string{"LOGIN"}, IsDbOwner: false},
|
||||||
|
"cron_admin": {Origin: spec.RoleOriginSpilo, Name: "cron_admin", Namespace: cl.Namespace, MemberOf: []string{"foo_owner", "bar_owner"}},
|
||||||
|
"part_man": {Origin: spec.RoleOriginSpilo, Name: "part_man", Namespace: cl.Namespace, MemberOf: []string{"foo_owner", "bar_owner"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.Spec.Databases = map[string]string{"foo_db": "foo_owner", "bar_db": "bar_owner"}
|
||||||
|
cl.Spec.Users = manifestUsers
|
||||||
|
|
||||||
|
// this should set IsDbOwner field for manifest users
|
||||||
|
if err := cl.initRobotUsers(); err != nil {
|
||||||
|
t.Errorf("%s could not init manifest users", testName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update passwords to compare with result
|
||||||
|
for manifestUser := range manifestUsers {
|
||||||
|
pgUser := cl.pgUsers[manifestUser]
|
||||||
|
pgUser.Password = manifestUser[0:1] + "123"
|
||||||
|
cl.pgUsers[manifestUser] = pgUser
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.initAdditionalOwnerRoles()
|
||||||
|
if !reflect.DeepEqual(cl.pgUsers, expectedUsers) {
|
||||||
|
t.Errorf("%s expected: %#v, got %#v", testName, expectedUsers, cl.pgUsers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type mockOAuthTokenGetter struct {
|
type mockOAuthTokenGetter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1622,7 +1622,7 @@ func (c *Cluster) generateUserSecrets() map[string]*v1.Secret {
|
||||||
func (c *Cluster) generateSingleUserSecret(namespace string, pgUser spec.PgUser) *v1.Secret {
|
func (c *Cluster) generateSingleUserSecret(namespace string, pgUser spec.PgUser) *v1.Secret {
|
||||||
//Skip users with no password i.e. human users (they'll be authenticated using pam)
|
//Skip users with no password i.e. human users (they'll be authenticated using pam)
|
||||||
if pgUser.Password == "" {
|
if pgUser.Password == "" {
|
||||||
if pgUser.Origin != spec.RoleOriginTeamsAPI {
|
if pgUser.Origin != spec.RoleOriginTeamsAPI && pgUser.Origin != spec.RoleOriginSpilo {
|
||||||
c.logger.Warningf("could not generate secret for a non-teamsAPI role %q: role has no password",
|
c.logger.Warningf("could not generate secret for a non-teamsAPI role %q: role has no password",
|
||||||
pgUser.Name)
|
pgUser.Name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
// user config
|
// user config
|
||||||
result.SuperUsername = util.Coalesce(fromCRD.PostgresUsersConfiguration.SuperUsername, "postgres")
|
result.SuperUsername = util.Coalesce(fromCRD.PostgresUsersConfiguration.SuperUsername, "postgres")
|
||||||
result.ReplicationUsername = util.Coalesce(fromCRD.PostgresUsersConfiguration.ReplicationUsername, "standby")
|
result.ReplicationUsername = util.Coalesce(fromCRD.PostgresUsersConfiguration.ReplicationUsername, "standby")
|
||||||
|
result.AdditionalOwnerRoles = fromCRD.PostgresUsersConfiguration.AdditionalOwnerRoles
|
||||||
result.EnablePasswordRotation = fromCRD.PostgresUsersConfiguration.EnablePasswordRotation
|
result.EnablePasswordRotation = fromCRD.PostgresUsersConfiguration.EnablePasswordRotation
|
||||||
result.PasswordRotationInterval = util.CoalesceUInt32(fromCRD.PostgresUsersConfiguration.PasswordRotationInterval, 90)
|
result.PasswordRotationInterval = util.CoalesceUInt32(fromCRD.PostgresUsersConfiguration.PasswordRotationInterval, 90)
|
||||||
result.PasswordRotationUserRetention = util.CoalesceUInt32(fromCRD.PostgresUsersConfiguration.DeepCopy().PasswordRotationUserRetention, 180)
|
result.PasswordRotationUserRetention = util.CoalesceUInt32(fromCRD.PostgresUsersConfiguration.DeepCopy().PasswordRotationUserRetention, 180)
|
||||||
|
|
@ -188,7 +189,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
result.TeamAdminRole = fromCRD.TeamsAPI.TeamAdminRole
|
result.TeamAdminRole = fromCRD.TeamsAPI.TeamAdminRole
|
||||||
result.PamRoleName = util.Coalesce(fromCRD.TeamsAPI.PamRoleName, "zalandos")
|
result.PamRoleName = util.Coalesce(fromCRD.TeamsAPI.PamRoleName, "zalandos")
|
||||||
result.PamConfiguration = util.Coalesce(fromCRD.TeamsAPI.PamConfiguration, "https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees")
|
result.PamConfiguration = util.Coalesce(fromCRD.TeamsAPI.PamConfiguration, "https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees")
|
||||||
result.ProtectedRoles = util.CoalesceStrArr(fromCRD.TeamsAPI.ProtectedRoles, []string{"admin"})
|
result.ProtectedRoles = util.CoalesceStrArr(fromCRD.TeamsAPI.ProtectedRoles, []string{"admin", "cron_admin"})
|
||||||
result.PostgresSuperuserTeams = fromCRD.TeamsAPI.PostgresSuperuserTeams
|
result.PostgresSuperuserTeams = fromCRD.TeamsAPI.PostgresSuperuserTeams
|
||||||
result.EnablePostgresTeamCRD = fromCRD.TeamsAPI.EnablePostgresTeamCRD
|
result.EnablePostgresTeamCRD = fromCRD.TeamsAPI.EnablePostgresTeamCRD
|
||||||
result.EnablePostgresTeamCRDSuperusers = fromCRD.TeamsAPI.EnablePostgresTeamCRDSuperusers
|
result.EnablePostgresTeamCRDSuperusers = fromCRD.TeamsAPI.EnablePostgresTeamCRDSuperusers
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ const (
|
||||||
RoleOriginManifest
|
RoleOriginManifest
|
||||||
RoleOriginInfrastructure
|
RoleOriginInfrastructure
|
||||||
RoleOriginTeamsAPI
|
RoleOriginTeamsAPI
|
||||||
|
RoleOriginSpilo
|
||||||
RoleOriginSystem
|
RoleOriginSystem
|
||||||
RoleOriginBootstrap
|
RoleOriginBootstrap
|
||||||
RoleConnectionPooler
|
RoleConnectionPooler
|
||||||
|
|
|
||||||
|
|
@ -101,6 +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"`
|
||||||
|
AdditionalOwnerRoles []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"`
|
||||||
|
|
@ -213,7 +214,7 @@ type Config struct {
|
||||||
TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"`
|
TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"`
|
||||||
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
||||||
PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"`
|
PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"`
|
||||||
ProtectedRoles []string `name:"protected_role_names" default:"admin"`
|
ProtectedRoles []string `name:"protected_role_names" default:"admin,cron_admin"`
|
||||||
PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""`
|
PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""`
|
||||||
SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"`
|
SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"`
|
||||||
EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"`
|
EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"`
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
if dbUser.Password != newMD5Password {
|
// do not compare for roles coming from docker image
|
||||||
r.User.Password = newMD5Password
|
if newUser.Origin != spec.RoleOriginSpilo {
|
||||||
r.Kind = spec.PGsyncUserAlter
|
if dbUser.Password != newMD5Password {
|
||||||
|
r.User.Password = newMD5Password
|
||||||
|
r.Kind = spec.PGsyncUserAlter
|
||||||
|
}
|
||||||
|
if addNewFlags, equal := util.SubstractStringSlices(newUser.Flags, dbUser.Flags); !equal {
|
||||||
|
r.User.Flags = addNewFlags
|
||||||
|
r.Kind = spec.PGsyncUserAlter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if addNewRoles, equal := util.SubstractStringSlices(newUser.MemberOf, dbUser.MemberOf); !equal {
|
if addNewRoles, equal := util.SubstractStringSlices(newUser.MemberOf, dbUser.MemberOf); !equal {
|
||||||
r.User.MemberOf = addNewRoles
|
r.User.MemberOf = addNewRoles
|
||||||
r.Kind = spec.PGsyncUserAlter
|
r.Kind = spec.PGsyncUserAlter
|
||||||
}
|
}
|
||||||
if addNewFlags, equal := util.SubstractStringSlices(newUser.Flags, dbUser.Flags); !equal {
|
|
||||||
r.User.Flags = addNewFlags
|
|
||||||
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