Skip to content

Commit 70ec3a9

Browse files
committed
test superuser-only flags and password modes with a non-superuser admin
The flag test now covers `superuser`, `replication`, and `bypassrls`. Two tests run `passwordEncryption: server` and a pre-hashed SCRAM-SHA-256 verifier under the non-superuser admin.
1 parent 312dc94 commit 70ec3a9

1 file changed

Lines changed: 94 additions & 7 deletions

File tree

operator/src/test/java/it/aboutbits/postgresql/crd/role/RoleReconcilerNonSuperuserTest.java

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@
1515
import org.junit.jupiter.api.BeforeEach;
1616
import org.junit.jupiter.api.DisplayName;
1717
import org.junit.jupiter.api.Test;
18+
import org.junit.jupiter.params.ParameterizedTest;
19+
import org.junit.jupiter.params.provider.Arguments;
20+
import org.junit.jupiter.params.provider.MethodSource;
1821

1922
import java.util.List;
2023
import java.util.concurrent.TimeUnit;
24+
import java.util.function.BiConsumer;
25+
import java.util.stream.Stream;
2126

2227
import static it.aboutbits.postgresql.core.KubernetesService.SECRET_DATA_BASIC_AUTH_PASSWORD_KEY;
2328
import static org.assertj.core.api.Assertions.assertThat;
@@ -206,18 +211,22 @@ void nonSuperuserAdmin_updatesLoginAndMembership() {
206211
adminDsl.execute("drop role if exists {0}", role(parentRole));
207212
}
208213

209-
@Test
210-
@DisplayName("When the admin is not a superuser and the Role asks for SUPERUSER, the status should be ERROR")
211-
void nonSuperuserAdmin_superuserFlag_setsError() {
214+
@ParameterizedTest(name = "flag {0}")
215+
@MethodSource("provideSuperuserOnlyFlags")
216+
@DisplayName("When the admin is not a superuser and the Role asks for a superuser-only flag, the status should be ERROR")
217+
void nonSuperuserAdmin_superuserOnlyFlag_setsError(
218+
String flagName,
219+
BiConsumer<RoleSpec.Flags, Boolean> flagSetter
220+
) {
212221
// given
213-
var rootConnection = givenRootClusterConnection("test-connection-root-superuser-flag");
222+
var rootConnection = givenRootClusterConnection("test-connection-root-%s-flag".formatted(flagName));
214223
var rootDsl = postgreSQLContextFactory.getDSLContext(rootConnection);
215-
var adminConnection = givenNonSuperuserClusterConnection(rootDsl, "test-connection-non-superuser-flag");
224+
var adminConnection = givenNonSuperuserClusterConnection(rootDsl, "test-connection-non-superuser-%s-flag".formatted(flagName));
216225

217-
var roleName = "test-non-superuser-role-superuser-flag";
226+
var roleName = "test-non-superuser-role-%s-flag".formatted(flagName);
218227

219228
var flags = new RoleSpec.Flags();
220-
flags.setSuperuser(true);
229+
flagSetter.accept(flags, true);
221230

222231
// when
223232
var role = given.one()
@@ -242,6 +251,84 @@ void nonSuperuserAdmin_superuserFlag_setsError() {
242251
assertThat(roleService.roleExists(rootDsl, role.getSpec())).isFalse();
243252
}
244253

254+
@Test
255+
@DisplayName("When the admin is not a superuser and passwordEncryption is 'server', the server should hash the password")
256+
void nonSuperuserAdmin_serverPasswordEncryption_letsTheServerHash() {
257+
// given
258+
var rootConnection = givenRootClusterConnection("test-connection-root-server-encryption");
259+
var rootDsl = postgreSQLContextFactory.getDSLContext(rootConnection);
260+
var adminConnection = givenNonSuperuserClusterConnection(rootDsl, "test-connection-non-superuser-server-encryption");
261+
262+
var roleName = "test-non-superuser-role-server-encryption";
263+
var password = "server-side-password";
264+
265+
var secretRef = given.one()
266+
.secretRef()
267+
.withPassword(password)
268+
.returnFirst();
269+
270+
// when
271+
var role = given.one()
272+
.role()
273+
.withName(roleName)
274+
.withClusterConnectionName(adminConnection.getMetadata().getName())
275+
.withPasswordSecretRef(secretRef)
276+
.withPasswordEncryption(PasswordEncryption.SERVER)
277+
.returnFirst();
278+
279+
// then
280+
assertThat(role.getStatus().getPhase()).isEqualTo(CRPhase.READY);
281+
assertThat(PostgreSQLPasswordVerifier.passwordMatches(
282+
rootDsl,
283+
roleName,
284+
password
285+
)).isTrue();
286+
}
287+
288+
@Test
289+
@DisplayName("When the admin is not a superuser and the Secret contains a SCRAM-SHA-256 verifier, it should be stored verbatim")
290+
void nonSuperuserAdmin_preHashedPassword_isStoredVerbatim() {
291+
// given
292+
var rootConnection = givenRootClusterConnection("test-connection-root-prehashed");
293+
var rootDsl = postgreSQLContextFactory.getDSLContext(rootConnection);
294+
var adminConnection = givenNonSuperuserClusterConnection(rootDsl, "test-connection-non-superuser-prehashed");
295+
296+
var roleName = "test-non-superuser-role-prehashed";
297+
298+
// Verifier for the password "abc", generated by PostgreSQL
299+
var verifier = "SCRAM-SHA-256$4096:gxUQWxfrRYegSTNiHXFT+g==$lxMC2yO9Lx9gm2dgNPo/1Qar+pjAvxCP2VN4yPWYnzE=:0QzcS9VJHJszBq4vSce3n4M6NZmyWa1GWdkJDi8hRNc=";
300+
301+
var secretRef = given.one()
302+
.secretRef()
303+
.withPassword(verifier)
304+
.returnFirst();
305+
306+
// when
307+
var role = given.one()
308+
.role()
309+
.withName(roleName)
310+
.withClusterConnectionName(adminConnection.getMetadata().getName())
311+
.withPasswordSecretRef(secretRef)
312+
.returnFirst();
313+
314+
// then
315+
assertThat(role.getStatus().getPhase()).isEqualTo(CRPhase.READY);
316+
assertThat(PostgreSQLPasswordVerifier.storedVerifier(rootDsl, roleName)).isEqualTo(verifier);
317+
assertThat(PostgreSQLPasswordVerifier.passwordMatches(
318+
rootDsl,
319+
roleName,
320+
"abc"
321+
)).isTrue();
322+
}
323+
324+
private static Stream<Arguments> provideSuperuserOnlyFlags() {
325+
return Stream.of(
326+
Arguments.of("superuser", (BiConsumer<RoleSpec.Flags, Boolean>) RoleSpec.Flags::setSuperuser),
327+
Arguments.of("replication", (BiConsumer<RoleSpec.Flags, Boolean>) RoleSpec.Flags::setReplication),
328+
Arguments.of("bypassrls", (BiConsumer<RoleSpec.Flags, Boolean>) RoleSpec.Flags::setBypassrls)
329+
);
330+
}
331+
245332
private ClusterConnection givenRootClusterConnection(String name) {
246333
return given.one()
247334
.clusterConnection()

0 commit comments

Comments
 (0)