Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,17 @@ public UpdateControl<Role> reconcile(

var passwordSecretRef = spec.getPasswordSecretRef();

String password;
if (passwordSecretRef != null) {
password = kubernetesService.getSecretRefCredentials(
kubernetesClient,
passwordSecretRef,
namespace
).password();
} else {
password = null;
}

UpdateControl<Role> updateControl;

try (var dsl = contextFactory.getDSLContext(clusterConnection)) {
// Read the Secret inside the try block, so that a missing or invalid Secret sets the phase to ERROR
var password = passwordSecretRef != null
? kubernetesService.getSecretRefCredentials(
kubernetesClient,
passwordSecretRef,
namespace
).password()
: null;
var passwordEncryption = spec.getPasswordEncryption();

// The password hash in pg_authid is readable by superusers only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.util.function.Predicate;
import java.util.stream.Stream;

import static it.aboutbits.postgresql._support.testdata.base.TestDataCreator.randomKubernetesNameSuffix;
import static it.aboutbits.postgresql.core.KubernetesService.SECRET_DATA_BASIC_AUTH_PASSWORD_KEY;
import static it.aboutbits.postgresql.core.infrastructure.persistence.Tables.PG_ROLES;
import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -525,6 +526,61 @@ void upToDateRole_afterPendingClusterConnection_setsReady() {
assertThat(updatedRole.getStatus().getMessage()).isNull();
}

@Test
@DisplayName(
"When the password Secret of a Role does not exist, the status should be ERROR until the Secret exists"
)
void missingPasswordSecret_setsErrorUntilSecretExists() {
// given: a reconciled login Role
var clusterConnection = given.one()
.clusterConnection()
.withName("test-connection-role-missing-secret")
.returnFirst();

var secretRef = given.one()
.secretRef()
.returnFirst();

var role = given.one()
.role()
.withName("test-role-missing-secret")
.withClusterConnectionName(clusterConnection.getMetadata().getName())
.withPasswordSecretRef(secretRef)
.returnFirst();

assertThat(role.getStatus().getPhase()).isEqualTo(CRPhase.READY);

// when: the Role references a Secret that does not exist
var missingSecretRef = new ResourceRef();
missingSecretRef.setName(randomKubernetesNameSuffix("test-missing-secret"));

role.getSpec().setPasswordSecretRef(missingSecretRef);

var erroredRole = applyRole(role);

// then
assertThat(erroredRole.getStatus().getPhase()).isEqualTo(CRPhase.ERROR);
assertThat(erroredRole.getStatus().getMessage()).startsWith("Secret reference not found");

// when: the missing Secret is created
given.one()
.secretRef()
.withName(missingSecretRef.getName())
.returnFirst();

// then: the Secret event source reconciles the Role without a spec change
var updatedRole = kubernetesClient.resources(Role.class)
.inNamespace(kubernetesClient.getNamespace())
.withName(role.getMetadata().getName())
.waitUntilCondition(
r -> r.getStatus() != null && r.getStatus().getPhase() == CRPhase.READY,
5,
TimeUnit.SECONDS
);

assertThat(updatedRole.getStatus().getMessage()).isNull();
}

@Test
@DisplayName("When the Secret already contains a SCRAM-SHA-256 verifier, it should be stored verbatim")
void preHashedPassword_isStoredVerbatim() {
Expand Down