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@8a6efdbf21
This commit is contained in:
jaymode 2014-12-11 12:48:55 -05:00
parent 9bfab4d8d5
commit 88162d142b
3 changed files with 33 additions and 12 deletions

View File

@ -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);

View File

@ -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();
}
}