Background: I have a springboot app that is containerized using docker and runs on a kubernetes cluster. It performs API calls, and relies on an SSLContext that requires loading a .jks truststore, like so:
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(ResourceUtils.getFile(keyStoreFilePath),
keyStorePassword.toCharArray(), new TrustSelfSignedStrategy()).build();
Note that the String keyStoreFilePath is currently injected as an environment/property variable at release time, and points to a location like /etc/ssl/keystore.jks on the host machine that runs a container. The disadvantage is that I have to resort to mounting this as a persistent volume in kubernetes for my containerized application to access it.
Instead, I decided to embed it into the application's classpath so that our operations team don't have to setting it up in all the host machines. But when I do, by specifying the keyStoreFilePath value like so: classpath:security/keystore.jks
, it runs fine when I run the project in Eclipse/STS. But it fails with the error below inside the container:
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)
Again, what is interesting is that the exact same thing runs just fine in Eclipse, but fails inside the container. Any pointers?
Update: verified the keystore.jks file is < 1 MB in size.
I was able to figure this out. Since the keystore.jks is embedded within the jar and needs to be loaded from the classpath (classpath:security/keystore.jks
), we can not read it as a file. Instead, we will have to read it as an input stream - true for all resources within the jar file (classpath). So, I have to do something like this to get it to work:
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(truststoreResource.getInputStream(), keyStorePassword.toCharArray());
SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore, new TrustSelfSignedStrategy()).build();
This answer was helpful.