1

A standard configuration to enable Java to use the PKCS#11 HSM based keystore is not to configure anything to keystore path (keep it null) and configure the java security to get the PKCS 11 security provider. More information (with Sun/Oracle JVM) is available here. Java docs on Keystore specify - In order to create an empty keystore, or if the keystore cannot be initialized from a stream, pass null as the stream argument. (Ref: here) However doing so with Spring Boot results in following exception:

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is
java.lang.IllegalArgumentException: Resource location must not be null
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531) ~[spring-context-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:347) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:295) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1112) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1101) [spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at com.example.manager.ManagerApplication.main(ManagerApplication.java:27) [axon-manager-ws-0.3.2-SNAPSHOT.jar:0.3.2-SNAPSHOT] Caused by:
java.lang.IllegalArgumentException: Resource location must not be null
        at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.util.ResourceUtils.getURL(ResourceUtils.java:131) ~[spring-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.configureSslKeyStore(TomcatEmbeddedServletContainerFactory.java:329) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.configureSsl(TomcatEmbeddedServletContainerFactory.java:312) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.customizeSsl(TomcatEmbeddedServletContainerFactory.java:278) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.customizeConnector(TomcatEmbeddedServletContainerFactory.java:257) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:159) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:158) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130) ~[spring-boot-1.3.0.RELEASE.jar:1.3.0.RELEASE]
        ... 8 more

It appears that the class "org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory" does not allow for Keystore path to be null. It attempts to load the resource from the given path.

The Spring Boot version is 1.3.0. I looked at the latest version, https://github.com/spring-projects/spring-boot/blob/master/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java and the code does not seem to be changed (line 343) Interestingly enough, when the code attempt to load the Trust store, it is well protected (allows for null trust store path), see line 358.

It is a simple fix - to check if the keystore path is null and/or empty and let it be.

For anybody else looking to resolve this, the workaround exist - by overriding the "configureSsl" method of "org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory" and configuring this instance to be EmbeddedServletContainerFactory in the Application configuration.

The question is: Is there another way to configure the security / keystores in Spring Boot such that I wont need to override the TomcatEmbeddedServletContainerFactory? Or should I consider logging issue on Spring Boot and suggest a patch?

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
vjkumar
  • 171
  • 1
  • 3
  • 10
  • Even if you do the Null check, you get Failed to load keystore type PKCS11 with path //.keystore due to PKCS11 not found... – Ali Moghadam Aug 23 '16 at 01:24

0 Answers0