容器化的 Springboot 应用程序 - 从 JAR 中加载嵌入式密钥库 (.jks/.p12)
Containerized Springboot Application - Loading an Embedded Keystore (.jks/.p12) from within the JAR
背景:我有一个 springboot 应用程序,它在 kubernetes 集群上使用 docker 和 运行s 进行容器化。它执行 API 调用,并依赖于需要加载 .jks 信任库的 SSLContext,如下所示:
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(ResourceUtils.getFile(keyStoreFilePath),
keyStorePassword.toCharArray(), new TrustSelfSignedStrategy()).build();
请注意,字符串 keyStoreFilePath 当前在发布时作为 environment/property 变量注入,并指向主机上的 /etc/ssl/keystore.jks 这样的位置,运行 是一个容器.缺点是我必须将其作为持久卷安装在 kubernetes 中,以便我的容器化应用程序访问它。
相反,我决定将它嵌入到应用程序的类路径中,这样我们的运营团队就不必在所有主机上设置它。但是当我这样做时,通过像这样指定 keyStoreFilePath 值:classpath:security/keystore.jks
,当我 运行 Eclipse/STS 中的项目时,它 运行 没问题。但它失败并在容器内出现以下错误:
class path resource [security/cacerts] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/security/cacerts","stackTrace":"org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:217)
同样,有趣的是完全相同的事情 运行 在 Eclipse 中很好,但在容器中失败了。有什么指点吗?
更新: 验证了 keystore.jks 文件的大小 < 1 MB。
错误消息显示 file:/<some-path-in-the-container>/App.jar!/keystore.jks
- 没有 "security" 文件夹,而为 keyStoreFilePath
传入的值是 classpath:security/keystore.jks
?
JKS 文件不太可能大于 1MB,这是 Kubernetes 中对 ConfigMap-s 和 Secrets 的限制,因此一种选择是创建一个 Secret with the JKS file and mount a volume from the Secret - no need to use a persistent volume or hostPath
卷。
HTH
我想通了。由于 keystore.jks 嵌入在 jar 中,需要从类路径 (classpath:security/keystore.jks
) 加载,我们不能将其作为文件读取。相反,我们必须将其作为输入流读取 - 对于 jar 文件(类路径)中的所有资源都是如此。所以,我必须做这样的事情才能让它工作:
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(truststoreResource.getInputStream(), keyStorePassword.toCharArray());
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore, new TrustSelfSignedStrategy()).build();
This 回答很有帮助。
背景:我有一个 springboot 应用程序,它在 kubernetes 集群上使用 docker 和 运行s 进行容器化。它执行 API 调用,并依赖于需要加载 .jks 信任库的 SSLContext,如下所示:
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(ResourceUtils.getFile(keyStoreFilePath),
keyStorePassword.toCharArray(), new TrustSelfSignedStrategy()).build();
请注意,字符串 keyStoreFilePath 当前在发布时作为 environment/property 变量注入,并指向主机上的 /etc/ssl/keystore.jks 这样的位置,运行 是一个容器.缺点是我必须将其作为持久卷安装在 kubernetes 中,以便我的容器化应用程序访问它。
相反,我决定将它嵌入到应用程序的类路径中,这样我们的运营团队就不必在所有主机上设置它。但是当我这样做时,通过像这样指定 keyStoreFilePath 值:classpath:security/keystore.jks
,当我 运行 Eclipse/STS 中的项目时,它 运行 没问题。但它失败并在容器内出现以下错误:
class path resource [security/cacerts] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/app.jar!/BOOT-INF/classes!/security/cacerts","stackTrace":"org.springframework.util.ResourceUtils.getFile(ResourceUtils.java:217)
同样,有趣的是完全相同的事情 运行 在 Eclipse 中很好,但在容器中失败了。有什么指点吗?
更新: 验证了 keystore.jks 文件的大小 < 1 MB。
错误消息显示 file:/<some-path-in-the-container>/App.jar!/keystore.jks
- 没有 "security" 文件夹,而为 keyStoreFilePath
传入的值是 classpath:security/keystore.jks
?
JKS 文件不太可能大于 1MB,这是 Kubernetes 中对 ConfigMap-s 和 Secrets 的限制,因此一种选择是创建一个 Secret with the JKS file and mount a volume from the Secret - no need to use a persistent volume or hostPath
卷。
HTH
我想通了。由于 keystore.jks 嵌入在 jar 中,需要从类路径 (classpath:security/keystore.jks
) 加载,我们不能将其作为文件读取。相反,我们必须将其作为输入流读取 - 对于 jar 文件(类路径)中的所有资源都是如此。所以,我必须做这样的事情才能让它工作:
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(truststoreResource.getInputStream(), keyStorePassword.toCharArray());
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore, new TrustSelfSignedStrategy()).build();
This 回答很有帮助。