grant db owners to cron_admin
This commit is contained in:
		
							parent
							
								
									ca0c27a51b
								
							
						
					
					
						commit
						89801ef30a
					
				|  | @ -130,6 +130,8 @@ spec: | ||||||
|               users: |               users: | ||||||
|                 type: object |                 type: object | ||||||
|                 properties: |                 properties: | ||||||
|  |                   cron_admin_username: | ||||||
|  |                      type: string | ||||||
|                   enable_password_rotation: |                   enable_password_rotation: | ||||||
|                     type: boolean |                     type: boolean | ||||||
|                     default: false |                     default: false | ||||||
|  |  | ||||||
|  | @ -59,6 +59,14 @@ 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 | ||||||
|  |   cron_admin_username: 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 | ||||||
|  |  | ||||||
|  | @ -177,6 +177,13 @@ 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** | ||||||
|  |   Specifies the role that owns rights to set up cron jobs with `pg_cron` | ||||||
|  |   extension inside the `postgres` database. The must be pre-configured in the | ||||||
|  |   docker image. In Spilo this role is called `cron_admin`. This role will | ||||||
|  |   become a member of all database owners so that they can set up cron jobs | ||||||
|  |   e.g. as part of a migration script. 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 | ||||||
|  |  | ||||||
|  | @ -23,6 +23,7 @@ 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 | ||||||
|  | @ -109,7 +110,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,8 @@ spec: | ||||||
|               users: |               users: | ||||||
|                 type: object |                 type: object | ||||||
|                 properties: |                 properties: | ||||||
|  |                   cron_admin_username: | ||||||
|  |                      type: string | ||||||
|                   enable_password_rotation: |                   enable_password_rotation: | ||||||
|                     type: boolean |                     type: boolean | ||||||
|                     default: false |                     default: false | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ configuration: | ||||||
|     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: | ||||||
|  | @ -163,6 +164,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: | ||||||
|  |  | ||||||
|  | @ -1142,6 +1142,18 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{ | ||||||
| 					"users": { | 					"users": { | ||||||
| 						Type: "object", | 						Type: "object", | ||||||
| 						Properties: map[string]apiextv1.JSONSchemaProps{ | 						Properties: map[string]apiextv1.JSONSchemaProps{ | ||||||
|  | 							"cron_admin_username": { | ||||||
|  | 								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", | ||||||
| 							}, | 							}, | ||||||
|  |  | ||||||
|  | @ -39,6 +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"` | ||||||
| 	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"` | ||||||
|  |  | ||||||
|  | @ -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.initCronAdmin() | ||||||
|  | 
 | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1297,6 +1299,40 @@ func (c *Cluster) initRobotUsers() error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (c *Cluster) initCronAdmin() { | ||||||
|  | 	cronAdminName := c.OpConfig.CronAdminUsername | ||||||
|  | 	if cronAdminName == "" { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	memberOf := make([]string, 0) | ||||||
|  | 	for username, pgUser := range c.pgUsers { | ||||||
|  | 		if pgUser.IsDbOwner { | ||||||
|  | 			memberOf = append(memberOf, username) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(memberOf) > 1 { | ||||||
|  | 		namespace := c.Namespace | ||||||
|  | 		adminRole := "" | ||||||
|  | 		if c.OpConfig.EnableAdminRoleForUsers && cronAdminName != c.OpConfig.TeamAdminRole { | ||||||
|  | 			adminRole = c.OpConfig.TeamAdminRole | ||||||
|  | 		} | ||||||
|  | 		cronAdmin := spec.PgUser{ | ||||||
|  | 			Origin:    spec.RoleOriginSpilo, | ||||||
|  | 			MemberOf:  memberOf, | ||||||
|  | 			Name:      cronAdminName, | ||||||
|  | 			Namespace: namespace, | ||||||
|  | 			Flags:     []string{constants.RoleFlagNoLogin}, | ||||||
|  | 			AdminRole: adminRole, | ||||||
|  | 		} | ||||||
|  | 		if currentRole, present := c.pgUsers[cronAdminName]; present { | ||||||
|  | 			c.pgUsers[cronAdminName] = c.resolveNameConflict(¤tRole, &cronAdmin) | ||||||
|  | 		} else { | ||||||
|  | 			c.pgUsers[cronAdminName] = cronAdmin | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 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) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -55,6 +55,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.CronAdminUsername = fromCRD.PostgresUsersConfiguration.CronAdminUsername | ||||||
| 	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) | ||||||
|  | @ -186,7 +187,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"` | ||||||
|  | 	CronAdminUsername             string                `name:"cron_admin_username" 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"` | ||||||
|  | @ -210,7 +211,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"` | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue