我有一个 Spring Boot 应用程序,其中 Dockerfile 执行“keytool -importkeystore ...”命令来导入 p12 密钥库。在entrypoint.sh中执行keytool命令的原因是能够参数化证书本身的设置,这样它就不必与应用程序的docker镜像捆绑在一起。
这是 Dockerfile
FROM openjdk:8-jdk-alpine as builder
WORKDIR application
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM openjdk:8-jdk-alpine
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
COPY entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
# Install CURL
RUN apk --no-cache add curl
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
这里是docker启动容器时执行的entrypoint.sh
#!/bin/sh
#echo "executing keytool import store"
echo "statement is ${STATEMENT}"
keytool ${STATEMENT}
echo "Executing springboot load for app"
#Execute using linux 'exec' Java launcher
exec java org.springframework.boot.loader.JarLauncher "$@"
使用 docker-compose 引用自定义 .env,上面 .sh 文件中引用的变量 STATEMENT 与 keytool 命令配对给出:
-v -importkeystore -srckeystore /etc/certs/ssl/appc.com.p12 -srcstorepass Appcpassword1234 -destkeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -srcstoretype pkcs12 -deststoretype JKS -deststorepass changeit
请注意,相对于上面打印的命令:
在同一个 .env 文件中,我使用 Spring Boot 应用程序属性来设置 SSL 变量,并且该进程确实对它们做出响应:
SERVER_SSL_KEYALIAS=appc-alias
SERVER_SSL_KEYSTORE=file:/etc/certs/ssl/appc.com.p12 #tried different formats as well like removing the "file:"
SERVER_SSL_KEYPASSWORD=Appcpassword1234
SERVER_SSL_KEYSTORE_PASSWORD=Appcpassword1234
当通过 docker 桌面在我的 Windows 系统中运行容器时,一切都很好,应用程序启动得很好。当使用 docker 引擎在 centOs 中运行时,应用程序始终失败并显示以下错误堆栈跟踪。我可以控制创建所有密码(也许除了我认为默认情况下会更改的 cacerts)。然而,它似乎想要一个与我在 p12 上创建和设置的不同的。我完全困惑了。 我设置的密码是否可以以一种方式编码,然后需要以不同的方式在 keytool 命令中提供??
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
at org.apache.catalina.connector.Connector.startInternal(Connector.java:1058) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.StandardService.addConnector(StandardService.java:227) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
... 26 common frames omitted
Caused by: java.lang.IllegalArgumentException: keystore password was incorrect
at org.apache.tomcat.util.net.AbstractJsseEndpoint.createSSLContext(AbstractJsseEndpoint.java:99) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:71) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:216) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.util.net.AbstractEndpoint.bindWithCleanup(AbstractEndpoint.java:1141) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:1227) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:592) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.connector.Connector.startInternal(Connector.java:1055) ~[tomcat-embed-core-9.0.35.jar:9.0.35]
... 28 common frames omitted
Caused by: java.io.IOException: keystore password was incorrect
at sun.security.pkcs12.PKCS12KeyStore.engineLoad(PKCS12KeyStore.java:2059) ~[na:1.8.0_212]
at java.security.KeyStore.load(KeyStore.java:1445) ~[na:1.8.0_212]
-v -importkeystore -srckeystore /etc/certs/ssl/appc.com.p12 -srcstorepass Appcpassword1234 -keypass Appcpassword1234 -destkeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -srcstoretype PKCS12 -storepass changeit -J-showversion
标志 -J-showversion 只是打印版本详细信息,在本例中是:
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (IcedTea 3.12.0) (Alpine 8.212.04-r0)
OpenJDK 64-Bit Server VM (build 25.212-b04, mixed mode)
keytool error: java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
java.io.IOException: DerInputStream.getLength(): lengthTag=109, too big.
at sun.security.util.DerInputStream.getLength(DerInputStream.java:599)
at sun.security.util.DerValue.init(DerValue.java:391)
at sun.security.util.DerValue.<init>(DerValue.java:332)
我还根据此线程使用 OPENSSL (而不是 keytool)创建了 P12:Java keytool : Importing PKCS12 to jks ,获取错误 keystore 密码不正确。结果是一样的。
我没有尝试按照此处的建议使用 Oracle JDK 8:“java.io.IOException:密钥库密码不正确” on KeyStore load。如果有我可以尝试的 OpenJDK 的等效版本,我更愿意使用它,而不是使用 Oracle 的(许可证/开源需求)
[1] 来自 keytool 的警告如下,但我通过谷歌搜索发现这是错误的消息
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -destkeystore /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/cacerts -deststoretype pkcs12".
我让它工作了,但这可能更多的是关于 spring boot 属性转换为环境变量的故事,而不是一般复杂的“keytool”、openssl 和 TLS 证书。
我仍然无法完全解释这一点,但是我的 docker-compose 中引用的 .env 文件中的这两个更改的组合做到了这一点 - 它允许所有服务在没有“keytool”的情况下启动错误”并使用 TLS 加密:
内置 SSL spring 属性不起作用的方式和原因 这些是