allow specifiying more extra owner roles
This commit is contained in:
		
							parent
							
								
									89801ef30a
								
							
						
					
					
						commit
						78eaae2efc
					
				|  | @ -130,8 +130,11 @@ spec: | ||||||
|               users: |               users: | ||||||
|                 type: object |                 type: object | ||||||
|                 properties: |                 properties: | ||||||
|                   cron_admin_username: |                   additional_owner_roles: | ||||||
|                      type: string |                     type: array | ||||||
|  |                     nullable: true | ||||||
|  |                     items: | ||||||
|  |                       type: string | ||||||
|                   enable_password_rotation: |                   enable_password_rotation: | ||||||
|                     type: boolean |                     type: boolean | ||||||
|                     default: false |                     default: false | ||||||
|  | @ -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,8 +128,11 @@ spec: | ||||||
|               users: |               users: | ||||||
|                 type: object |                 type: object | ||||||
|                 properties: |                 properties: | ||||||
|                   cron_admin_username: |                   additional_owner_roles: | ||||||
|                      type: string |                     type: array | ||||||
|  |                     nullable: true | ||||||
|  |                     items: | ||||||
|  |                       type: string | ||||||
|                   enable_password_rotation: |                   enable_password_rotation: | ||||||
|                     type: boolean |                     type: boolean | ||||||
|                     default: false |                     default: false | ||||||
|  | @ -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,8 +1142,14 @@ 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: "string", | 								Type:     "array", | ||||||
|  | 								Nullable: true, | ||||||
|  | 								Items: &apiextv1.JSONSchemaPropsOrArray{ | ||||||
|  | 									Schema: &apiextv1.JSONSchemaProps{ | ||||||
|  | 										Type: "string", | ||||||
|  | 									}, | ||||||
|  | 								}, | ||||||
| 							}, | 							}, | ||||||
| 							"enable_password_rotation": { | 							"enable_password_rotation": { | ||||||
| 								Type: "boolean", | 								Type: "boolean", | ||||||
|  |  | ||||||
|  | @ -37,12 +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"` | ||||||
| 	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"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 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 | ||||||
|  | @ -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,36 +1299,29 @@ 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) | ||||||
| 	} | 		for username, pgUser := range c.pgUsers { | ||||||
| 	memberOf := make([]string, 0) | 			if pgUser.IsDbOwner { | ||||||
| 	for username, pgUser := range c.pgUsers { | 				memberOf = append(memberOf, username) | ||||||
| 		if pgUser.IsDbOwner { | 			} | ||||||
| 			memberOf = append(memberOf, username) |  | ||||||
| 		} | 		} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	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 { | 				Origin:    spec.RoleOriginSpilo, | ||||||
| 			adminRole = c.OpConfig.TeamAdminRole | 				MemberOf:  memberOf, | ||||||
| 		} | 				Name:      additionalOwner, | ||||||
| 		cronAdmin := spec.PgUser{ | 				Namespace: namespace, | ||||||
| 			Origin:    spec.RoleOriginSpilo, | 			} | ||||||
| 			MemberOf:  memberOf, | 			if currentRole, present := c.pgUsers[additionalOwner]; present { | ||||||
| 			Name:      cronAdminName, | 				c.pgUsers[additionalOwner] = c.resolveNameConflict(¤tRole, &additionalOwnerPgUser) | ||||||
| 			Namespace: namespace, | 			} else { | ||||||
| 			Flags:     []string{constants.RoleFlagNoLogin}, | 				c.pgUsers[additionalOwner] = additionalOwnerPgUser | ||||||
| 			AdminRole: adminRole, | 			} | ||||||
| 		} |  | ||||||
| 		if currentRole, present := c.pgUsers[cronAdminName]; present { |  | ||||||
| 			c.pgUsers[cronAdminName] = c.resolveNameConflict(¤tRole, &cronAdmin) |  | ||||||
| 		} else { |  | ||||||
| 			c.pgUsers[cronAdminName] = cronAdmin |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 
 | 
 | ||||||
| 			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