Skip to content

Commit

Permalink
Simplify SSL configuration.
Browse files Browse the repository at this point in the history
Use a more static setup when it comes to testcontainers and postgres.
  • Loading branch information
gregturn committed Sep 20, 2019
1 parent d566eed commit 9f5becb
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 110 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<scram-client.version>1.0.0-beta.2</scram-client.version>
<slf4j.version>1.7.26</slf4j.version>
<spring-boot.version>2.1.7.RELEASE</spring-boot.version>
<testcontainers.version>1.12.0</testcontainers.version>
<testcontainers.version>1.12.1</testcontainers.version>
</properties>

<dependencyManagement>
Expand Down
156 changes: 48 additions & 108 deletions src/test/java/io/r2dbc/postgresql/util/PostgresqlServerExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,22 @@
import org.springframework.jdbc.core.JdbcTemplate;
import org.testcontainers.containers.JdbcDatabaseContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.MountableFile;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import reactor.util.annotation.Nullable;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;

import java.io.FileWriter;
import java.io.IOException;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

public final class PostgresqlServerExtension implements BeforeAllCallback, AfterAllCallback {

private static final Path clientCrt;

private static final Path clientKey;

private static final Path initContainerConfig;

private static final Path pgHba;
import static org.testcontainers.utility.MountableFile.forHostPath;

private static final Path serverCrt;

private static final Path serverKey;
public final class PostgresqlServerExtension implements BeforeAllCallback, AfterAllCallback {

private volatile PostgreSQLContainer<?> containerInstance = null;

Expand All @@ -75,64 +65,16 @@ public final class PostgresqlServerExtension implements BeforeAllCallback, After

private JdbcOperations jdbcOperations;

static {
try {
Path keysDir = Files.createTempDirectory("keys");
keysDir.toFile().deleteOnExit();
Tuple2<Path, Path> server = createPair(keysDir, "server", "r2dbc-postgresql-test-server");
Tuple2<Path, Path> client = createPair(keysDir, "client", "test-ssl-with-cert");
serverCrt = server.getT1();
serverKey = server.getT2();
clientCrt = client.getT1();
clientKey = client.getT2();
initContainerConfig = createTempFile("init-container-config.sh",
"touch /tmp/server.key\n",
"chown postgres:postgres /tmp/server.key\n",
"chmod 0600 /tmp/server.key\n",
"cp /var/server.key /tmp/server.key\n",
"echo \"/tmp/server.key initialized\"\n",
"touch /tmp/pg_hba.conf\n",
"chmod 0600 /tmp/pg_hba.conf\n",
"chown postgres:postgres /tmp/pg_hba.conf\n",
"cp /var/pg_hba.conf /tmp/pg_hba.conf\n",
"echo \"/tmp/pg_hba initialized\"\n"
);
pgHba = createTempFile("pg_hba.conf",
"hostnossl all test all md5\n",
"hostnossl all test-scram all scram-sha-256\n",
"hostssl all test-ssl all password\n",
"hostssl all test-ssl-with-cert all cert\n"
);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

public PostgresqlServerExtension() {
}


public String getClientCrt() {
return PostgresqlServerExtension.clientCrt.toString();
}

public String getClientKey() {
return PostgresqlServerExtension.clientKey.toString();
}

public String getServerCrt() {
return PostgresqlServerExtension.serverCrt.toString();
}

public String getServerKey() {
return PostgresqlServerExtension.serverKey.toString();
}

@Override
public void afterAll(ExtensionContext context) {
int nesting = nestingCounter.decrementAndGet();
if (nesting == 0) {
this.dataSource.close();
if (this.dataSource != null) {
this.dataSource.close();
}
if (this.useTestContainer) {
this.container.get().stop();
}
Expand Down Expand Up @@ -160,6 +102,14 @@ public void beforeAll(ExtensionContext context) {
}
}

public String getClientCrt() {
return Paths.get("client.crt").toAbsolutePath().toString();
}

public String getClientKey() {
return Paths.get("client.key").toAbsolutePath().toString();
}

public String getDatabase() {
return this.postgres.getDatabase();
}
Expand All @@ -177,6 +127,14 @@ public int getPort() {
return this.postgres.getPort();
}

public String getServerCrt() {
return Paths.get("server.crt").toAbsolutePath().toString();
}

public String getServerKey() {
return Paths.get("server.key").toAbsolutePath().toString();
}

public String getUsername() {
return this.postgres.getUsername();
}
Expand All @@ -185,27 +143,6 @@ public String getPassword() {
return this.postgres.getPassword();
}

private static Tuple2<Path, Path> createPair(Path dir, String name, String cn) throws IOException, InterruptedException {
new ProcessBuilder("docker", "run",
"-v", dir.toAbsolutePath() + ":/out",
"--rm",
"--entrypoint", "openssl",
"frapsoft/openssl",
"req", "-newkey", "rsa:2048", "-nodes",
"-keyout", String.format("/out/%s.key", name),
"-out", String.format("/out/%s.crt", name),
"-x509",
"-days", "365",
"-subj", String.format("/CN=%s", cn))
.start()
.waitFor();
Path cert = dir.resolve(String.format("%s.crt", name));
Path key = dir.resolve(String.format("%s.key", name));
cert.toFile().deleteOnExit();
key.toFile().deleteOnExit();
return Tuples.of(cert, key);
}

private static Path createTempFile(String name, String... lines) throws IOException {
Path tempFile = Files.createTempFile(null, name);
tempFile.toFile().deleteOnExit();
Expand All @@ -218,27 +155,30 @@ private static Path createTempFile(String name, String... lines) throws IOExcept
}

private <T extends PostgreSQLContainer<T>> T container() {
return new PostgreSQLContainer<T>("postgres:11.1") {

@Override
protected void configure() {
super.configure();
setCommand(
"postgres",
"-c", "ssl=on",
"-c", "ssl_key_file=/tmp/server.key",
"-c", "ssl_cert_file=/var/server.crt",
"-c", "ssl_ca_file=/var/client.crt",
"-c", "hba_file=/tmp/pg_hba.conf"
);
}
}
.withInitScript("test-db-init-script.sql")
.withCopyFileToContainer(MountableFile.forHostPath(serverCrt, 0755), "/var/server.crt")
.withCopyFileToContainer(MountableFile.forHostPath(serverKey, 0755), "/var/server.key")
.withCopyFileToContainer(MountableFile.forHostPath(clientCrt, 0755), "/var/client.crt")
.withCopyFileToContainer(MountableFile.forHostPath(pgHba, 0755), "/var/pg_hba.conf")
.withCopyFileToContainer(MountableFile.forHostPath(initContainerConfig, 0755), "/docker-entrypoint-initdb.d/init-container-config.sh");
T container = new PostgreSQLContainer<T>("postgres:11.1")
.withCopyFileToContainer(forHostPath("server.crt", 0600), "/var/server.crt")
.withCopyFileToContainer(forHostPath("server.key", 0600), "/var/server.key")
.withCopyFileToContainer(forHostPath("client.crt", 0600), "/var/client.crt")
.withCopyFileToContainer(forHostPath("pg_hba.conf", 0600), "/var/pg_hba.conf")
.withCopyFileToContainer(forHostPath("setup.sh", 0755), "/var/setup.sh")
.withCopyFileToContainer(forHostPath("test-db-init-script.sql", 0755), "/docker-entrypoint-initdb.d/test-db-init-script.sql")
// .withInitScript("test-db-init-script.sql")
.withCommand("postgres",
"-c", "ssl=on",
"-c", "ssl_key_file=/var/server.key",
"-c", "ssl_cert_file=/var/server.crt",
"-c", "ssl_ca_file=/var/client.crt",
"-c", "hba_file=/var/pg_hba.conf");

// container.setWaitStrategy(new DockerHealthcheckWaitStrategy().withStartupTimeout(Duration.ofSeconds(15)));

container.setWaitStrategy(new LogMessageWaitStrategy()
.withRegEx(".*database system is ready to accept connections.*")
.withTimes(2)
.withStartupTimeout(Duration.ofSeconds(60)));

return container
;
}

/**
Expand Down
19 changes: 19 additions & 0 deletions src/test/resources/client.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDDTCCAfWgAwIBAgIJAL7UUZhBI3OFMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV
BAMMEnRlc3Qtc3NsLXdpdGgtY2VydDAeFw0xOTA5MTkxOTA3NDdaFw0yOTA5MTYx
OTA3NDdaMB0xGzAZBgNVBAMMEnRlc3Qtc3NsLXdpdGgtY2VydDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBANymB+VD5m0OE9NOlfViVbXV1kE3Q/Aqxzfa
Twh6/pgTHJNTfpz8gqzC4y8PwaVs+ZH4xllvUQyY1tm9prFpCBUG+8U9WT4Arejq
ealNk6pOiXushdPsm1aMyfdiOSoJ4DUBXuLXTTmRvr9lDvk37jEWMhmVEfX+JOTC
VWC19qcSyE1yiacfOimeMZxt6Qm4i9645wxazjUseUssvV0ZPvsU/yTnzt6q4Cw7
WjLkzul66cP3hV0uyp24aK9Wn6rSUoVdrkB+9oh9EA0ADiio6Y1b10myAPYU0T3a
DsoD23pNkc8VfzEPQqOaXwhVmr/QsryGJHsNRc50T5Ea7if4W2MCAwEAAaNQME4w
HQYDVR0OBBYEFGYugDbhEwU7Ugws1MPw8IGSWVX+MB8GA1UdIwQYMBaAFGYugDbh
EwU7Ugws1MPw8IGSWVX+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
AH0oWrPEZt/vwYVKtK8e0DlWVXVgFp3d5v3MfOl6Y/zwnyzNycnirgK4Rkl1I+Ix
yivWGSvj3vNxIUa5VQtqpQREHDKgPqL5g1GA0t/nUI36wN+MOm5o7w9UF+vJWPpc
J9+fEBKSqmatMaiTna2QSDE2Tsz+7Xvs0poJH5/IZdvTr+eeYx4NlC7GbUnpaX1a
A+4nlNkeeyaT995tfHC/+xeaRLr94GSPSQtMeXgr2T3UU5rYsE991sdW1eU9WS7d
eFxp2nIc7LYtBd2nxBiPLkD7XwcLiwgeGnSe1NUGfWNH1jBFIeGK0gZpDeQWS76B
eA2yu8P4QRAg0jPvGNR6LVo=
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions src/test/resources/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcpgflQ+ZtDhPT
TpX1YlW11dZBN0PwKsc32k8Iev6YExyTU36c/IKswuMvD8GlbPmR+MZZb1EMmNbZ
vaaxaQgVBvvFPVk+AK3o6nmpTZOqTol7rIXT7JtWjMn3YjkqCeA1AV7i1005kb6/
ZQ75N+4xFjIZlRH1/iTkwlVgtfanEshNcomnHzopnjGcbekJuIveuOcMWs41LHlL
LL1dGT77FP8k587equAsO1oy5M7peunD94VdLsqduGivVp+q0lKFXa5AfvaIfRAN
AA4oqOmNW9dJsgD2FNE92g7KA9t6TZHPFX8xD0Kjml8IVZq/0LK8hiR7DUXOdE+R
Gu4n+FtjAgMBAAECggEAdQd62JcS+HSm/0SHNQda/n7UjPKLDi8iSvV3RcA2mOJK
HboDRbCIfqk/Zg6tXthV5p5UVcs86bmG+yYj66URrFVv5EWNt90UYJ08uhdzYrkV
Iot2z9iG63jxBk0KlMl4KaT4dshLJWWwDkPDlVuc8lwbZoYyaI7LcqnALvNUR3gq
RlukU0nAzeZkX7z3cZe/zLbTZ6yL9CEA2gdBtZ3Ceax1oCsuP840k6dz/tgNHgaC
uhCVPANS8pUKrMf7m1QZ+YB55OuRqjR2ILnumAs6m87KLMmYUs/QqWg+3PBfC4cq
JWRjeiDmTDYTYLXoRwK4k1mmPOyW1aPYEyoPSLpbQQKBgQD8KWGTKiNAmsl1csU0
ZKLBTYsq1WvU/5s7n69TzU0kHylDgCJIZQoLtSn01wQ5R7qBWEBhBKM2bwYybTzZ
59c777VP7DF8ZcOOuxdtXBr07Owpn541N02mI4qtv+C+B7ULwifO/9yUMs4LzCUv
215Gs17M+44UHO1PiUK9BElKbwKBgQDgAdmeacqDInx1amZ8zQmk05b2YMQN4nS/
JmSFc/3j5HjJ3ibty7pAGFtINPYekncMkBo/ahlI9YukAnMH5wp8WqmUq9Cjv5Q1
GbNAznxCs1a2PXaQcOMR74dZdbpFIT4o/CXFpjyEgxbrMcBJ67sSQiuSfFp12HPe
VjCrUL6ITQKBgQCGTxg8xXXvZEKnvxDQ3kVeRoo4r2J3Ggo50M0XCsPq2HonDOm1
u7OFFuKZGamTRORPHo1z3397b9lSJKMDwZv/vabKQhj9lEp8DKTmx+dHy6XiabVf
zOwb8NRdxVTUgtBoyepgNCHuAb2DxSGNgv+NEt8MuXQsvFeeRJL6kHzlGwKBgQDG
tP1tB50L3FCY+0x0kpFmdAdrAIWJZ4N2eMEcnLrwKCB5uaXAtUK/TpvSnqBgmD4g
l8egzyYk0SQQ1ddigDGOBAKADjVivDPlMqoO59vUcy+NM1J0aJ8Uruzaj5MvdYCl
bJ65CHCQf5SaB6TyLbjhRm9OXx8DgIGwDbbYkSSi1QKBgQDDhEsNjhWzFGuQugn8
3pYzcO3D6Cz4RhXwZ1UkUFXWq86Xxvg80T7/57F6D9SNBpqqVMiY1FOoakdbFlz0
PSeFlvFre23WAyKSt0GE9CgAIJPtgNGxg1Wf0KdtgAir4gD3kC8wn2lwF60pz3iC
3Myq3f9x4D7Xj0L64ZtbNi7hGw==
-----END PRIVATE KEY-----
43 changes: 43 additions & 0 deletions src/test/resources/create-certificates.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
##################################################################################
#
# Copyright 2019 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################################################


##################################################################################
#
# Script to generate client and server certificates to run postgresql with SSL enabled
#
##################################################################################

echo "Creating client certificate..."

docker run \
-v "$(pwd)":/out \
--rm \
--entrypoint openssl \
frapsoft/openssl \
req -newkey rsa:2048 -nodes -keyout /out/client.key -out /out/client.crt -x509 -days 3650 -subj "/CN=test-ssl-with-cert"


echo "Creating server certificate..."

docker run \
-v "$(pwd)":/out \
--rm \
--entrypoint openssl \
frapsoft/openssl \
req -newkey rsa:2048 -nodes -keyout /out/server.key -out /out/server.crt -x509 -days 3650 -subj "/CN=r2dbc-postgresql-test-server"
2 changes: 1 addition & 1 deletion src/test/resources/logback-test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</encoder>
</appender>

<logger name="io.r2dbc.postgresql" level="INFO"/>
<logger name="io.r2dbc.postgresql" level="TRACE"/>
<logger name="org.testcontainers" level="INFO"/>
<logger name="reactor.netty" level="WARN"/>
<logger name="stream" level="INFO"/>
Expand Down
4 changes: 4 additions & 0 deletions src/test/resources/pg_hba.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
hostnossl all test all md5
hostnossl all test-scram all scram-sha-256
hostssl all test-ssl all password
hostssl all test-ssl-with-cert all cert
19 changes: 19 additions & 0 deletions src/test/resources/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIJAKojIeelKo/RMA0GCSqGSIb3DQEBCwUAMCcxJTAjBgNV
BAMMHHIyZGJjLXBvc3RncmVzcWwtdGVzdC1zZXJ2ZXIwHhcNMTkwOTE5MTkwNzQ4
WhcNMjkwOTE2MTkwNzQ4WjAnMSUwIwYDVQQDDBxyMmRiYy1wb3N0Z3Jlc3FsLXRl
c3Qtc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyZWNi8Br
/b6YfLN/LLbHDzDxT6CL1rnr6ziRWo1Lvg16JJxdpZxfSkZ/+MA0L/+eMilqLL5d
0KLIzu66FWt1NFrE3ToCHG+/ay9COE5wi8xPBGPAfwflSp1lnnl7Z9gpJkQqLZyZ
IpLhSMcC1i8L8525uSJ1tGGSI3pHNEyttzfZrNvxFi+5X2ic0HkKpEJWDzYWE9oX
BO6dK99KJQAbp0LZwp9XrAR3yQpRheXvZQnUqgVEdNwL2tGp49mXDEzIrxfUUHQb
8pohRJR3k4LNL9v2bVeb5YhTst6btZ6sR63r0bFckTTPhnLr0yxT0C+LqjPiDtsG
KO+vAU2pC/1ACwIDAQABo1AwTjAdBgNVHQ4EFgQUQ8UubLz9hGTfahrGjZobBicV
iYYwHwYDVR0jBBgwFoAUQ8UubLz9hGTfahrGjZobBicViYYwDAYDVR0TBAUwAwEB
/zANBgkqhkiG9w0BAQsFAAOCAQEAf1k+eYuB45YneVy2OB9n9KRhfCR8smcIFBVM
BydDMRXJtTxof1lrGvub4Z3YlKpS1W7J9palNlsne0dLZgmoL+J5OobRIR6zISLT
h1/NdHklfKP2ZHGKFpaWuUBxWPLlBjSnht0CxWe/7L1wMHrvXocWIJJf5r3TzWM0
eld7CCW1950O7b7FQkLMIC2pDFfdQd9q5IsxgLo7MtHkpVYHETumYU6u9T+Xwjex
lQ7AGDeCNLlzp6lYGKRK9oBfn1YZ8crl4xEYM40CS1CcVFQs6DvRVFxxYDnSNyQd
VpCWpZ1Jqg5sZ/5ewvOur1HFrzXVJP7LzHjn3xc0BkCTPAIF5w==
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions src/test/resources/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDJlY2LwGv9vph8
s38stscPMPFPoIvWuevrOJFajUu+DXoknF2lnF9KRn/4wDQv/54yKWosvl3QosjO
7roVa3U0WsTdOgIcb79rL0I4TnCLzE8EY8B/B+VKnWWeeXtn2CkmRCotnJkikuFI
xwLWLwvznbm5InW0YZIjekc0TK23N9ms2/EWL7lfaJzQeQqkQlYPNhYT2hcE7p0r
30olABunQtnCn1esBHfJClGF5e9lCdSqBUR03Ava0anj2ZcMTMivF9RQdBvymiFE
lHeTgs0v2/ZtV5vliFOy3pu1nqxHrevRsVyRNM+GcuvTLFPQL4uqM+IO2wYo768B
TakL/UALAgMBAAECggEBAIZD8UJLCOK6hxBP8f3TQ+SvYZr6wQllTmiehdn9UJym
l1s5Nvqum516NZR2WIw7wp+AjDJ/HTdwpTWHNjQ8HZWge40qLOvJ1oJKuN2OCVJj
46F122oA1U0MZvnVykdRZ58QOdOlgS3RDPKPcyk7rsc1n9VayXE6p76vnCuOgwoL
noWc4QG+Ekv5KpEZV7MLE0pcFXSOqjlsOOd3r9rEW7FN3LnJacxVWxYT7XpSbckr
yfEp3sEsSrmiJUjccH8avsz0AiH3biXA79lPPEoNYs0/N9CHSX8iEw0+FQbBCkRO
WQ0pP9HOzDBzvCC8reHDInILGqTm8Fcc6ZkZlUa+/hkCgYEA9dqQgiPLatyC7SHE
J7ejpdjUY3ZyyTFaaWzXhJK7XKT0Dpe6y/EVwRHflf0lmFEf9Ki9Fwpt+R9arIXA
ZVIhZxFXbBEsBzOnh3G4ztC8OVFI+ZhDT11p3QoNdNpzpwEupbHF2Un7413A6Y37
1kR8DKaDbBV1x/LqH0CEUE97Dk0CgYEA0edINcSrkAON5PexfG+4fzXXAqiLtp3N
iJS2jLXfM7fwrT93Hmtn/8Z/RlmkB9YYpTSv6CXEC13dbcy4UazHaAWxWh6JIDFV
D03LGwPmM3A2TrL8uQOz1Jks0MHnDHIk/xsmdAGWT95+4IQi6PYBLcIJYJvrpJW8
7c4grPgXo7cCgYEAw4WG13jQFbQ5C42HCm8pXoQKpO9WalstpBpDa9Ol3g/xaImS
rQ6WVm14ezhP5cretxxbBS/uNemRmxLj57BhkC5icDdX5IJYAYeXiiLHDm5ustE8
9qk7v+Z2vS/eOjredjfjOON1x2SQPy4D0mu0m/rxGcwXV2UAfMo6cARFwSECgYBi
wlH8UltyN+nkKBJO/PWujLNsIccSle6la2r0i4HIAKxxpyGxo1FcS5WIkRaXRUl1
OXPmYxZ5TqGnTqIOc5+itsL6JtHX3r4ppC2CuXPvEcXLg3Vay34p8iPe2MyP04jK
qoiOHk0NqR7DHgia2Vw2nkvxM4tMddNdhBVlrJjawwKBgQDbTVtJbylbuS626dNo
Ijlj+C6I91Rkjl3+JFc3cGKzDIvUt65Vq8YnKvT8lwlMeZCeYkQkPe/yuCAoB22R
EPw0hkFv+MwPAMxAW1mee93aKDEgOiW2WAKZTOF1NSNIeZjbhf3s7prujhp4TZqc
puJNxgJJQglziz8SXm5ZyRGXeQ==
-----END PRIVATE KEY-----
Loading

0 comments on commit 9f5becb

Please sign in to comment.