mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-10-17 23:26:02 +02:00
Password rotation in secrets (#1749)
* password rotation in K8s secrets * add db connection to syncSecrets * add user retention * add e2e test * cleanup on username mismatch if rotation was switched off * add unit test for syncSecrets + new updateSecret func
This commit is contained in:
@@ -293,6 +293,84 @@ that are aggregated into the K8s [default roles](https://kubernetes.io/docs/refe
|
||||
|
||||
For Helm deployments setting `rbac.createAggregateClusterRoles: true` adds these clusterroles to the deployment.
|
||||
|
||||
## Password rotation in K8s secrets
|
||||
|
||||
The operator regularly updates credentials in the K8s secrets if the
|
||||
`enable_password_rotation` option is set to `true` in the configuration.
|
||||
It happens only for `LOGIN` roles with an associated secret (manifest roles,
|
||||
default users from `preparedDatabases`). Furthermore, there are the following
|
||||
exceptions:
|
||||
|
||||
1. Infrastructure role secrets since rotation should happen by the infrastructure.
|
||||
2. Team API roles that connect via OAuth2 and JWT token (no secrets to these roles anyway).
|
||||
3. Database owners since ownership on database objects can not be inherited.
|
||||
4. System users such as `postgres`, `standby` and `pooler` user.
|
||||
|
||||
The interval of days can be set with `password_rotation_interval` (default
|
||||
`90` = 90 days, minimum 1). On each rotation the user name and password values
|
||||
are replaced in the K8s secret. They belong to a newly created user named after
|
||||
the original role plus rotation date in YYMMDD format. All priviliges are
|
||||
inherited meaning that migration scripts should still grant and revoke rights
|
||||
against the original role. The timestamp of the next rotation is written to the
|
||||
secret as well. Note, if the rotation interval is decreased it is reflected in
|
||||
the secrets only if the next rotation date is more days away than the new
|
||||
length of the interval.
|
||||
|
||||
Pods still using the previous secret values which they keep in memory continue
|
||||
to connect to the database since the password of the corresponding user is not
|
||||
replaced. However, a retention policy can be configured for users created by
|
||||
the password rotation feature with `password_rotation_user_retention`. The
|
||||
operator will ensure that this period is at least twice as long as the
|
||||
configured rotation interval, hence the default of `180` = 180 days. When
|
||||
the creation date of a rotated user is older than the retention period it
|
||||
might not get removed immediately. Only on the next user rotation it is checked
|
||||
if users can get removed. Therefore, you might want to configure the retention
|
||||
to be a multiple of the rotation interval.
|
||||
|
||||
### Password rotation for single users
|
||||
|
||||
From the configuration, password rotation is enabled for all secrets with the
|
||||
mentioned exceptions. If you wish to first test rotation for a single user (or
|
||||
just have it enabled only for a few secrets) you can specify it in the cluster
|
||||
manifest. The rotation and retention intervals can only be configured globally.
|
||||
|
||||
```
|
||||
spec:
|
||||
usersWithSecretRotation:
|
||||
- foo_user
|
||||
- bar_reader_user
|
||||
```
|
||||
|
||||
### Password replacement without extra users
|
||||
|
||||
For some use cases where the secret is only used rarely - think of a `flyway`
|
||||
user running a migration script on pod start - we do not need to create extra
|
||||
database users but can replace only the password in the K8s secret. This type
|
||||
of rotation cannot be configured globally but specified in the cluster
|
||||
manifest:
|
||||
|
||||
```
|
||||
spec:
|
||||
usersWithInPlaceSecretRotation:
|
||||
- flyway
|
||||
- bar_owner_user
|
||||
```
|
||||
|
||||
This would be the recommended option to enable rotation in secrets of database
|
||||
owners, but only if they are not used as application users for regular read
|
||||
and write operations.
|
||||
|
||||
### Turning off password rotation
|
||||
|
||||
When password rotation is turned off again the operator will check if the
|
||||
`username` value in the secret matches the original username and replace it
|
||||
with the latter. A new password is assigned and the `nextRotation` field is
|
||||
cleared. A final lookup for child (rotation) users to be removed is done but
|
||||
they will only be dropped if the retention policy allows for it. This is to
|
||||
avoid sudden connection issues in pods which still use credentials of these
|
||||
users in memory. You have to remove these child users manually or re-enable
|
||||
password rotation with smaller interval so they get cleaned up.
|
||||
|
||||
## Use taints and tolerations for dedicated PostgreSQL nodes
|
||||
|
||||
To ensure Postgres pods are running on nodes without any other application pods,
|
||||
|
||||
Reference in New Issue
Block a user