Skip to content

Commit

Permalink
Adding test coverage for property driven ssl
Browse files Browse the repository at this point in the history
  • Loading branch information
scottf committed Jul 24, 2023
1 parent 9b6b86a commit cf5b313
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 114 deletions.
20 changes: 6 additions & 14 deletions src/main/java/io/nats/client/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -396,19 +396,19 @@ public class Options {
/**
* Property for the keystore path used to create an SSLContext
*/
public static final String PROP_KEYSTORE_PATH = PFX + "keystore.path";
public static final String PROP_KEYSTORE_PATH = PFX + "keyStore";
/**
* Property for the truststore path used to create an SSLContext
*/
public static final String PROP_TRUSTSTORE_PATH = PFX + "truststore.path";
public static final String PROP_TRUSTSTORE_PATH = PFX + "trustStore";
/**
* Property for the keystore password used to create an SSLContext
*/
public static final String PROP_KEYSTORE_PASSWORD = PFX + "keystore.password";
public static final String PROP_KEYSTORE_PASSWORD = PFX + "keyStorePassword";
/**
* Property for the truststore password used to create an SSLContext
*/
public static final String PROP_TRUSTSTORE_PASSWORD = PFX + "truststore.password";
public static final String PROP_TRUSTSTORE_PASSWORD = PFX + "trustStorePassword";
/**
* Property for the algorithm used to create an SSLContext
*/
Expand Down Expand Up @@ -715,8 +715,8 @@ public Builder(Properties props) throws IllegalArgumentException {

stringProperty(props, PROP_CREDENTIAL_PATH, s -> this.credentialPath = s);
stringProperty(props, PROP_KEYSTORE_PATH, s -> this.keystorePath = s);
stringProperty(props, PROP_TRUSTSTORE_PATH, s -> this.truststorePath = s);
charArrayProperty(props, PROP_KEYSTORE_PASSWORD, ca -> this.keystorePassword = ca);
stringProperty(props, PROP_TRUSTSTORE_PATH, s -> this.truststorePath = s);
charArrayProperty(props, PROP_TRUSTSTORE_PASSWORD, ca -> this.truststorePassword = ca);
stringProperty(props, PROP_TLS_ALGORITHM, s -> this.tlsAlgorithm = s);

Expand Down Expand Up @@ -1450,14 +1450,6 @@ public Options build() throws IllegalStateException {
inboxPrefix = DEFAULT_INBOX_PREFIX;
}

// sslContext
// private boolean useDefaultTls;
// private boolean useTrustAllTls;
// private String keystorePath;
// private String truststorePath;
// private String keystorePassword;
// private String truststorePassword;

boolean checkUrisForSecure = true;
if (natsServerUris.size() == 0) {
server(DEFAULT_URL);
Expand All @@ -1477,7 +1469,7 @@ public Options build() throws IllegalStateException {
if (sslContext == null) {
// if we haven't been told to use the default or the trust all context
// and the server isn't the default url, check to see if the server uris
// suggest we need an ssl context.
// suggest we need the ssl context.
if (!useDefaultTls && !useTrustAllTls && checkUrisForSecure) {
for (int i = 0; sslContext == null && i < natsServerUris.size(); i++) {
NatsUri natsUri = natsServerUris.get(i);
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/io/nats/client/support/SSLUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
public class SSLUtils {

public static final String DEFAULT_TLS_ALGORITHM = "SunX509";
public static final String KEYSTORE_TYPE = "JKS";
public static final String DEFAULT_KEYSTORE_TYPE = "JKS";

private static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
Expand Down Expand Up @@ -57,27 +57,38 @@ public static SSLContext createTrustAllTlsContext() throws GeneralSecurityExcept
}

public static KeyStore loadKeystore(String keystorePath, char[] keystorePwd) throws GeneralSecurityException, IOException {
final KeyStore store = KeyStore.getInstance(KEYSTORE_TYPE);
final KeyStore store = KeyStore.getInstance(DEFAULT_KEYSTORE_TYPE);
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(Paths.get(keystorePath)))) {
store.load(in, keystorePwd);
}
return store;
}

public static KeyManager[] createKeyManagers(String keystorePath, char[] keystorePwd) throws GeneralSecurityException, IOException {
return createKeyManagers(keystorePath, keystorePwd, DEFAULT_TLS_ALGORITHM);
}

public static KeyManager[] createKeyManagers(String keystorePath, char[] keystorePwd, String tlsAlgo) throws GeneralSecurityException, IOException {
KeyStore store = loadKeystore(keystorePath, keystorePwd);
KeyManagerFactory factory = KeyManagerFactory.getInstance(tlsAlgo);
factory.init(store, keystorePwd);
return factory.getKeyManagers();
}

public static TrustManager[] createTrustManagers(String truststorePath, char[] truststorePwd) throws GeneralSecurityException, IOException {
return createTrustManagers(truststorePath, truststorePwd, DEFAULT_TLS_ALGORITHM);
}

public static TrustManager[] createTrustManagers(String truststorePath, char[] truststorePwd, String tlsAlgo) throws GeneralSecurityException, IOException {
KeyStore store = loadKeystore(truststorePath, truststorePwd);
TrustManagerFactory factory = TrustManagerFactory.getInstance(tlsAlgo);
factory.init(store);
return factory.getTrustManagers();
}

public static SSLContext createSSLContext(String keystorePath, char[] keystorePwd, String truststorePath, char[] truststorePwd) throws GeneralSecurityException, IOException {
return createSSLContext(keystorePath, keystorePwd, truststorePath, truststorePwd, DEFAULT_TLS_ALGORITHM);
}
public static SSLContext createSSLContext(String keystorePath, char[] keystorePwd, String truststorePath, char[] truststorePwd, String tlsAlgo) throws GeneralSecurityException, IOException {
SSLContext ctx = SSLContext.getInstance(Options.DEFAULT_SSL_PROTOCOL);
ctx.init(createKeyManagers(keystorePath, keystorePwd, tlsAlgo), createTrustManagers(truststorePath, truststorePwd, tlsAlgo), SRAND);
Expand Down
15 changes: 15 additions & 0 deletions src/test/java/io/nats/client/OptionsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,21 @@ public void testPropertiesCoverageOptions() throws Exception {
_testPropertiesCoverageOptions(o);
_testPropertiesCoverageOptions(new Options.Builder(o).build());

props = new Properties();
props.setProperty(Options.PROP_SECURE, "false");
props.setProperty(Options.PROP_OPENTLS, "false");
props.setProperty(Options.PROP_NO_HEADERS, "true");
props.setProperty(Options.PROP_NO_NORESPONDERS, "true");
props.setProperty(Options.PROP_RECONNECT_JITTER, "1000");
props.setProperty(Options.PROP_RECONNECT_JITTER_TLS, "2000");
props.setProperty(Options.PROP_IGNORE_DISCOVERED_SERVERS_PREFERRED, "true");
props.setProperty(Options.PROP_SERVERS_POOL_IMPLEMENTATION_CLASS_PREFERRED, "io.nats.client.utils.CoverageServerPool");
props.setProperty(Options.PROP_NO_RESOLVE_HOSTNAMES, "true");

o = new Options.Builder(props).build();
_testPropertiesCoverageOptions(o);
_testPropertiesCoverageOptions(new Options.Builder(o).build());

props = new Properties();
props.load(ResourceUtils.resourceAsInputStream("options_coverage_with_prefix.properties"));
o = new Options.Builder(props).build();
Expand Down
55 changes: 21 additions & 34 deletions src/test/java/io/nats/client/TestSSLUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,64 +13,51 @@

package io.nats.client;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import io.nats.client.support.SSLUtils;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Properties;

public class TestSSLUtils {
public static String KEYSTORE_PATH = "src/test/resources/keystore.jks";
public static String TRUSTSTORE_PATH = "src/test/resources/truststore.jks";
public static String STORE_PASSWORD = "password";
public static String KEY_PASSWORD = "password";
public static String ALGORITHM = "SunX509";
public static String PASSWORD = "password";
public static char[] PASSWORD_CHARS = PASSWORD.toCharArray();

public static KeyStore loadKeystore(String path) throws Exception {
KeyStore store = KeyStore.getInstance("JKS");
BufferedInputStream in = new BufferedInputStream(new FileInputStream(path));

try {
store.load(in, STORE_PASSWORD.toCharArray());
} finally {
if (in != null) {
in.close();
}
}
return SSLUtils.loadKeystore(path, PASSWORD_CHARS);
}

return store;
public static Properties createTestSSLProperties() {
Properties props = new Properties();
props.setProperty(Options.PROP_KEYSTORE_PATH, TestSSLUtils.KEYSTORE_PATH);
props.setProperty(Options.PROP_KEYSTORE_PASSWORD, TestSSLUtils.PASSWORD);
props.setProperty(Options.PROP_TRUSTSTORE_PATH, TestSSLUtils.KEYSTORE_PATH);
props.setProperty(Options.PROP_TRUSTSTORE_PASSWORD, TestSSLUtils.PASSWORD);
return props;
}

public static void setKeystoreSystemParameters() {
System.setProperty("javax.net.ssl.keyStore",KEYSTORE_PATH);
System.setProperty("javax.net.ssl.keyStorePassword",KEY_PASSWORD);
System.setProperty("javax.net.ssl.keyStore", KEYSTORE_PATH);
System.setProperty("javax.net.ssl.keyStorePassword", PASSWORD);
System.setProperty("javax.net.ssl.trustStore",TRUSTSTORE_PATH);
System.setProperty("javax.net.ssl.trustStorePassword",STORE_PASSWORD);
System.setProperty("javax.net.ssl.trustStorePassword", PASSWORD);
}

public static KeyManager[] createTestKeyManagers() throws Exception {
KeyStore store = loadKeystore(KEYSTORE_PATH);
KeyManagerFactory factory = KeyManagerFactory.getInstance(ALGORITHM);
factory.init(store, KEY_PASSWORD.toCharArray());
return factory.getKeyManagers();
return SSLUtils.createKeyManagers(KEYSTORE_PATH, PASSWORD_CHARS);
}

public static TrustManager[] createTestTrustManagers() throws Exception {
KeyStore store = loadKeystore(TRUSTSTORE_PATH);
TrustManagerFactory factory = TrustManagerFactory.getInstance(ALGORITHM);
factory.init(store);
return factory.getTrustManagers();
return SSLUtils.createTrustManagers(TRUSTSTORE_PATH, PASSWORD_CHARS);
}

public static SSLContext createTestSSLContext() throws Exception {
SSLContext ctx = SSLContext.getInstance(Options.DEFAULT_SSL_PROTOCOL);
ctx.init(createTestKeyManagers(), createTestTrustManagers(), new SecureRandom());
return ctx;
return SSLUtils.createSSLContext(KEYSTORE_PATH, PASSWORD_CHARS, TRUSTSTORE_PATH, PASSWORD_CHARS);
}

public static SSLContext createEmptySSLContext() throws Exception {
Expand Down
Loading

0 comments on commit cf5b313

Please sign in to comment.