Skip to content

SslStoreProviderUrlStreamHandlerFactory changes the KeyStore password #11391

@jonatan-ivanov

Description

@jonatan-ivanov

The issue

I would like to use HTTPS with spring boot (1.5.9) and I would like to get the KeyStore from memory (eventually from HashiCorp Vault) and not from disk. In order to do this, I implemented a SslStoreProvider and set it up through an EmbeddedServletContainerCustomizer; please check this example.

The example above fails because of SslStoreProviderUrlStreamHandlerFactory re-encrypts the KeyStore with an empty password so I get an error: java.io.IOException: keystore password was incorrect:

ByteArrayOutputStream stream = new ByteArrayOutputStream();
this.keyStore.store(stream, new char[0]); //the second parameter is the password
return new ByteArrayInputStream(stream.toByteArray());

I tried to trick this with an empty password but when Tomcat tries to load the InputStream of the KeyStore, in SSLUtilBase, it checks if the password is empty and it will use null in this case:

char[] storePass = null;
if (pass != null && !"".equals(pass)) {
    storePass = pass.toCharArray();
}
ks.load(istream, storePass);

Based on these code snippets, I can't really see how could this work, the password can never be empty when Tomcat tries to load the KeyStore.

Additional details

Tomcat tries to get the KeyStore this way: url.openConnection().getInputStream() in ConfigFileLoader. In order to make this work, TomcatEmbeddedServletContainerFactory will set the url to springbootssl:keyStore and register SslStoreProviderUrlStreamHandlerFactory for this url.

I'm using Spring-Boot 1.5.9-RELEASE, OpenJDK 1.8.0_152 and Gradle 4.4

I created an example which reproduces the issue. I fixed it with a hack (registering a custom url handler before the original one) just to see if this works, please see the commits.

Possible fix

I think this could be fixed in SslStoreProviderUrlStreamHandlerFactory the way I did in the example because when TomcatEmbeddedServletContainerFactory sets this up, it has the Ssl object which contains the password. If this approach could work, I'm happy to create a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions