SSL/TLS: Properly test for client auth and allow to require
* Fixed issue, where client auth was never needed for HTTP. * Changed parameter name to `require.client.auth` * Added tests, removed useless code in SslIntegrationTests Original commit: elastic/x-pack-elasticsearch@ea424e0ae4
This commit is contained in:
parent
8e22ffa1fd
commit
ed959d684a
|
@ -30,19 +30,15 @@ public class SSLConfig {
|
||||||
private SSLContext sslContext;
|
private SSLContext sslContext;
|
||||||
private String[] ciphers;
|
private String[] ciphers;
|
||||||
|
|
||||||
public SSLConfig(Settings componentSettings) {
|
public SSLConfig(Settings componentSettings, Settings defaultSettings) {
|
||||||
this(componentSettings, ImmutableSettings.EMPTY);
|
this.clientAuth = componentSettings.getAsBoolean("require.client.auth", defaultSettings.getAsBoolean("require.client.auth", true));
|
||||||
}
|
String keyStore = componentSettings.get("keystore", defaultSettings.get("keystore", System.getProperty("javax.net.ssl.keyStore")));
|
||||||
|
String keyStorePassword = componentSettings.get("keystore_password", defaultSettings.get("keystore_password", System.getProperty("javax.net.ssl.keyStorePassword")));
|
||||||
public SSLConfig(Settings componentSettings, Settings settings) {
|
String keyStoreAlgorithm = componentSettings.get("keystore_algorithm", defaultSettings.get("keystore_algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm")));
|
||||||
this.clientAuth = componentSettings.getAsBoolean("client.auth", settings.getAsBoolean("shield.ssl.client.auth", true));
|
String trustStore = componentSettings.get("truststore", defaultSettings.get("truststore", System.getProperty("javax.net.ssl.trustStore")));
|
||||||
String keyStore = componentSettings.get("keystore", settings.get("shield.ssl.keystore", System.getProperty("javax.net.ssl.keyStore")));
|
String trustStorePassword = componentSettings.get("truststore_password", defaultSettings.get("truststore_password", System.getProperty("javax.net.ssl.trustStorePassword")));
|
||||||
String keyStorePassword = componentSettings.get("keystore_password", settings.get("shield.ssl.keystore_password", System.getProperty("javax.net.ssl.keyStorePassword")));
|
String trustStoreAlgorithm = componentSettings.get("truststore_algorithm", defaultSettings.get("truststore_algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm")));
|
||||||
String keyStoreAlgorithm = componentSettings.get("keystore_algorithm", settings.get("shield.ssl.keystore_algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm")));
|
this.ciphers = componentSettings.getAsArray("ciphers", defaultSettings.getAsArray("ciphers", DEFAULT_CIPHERS));
|
||||||
String trustStore = componentSettings.get("truststore", settings.get("shield.ssl.truststore", System.getProperty("javax.net.ssl.trustStore")));
|
|
||||||
String trustStorePassword = componentSettings.get("truststore_password", settings.get("shield.ssl.truststore_password", System.getProperty("javax.net.ssl.trustStorePassword")));
|
|
||||||
String trustStoreAlgorithm = componentSettings.get("truststore_algorithm", settings.get("shield.ssl.truststore_algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm")));
|
|
||||||
this.ciphers = componentSettings.getAsArray("ciphers", settings.getAsArray("shield.ssl.ciphers", DEFAULT_CIPHERS));
|
|
||||||
|
|
||||||
if (keyStore == null) {
|
if (keyStore == null) {
|
||||||
throw new ElasticsearchException("SSL Enabled, but keystore unconfigured");
|
throw new ElasticsearchException("SSL Enabled, but keystore unconfigured");
|
||||||
|
@ -101,7 +97,7 @@ public class SSLConfig {
|
||||||
|
|
||||||
// Initialize sslContext
|
// Initialize sslContext
|
||||||
try {
|
try {
|
||||||
String algorithm = componentSettings.get("context_algorithm", settings.get("shield.ssl.context_algorithm", "TLS"));
|
String algorithm = componentSettings.get("context_algorithm", defaultSettings.get("shield.ssl.context_algorithm", "TLS"));
|
||||||
sslContext = SSLContext.getInstance(algorithm);
|
sslContext = SSLContext.getInstance(algorithm);
|
||||||
sslContext.init(kmf.getKeyManagers(), trustManagers, null);
|
sslContext.init(kmf.getKeyManagers(), trustManagers, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.util.BigArrays;
|
||||||
import org.elasticsearch.http.netty.NettyHttpServerTransport;
|
import org.elasticsearch.http.netty.NettyHttpServerTransport;
|
||||||
import org.elasticsearch.shield.n2n.N2NNettyUpstreamHandler;
|
import org.elasticsearch.shield.n2n.N2NNettyUpstreamHandler;
|
||||||
import org.elasticsearch.shield.ssl.SSLConfig;
|
import org.elasticsearch.shield.ssl.SSLConfig;
|
||||||
|
import org.elasticsearch.transport.netty.NettyTransport;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ public class NettySSLHttpServerTransport extends NettyHttpServerTransport {
|
||||||
public HttpSslChannelPipelineFactory(NettyHttpServerTransport transport) {
|
public HttpSslChannelPipelineFactory(NettyHttpServerTransport transport) {
|
||||||
super(transport);
|
super(transport);
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
sslConfig = new SSLConfig(settings.getByPrefix("shield.http.ssl."));
|
sslConfig = new SSLConfig(settings.getByPrefix("shield.http.ssl."), settings.getByPrefix("shield.ssl."));
|
||||||
// try to create an SSL engine, so that exceptions lead to early exit
|
// try to create an SSL engine, so that exceptions lead to early exit
|
||||||
sslConfig.createSSLEngine();
|
sslConfig.createSSLEngine();
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,8 +62,6 @@ public class NettySSLHttpServerTransport extends NettyHttpServerTransport {
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
SSLEngine engine = sslConfig.createSSLEngine();
|
SSLEngine engine = sslConfig.createSSLEngine();
|
||||||
engine.setUseClientMode(false);
|
engine.setUseClientMode(false);
|
||||||
// TODO MAKE ME CONFIGURABLE
|
|
||||||
engine.setNeedClientAuth(false);
|
|
||||||
pipeline.addFirst("ssl", new SslHandler(engine));
|
pipeline.addFirst("ssl", new SslHandler(engine));
|
||||||
}
|
}
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class NettySSLTransport extends NettyTransport {
|
||||||
public SslServerChannelPipelineFactory(NettyTransport nettyTransport) {
|
public SslServerChannelPipelineFactory(NettyTransport nettyTransport) {
|
||||||
super(nettyTransport);
|
super(nettyTransport);
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
sslConfig = new SSLConfig(settings.getByPrefix("shield.transport.ssl."));
|
sslConfig = new SSLConfig(settings.getByPrefix("shield.transport.ssl."), settings.getByPrefix("shield.ssl."));
|
||||||
// try to create an SSL engine, so that exceptions lead to early exit
|
// try to create an SSL engine, so that exceptions lead to early exit
|
||||||
sslConfig.createSSLEngine();
|
sslConfig.createSSLEngine();
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,7 +83,7 @@ public class NettySSLTransport extends NettyTransport {
|
||||||
public SslClientChannelPipelineFactory(NettyTransport transport) {
|
public SslClientChannelPipelineFactory(NettyTransport transport) {
|
||||||
super(transport);
|
super(transport);
|
||||||
if (ssl) {
|
if (ssl) {
|
||||||
sslConfig = new SSLConfig(settings.getByPrefix("shield.transport.ssl."));
|
sslConfig = new SSLConfig(settings.getByPrefix("shield.transport.ssl."), settings.getByPrefix("shield.ssl."));
|
||||||
// try to create an SSL engine, so that exceptions lead to early exit
|
// try to create an SSL engine, so that exceptions lead to early exit
|
||||||
sslConfig.createSSLEngine();
|
sslConfig.createSSLEngine();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,11 +33,11 @@ public class SSLConfigTests extends ElasticsearchTestCase {
|
||||||
try {
|
try {
|
||||||
new SSLConfig(ImmutableSettings.EMPTY,
|
new SSLConfig(ImmutableSettings.EMPTY,
|
||||||
settingsBuilder()
|
settingsBuilder()
|
||||||
.put("shield.ssl.context_algorithm", "non-existing")
|
.put("context_algorithm", "non-existing")
|
||||||
.put("shield.ssl.keystore", testnodeStore.getPath())
|
.put("keystore", testnodeStore.getPath())
|
||||||
.put("shield.ssl.keystore_password", "testnode")
|
.put("keystore_password", "testnode")
|
||||||
.put("shield.ssl.truststore", testnodeStore.getPath())
|
.put("truststore", testnodeStore.getPath())
|
||||||
.put("shield.ssl.truststore_password", "testnode")
|
.put("truststore_password", "testnode")
|
||||||
.build());
|
.build());
|
||||||
} catch (ElasticsearchSSLException e) {
|
} catch (ElasticsearchSSLException e) {
|
||||||
assertThat(e.getRootCause(), instanceOf(NoSuchAlgorithmException.class));
|
assertThat(e.getRootCause(), instanceOf(NoSuchAlgorithmException.class));
|
||||||
|
@ -46,6 +46,7 @@ public class SSLConfigTests extends ElasticsearchTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testThatExactConfigOverwritesDefaultConfig() throws Exception {
|
public void testThatExactConfigOverwritesDefaultConfig() throws Exception {
|
||||||
|
//
|
||||||
Settings concreteSettings = settingsBuilder()
|
Settings concreteSettings = settingsBuilder()
|
||||||
.put("ciphers", "TLS_RSA_WITH_AES_128_CBC_SHA")
|
.put("ciphers", "TLS_RSA_WITH_AES_128_CBC_SHA")
|
||||||
.build();
|
.build();
|
||||||
|
@ -58,7 +59,7 @@ public class SSLConfigTests extends ElasticsearchTestCase {
|
||||||
.put("shield.ssl.truststore_password", "testnode")
|
.put("shield.ssl.truststore_password", "testnode")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
SSLConfig sslConfig = new SSLConfig(concreteSettings, genericSettings);
|
SSLConfig sslConfig = new SSLConfig(concreteSettings, genericSettings.getByPrefix("shield.ssl."));
|
||||||
SSLEngine sslEngine = sslConfig.createSSLEngine();
|
SSLEngine sslEngine = sslConfig.createSSLEngine();
|
||||||
assertThat(sslEngine.getEnabledCipherSuites().length, is(1));
|
assertThat(sslEngine.getEnabledCipherSuites().length, is(1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||||
import org.elasticsearch.transport.Transport;
|
import org.elasticsearch.transport.Transport;
|
||||||
import org.elasticsearch.transport.TransportModule;
|
import org.elasticsearch.transport.TransportModule;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -46,17 +47,15 @@ import static org.hamcrest.Matchers.*;
|
||||||
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, transportClientRatio = 0.0, numClientNodes = 0)
|
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, transportClientRatio = 0.0, numClientNodes = 0)
|
||||||
public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
||||||
|
|
||||||
private static File ipFilterFile = null;
|
@ClassRule
|
||||||
|
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||||
|
|
||||||
|
private static File ipFilterFile;
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void writeAllowAllIpFilterFile() {
|
public static void writeAllowAllIpFilterFile() throws Exception {
|
||||||
try {
|
ipFilterFile = temporaryFolder.newFile();
|
||||||
ipFilterFile = File.createTempFile("elasticsearch", "ipfilter");
|
|
||||||
ipFilterFile.deleteOnExit();
|
|
||||||
Files.write("allow: all\n".getBytes(com.google.common.base.Charsets.UTF_8), ipFilterFile);
|
Files.write("allow: all\n".getBytes(com.google.common.base.Charsets.UTF_8), ipFilterFile);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ElasticsearchException("error creating temp file", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -72,6 +71,8 @@ public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
||||||
return ImmutableSettings.settingsBuilder()
|
return ImmutableSettings.settingsBuilder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||||
|
//
|
||||||
|
.put("shield.authz.file.roles", "not/existing")
|
||||||
// needed to ensure that netty transport is started
|
// needed to ensure that netty transport is started
|
||||||
.put("node.mode", "network")
|
.put("node.mode", "network")
|
||||||
.put("shield.transport.ssl", true)
|
.put("shield.transport.ssl", true)
|
||||||
|
@ -80,6 +81,7 @@ public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
||||||
.put("shield.transport.ssl.truststore", testnodeStore.getPath())
|
.put("shield.transport.ssl.truststore", testnodeStore.getPath())
|
||||||
.put("shield.transport.ssl.truststore_password", "testnode")
|
.put("shield.transport.ssl.truststore_password", "testnode")
|
||||||
.put("shield.http.ssl", true)
|
.put("shield.http.ssl", true)
|
||||||
|
.put("shield.http.ssl.require.client.auth", false)
|
||||||
.put("shield.http.ssl.keystore", testnodeStore.getPath())
|
.put("shield.http.ssl.keystore", testnodeStore.getPath())
|
||||||
.put("shield.http.ssl.keystore_password", "testnode")
|
.put("shield.http.ssl.keystore_password", "testnode")
|
||||||
.put("shield.http.ssl.truststore", testnodeStore.getPath())
|
.put("shield.http.ssl.truststore", testnodeStore.getPath())
|
||||||
|
@ -92,16 +94,6 @@ public class SslIntegrationTests extends ElasticsearchIntegrationTest {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
System.setProperty("javax.net.debug", "all");
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void teardown() {
|
|
||||||
System.clearProperty("javax.net.debug");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestLogging("_root:INFO,org.elasticsearch.test:TRACE, org.elasticsearch.client.transport:DEBUG,org.elasticsearch.shield:TRACE")
|
@TestLogging("_root:INFO,org.elasticsearch.test:TRACE, org.elasticsearch.client.transport:DEBUG,org.elasticsearch.shield:TRACE")
|
||||||
public void testThatTransportClientCanConnectToNodeViaSsl() throws Exception {
|
public void testThatTransportClientCanConnectToNodeViaSsl() throws Exception {
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.shield.ssl;
|
||||||
|
|
||||||
|
import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.base.Charsets;
|
||||||
|
import com.google.common.io.Files;
|
||||||
|
import com.google.common.net.InetAddresses;
|
||||||
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.common.io.Streams;
|
||||||
|
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||||
|
import org.elasticsearch.common.transport.TransportAddress;
|
||||||
|
import org.elasticsearch.http.HttpServerTransport;
|
||||||
|
import org.elasticsearch.shield.plugin.SecurityPlugin;
|
||||||
|
import org.elasticsearch.shield.ssl.netty.NettySSLHttpServerTransportModule;
|
||||||
|
import org.elasticsearch.shield.ssl.netty.NettySSLTransportModule;
|
||||||
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
|
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||||
|
import org.elasticsearch.transport.TransportModule;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ElasticsearchIntegrationTest.ClusterScope(scope = ElasticsearchIntegrationTest.Scope.SUITE, numDataNodes = 1, transportClientRatio = 0.0, numClientNodes = 0)
|
||||||
|
public class SslRequireAuthTests extends ElasticsearchIntegrationTest {
|
||||||
|
|
||||||
|
public static final HostnameVerifier HOSTNAME_VERIFIER = new HostnameVerifier() {
|
||||||
|
@Override
|
||||||
|
public boolean verify(String s, SSLSession sslSession) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||||
|
|
||||||
|
private static File ipFilterFile;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void writeAllowAllIpFilterFile() throws Exception {
|
||||||
|
ipFilterFile = temporaryFolder.newFile();
|
||||||
|
Files.write("allow: all\n".getBytes(com.google.common.base.Charsets.UTF_8), ipFilterFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Settings nodeSettings(int nodeOrdinal) {
|
||||||
|
File testnodeStore;
|
||||||
|
try {
|
||||||
|
testnodeStore = new File(getClass().getResource("/certs/simple/testnode.jks").toURI());
|
||||||
|
assertThat(testnodeStore.exists(), is(true));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImmutableSettings.settingsBuilder()
|
||||||
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
|
.put("discovery.zen.ping.multicast.ping.enabled", false)
|
||||||
|
// prevents exception until parsing has been fixed in PR
|
||||||
|
.put("shield.authz.file.roles", "not/existing")
|
||||||
|
// needed to ensure that netty transport is started
|
||||||
|
.put("node.mode", "network")
|
||||||
|
.put("shield.transport.ssl", true)
|
||||||
|
.put("shield.transport.ssl.require.client.auth", true)
|
||||||
|
.put("shield.transport.ssl.keystore", testnodeStore.getPath())
|
||||||
|
.put("shield.transport.ssl.keystore_password", "testnode")
|
||||||
|
.put("shield.transport.ssl.truststore", testnodeStore.getPath())
|
||||||
|
.put("shield.transport.ssl.truststore_password", "testnode")
|
||||||
|
.put("shield.http.ssl", true)
|
||||||
|
.put("shield.http.ssl.require.client.auth", true)
|
||||||
|
.put("shield.http.ssl.keystore", testnodeStore.getPath())
|
||||||
|
.put("shield.http.ssl.keystore_password", "testnode")
|
||||||
|
.put("shield.http.ssl.truststore", testnodeStore.getPath())
|
||||||
|
.put("shield.http.ssl.truststore_password", "testnode")
|
||||||
|
// SSL SETUP
|
||||||
|
.put("http.type", NettySSLHttpServerTransportModule.class.getName())
|
||||||
|
.put(TransportModule.TRANSPORT_TYPE_KEY, NettySSLTransportModule.class.getName())
|
||||||
|
.put("plugin.types", SecurityPlugin.class.getName())
|
||||||
|
.put("shield.n2n.file", ipFilterFile.getPath())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test(expected = SSLHandshakeException.class)
|
||||||
|
public void testThatRequireClientAuthRejectsWithoutCert() throws Exception {
|
||||||
|
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||||
|
new X509TrustManager() {
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkClientTrusted(
|
||||||
|
java.security.cert.X509Certificate[] certs, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkServerTrusted(
|
||||||
|
java.security.cert.X509Certificate[] certs, String authType) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
setupTrustManagers(trustAllCerts);
|
||||||
|
|
||||||
|
TransportAddress transportAddress = internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddress();
|
||||||
|
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
|
||||||
|
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
|
||||||
|
String url = String.format(Locale.ROOT, "https://%s:%s/", InetAddresses.toUriString(inetSocketTransportAddress.address().getAddress()), inetSocketTransportAddress.address().getPort());
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
connection.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestLogging("_root:DEBUG")
|
||||||
|
public void testThatConnectionToHTTPWorks() throws Exception {
|
||||||
|
File store = new File(getClass().getResource("/certs/simple/testnode.jks").toURI());
|
||||||
|
|
||||||
|
KeyStore ks;
|
||||||
|
KeyManagerFactory kmf;
|
||||||
|
try (FileInputStream in = new FileInputStream(store)){
|
||||||
|
// Load KeyStore
|
||||||
|
ks = KeyStore.getInstance("jks");
|
||||||
|
ks.load(in, "testnode".toCharArray());
|
||||||
|
|
||||||
|
// Initialize KeyManagerFactory
|
||||||
|
kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||||
|
kmf.init(ks, "testnode".toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
TrustManagerFactory trustFactory;
|
||||||
|
try (FileInputStream in = new FileInputStream(store)) {
|
||||||
|
// Load TrustStore
|
||||||
|
ks.load(in, "testnode".toCharArray());
|
||||||
|
|
||||||
|
// Initialize a trust manager factory with the trusted store
|
||||||
|
trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
trustFactory.init(ks);
|
||||||
|
|
||||||
|
// Retrieve the trust managers from the factory
|
||||||
|
}
|
||||||
|
setupTrustManagers(kmf.getKeyManagers(), trustFactory.getTrustManagers());
|
||||||
|
|
||||||
|
TransportAddress transportAddress = internalCluster().getInstance(HttpServerTransport.class).boundAddress().boundAddress();
|
||||||
|
assertThat(transportAddress, is(instanceOf(InetSocketTransportAddress.class)));
|
||||||
|
InetSocketTransportAddress inetSocketTransportAddress = (InetSocketTransportAddress) transportAddress;
|
||||||
|
String url = String.format(Locale.ROOT, "https://%s:%s/", InetAddresses.toUriString(inetSocketTransportAddress.address().getAddress()), inetSocketTransportAddress.address().getPort());
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
connection.connect();
|
||||||
|
|
||||||
|
assertThat(connection.getResponseCode(), is(200));
|
||||||
|
String data = Streams.copyToString(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8));
|
||||||
|
assertThat(data, containsString("You Know, for Search"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTrustManagers(KeyManager[] keyManagers, TrustManager[] trustManagers) throws Exception {
|
||||||
|
SSLContext sc = SSLContext.getInstance("TLS");
|
||||||
|
sc.init(keyManagers, trustManagers, new SecureRandom());
|
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||||
|
// totally secure
|
||||||
|
HttpsURLConnection.setDefaultHostnameVerifier(HOSTNAME_VERIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupTrustManagers(TrustManager[] trustManagers) throws Exception {
|
||||||
|
setupTrustManagers(null, trustManagers);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue