背景:我有一个使用docker容器化并在kubernetes集群上运行的springboot应用程序。它执行API调用,并依赖于需要加载.jks信任库的SSLContext,如下所示:
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(ResourceUtils.getFile(keyStoreFilePath),
keyStorePassword.toCharArray(), new TrustSelfSignedStrategy()).build();
注意,字符串keyStoreFilePath当前在发布时作为环境/属性变量注入,并指向运行容器的主机上的/etc/ssl/keystore.jks之类的位置。缺点是我必须将其安装为kubernetes中的持久卷,以便我的容器化应用程序可以访问它。
相反,我决定将其嵌入到应用程序的类路径中,以便我们的运营团队不必在所有主机上进行设置。但是,当我这样做时,通过这样指定keyStoreFilePath值:classpath:security/keystore.jks
,当我在容器外部运行可执行jar时,它运行良好。但是它失败,并在容器内显示以下错误:
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)
再次,有趣的是,完全相同的东西在容器外部运行良好,但在容器内部运行失败。有指针吗?
[Update:验证keystore.jks文件的大小为<1 MB。
我能够弄清楚。由于keystore.jks嵌入在jar中,并且需要从类路径(hostPath
)加载,因此我们无法将其作为文件读取。相反,我们将不得不将其读取为输入流-对于jar文件(类路径)中的所有资源均为true。因此,我必须执行以下操作才能使其正常工作:
classpath:security/keystore.jks
[KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(truststoreResource.getInputStream(), keyStorePassword.toCharArray());
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore, new TrustSelfSignedStrategy()).build();
答案很有帮助。