diff --git a/src/main/java/org/opensearch/security/ssl/SslConfiguration.java b/src/main/java/org/opensearch/security/ssl/SslConfiguration.java index a9eda8c308..3b5633285c 100644 --- a/src/main/java/org/opensearch/security/ssl/SslConfiguration.java +++ b/src/main/java/org/opensearch/security/ssl/SslConfiguration.java @@ -17,11 +17,13 @@ import java.security.PrivilegedExceptionAction; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManagerFactory; +import javax.security.auth.x500.X500Principal; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -74,7 +76,10 @@ public KeyManagerFactory keyStoreFactory() { } public TrustManagerFactory trustStoreFactory() { - return trustStoreConfiguration.createTrustManagerFactory(sslParameters.shouldValidateNewCertDNs()); + return trustStoreConfiguration.createTrustManagerFactory( + sslParameters.shouldValidateNewCertDNs(), + keyStoreConfiguration.getIssuerDns() + ); } public SslParameters sslParameters() { @@ -84,10 +89,10 @@ public SslParameters sslParameters() { @SuppressWarnings("removal") SslContext buildServerSslContext(final boolean validateCertificates) { try { - return AccessController.doPrivileged( - (PrivilegedExceptionAction) () -> SslContextBuilder.forServer( - keyStoreConfiguration.createKeyManagerFactory(validateCertificates) - ) + return AccessController.doPrivileged((PrivilegedExceptionAction) () -> { + KeyManagerFactory kmFactory = keyStoreConfiguration.createKeyManagerFactory(validateCertificates); + Set issuerDns = keyStoreConfiguration.getIssuerDns(); + return SslContextBuilder.forServer(kmFactory) .sslProvider(sslParameters.provider()) .clientAuth(sslParameters.clientAuth()) .protocols(sslParameters.allowedProtocols().toArray(new String[0])) @@ -112,9 +117,9 @@ SslContext buildServerSslContext(final boolean validateCertificates) { ApplicationProtocolNames.HTTP_1_1 ) ) - .trustManager(trustStoreConfiguration.createTrustManagerFactory(validateCertificates)) - .build() - ); + .trustManager(trustStoreConfiguration.createTrustManagerFactory(validateCertificates, issuerDns)) + .build(); + }); } catch (PrivilegedActionException e) { throw new OpenSearchException("Failed to build server SSL context", e); } @@ -123,8 +128,10 @@ SslContext buildServerSslContext(final boolean validateCertificates) { @SuppressWarnings("removal") SslContext buildClientSslContext(final boolean validateCertificates) { try { - return AccessController.doPrivileged( - (PrivilegedExceptionAction) () -> SslContextBuilder.forClient() + return AccessController.doPrivileged((PrivilegedExceptionAction) () -> { + KeyManagerFactory kmFactory = keyStoreConfiguration.createKeyManagerFactory(validateCertificates); + Set issuerDns = keyStoreConfiguration.getIssuerDns(); + return SslContextBuilder.forClient() .sslProvider(sslParameters.provider()) .protocols(sslParameters.allowedProtocols()) .ciphers(sslParameters.allowedCiphers()) @@ -132,10 +139,10 @@ SslContext buildClientSslContext(final boolean validateCertificates) { .sessionCacheSize(0) .sessionTimeout(0) .sslProvider(sslParameters.provider()) - .keyManager(keyStoreConfiguration.createKeyManagerFactory(validateCertificates)) - .trustManager(trustStoreConfiguration.createTrustManagerFactory(validateCertificates)) - .build() - ); + .keyManager(kmFactory) + .trustManager(trustStoreConfiguration.createTrustManagerFactory(validateCertificates, issuerDns)) + .build(); + }); } catch (PrivilegedActionException e) { throw new OpenSearchException("Failed to build client SSL context", e); } diff --git a/src/main/java/org/opensearch/security/ssl/config/KeyStoreConfiguration.java b/src/main/java/org/opensearch/security/ssl/config/KeyStoreConfiguration.java index b1675f093a..cd6fca2a68 100644 --- a/src/main/java/org/opensearch/security/ssl/config/KeyStoreConfiguration.java +++ b/src/main/java/org/opensearch/security/ssl/config/KeyStoreConfiguration.java @@ -18,9 +18,12 @@ import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; import javax.net.ssl.KeyManagerFactory; +import javax.security.auth.x500.X500Principal; import com.google.common.collect.ImmutableList; @@ -41,6 +44,15 @@ default KeyManagerFactory createKeyManagerFactory(boolean validateCertificates) return buildKeyManagerFactory(keyStore.v1(), keyStore.v2()); } + default Set getIssuerDns() { + Set issuerDns = new HashSet<>(); + final List certificates = loadCertificates(); + for (Certificate certificate : certificates) { + issuerDns.add(certificate.x509Certificate().getIssuerX500Principal()); + } + return issuerDns; + } + default KeyManagerFactory buildKeyManagerFactory(final KeyStore keyStore, final char[] password) { try { final var keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); diff --git a/src/main/java/org/opensearch/security/ssl/config/KeyStoreUtils.java b/src/main/java/org/opensearch/security/ssl/config/KeyStoreUtils.java index 7c063bd312..a9df50c159 100644 --- a/src/main/java/org/opensearch/security/ssl/config/KeyStoreUtils.java +++ b/src/main/java/org/opensearch/security/ssl/config/KeyStoreUtils.java @@ -24,10 +24,16 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; import java.util.List; +import java.util.Set; import javax.crypto.NoSuchPaddingException; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLSessionContext; +import javax.security.auth.x500.X500Principal; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.opensearch.OpenSearchException; @@ -37,6 +43,8 @@ final class KeyStoreUtils { + private final static Logger log = LogManager.getLogger(KeyStoreUtils.class); + private final static class SecuritySslContext extends SslContext { private SecuritySslContext() {} @@ -141,15 +149,10 @@ public static void validateKeyStoreCertificates(final KeyStore keyStore) { final var a = aliases.nextElement(); if (keyStore.isCertificateEntry(a)) { final var c = (X509Certificate) keyStore.getCertificate(a); - if (c == null) { - throw new CertificateException("Alias " + a + " does not contain a certificate entry"); - } c.checkValidity(); - } else if (keyStore.isKeyEntry(a)) { - final var cc = keyStore.getCertificateChain(a); - if (cc == null) { - throw new CertificateException("Alias " + a + " does not contain a certificate chain"); - } + } + final var cc = keyStore.getCertificateChain(a); + if (cc != null) { for (final var c : cc) { ((X509Certificate) c).checkValidity(); } @@ -162,6 +165,48 @@ public static void validateKeyStoreCertificates(final KeyStore keyStore) { } } + // If dnsToCheck is present, this method will only validate the validate for certificates that match the dns in this list or + // up the chain + public static void validateKeyStoreCertificates(final KeyStore keyStore, Set dnsToCheck) { + try { + final var aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) { + final var a = aliases.nextElement(); + if (keyStore.isCertificateEntry(a)) { + final var c = (X509Certificate) keyStore.getCertificate(a); + if (dnsToCheck.contains(c.getSubjectX500Principal())) { + c.checkValidity(); + final var cc = keyStore.getCertificateChain(a); + if (cc != null) { + for (final var c1 : cc) { + ((X509Certificate) c1).checkValidity(); + } + } + } else { + log.info("Skipping validation for " + c.getSubjectX500Principal().getName()); + } + } else { + if (keyStore.isCertificateEntry(a)) { + final var c = (X509Certificate) keyStore.getCertificate(a); + c.checkValidity(); + } + final var cc = keyStore.getCertificateChain(a); + if (cc != null) { + if (Arrays.stream(cc).anyMatch(c -> dnsToCheck.contains(((X509Certificate) c).getSubjectX500Principal()))) { + for (final var c : cc) { + ((X509Certificate) c).checkValidity(); + } + } + } + } + } + } catch (KeyStoreException e) { + throw new OpenSearchException("Couldn't load keys store", e); + } catch (CertificateException e) { + throw new OpenSearchException("Invalid certificates", e); + } + } + public static KeyStore loadKeyStore(final Path path, final String type, final char[] password) { try { final var keyStore = KeyStore.getInstance(type); diff --git a/src/main/java/org/opensearch/security/ssl/config/TrustStoreConfiguration.java b/src/main/java/org/opensearch/security/ssl/config/TrustStoreConfiguration.java index 4965aa3216..62b4a707a7 100644 --- a/src/main/java/org/opensearch/security/ssl/config/TrustStoreConfiguration.java +++ b/src/main/java/org/opensearch/security/ssl/config/TrustStoreConfiguration.java @@ -19,9 +19,11 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.net.ssl.TrustManagerFactory; +import javax.security.auth.x500.X500Principal; import com.google.common.collect.ImmutableList; @@ -46,7 +48,7 @@ public KeyStore createTrustStore() { } @Override - public TrustManagerFactory createTrustManagerFactory(boolean validateCertificates) { + public TrustManagerFactory createTrustManagerFactory(boolean validateCertificates, Set issuerDns) { return null; } }; @@ -55,10 +57,10 @@ public TrustManagerFactory createTrustManagerFactory(boolean validateCertificate List loadCertificates(); - default TrustManagerFactory createTrustManagerFactory(boolean validateCertificates) { + default TrustManagerFactory createTrustManagerFactory(boolean validateCertificates, Set issuerDns) { final var trustStore = createTrustStore(); if (validateCertificates) { - KeyStoreUtils.validateKeyStoreCertificates(trustStore); + KeyStoreUtils.validateKeyStoreCertificates(trustStore, issuerDns); } return buildTrustManagerFactory(trustStore); } diff --git a/src/test/java/org/opensearch/security/ssl/SSLTest.java b/src/test/java/org/opensearch/security/ssl/SSLTest.java index 4b35bcefd6..a9e2a38601 100644 --- a/src/test/java/org/opensearch/security/ssl/SSLTest.java +++ b/src/test/java/org/opensearch/security/ssl/SSLTest.java @@ -129,6 +129,86 @@ public void testHttps() throws Exception { } + @Test + public void testHttpsWithTrustStoreContainingValidCertsNotInChain() throws Exception { + + final Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore_valid.jks") + ) + .build(); + + setupSslOnlyMode(settings); + + RestHelper rh = restHelper(); + rh.enableHTTPClientSSL = true; + rh.trustHTTPServerCertificate = true; + rh.sendAdminCertificate = true; + rh.keystore = "node-untspec5-keystore.p12"; + + String res = rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=true"); + Assert.assertTrue(res.contains("EMAILADDRESS=unt@tst.com")); + Assert.assertTrue(res.contains("local_certificates_list")); + Assert.assertFalse( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=false").contains("local_certificates_list") + ); + Assert.assertFalse(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("local_certificates_list")); + + res = rh.executeSimpleRequest("_nodes/settings?pretty"); + Assert.assertTrue(res.contains(clusterInfo.clustername)); + Assert.assertFalse(res.contains("\"opendistro_security\"")); + Assert.assertFalse(res.contains("keystore_filepath")); + // Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + + } + + @Test + public void testHttpsWithTrustStoreContainingInvalidCertsNotInChain() throws Exception { + + final Settings settings = Settings.builder() + .put(ConfigConstants.SECURITY_SSL_ONLY, true) + .put(SSLConfigConstants.SECURITY_SSL_HTTP_ENABLED, true) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_KEYSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/node-0-keystore.jks") + ) + .put( + SSLConfigConstants.SECURITY_SSL_HTTP_TRUSTSTORE_FILEPATH, + FileHelper.getAbsoluteFilePathFromClassPath("ssl/truststore_invalid.jks") + ) + .build(); + + setupSslOnlyMode(settings); + + RestHelper rh = restHelper(); + rh.enableHTTPClientSSL = true; + rh.trustHTTPServerCertificate = true; + rh.sendAdminCertificate = true; + rh.keystore = "node-untspec5-keystore.p12"; + + String res = rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=true"); + Assert.assertTrue(res.contains("EMAILADDRESS=unt@tst.com")); + Assert.assertTrue(res.contains("local_certificates_list")); + Assert.assertFalse( + rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty&show_dn=false").contains("local_certificates_list") + ); + Assert.assertFalse(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("local_certificates_list")); + + res = rh.executeSimpleRequest("_nodes/settings?pretty"); + Assert.assertTrue(res.contains(clusterInfo.clustername)); + Assert.assertFalse(res.contains("\"opendistro_security\"")); + Assert.assertFalse(res.contains("keystore_filepath")); + // Assert.assertTrue(rh.executeSimpleRequest("_opendistro/_security/sslinfo?pretty").contains("CN=node-0.example.com,OU=SSL,O=Test,L=Test,C=DE")); + + } + @Test public void testCipherAndProtocols() throws Exception { diff --git a/src/test/java/org/opensearch/security/ssl/config/SslCertificatesLoaderTest.java b/src/test/java/org/opensearch/security/ssl/config/SslCertificatesLoaderTest.java index 0dfc02b386..6d2ff96fec 100644 --- a/src/test/java/org/opensearch/security/ssl/config/SslCertificatesLoaderTest.java +++ b/src/test/java/org/opensearch/security/ssl/config/SslCertificatesLoaderTest.java @@ -13,6 +13,7 @@ import java.nio.file.Path; import java.util.List; +import java.util.Set; import com.carrotsearch.randomizedtesting.RandomizedTest; import org.junit.ClassRule; @@ -49,7 +50,7 @@ void assertTrustStoreConfiguration( assertThat("Truststore configuration created", nonNull(trustStoreConfiguration)); assertThat(trustStoreConfiguration.file(), is(expectedFile)); assertThat(trustStoreConfiguration.loadCertificates(), containsInAnyOrder(expectedCertificates)); - assertThat(trustStoreConfiguration.createTrustManagerFactory(true), is(notNullValue())); + assertThat(trustStoreConfiguration.createTrustManagerFactory(true, Set.of()), is(notNullValue())); } void assertKeyStoreConfiguration( diff --git a/src/test/resources/ssl/root-ca-invalid.pem b/src/test/resources/ssl/root-ca-invalid.pem new file mode 100644 index 0000000000..787818188d --- /dev/null +++ b/src/test/resources/ssl/root-ca-invalid.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE2DCCA8CgAwIBAgIUI6tTo8QuZUoMod2uJWb587o/WSQwDQYJKoZIhvcNAQEL +BQAwgZUxEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSQwIgYDVQQLDBtFeGFtcGxl +IENvbSBJbmMuIEludmFsaWQgQ0ExJDAiBgNVBAMMG0V4YW1wbGUgQ29tIEluYy4g +SW52YWxpZCBDQTAeFw0yNTA0MDgxOTAwMzNaFw0yNTA0MDkxOTAwMzNaMIGVMRMw +EQYKCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcG +A1UECgwQRXhhbXBsZSBDb20gSW5jLjEkMCIGA1UECwwbRXhhbXBsZSBDb20gSW5j +LiBJbnZhbGlkIENBMSQwIgYDVQQDDBtFeGFtcGxlIENvbSBJbmMuIEludmFsaWQg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmFZGps52e1aA0bmAo +Gy8cIT5ZbqZlBK9jEAXj8m4snFPpS87MtEN5vDA3OLsB44tt3mRLKc/GkvG4v4yl +MDILNSarVWME53fGzoyc0i0gd/VZxPwxR0e+LphnmCbec44GzfN3dOxCdqZ3AnZA +9JCsogf36omgb6hYXsi6FsPkB0YxnUHviiYVtxPcV/Q11cGLq55kwm5INSnGuUxX +NEz0RRj9Hm+4PEGnGBRyWOuAAxQYeexXGHpXDy2II8X7uyCb1gbd3zI+hlM9hgeA +bMUaR4P42INB6SJkk/nzHg+g3ssZ+N3ZFN9QxDCG+v+LA6p6oRNL1J6iICkN6vfi +ZuVdAgMBAAGjggEcMIIBGDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQUA+uQ1+AW5h2XztdP2wbwhix8XWgwgdUGA1UdIwSBzTCByoAU +A+uQ1+AW5h2XztdP2wbwhix8XWihgZukgZgwgZUxEzARBgoJkiaJk/IsZAEZFgNj +b20xFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENv +bSBJbmMuMSQwIgYDVQQLDBtFeGFtcGxlIENvbSBJbmMuIEludmFsaWQgQ0ExJDAi +BgNVBAMMG0V4YW1wbGUgQ29tIEluYy4gSW52YWxpZCBDQYIUI6tTo8QuZUoMod2u +JWb587o/WSQwDQYJKoZIhvcNAQELBQADggEBAIxYxDaCwhovQmvSkK/E8BqwSuG5 +yKbfo5BHYlhNbhmBzOvXkoF9jka2TqKRZceWCq4MTztKLQrjpm3jnKAGxNnhTXqL +/edEE3RJ13EuzJyk13Chem8asgoZlXwjJwSFqWJS30P75HTuVwFwMFNLLtbCGvKb +oobDQMM6lHtlnvagUrAQG9sT0wPO43sfRzEabWs2CvMnbMZpJ7mn7zDmiIU1z+ub +rXCG2eSDILaFB0FACkRRdpm0SStF2ftPua3HSKKGh99TjGECxmpcQoO0kKp+fsdA +SdyR6KGYHKFRftw0eMZ6RsOwF1BhGq8nT3UlEJTpaBJSAkzzgbMeUFkLRGk= +-----END CERTIFICATE----- diff --git a/src/test/resources/ssl/root-ca-other.pem b/src/test/resources/ssl/root-ca-other.pem new file mode 100644 index 0000000000..596d8461e1 --- /dev/null +++ b/src/test/resources/ssl/root-ca-other.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEzDCCA7SgAwIBAgIUBVbjdAIYKfChQdrfXZpAIyNs2mswDQYJKoZIhvcNAQEL +BQAwgZExEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSIwIAYDVQQLDBlFeGFtcGxl +IENvbSBJbmMuIE90aGVyIENBMSIwIAYDVQQDDBlFeGFtcGxlIENvbSBJbmMuIE90 +aGVyIENBMB4XDTI1MDQwODE4NTQwM1oXDTM1MDQwNjE4NTQwM1owgZExEzARBgoJ +kiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMRkwFwYDVQQK +DBBFeGFtcGxlIENvbSBJbmMuMSIwIAYDVQQLDBlFeGFtcGxlIENvbSBJbmMuIE90 +aGVyIENBMSIwIAYDVQQDDBlFeGFtcGxlIENvbSBJbmMuIE90aGVyIENBMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtX0FZtu9rARzLJ3Ql8ugU64yALps +mhD9j5CnvuNLAmeTqEsTXS/9mqH43OCTFyF1fqXrSXlk0W/JAWMhXZZswsPkYZoj +zUoZNT+e8OXlqMPik00EKhdnH2CdSSDBBgLfpcOfMDYoLLRWiz7RnajHKRsRSnKl +5YDrbQqMOOtOX7ImzRNwFJ8DNh1OUzY/Id3cjosH57clxRyJ3U+q88+UDejeT8JT +7hOtzAqufgIqvungpZt+BtqeIeZonxoUyDifp1i/mC+2sLxx3//cmP7wLCzMM3Eq +tBp8F3DsgfvsMAD/yYPTCIdX75/aWbSywrRwxA27UZaASrEkQx+6uaQa4wIDAQAB +o4IBGDCCARQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0O +BBYEFO8uD2PZZw/PpBp1JxW9KlO1cXAHMIHRBgNVHSMEgckwgcaAFO8uD2PZZw/P +pBp1JxW9KlO1cXAHoYGXpIGUMIGRMRMwEQYKCZImiZPyLGQBGRYDY29tMRcwFQYK +CZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBsZSBDb20gSW5jLjEi +MCAGA1UECwwZRXhhbXBsZSBDb20gSW5jLiBPdGhlciBDQTEiMCAGA1UEAwwZRXhh +bXBsZSBDb20gSW5jLiBPdGhlciBDQYIUBVbjdAIYKfChQdrfXZpAIyNs2mswDQYJ +KoZIhvcNAQELBQADggEBAHNxdIYNhLV5EdRGTV//yzfemsgCHU1DUnHKMn4TtSYe +nYFL8rmX1tkOpzRI6/mrzE4IBsaEidAjbwYMWrn3rDHCkoHc6XTqr8WCW7y1KruJ +5MVlNLdPDDQuuP+loWzDao9qdzPqQwp9ue44o9prikvyAUmWZBEbNLxarrgjiPUn +VLli1agzG3kXIS0oWL+ZcwIzS+rQ6Ma5jTuCR7ljxEtobVrSioxfJQ9bZNKwAdd6 +fv7XqZ0T2Fz4x+gRs22M9Uu1dzkX4waRfA/JfIOVYR91Lz0Iw6HIn9V8bHZliI6E +wgxliW2yzFUt1FZDO7PCZPGuxF0g7WK6fva3AqokK+Y= +-----END CERTIFICATE----- diff --git a/src/test/resources/ssl/truststore_invalid.jks b/src/test/resources/ssl/truststore_invalid.jks new file mode 100644 index 0000000000..19b1f9e22c Binary files /dev/null and b/src/test/resources/ssl/truststore_invalid.jks differ diff --git a/src/test/resources/ssl/truststore_valid.jks b/src/test/resources/ssl/truststore_valid.jks new file mode 100644 index 0000000000..2ed07010e8 Binary files /dev/null and b/src/test/resources/ssl/truststore_valid.jks differ