Skip to content

Commit

Permalink
fixes #2033 update keystore loader to support both jks and pkcs12 (#2034
Browse files Browse the repository at this point in the history
)
  • Loading branch information
stevehu authored Dec 7, 2023
1 parent b21172b commit c7d3af1
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 31 deletions.
2 changes: 1 addition & 1 deletion client/src/main/java/com/networknt/client/Http2Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ public static SSLContext createSSLContext() throws IOException {
}
if(logger.isInfoEnabled()) logger.info("Loading trust store from config at " + Encode.forJava(trustStoreName));
if (trustStoreName != null && trustStorePass != null) {
KeyStore trustStore = TlsUtil.loadTrustStore(trustStoreName, trustStorePass.toCharArray());
KeyStore trustStore = TlsUtil.loadKeyStore(trustStoreName, trustStorePass.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManagers = trustManagerFactory.getTrustManagers();
Expand Down
52 changes: 30 additions & 22 deletions config/src/main/java/com/networknt/config/TlsUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,53 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;

public class TlsUtil {
static final Logger logger = LoggerFactory.getLogger(TlsUtil.class);

public static KeyStore loadKeyStore(final String name, final char[] password) {
try (InputStream stream = Config.getInstance().getInputStreamFromFile(name)) {
InputStream stream = null;
try {
stream = Config.getInstance().getInputStreamFromFile(name);
if (stream == null) {
String message = "Unable to load keystore '" + name + "', please provide the keystore matching the configuration in client.yml/server.yml to enable TLS connection.";
if (logger.isErrorEnabled()) {
logger.error(message);
}
throw new RuntimeException(message);
}
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(stream, password);
return loadedKeystore;
} catch (Exception e) {
logger.error("Unable to load keystore " + name, e);
throw new RuntimeException("Unable to load keystore " + name, e);
}
}

public static KeyStore loadTrustStore(final String name, final char[] password) {
try (InputStream stream = Config.getInstance().getInputStreamFromFile(name)) {
if (stream == null) {
String message = "Unable to load truststore '" + name + "', please provide the truststore matching the configuration in client.yml/server.yml to enable TLS connection.";
if (logger.isErrorEnabled()) {
logger.error(message);
// try to load keystore as JKS
try {
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(stream, password);
return loadedKeystore;
} catch (Exception e) {
// if JKS fails, attempt to load as PKCS12
try {
stream.close();
stream = Config.getInstance().getInputStreamFromFile(name);
KeyStore loadedKeystore = KeyStore.getInstance("PKCS12");
loadedKeystore.load(stream, password);
return loadedKeystore;
} catch (Exception e2) {
logger.error("Unable to load keystore " + name, e2);
throw new RuntimeException("Unable to load keystore " + name, e2);
}
throw new RuntimeException(message);
}
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(stream, password);
return loadedKeystore;
} catch (Exception e) {
logger.error("Unable to load truststore " + name, e);
throw new RuntimeException("Unable to load truststore " + name, e);
logger.error("Unable to load stream for keystore " + name, e);
throw new RuntimeException("Unable to load stream for keystore " + name, e);
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
logger.error("Unable to close stream for keystore " + name, e);
}
}
}
}
}
23 changes: 18 additions & 5 deletions config/src/test/java/com/networknt/config/TlsUtilTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,42 @@ public void testLoadInvalidKeyStore() {
KeyStore keyStore = TlsUtil.loadKeyStore(INVALID_KEYSTORE_NAME, PASSWORD);
fail();
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Unable to load keystore " + INVALID_KEYSTORE_NAME);
Assert.assertEquals(e.getMessage(), "Unable to load stream for keystore " + INVALID_KEYSTORE_NAME);
}
try {
KeyStore keyStore = TlsUtil.loadKeyStore(OTHER_EXTENTION, PASSWORD);
fail();
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Unable to load keystore " + OTHER_EXTENTION);
Assert.assertEquals(e.getMessage(), "Unable to load stream for keystore " + OTHER_EXTENTION);
}
}

@Test
public void testLoadTrustStore() {
KeyStore keyStore = TlsUtil.loadTrustStore(TRUSTSTORE_NAME, PASSWORD);
KeyStore keyStore = TlsUtil.loadKeyStore(TRUSTSTORE_NAME, PASSWORD);
Assert.assertNotNull(keyStore);
}

@Test
public void testLoadInvalidTrustStore() {
try {
KeyStore keyStore = TlsUtil.loadTrustStore(INVALID_TRUST_NAME, PASSWORD);
KeyStore keyStore = TlsUtil.loadKeyStore(INVALID_TRUST_NAME, PASSWORD);
fail();
} catch (Exception e) {
Assert.assertEquals(e.getMessage(), "Unable to load truststore " + INVALID_TRUST_NAME);
Assert.assertEquals(e.getMessage(), "Unable to load stream for keystore " + INVALID_TRUST_NAME);
}
}

@Test
public void testLoadPKCS12TrustStore() {
KeyStore keyStore = TlsUtil.loadKeyStore("clientpkcs12.truststore", PASSWORD);
Assert.assertNotNull(keyStore);
}

@Test
public void testLoadPKCS12KeyStore() {
KeyStore keyStore = TlsUtil.loadKeyStore("serverpkcs12.keystore", PASSWORD);
Assert.assertNotNull(keyStore);
}

}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ private SSLContext createSSLContext() throws IOException {
String trustStorePass = config.getKeyStorePass();
if(logger.isTraceEnabled()) logger.trace("trustStoreName = " + trustStoreName + " trustStorePass = " + (trustStorePass == null ? null : trustStorePass.substring(0, 4)));
if (trustStoreName != null && trustStorePass != null) {
KeyStore trustStore = TlsUtil.loadTrustStore(trustStoreName, trustStorePass.toCharArray());
KeyStore trustStore = TlsUtil.loadKeyStore(trustStoreName, trustStorePass.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManagers = trustManagerFactory.getTrustManagers();
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
<version.jsr305>3.0.2</version.jsr305>
<version.json-schema-validator>1.0.65</version.json-schema-validator>
<version.yaml-rule>1.0.2</version.yaml-rule>
<version.http-client>1.0.5</version.http-client>
<version.http-client>1.0.6</version.http-client>
<version.snakeyaml>2.2</version.snakeyaml>
<version.caffeine>3.1.5</version.caffeine>
<version.prometheus>0.16.0</version.prometheus>
Expand Down
2 changes: 1 addition & 1 deletion server/src/main/java/com/networknt/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ protected static KeyStore loadTrustStore() {
Map<String, Object> secretConfig = Config.getInstance().getJsonMapConfig(SECRET_CONFIG_NAME);
pass = (String) secretConfig.get(SecretConstants.SERVER_TRUSTSTORE_PASS);
}
return TlsUtil.loadTrustStore(name, pass.toCharArray());
return TlsUtil.loadKeyStore(name, pass.toCharArray());
}

private static TrustManager[] buildTrustManagers(final KeyStore trustStore) {
Expand Down

0 comments on commit c7d3af1

Please sign in to comment.