do not reset secrets of standby clusters
align error message with unit test
This commit is contained in:
parent
aefe9d8298
commit
5b72a725bd
|
|
@ -385,7 +385,7 @@ func (c *Cluster) Create() (err error) {
|
|||
|
||||
// create database objects unless we are running without pods or disabled
|
||||
// that feature explicitly
|
||||
if !(c.databaseAccessDisabled() || c.getNumberOfInstances(&c.Spec) <= 0 || c.Spec.StandbyCluster != nil) {
|
||||
if !(c.databaseAccessDisabled() || c.getNumberOfInstances(&c.Spec) <= 0 || isStandbyCluster(&c.Spec)) {
|
||||
c.logger.Infof("Create roles")
|
||||
if err = c.createRoles(); err != nil {
|
||||
return fmt.Errorf("could not create users: %v", err)
|
||||
|
|
|
|||
|
|
@ -1691,7 +1691,7 @@ func (c *Cluster) getNumberOfInstances(spec *acidv1.PostgresSpec) int32 {
|
|||
}
|
||||
}
|
||||
|
||||
if spec.StandbyCluster != nil {
|
||||
if isStandbyCluster(spec) {
|
||||
if newcur == 1 {
|
||||
min = newcur
|
||||
max = newcur
|
||||
|
|
|
|||
|
|
@ -1174,42 +1174,15 @@ func (c *Cluster) updateSecret(
|
|||
pwdUser := userMap[userKey]
|
||||
secretName := util.NameFromMeta(secret.ObjectMeta)
|
||||
|
||||
// if password rotation is enabled update password and username if rotation interval has been passed
|
||||
// rotation can be enabled globally or via the manifest (excluding the Postgres superuser)
|
||||
rotationEnabledInManifest := secretUsername != constants.SuperuserKeyName &&
|
||||
(slices.Contains(c.Spec.UsersWithSecretRotation, secretUsername) ||
|
||||
slices.Contains(c.Spec.UsersWithInPlaceSecretRotation, secretUsername))
|
||||
|
||||
// globally enabled rotation is only allowed for manifest and bootstrapped roles
|
||||
allowedRoleTypes := []spec.RoleOrigin{spec.RoleOriginManifest, spec.RoleOriginBootstrap}
|
||||
rotationAllowed := !pwdUser.IsDbOwner && slices.Contains(allowedRoleTypes, pwdUser.Origin) && c.Spec.StandbyCluster == nil
|
||||
|
||||
// users can ignore any kind of rotation
|
||||
isIgnoringRotation := slices.Contains(c.Spec.UsersIgnoringSecretRotation, secretUsername)
|
||||
|
||||
if ((c.OpConfig.EnablePasswordRotation && rotationAllowed) || rotationEnabledInManifest) && !isIgnoringRotation {
|
||||
updateSecretMsg, err = c.rotatePasswordInSecret(secret, secretUsername, pwdUser.Origin, currentTime, retentionUsers)
|
||||
// do not perform any rotation of reset for standby clusters
|
||||
if !isStandbyCluster(&c.Spec) {
|
||||
updateSecretMsg, err = c.checkForPasswordRotation(secret, secretUsername, pwdUser, retentionUsers, currentTime)
|
||||
if err != nil {
|
||||
c.logger.Warnf("password rotation failed for user %s: %v", secretUsername, err)
|
||||
return nil, fmt.Errorf("error while checking for password rotation: %v", err)
|
||||
}
|
||||
if updateSecretMsg != "" {
|
||||
updateSecret = true
|
||||
}
|
||||
} else {
|
||||
// username might not match if password rotation has been disabled again
|
||||
usernameFromSecret := string(secret.Data["username"])
|
||||
if secretUsername != usernameFromSecret {
|
||||
// handle edge case when manifest user conflicts with a user from prepared databases
|
||||
if strings.Replace(usernameFromSecret, "-", "_", -1) == strings.Replace(secretUsername, "-", "_", -1) {
|
||||
return nil, fmt.Errorf("could not update secret because of user name mismatch: expected: %s, got: %s", secretUsername, usernameFromSecret)
|
||||
}
|
||||
*retentionUsers = append(*retentionUsers, secretUsername)
|
||||
secret.Data["username"] = []byte(secretUsername)
|
||||
secret.Data["password"] = []byte(util.RandomPassword(constants.PasswordLength))
|
||||
secret.Data["nextRotation"] = []byte{}
|
||||
updateSecret = true
|
||||
updateSecretMsg = fmt.Sprintf("secret does not contain the role %s - updating username and resetting password", secretUsername)
|
||||
}
|
||||
}
|
||||
|
||||
// if this secret belongs to the infrastructure role and the password has changed - replace it in the secret
|
||||
|
|
@ -1256,6 +1229,55 @@ func (c *Cluster) updateSecret(
|
|||
return secret, nil
|
||||
}
|
||||
|
||||
func (c *Cluster) checkForPasswordRotation(
|
||||
secret *v1.Secret,
|
||||
secretUsername string,
|
||||
pwdUser spec.PgUser,
|
||||
retentionUsers *[]string,
|
||||
currentTime time.Time) (string, error) {
|
||||
|
||||
var (
|
||||
passwordRotationMsg string
|
||||
err error
|
||||
)
|
||||
|
||||
// if password rotation is enabled update password and username if rotation interval has been passed
|
||||
// rotation can be enabled globally or via the manifest (excluding the Postgres superuser)
|
||||
rotationEnabledInManifest := secretUsername != constants.SuperuserKeyName &&
|
||||
(slices.Contains(c.Spec.UsersWithSecretRotation, secretUsername) ||
|
||||
slices.Contains(c.Spec.UsersWithInPlaceSecretRotation, secretUsername))
|
||||
|
||||
// globally enabled rotation is only allowed for manifest and bootstrapped roles
|
||||
allowedRoleTypes := []spec.RoleOrigin{spec.RoleOriginManifest, spec.RoleOriginBootstrap}
|
||||
rotationAllowed := !pwdUser.IsDbOwner && slices.Contains(allowedRoleTypes, pwdUser.Origin)
|
||||
|
||||
// users can ignore any kind of rotation
|
||||
isIgnoringRotation := slices.Contains(c.Spec.UsersIgnoringSecretRotation, secretUsername)
|
||||
|
||||
if ((c.OpConfig.EnablePasswordRotation && rotationAllowed) || rotationEnabledInManifest) && !isIgnoringRotation {
|
||||
passwordRotationMsg, err = c.rotatePasswordInSecret(secret, secretUsername, pwdUser.Origin, currentTime, retentionUsers)
|
||||
if err != nil {
|
||||
c.logger.Warnf("password rotation failed for user %s: %v", secretUsername, err)
|
||||
}
|
||||
} else {
|
||||
// username might not match if password rotation has been disabled again
|
||||
usernameFromSecret := string(secret.Data["username"])
|
||||
if secretUsername != usernameFromSecret {
|
||||
// handle edge case when manifest user conflicts with a user from prepared databases
|
||||
if strings.Replace(usernameFromSecret, "-", "_", -1) == strings.Replace(secretUsername, "-", "_", -1) {
|
||||
return "", fmt.Errorf("could not update secret because of user name mismatch: expected: %s, got: %s", secretUsername, usernameFromSecret)
|
||||
}
|
||||
*retentionUsers = append(*retentionUsers, secretUsername)
|
||||
secret.Data["username"] = []byte(secretUsername)
|
||||
secret.Data["password"] = []byte(util.RandomPassword(constants.PasswordLength))
|
||||
secret.Data["nextRotation"] = []byte{}
|
||||
passwordRotationMsg = fmt.Sprintf("secret does not contain the role %s - updating username and resetting password", secretUsername)
|
||||
}
|
||||
}
|
||||
|
||||
return passwordRotationMsg, nil
|
||||
}
|
||||
|
||||
func (c *Cluster) rotatePasswordInSecret(
|
||||
secret *v1.Secret,
|
||||
secretUsername string,
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,6 @@ func TestUpdateSecretNameConflict(t *testing.T) {
|
|||
assert.Error(t, err)
|
||||
|
||||
// the order of secrets to sync is not deterministic, check only first part of the error message
|
||||
expectedError := fmt.Sprintf("syncing secret %s failed: could not update secret because of user name mismatch", "default/prepared-owner-user.acid-test-cluster.credentials")
|
||||
expectedError := fmt.Sprintf("syncing secret %s failed: error while checking for password rotation: could not update secret because of user name mismatch", "default/prepared-owner-user.acid-test-cluster.credentials")
|
||||
assert.Contains(t, err.Error(), expectedError)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -663,6 +663,15 @@ func parseResourceRequirements(resourcesRequirement v1.ResourceRequirements) (ac
|
|||
return resources, nil
|
||||
}
|
||||
|
||||
func isStandbyCluster(spec *acidv1.PostgresSpec) bool {
|
||||
for _, env := range spec.Env {
|
||||
if env.Name == "STANDBY_WALE_S3_PREFIX" && env.Value != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return spec.StandbyCluster != nil
|
||||
}
|
||||
|
||||
func (c *Cluster) isInMaintenanceWindow(specMaintenanceWindows []acidv1.MaintenanceWindow) bool {
|
||||
if len(specMaintenanceWindows) == 0 && len(c.OpConfig.MaintenanceWindows) == 0 {
|
||||
return true
|
||||
|
|
|
|||
Loading…
Reference in New Issue