Spring Boot v3.2.0 Ssl Bundle is unable to find the JKS file present inside a library jar. The JKS file is commonly shared across multiple applications and benefits being in a single place (here dependent jar)
ResourceUtils.getURL fails to load the JKS file from classpath like classpath:/common/path/in/jar/app.jks
Same works fine if the JKS file is from within the application
Comment From: scottfrederick
Thanks for getting in touch. I can't reproduce this problem with a trivial sample app and library. It's not clear from your description if the configuration that sets the SSL bundle is in the library or in the application, but it works either way for me.
Since there are so many possible ways to configure an application, we'll need more information to know what's going on. Please provide a complete minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it and attaching it to this issue.
Comment From: syedyusufh
Thanks for the quick revert @scottfrederick
Please find below the 2 projects to reproduce the issue reported. Usage of common-lib for JKS has been the pattern working for us prior to Ssl Bundle by manually configuring the Ssl across WebClient, JMS, Kafka, etc
https://github.com/syedyusufh/common-lib.git https://github.com/syedyusufh/ssl-bundle-error.git
You would be getting the below error,
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.ssl.DefaultSslBundleRegistry]: Factory method 'sslBundleRegistry' threw exception with message: Unable to register SSL bundle 'common'
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:178) ~[spring-beans-6.1.1.jar:6.1.1]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~[spring-beans-6.1.1.jar:6.1.1]
... 57 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to register SSL bundle 'common'
at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.lambda$registerBundles$2(SslPropertiesBundleRegistrar.java:68) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721) ~[na:na]
at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.registerBundles(SslPropertiesBundleRegistrar.java:58) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.registerBundles(SslPropertiesBundleRegistrar.java:53) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration.lambda$sslBundleRegistry$0(SslAutoConfiguration.java:59) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[na:na]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) ~[na:na]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) ~[na:na]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
at org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration.sslBundleRegistry(SslAutoConfiguration.java:59) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.1.jar:6.1.1]
... 58 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to create key store: Could not load store from 'classpath:/com/sample/common.jks'
at org.springframework.boot.ssl.jks.JksSslStoreBundle.createKeyStore(JksSslStoreBundle.java:93) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.ssl.jks.JksSslStoreBundle.<init>(JksSslStoreBundle.java:56) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.autoconfigure.ssl.PropertiesSslBundle.asSslStoreBundle(PropertiesSslBundle.java:146) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at org.springframework.boot.autoconfigure.ssl.PropertiesSslBundle.get(PropertiesSslBundle.java:139) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.lambda$registerBundles$0(SslPropertiesBundleRegistrar.java:59) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
at org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar.lambda$registerBundles$2(SslPropertiesBundleRegistrar.java:61) ~[spring-boot-autoconfigure-3.2.0.jar:3.2.0]
... 79 common frames omitted
Caused by: java.lang.IllegalStateException: Could not load store from 'classpath:/com/sample/common.jks'
at org.springframework.boot.ssl.jks.JksSslStoreBundle.loadKeyStore(JksSslStoreBundle.java:122) ~[spring-boot-3.2.0.jar:3.2.0]
at org.springframework.boot.ssl.jks.JksSslStoreBundle.createKeyStore(JksSslStoreBundle.java:88) ~[spring-boot-3.2.0.jar:3.2.0]
... 84 common frames omitted
Caused by: java.io.FileNotFoundException: class path resource [/com/sample/common.jks] cannot be resolved to URL because it does not exist
at org.springframework.util.ResourceUtils.getURL(ResourceUtils.java:138) ~[spring-core-6.1.1.jar:6.1.1]
at org.springframework.boot.ssl.jks.JksSslStoreBundle.loadKeyStore(JksSslStoreBundle.java:116) ~[spring-boot-3.2.0.jar:3.2.0]
... 85 common frames omitted
Comment From: philwebb
I think that the problem you're seeing is caused by an error in the classpath resource reference. The following values:
spring.ssl.bundle.jks.common.keystore.location: classpath:/com/sample/common.jks
spring.ssl.bundle.jks.common.truststore.location: classpath:/com/sample/common.jks
Should be:
spring.ssl.bundle.jks.common.keystore.location: classpath:com/sample/common.jks
spring.ssl.bundle.jks.common.truststore.location: classpath:com/sample/common.jks
We may have been more lenient with our loading before the SSL bundle support was added.
In addition to that, you need to remove the following:
spring.ssl.bundle.jks.common.reload-on-update: true
spring.ssl.bundle.watch.file.quiet-period: 300s
You can only watch external files for changes, not those that are bundled in a jar.
Comment From: scottfrederick
I think the exception message that is given when reload-on-update is combined with classpath: resources could be more clear. I've opened #38903 to track that.