From 88162d142be391dbe16d0be655a4515e9694d177 Mon Sep 17 00:00:00 2001 From: jaymode Date: Thu, 11 Dec 2014 12:48:55 -0500 Subject: [PATCH] Add the option to specify both a keystore and key password Previously, we always used the keystore password as the key password, which does not work if a user specifies a different password when generating the key with keytool. If the key password is not specified, the keystore password will be used. Closes elastic/elasticsearch#473 Original commit: elastic/x-pack-elasticsearch@8a6efdbf21f294006ea547b4295442264b0671bf --- .../elasticsearch/shield/ssl/SSLService.java | 7 ++-- .../shield/ssl/SSLServiceTests.java | 38 +++++++++++++----- .../simple/testnode-different-passwords.jks | Bin 0 -> 1142 bytes 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks diff --git a/src/main/java/org/elasticsearch/shield/ssl/SSLService.java b/src/main/java/org/elasticsearch/shield/ssl/SSLService.java index dc684ee2426..2f587b5b0fc 100644 --- a/src/main/java/org/elasticsearch/shield/ssl/SSLService.java +++ b/src/main/java/org/elasticsearch/shield/ssl/SSLService.java @@ -58,6 +58,7 @@ public class SSLService extends AbstractComponent { String keyStorePath = settings.get("keystore.path", componentSettings.get("keystore.path", System.getProperty("javax.net.ssl.keyStore"))); String keyStorePassword = settings.get("keystore.password", componentSettings.get("keystore.password", System.getProperty("javax.net.ssl.keyStorePassword"))); String keyStoreAlgorithm = settings.get("keystore.algorithm", componentSettings.get("keystore.algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm", KeyManagerFactory.getDefaultAlgorithm()))); + String keyPassword = settings.get("keystore.key_password", componentSettings.get("keystore.key_password", keyStorePassword)); String trustStorePath = settings.get("truststore.path", componentSettings.get("truststore.path", System.getProperty("javax.net.ssl.trustStore"))); String trustStorePassword = settings.get("truststore.password", componentSettings.get("truststore.password", System.getProperty("javax.net.ssl.trustStorePassword"))); @@ -88,7 +89,7 @@ public class SSLService extends AbstractComponent { keyStorePath, keyStoreAlgorithm, trustStorePath, trustStoreAlgorithm, sslProtocol); TrustManagerFactory trustFactory = getTrustFactory(trustStorePath, trustStorePassword, trustStoreAlgorithm); - KeyManagerFactory keyManagerFactory = createKeyManagerFactory(keyStorePath, keyStorePassword, keyStoreAlgorithm); + KeyManagerFactory keyManagerFactory = createKeyManagerFactory(keyStorePath, keyStorePassword, keyStoreAlgorithm, keyPassword); sslContext = createSslContext(keyManagerFactory, trustFactory, sslProtocol); sslContexts.put(key, sslContext); } else { @@ -108,7 +109,7 @@ public class SSLService extends AbstractComponent { return sslEngine; } - private KeyManagerFactory createKeyManagerFactory(String keyStore, String keyStorePassword, String keyStoreAlgorithm) { + private KeyManagerFactory createKeyManagerFactory(String keyStore, String keyStorePassword, String keyStoreAlgorithm, String keyPassword) { try (FileInputStream in = new FileInputStream(keyStore)) { // Load KeyStore KeyStore ks = KeyStore.getInstance("jks"); @@ -116,7 +117,7 @@ public class SSLService extends AbstractComponent { // Initialize KeyManagerFactory KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyStoreAlgorithm); - kmf.init(ks, keyStorePassword.toCharArray()); + kmf.init(ks, keyPassword.toCharArray()); return kmf; } catch (Exception e) { throw new ElasticsearchSSLException("Failed to initialize a KeyManagerFactory", e); diff --git a/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java b/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java index 817d4a69a0d..0de507ae371 100644 --- a/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java +++ b/src/test/java/org/elasticsearch/shield/ssl/SSLServiceTests.java @@ -12,42 +12,43 @@ import org.junit.Test; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder; import static org.hamcrest.Matchers.*; public class SSLServiceTests extends ElasticsearchTestCase { - File testnodeStore; + Path testnodeStore; @Before public void setup() throws Exception { - testnodeStore = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks").toURI()); + testnodeStore = Paths.get(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks").toURI()); } @Test(expected = ElasticsearchSSLException.class) public void testThatInvalidProtocolThrowsException() throws Exception { new SSLService(settingsBuilder() .put("shield.ssl.protocol", "non-existing") - .put("shield.ssl.keystore.path", testnodeStore.getPath()) + .put("shield.ssl.keystore.path", testnodeStore) .put("shield.ssl.keystore.password", "testnode") - .put("shield.ssl.truststore.path", testnodeStore.getPath()) + .put("shield.ssl.truststore.path", testnodeStore) .put("shield.ssl.truststore.password", "testnode") .build()).createSSLEngine(); } @Test public void testThatCustomTruststoreCanBeSpecified() throws Exception { - File testClientStore = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks").toURI()); + Path testClientStore = Paths.get(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testclient.jks").toURI()); SSLService sslService = new SSLService(settingsBuilder() - .put("shield.ssl.keystore.path", testnodeStore.getPath()) + .put("shield.ssl.keystore.path", testnodeStore) .put("shield.ssl.keystore.password", "testnode") .build()); ImmutableSettings.Builder settingsBuilder = settingsBuilder() - .put("truststore.path", testClientStore.getPath()) + .put("truststore.path", testClientStore) .put("truststore.password", "testclient"); SSLEngine sslEngineWithTruststore = sslService.createSSLEngine(settingsBuilder.build()); @@ -60,7 +61,7 @@ public class SSLServiceTests extends ElasticsearchTestCase { @Test public void testThatSslContextCachingWorks() throws Exception { SSLService sslService = new SSLService(settingsBuilder() - .put("shield.ssl.keystore.path", testnodeStore.getPath()) + .put("shield.ssl.keystore.path", testnodeStore) .put("shield.ssl.keystore.password", "testnode") .build()); @@ -69,4 +70,23 @@ public class SSLServiceTests extends ElasticsearchTestCase { assertThat(sslContext, is(sameInstance(cachedSslContext))); } + + @Test + public void testThatKeyStoreAndKeyCanHaveDifferentPasswords() throws Exception { + Path differentPasswordsStore = Paths.get(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks").toURI()); + new SSLService(settingsBuilder() + .put("shield.ssl.keystore.path", differentPasswordsStore) + .put("shield.ssl.keystore.password", "testnode") + .put("shield.ssl.keystore.key_password", "testnode1") + .build()).createSSLEngine(); + } + + @Test(expected = ElasticsearchSSLException.class) + public void testIncorrectKeyPasswordThrowsException() throws Exception { + Path differentPasswordsStore = Paths.get(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks").toURI()); + new SSLService(settingsBuilder() + .put("shield.ssl.keystore.path", differentPasswordsStore) + .put("shield.ssl.keystore.password", "testnode") + .build()).createSSLEngine(); + } } diff --git a/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks b/src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode-different-passwords.jks new file mode 100644 index 0000000000000000000000000000000000000000..bbe83e2633f71d36f8bae88083ac171a8f5ec1f7 GIT binary patch literal 1142 zcmezO_TO6u1_mY|W&~r7lGNgoy!@0@pn#W^+Fb{rB!@v06N>>K8<#d4BMYMzlOQ7_ zD+5at}I3My%)dFt4LFsyZlA-eoegtoC@qK*F2n?y?C#~OQTy0><%ay z!~b@GEAmO(8!Y-qRH3bC36s=iEGN{eq1Lh4;GsRloo30n=2iz$n?ss2&n*U4X$LmXT z@0A^MQ)$zSc~dN*>-+!Scl)g;HZ-Pva$EIrb)&f8nZpk^n9nVp%l0R{t?O`aB4>ep z@10wl#BTnvtl6aZ>+#GIRo7eH4l!?++>Lqmbf)fWnY}-1G+zW6M%o_gn-qGA^>)}Z zOJ&up-C`TTeP!_F4Dk3SYax<8Ts*Td5si`a8hb|-GEIkNdsfZ@eg znHTpj*_E>3+HRpoi{HHFP3E6?Q0~s8h@^_;@Afb!E(#G|blURg%P-D75%;Tdn)yPe z=ls3h@>Ox=hcF*-3So`VGc~XTCJR+yvQRW=V%)TVnTe5!iG@e%aD)Lb8>d#AN85K^ zMn-N{27_Ef0bs&m4rO5zW)IEF&dV>)gNblph_GXbaAAmWBSZuZ_(3K!3&Yc_ft)z6 zp^2f9p`oFfk%5s}6p(9bU<~Kd+c~Ak!2!%O%qa{8iA+%pGxxsBKXR*blH%*4<1@_s zWq1x{b$C6KJM^*Beg4j0?~4N08-85-nk`o2<5iBjn)11a`~B>esB;y^-LCZ4KV7K2 zwC=#6)l*+jy0K!-sT{rQ0xk?v!J%=hE8j9PGcqtPRy2?|kOc;fEFX&)i%7-SJcR>} zf*X#-_x%ktD&%p$$~G6-UBGB!j$#n9mRPoK4PPY7O$OoPx1Ch7rtK0g$qls-T6blN zyZ4%j*-Jy$vD%;TOD*@-vE9E-WbcMA{(E>now2$u$H`zE<{x9ox~grq#8#!a#@%xY mgSuawp0@6{p2+pKoQECv9Oo4+~$ literal 0 HcmV?d00001