Tomcat java.io.IOException: Invalid keystore format when loading keystore via Classloader

I was trying to figure out the cause of this problem. I am keeping an invalid keystore format error when loading a keystore via Classloader on Tomcat. I wrote some unit tests that successfully load my keystore through the classpath, but when run in Tomcat I get an Invalid keystore format error.

This is for Spring REST RestTemplate client.

My Spring config code ... almost the same in unit test and real config.

@Value("${env}")
private String env;

@Bean
public RestTemplate getRestTemplate(HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory) {
    return new RestTemplate(httpComponentsClientHttpRequestFactory);
}

@Bean
public HttpComponentsClientHttpRequestFactory getHttpComponentsClientHttpRequestFactory(HttpClient httpClient) {
    HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
    return httpComponentsClientHttpRequestFactory;
}


@Bean
public HttpClientConnectionManager getHttpClientConnectionManager() throws Exception {
    String password = environment.getProperty("keystore.password");
    InputStream cpStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(env + "/keystore.jks");

    //load the keystore
    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
    keystore.load(cpStream, password.toCharArray());
    SSLContext sslContext  = SSLContexts.custom().loadTrustMaterial(keystore).build();
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

    PlainConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
    Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create().register("http",plainsf).register("https",sslsf).build();

    PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(r);
    cm.setMaxTotal(200);
    cm.setDefaultMaxPerRoute(50);
    return cm;
}

@Bean
public HttpClient getHttpClient(HttpClientConnectionManager httpClientConnectionManager) {
    return HttpClients.custom().setConnectionManager(httpClientConnectionManager).build();
}

      

This code works great to create mine RestTemplate

with the keystore I need for mine SSLContext

in my unit test. I've also tried various ways to get the InputStream for my keystore from the classloader via my unit test and it all worked too.

InputStream cpStream = this.getClass().getClassLoader().getResourceAsStream(env + "/csaa.jks");

InputStream cpStream = this.getClass().getResourceAsStream("/" + env + "/csaa.jks");

      

A variable env

is just a way to load certain environment properties ... env = DEV etc. Everything works fine with running this with JUnit SpringJUnit4ClassRunner.class

, but when deploying it to Tomcat, I always get Invalid keystore error. If I use FileInputStream

with a hardcoded path to the keystore on the filesystem, it works fine in Tomcat. I really want to load it using Classloader.

I also tried on Liberty profile with the same results.

Relevant part of the stack trace:

Caused by: java.io.IOException: Invalid keystore format
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:650)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:55)
at java.security.KeyStore.load(KeyStore.java:1445)

      

+3


source to share


1 answer


I found my problem ... my Maven filtering was corrupting the keystore. I need to add the following to pom.xml. Unfortunately I don't think the first time I had this problem. :(



pom.xml: <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*.xml</include> </includes> <excludes> <exclude>**/*.jks</exclude> </excludes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <includes> <include>**/*.jks</include> </includes> <excludes> <exclude>**/*.xml</exclude> </excludes> </resource> </resources>

+9


source







All Articles