From af89924582241bf2d3340cd8f5e851a3bf031621 Mon Sep 17 00:00:00 2001 From: sid Date: Tue, 16 Jul 2024 00:25:09 -0300 Subject: [PATCH 1/2] Add support for Postgres trust host auth method with Docker Compose See gh-41511 --- .../service/connection/postgres/PostgresEnvironment.java | 9 +++++++++ .../connection/postgres/PostgresEnvironmentTests.java | 6 ++++++ 2 files changed, 15 insertions(+) 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 4a63bbc0b6..7858bdba5c 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 @@ -28,6 +28,7 @@ import org.springframework.util.StringUtils; * @author Andy Wilkinson * @author Phillip Webb * @author Scott Frederick + * @author Sidmar Theodoro */ class PostgresEnvironment { @@ -44,11 +45,19 @@ class PostgresEnvironment { } private String extractPassword(Map env) { + if (hasTrustAuthMethod(env)) { + return null; + } String password = env.getOrDefault("POSTGRES_PASSWORD", env.get("POSTGRESQL_PASSWORD")); Assert.state(StringUtils.hasLength(password), "PostgreSQL password must be provided"); return password; } + private Boolean hasTrustAuthMethod(Map env) { + String hostAuthMethod = env.get("POSTGRES_HOST_AUTH_METHOD"); + return "trust".equals(hostAuthMethod); + } + String getUsername() { return this.username; } 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 9058c1f11d..0bd2c4b1cb 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 @@ -78,6 +78,12 @@ class PostgresEnvironmentTests { assertThat(environment.getPassword()).isEqualTo("secret"); } + @Test + void getPasswordWhenHasTrustHostAuthMethod() { + PostgresEnvironment environment = new PostgresEnvironment(Map.of("POSTGRES_HOST_AUTH_METHOD", "trust")); + assertThat(environment.getPassword()).isNull(); + } + @Test void getDatabaseWhenNoPostgresDbOrPostgresUser() { PostgresEnvironment environment = new PostgresEnvironment(Map.of("POSTGRES_PASSWORD", "secret")); From 3b134906892976d000486b42cc51a6886f8af591 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 16 Jul 2024 19:16:59 +0100 Subject: [PATCH 2/2] 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 95479da392..48aea480e6 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 31ae113c41..be35ec0d5a 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 2c01091b09..dab0edc7cf 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 0000000000..7a9607dcdc --- /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 7858bdba5c..91649a79fe 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 0bd2c4b1cb..3a5cb93357 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 {