From 3b134906892976d000486b42cc51a6886f8af591 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 16 Jul 2024 19:16:59 +0100 Subject: [PATCH] Polish "Add support for Postgres trust host auth method with Docker Compose" See gh-41511 --- .../spring-boot-docker-compose/build.gradle | 2 ++ ...nectionDetailsFactoryIntegrationTests.java | 27 +++++++++++++++++++ ...nectionDetailsFactoryIntegrationTests.java | 26 ++++++++++++++++++ ...s-with-trust-host-auth-method-compose.yaml | 9 +++++++ .../postgres/PostgresEnvironment.java | 4 +-- .../postgres/PostgresEnvironmentTests.java | 1 + 6 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 spring-boot-project/spring-boot-docker-compose/src/dockerTest/resources/org/springframework/boot/docker/compose/service/connection/postgres/postgres-with-trust-host-auth-method-compose.yaml diff --git a/spring-boot-project/spring-boot-docker-compose/build.gradle b/spring-boot-project/spring-boot-docker-compose/build.gradle index 95479da392b..48aea480e6f 100644 --- a/spring-boot-project/spring-boot-docker-compose/build.gradle +++ b/spring-boot-project/spring-boot-docker-compose/build.gradle @@ -21,6 +21,8 @@ dependencies { dockerTestRuntimeOnly("com.microsoft.sqlserver:mssql-jdbc") dockerTestRuntimeOnly("com.oracle.database.r2dbc:oracle-r2dbc") dockerTestRuntimeOnly("io.r2dbc:r2dbc-mssql") + dockerTestRuntimeOnly("org.postgresql:postgresql") + dockerTestRuntimeOnly("org.postgresql:r2dbc-postgresql") implementation("com.fasterxml.jackson.core:jackson-databind") implementation("com.fasterxml.jackson.module:jackson-module-parameter-names") diff --git a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java index 31ae113c413..be35ec0d5a0 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -16,11 +16,17 @@ package org.springframework.boot.docker.compose.service.connection.postgres; +import java.sql.Driver; + import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails; import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; +import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.SimpleDriverDataSource; +import org.springframework.util.ClassUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -39,6 +45,15 @@ class PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests { assertConnectionDetails(connectionDetails); } + @DockerComposeTest(composeFile = "postgres-with-trust-host-auth-method-compose.yaml", image = TestImage.POSTGRESQL) + void runCreatesConnectionDetailsThatCanAccessDatabaseWhenHostAuthMethodIsTrust( + JdbcConnectionDetails connectionDetails) throws ClassNotFoundException { + assertThat(connectionDetails.getUsername()).isEqualTo("myuser"); + assertThat(connectionDetails.getPassword()).isNull(); + assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:postgresql://").endsWith("/mydatabase"); + checkDatabaseAccess(connectionDetails); + } + @Test @DockerComposeTest(composeFile = "postgres-bitnami-compose.yaml", image = TestImage.BITNAMI_POSTGRESQL) void runWithBitnamiImageCreatesConnectionDetails(JdbcConnectionDetails connectionDetails) { @@ -51,4 +66,16 @@ class PostgresJdbcDockerComposeConnectionDetailsFactoryIntegrationTests { assertThat(connectionDetails.getJdbcUrl()).startsWith("jdbc:postgresql://").endsWith("/mydatabase"); } + @SuppressWarnings("unchecked") + private void checkDatabaseAccess(JdbcConnectionDetails connectionDetails) throws ClassNotFoundException { + SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); + dataSource.setUrl(connectionDetails.getJdbcUrl()); + dataSource.setUsername(connectionDetails.getUsername()); + dataSource.setPassword(connectionDetails.getPassword()); + dataSource.setDriverClass((Class) ClassUtils.forName(connectionDetails.getDriverClassName(), + getClass().getClassLoader())); + JdbcTemplate template = new JdbcTemplate(dataSource); + assertThat(template.queryForObject(DatabaseDriver.POSTGRESQL.getValidationQuery(), Integer.class)).isEqualTo(1); + } + } diff --git a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java index 2c01091b097..dab0edc7cf3 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -16,11 +16,16 @@ package org.springframework.boot.docker.compose.service.connection.postgres; +import java.time.Duration; + +import io.r2dbc.spi.ConnectionFactories; import io.r2dbc.spi.ConnectionFactoryOptions; import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails; import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest; +import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.r2dbc.core.DatabaseClient; import static org.assertj.core.api.Assertions.assertThat; @@ -39,6 +44,17 @@ class PostgresR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests { assertConnectionDetails(connectionDetails); } + @DockerComposeTest(composeFile = "postgres-with-trust-host-auth-method-compose.yaml", image = TestImage.POSTGRESQL) + void runCreatesConnectionDetailsThatCanAccessDatabaseWhenHostAuthMethodIsTrust( + R2dbcConnectionDetails connectionDetails) { + ConnectionFactoryOptions connectionFactoryOptions = connectionDetails.getConnectionFactoryOptions(); + assertThat(connectionFactoryOptions.getRequiredValue(ConnectionFactoryOptions.USER)).isEqualTo("myuser"); + assertThat(connectionFactoryOptions.getValue(ConnectionFactoryOptions.PASSWORD)).isNull(); + assertThat(connectionFactoryOptions.getRequiredValue(ConnectionFactoryOptions.DATABASE)) + .isEqualTo("mydatabase"); + checkDatabaseAccess(connectionDetails); + } + @DockerComposeTest(composeFile = "postgres-bitnami-compose.yaml", image = TestImage.BITNAMI_POSTGRESQL) void runWithBitnamiImageCreatesConnectionDetails(R2dbcConnectionDetails connectionDetails) { assertConnectionDetails(connectionDetails); @@ -51,4 +67,14 @@ class PostgresR2dbcDockerComposeConnectionDetailsFactoryIntegrationTests { assertThat(connectionFactoryOptions.getRequiredValue(ConnectionFactoryOptions.PASSWORD)).isEqualTo("secret"); } + private void checkDatabaseAccess(R2dbcConnectionDetails connectionDetails) { + ConnectionFactoryOptions connectionFactoryOptions = connectionDetails.getConnectionFactoryOptions(); + Object result = DatabaseClient.create(ConnectionFactories.get(connectionFactoryOptions)) + .sql(DatabaseDriver.POSTGRESQL.getValidationQuery()) + .map((row, metadata) -> row.get(0)) + .first() + .block(Duration.ofSeconds(30)); + assertThat(result).isEqualTo(1); + } + } diff --git a/spring-boot-project/spring-boot-docker-compose/src/dockerTest/resources/org/springframework/boot/docker/compose/service/connection/postgres/postgres-with-trust-host-auth-method-compose.yaml b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/resources/org/springframework/boot/docker/compose/service/connection/postgres/postgres-with-trust-host-auth-method-compose.yaml new file mode 100644 index 00000000000..7a9607dcdcb --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/dockerTest/resources/org/springframework/boot/docker/compose/service/connection/postgres/postgres-with-trust-host-auth-method-compose.yaml @@ -0,0 +1,9 @@ +services: + database: + image: '{imageName}' + ports: + - '5432' + environment: + - 'POSTGRES_USER=myuser' + - 'POSTGRES_DB=mydatabase' + - 'POSTGRES_HOST_AUTH_METHOD=trust' diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironment.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironment.java index 7858bdba5c4..91649a79fe0 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironment.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironment.java @@ -45,7 +45,7 @@ class PostgresEnvironment { } private String extractPassword(Map env) { - if (hasTrustAuthMethod(env)) { + if (hasTrustHostAuthMethod(env)) { return null; } String password = env.getOrDefault("POSTGRES_PASSWORD", env.get("POSTGRESQL_PASSWORD")); @@ -53,7 +53,7 @@ class PostgresEnvironment { return password; } - private Boolean hasTrustAuthMethod(Map env) { + private Boolean hasTrustHostAuthMethod(Map env) { String hostAuthMethod = env.get("POSTGRES_HOST_AUTH_METHOD"); return "trust".equals(hostAuthMethod); } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironmentTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironmentTests.java index 0bd2c4b1cb7..3a5cb93357f 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironmentTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/postgres/PostgresEnvironmentTests.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; * @author Andy Wilkinson * @author Phillip Webb * @author Scott Frederick + * @author Sidmar Theodoro */ class PostgresEnvironmentTests {