目次
- 自己署名証明書の作成
- PostgreSQLの起動
- TLSを使用しない場合
- sslMode=REQUIREの場合
- sslMode=VERIFY_CAの場合
- sslMode=VERIFY_CAの場合
- 別解: Paketo CA Certificates Buildpackを使用
Production環境でデータベースにTLS接続しないのは許されないです。
PostgreSQL R2DBC Driver でTLS接続するときのメモ。
基本的にspring.r2dbc.properties.sslModeに次のいずれかの値を設定します。
REQUIRE... 通信の暗号化のみ行い、サーバーの証明は行わないVERIFY_CA...REQUIREに加え、サーバーが信頼されているかどうかチェックするがhostnameはチェックしないVERIFY_FULL...VERIFY_CAに加え、hostnameのチェックも行う
REQUIRE < VERIFY_CA < VERIFY_FULLの順で安全な接続になります。
JavaのTrustStoreに登録されていないCAに関してはspring.r2dbc.properties.sslRootCertで証明書(PEMファイル)へのパスを指定できます。
spring.r2dbc.url=r2dbc:postgresql://hostname:5432/demo?sslMode=****&sslRootCert=****のようにURLの末尾にパラメータを指定することもできます。
実際のアプリを使って試してみます。
https://github.com/making/demo-r2dbc
のDocker Imageghcr.io/making/demo-r2dbcを使用します。
自己署名証明書の作成
certsディレクトリを作成し、次のgenerate-certs.shを作成します。
#!/bin/bash
set -ex
cd /certs
openssl req -new -nodes -out root.csr \
-keyout root.key -subj "/CN=sslip.io"
chmod og-rwx root.key
openssl x509 -req -in root.csr -days 3650 \
-extfile /etc/ssl/openssl.cnf -extensions v3_ca \
-signkey root.key -out root.crt
openssl req -new -nodes -out server.csr \
-keyout server.key -subj "/CN=*.sslip.io"
chmod og-rwx server.key
openssl x509 -req -in server.csr -days 3650 \
-CA root.crt -CAkey root.key -CAcreateserial \
-out server.crt
certsディレクトリの上の階層で次のコマンドを実行して自己署名証明書を作成します。
docker run --rm \
-v ${PWD}/certs:/certs \
gcr.io/paketo-buildpacks/run:base-cnb \
sh /certs/generate-certs.sh
PostgreSQLの起動
PostgreSQLはDockerを使って次のように起動します。
docker run --rm \
-p 5432:5432 \
-e POSTGRES_DB=demo \
-e POSTGRES_USER=demo \
-e POSTGRES_PASSWORD=demo \
-e POSTGRESQL_ENABLE_TLS=yes \
-e POSTGRESQL_TLS_CERT_FILE=/certs/server.crt \
-e POSTGRESQL_TLS_KEY_FILE=/certs/server.key \
-e POSTGRESQL_TLS_CA_FILE=/certs/root.crt \
-e POSTGRESQL_PGHBA_REMOVE_FILTERS=hostssl \
-v ${PWD}/certs:/certs \
bitnami/postgresql:11.11.0-debian-10-r59
TLSを使用しない場合
まずはTLSを使用せずplaintextで接続します。
PostgreSQLはDockerのhost側で5432ポートでリッスンしているので、アプリのDockerコンテナ側から見たPostgreSQLのhostnameはdocker.host.internalになります。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://host.docker.internal:5432/demo" \
ghcr.io/making/demo-r2dbc
sslModeを指定しなければ、次のログのようにplaintextで普通に接続できます。
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 129 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:12:42.627 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on dda341fc71a0 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:12:42.631 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:12:43.454 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:12:43.465 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:12:45.110 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-04-18 15:12:45.412 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
2021-04-18 15:12:45.428 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Started DemoR2dbcApplication in 3.38 seconds (JVM running for 3.895)
sslMode=REQUIREの場合
次にsslMode=REQUIREを設定して通信を暗号化します。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://host.docker.internal:5432/demo?sslMode=REQUIRE" \
ghcr.io/making/demo-r2dbc
PostgreSQL側がTLSに対応していれば、こちらも次のログのようにPostgreSQLに接続できます。信頼されたサーバーかどうかの検証は行わないので自己署名証明書でも問題ありません。
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 129 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:13:17.367 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on 2463512e041a with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:13:17.372 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:13:18.191 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:13:18.203 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:13:20.294 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-04-18 15:13:20.569 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
2021-04-18 15:13:20.587 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Started DemoR2dbcApplication in 3.834 seconds (JVM running for 4.363)
sslMode=VERIFY_CAの場合
次にsslMode=VERIFY_CAを設定して通信を暗号化します。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://host.docker.internal:5432/demo?sslMode=VERIFY_CA" \
ghcr.io/making/demo-r2dbc
PostgreSQLサーバーは自己署名証明書を使用しており、信頼されたサーバーではないので次のログのようにunable to find valid certification path to requested targetというエラーメッセージがに出力されます。
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 129 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:13:40.832 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on f9b4293c3462 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:13:40.836 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:13:41.707 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:13:41.721 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:13:43.363 ERROR 1 --- [tor-tcp-epoll-1] reactor.core.publisher.Operators : Operator called default onErrorDropped
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:478) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar:4.1.63.Final]
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar:4.1.63.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar:4.1.63.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.SSLHandshake.consume(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(Unknown Source) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(Unknown Source) ~[na:na]
at io.netty.handler.ssl.SslHandler.runAllDelegatedTasks(SslHandler.java:1528) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1542) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1426) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1253) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1300) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
... 15 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(Unknown Source) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.engineValidate(Unknown Source) ~[na:na]
at java.base/sun.security.validator.Validator.validate(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) ~[na:na]
... 31 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source) ~[na:na]
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) ~[na:na]
at java.base/java.security.cert.CertPathBuilder.build(Unknown Source) ~[na:na]
... 37 common frames omitted
対象のサーバーを信頼するために、CA証明書をsslRootCertで指定します。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://host.docker.internal:5432/demo?sslMode=VERIFY_CA&sslRootCert=/certs/root.crt" \
-v ${PWD}/certs:/certs \
ghcr.io/making/demo-r2dbc
これでVERIFY_CAでも次のログのようにPostgreSQLに接続できます。
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 129 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:14:07.243 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on c87ecd21dfb7 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:14:07.246 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:14:08.101 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:14:08.112 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:14:10.245 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-04-18 15:14:10.541 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
2021-04-18 15:14:10.555 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Started DemoR2dbcApplication in 3.877 seconds (JVM running for 4.405)
sslMode=VERIFY_CAの場合
次にsslMode=VERIFY_FULLを設定して通信を暗号化します。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://host.docker.internal:5432/demo?sslMode=VERIFY_FULL&sslRootCert=/certs/root.crt" \
-v ${PWD}/certs:/certs \
ghcr.io/making/demo-r2dbc
generate-certs.shで作成した証明書のCommon Nameは*.sslip.ioであり、SPRING_R2DBC_URLのhostnameに指定したhost.docker.internalに合致しない為、hostnameの検証に失敗し、次のログのようにThe hostname 'host.docker.internal/192.168.65.2' could not be verified.というエラーメッセージが出力されます。
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 129 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:14:37.819 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on 4588d584368b with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:14:37.826 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:14:38.644 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:14:38.656 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:14:40.315 WARN 1 --- [tor-tcp-epoll-1] i.r.p.client.DefaultHostnameVerifier : Server name validation failed: hostname host.docker.internal does not match common name *.sslip.io
2021-04-18 15:14:40.358 WARN 1 --- [tor-tcp-epoll-1] i.r.p.client.DefaultHostnameVerifier : Server name validation failed: hostname host.docker.internal does not match common name *.sslip.io
2021-04-18 15:14:40.367 WARN 1 --- [ main] onfigReactiveWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initializer' defined in class path resource [lol/maki/demo/config/R2dbcConfig.class]: Invocation of init method failed; nested exception is org.springframework.r2dbc.connection.init.UncategorizedScriptException: Failed to execute database script; nested exception is org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter$PostgresqlSslException: The hostname 'host.docker.internal/192.168.65.2' could not be verified.
2021-04-18 15:14:40.389 INFO 1 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-04-18 15:14:40.414 ERROR 1 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initializer' defined in class path resource [lol/maki/demo/config/R2dbcConfig.class]: Invocation of init method failed; nested exception is org.springframework.r2dbc.connection.init.UncategorizedScriptException: Failed to execute database script; nested exception is org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter$PostgresqlSslException: The hostname 'host.docker.internal/192.168.65.2' could not be verified.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1786) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.6.jar:5.3.6]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.6.jar:5.3.6]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:63) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) ~[spring-boot-2.4.5.jar:2.4.5]
at lol.maki.demo.DemoR2dbcApplication.main(DemoR2dbcApplication.java:10) ~[classes/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[workspace/:na]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[workspace/:na]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[workspace/:na]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) ~[workspace/:na]
Caused by: org.springframework.r2dbc.connection.init.UncategorizedScriptException: Failed to execute database script; nested exception is org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter$PostgresqlSslException: The hostname 'host.docker.internal/192.168.65.2' could not be verified.
at org.springframework.r2dbc.connection.init.DatabasePopulator.lambda$populate$4(DatabasePopulator.java:63) ~[spring-r2dbc-5.3.6.jar:5.3.6]
at reactor.core.publisher.Mono.lambda$onErrorMap$30(Mono.java:3474) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Mono.lambda$onErrorResume$32(Mono.java:3564) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoUsingWhen$ResourceSubscriber.onError(MonoUsingWhen.java:208) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Operators.error(Operators.java:197) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoError.subscribe(MonoError.java:52) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Mono.subscribe(Mono.java:4150) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxRetry$RetrySubscriber.onError(FluxRetry.java:94) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onError(FluxPeekFuseable.java:234) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:221) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:221) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.pool.AbstractPool$Borrower.fail(AbstractPool.java:418) ~[reactor-pool-0.2.4.jar:0.2.4]
at reactor.pool.SimpleDequePool.lambda$drainLoop$7(SimpleDequePool.java:390) ~[reactor-pool-0.2.4.jar:0.2.4]
at reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:186) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onError(FluxMap.java:259) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Operators.error(Operators.java:197) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoError.subscribe(MonoError.java:52) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Mono.subscribe(Mono.java:4150) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onError(MonoFlatMap.java:172) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Operators.error(Operators.java:197) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoError.subscribe(MonoError.java:52) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Mono.subscribe(Mono.java:4150) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Operators.error(Operators.java:197) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoError.subscribe(MonoError.java:52) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Mono.subscribe(Mono.java:4150) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:132) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoDelayUntil$DelayUntilCoordinator.onError(MonoDelayUntil.java:200) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:140) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:270) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoSubscribeOn$SubscribeOnSubscriber.onError(MonoSubscribeOn.java:152) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.MonoCompletionStage.lambda$subscribe$0(MonoCompletionStage.java:79) ~[reactor-core-3.4.5.jar:3.4.5]
at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.postComplete(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(Unknown Source) ~[na:na]
at io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter.completeHandshakeExceptionally(AbstractPostgresSSLHandlerAdapter.java:73) ~[r2dbc-postgresql-0.8.7.RELEASE.jar:0.8.7.RELEASE]
at io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter.operationComplete(AbstractPostgresSSLHandlerAdapter.java:68) ~[r2dbc-postgresql-0.8.7.RELEASE.jar:0.8.7.RELEASE]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:571) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:550) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:616) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:605) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.setHandshakeSuccess(SslHandler.java:1780) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.wrapNonAppData(SslHandler.java:964) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1421) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1253) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1300) ~[netty-handler-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.63.Final.jar:4.1.63.Final]
at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar:4.1.63.Final]
at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar:4.1.63.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar:4.1.63.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.63.Final.jar:4.1.63.Final]
at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.Mono.block(Mono.java:1703) ~[reactor-core-3.4.5.jar:3.4.5]
at org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer.execute(ConnectionFactoryInitializer.java:109) ~[spring-r2dbc-5.3.6.jar:5.3.6]
at org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer.afterPropertiesSet(ConnectionFactoryInitializer.java:95) ~[spring-r2dbc-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1845) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:602) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.6.jar:5.3.6]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.6.jar:5.3.6]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.6.jar:5.3.6]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:63) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340) ~[spring-boot-2.4.5.jar:2.4.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) ~[spring-boot-2.4.5.jar:2.4.5]
at lol.maki.demo.DemoR2dbcApplication.main(DemoR2dbcApplication.java:10) ~[classes/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) ~[workspace/:na]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) ~[workspace/:na]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) ~[workspace/:na]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) ~[workspace/:na]
Caused by: org.springframework.dao.DataAccessResourceFailureException: Failed to obtain R2DBC Connection; nested exception is io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter$PostgresqlSslException: The hostname 'host.docker.internal/192.168.65.2' could not be verified.
at org.springframework.r2dbc.connection.ConnectionFactoryUtils.lambda$getConnection$0(ConnectionFactoryUtils.java:88) ~[spring-r2dbc-5.3.6.jar:5.3.6]
at reactor.core.publisher.Mono.lambda$onErrorMap$31(Mono.java:3488) ~[reactor-core-3.4.5.jar:3.4.5]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:94) ~[reactor-core-3.4.5.jar:3.4.5]
... 69 common frames omitted
Caused by: io.r2dbc.postgresql.client.AbstractPostgresSSLHandlerAdapter$PostgresqlSslException: The hostname 'host.docker.internal/192.168.65.2' could not be verified.
... 30 common frames omitted
エラーメッセージからわかるように、今回の環境ではPostgreSQLのIPアドレスは192.168.65.2です。sslip.io の機能で、192-168-65-2.sslip.ioを192.168.65.2に解決できるので、
$ nslookup 192-168-65-2.sslip.io
Server: 8.8.8.8
Address: 8.8.8.8#53
Non-authoritative answer:
Name: 192-168-65-2.sslip.io
Address: 192.168.65.2
証明書のCommon Nameに合致するようにPostgreSQLのhostnameを192-168-65-2.sslip.ioに変更します。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://192-168-65-2.sslip.io:5432/demo?sslMode=VERIFY_FULL&sslRootCert=/certs/root.crt" \
-v ${PWD}/certs:/certs \
ghcr.io/making/demo-r2dbc
これでVERIFY_FULLでも次のログのようにPostgreSQLに接続できます。
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 129 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:16:46.891 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on 303c1f93b565 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:16:46.896 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:16:47.767 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:16:47.780 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 7 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:16:49.932 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-04-18 15:16:50.185 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
2021-04-18 15:16:50.200 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Started DemoR2dbcApplication in 3.924 seconds (JVM running for 4.43)
これで安心。
別解: Paketo CA Certificates Buildpackを使用
ghcr.io/making/demo-r2dbcはPaketo Buildpackでビルドされています。
Paketo Buildpackを使っている場合はCA Certificates Buildpack を使うことで、簡単にCA証明書をTrustStoreに追加することできます。
次のコマンドを実行して、Binding の仕様に合わせてディレクトリとファイルを作成します。
mkdir -p bindings/trusted-certs
echo ca-certificates > bindings/trusted-certs/type
cp certs/root.crt bindings/trusted-certs/
次の構造になります。
$ tree bindings
bindings
`-- trusted-certs
|-- root.crt
`-- type
1 directory, 2 files
Service Binding の仕様に合わせて次のコマンドを実行します。
docker run \
--rm \
-m 512m \
-p 8080:8080 \
-e SPRING_R2DBC_URL="r2dbc:postgresql://192-168-65-2.sslip.io:5432/demo?sslMode=VERIFY_FULL" \
-e SERVICE_BINDING_ROOT=/bindings \
-v ${PWD}/bindings:/bindings \
ghcr.io/making/demo-r2dbc
次のログのようにPostgreSQLに接続できます。
Added 1 additional CA certificate(s) to system truststore
Setting Active Processor Count to 4
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M (Total Memory: 512M, Thread Count: 50, Loaded Class Count: 14180, Headroom: 0%)
Adding 130 container CA certificates to JVM truststore
Spring Cloud Bindings Enabled
Picked up JAVA_TOOL_OPTIONS: -Djava.security.properties=/layers/paketo-buildpacks_bellsoft-liberica/java-security-properties/java-security.properties -agentpath:/layers/paketo-buildpacks_bellsoft-liberica/jvmkill/jvmkill-1.16.0-RELEASE.so=printHeapHistogram=1 -XX:ActiveProcessorCount=4 -XX:MaxDirectMemorySize=10M -Xmx123099K -XX:MaxMetaspaceSize=93988K -XX:ReservedCodeCacheSize=240M -Xss1M -Dorg.springframework.cloud.bindings.boot.enable=true
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.4.5)
2021-04-18 15:30:59.566 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Starting DemoR2dbcApplication v0.0.1-SNAPSHOT using Java 11.0.10 on aa73c23c4672 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
2021-04-18 15:30:59.571 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : No active profile set, falling back to default profiles: default
2021-04-18 15:31:00.419 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data R2DBC repositories in DEFAULT mode.
2021-04-18 15:31:00.431 INFO 1 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 6 ms. Found 0 R2DBC repository interfaces.
2021-04-18 15:31:02.595 INFO 1 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoint(s) beneath base path '/actuator'
2021-04-18 15:31:02.852 INFO 1 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port 8080
2021-04-18 15:31:02.872 INFO 1 --- [ main] lol.maki.demo.DemoR2dbcApplication : Started DemoR2dbcApplication in 3.92 seconds (JVM running for 4.467)
Bindingを行う前はAdding 129 container CA certificates to JVM truststoreというメッセージが出力されていましたが、今回はAdding 130 container CA certificates to JVM truststoreというメッセージが出力されています。
用意したroot.crtがTrustStoreに追加されるので、Driver側にsslRootCertを指定する必要がありません。
この手法はPostgreSQLに限らず任意のTLS通信に利用できるので、こちらの方が良いかもしれません。