--- title: Spring BootでPostgreSQL R2DBC DriverのTLS接続を使うメモ tags: ["Spring WebFlux", "Spring Boot", "Java", "TLS", "R2DBC", "PostgreSQL", "Cloud Native Buildpacks", "Paketo"] categories: ["Programming", "Java", "io", "r2dbc", "postgresql"] date: 2021-04-18T15:35:20Z updated: 2021-04-18T15:36:27Z --- **目次** Production環境でデータベースにTLS接続しないのは許されないです。
[PostgreSQL R2DBC Driver](https://github.com/pgjdbc/r2dbc-postgresql) で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 Image`ghcr.io/making/demo-r2dbc`を使用します。 ### 自己署名証明書の作成 `certs`ディレクトリを作成し、次の`generate-certs.sh`を作成します。 ```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](https://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](https://paketo.io)でビルドされています。 Paketo Buildpackを使っている場合は[CA Certificates Buildpack](https://paketo.io/docs/buildpacks/configuration/#ca-certificates) を使うことで、簡単にCA証明書をTrustStoreに追加することできます。 次のコマンドを実行して、[Binding](https://paketo.io/docs/buildpacks/configuration/#bindings) の仕様に合わせてディレクトリとファイルを作成します。 ``` 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](https://github.com/k8s-service-bindings/spec) の仕様に合わせて次のコマンドを実行します。 ``` 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通信に利用できるので、こちらの方が良いかもしれません。