SSL/TLS: Allow control of SSL per profile
SSL can now be enabled or disabled per profile. This allows to have both secured and unsecured client connections. Closes elastic/elasticsearch#612 Original commit: elastic/x-pack-elasticsearch@53a7efa5b1
This commit is contained in:
parent
2c55d85aa5
commit
c5028f7384
|
@ -66,7 +66,8 @@ public class NettySecuredTransport extends NettyTransport {
|
|||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = super.getPipeline();
|
||||
if (ssl) {
|
||||
boolean profileSsl = profileSettings.getAsBoolean("shield.ssl", ssl);
|
||||
if (profileSsl) {
|
||||
SSLEngine serverEngine;
|
||||
if (profileSettings.get("shield.truststore.path") != null) {
|
||||
serverEngine = sslService.createSSLEngine(profileSettings.getByPrefix("shield."));
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.transport.netty;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.netty.OpenChannelsHandler;
|
||||
import org.elasticsearch.common.netty.channel.ChannelPipelineFactory;
|
||||
import org.elasticsearch.common.netty.handler.ssl.SslHandler;
|
||||
import org.elasticsearch.common.network.NetworkService;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.netty.NettyTransport;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class NettySecuredTransportTests extends ElasticsearchTestCase {
|
||||
|
||||
private SSLService sslService;
|
||||
|
||||
@Before
|
||||
public void createSSLService() throws Exception {
|
||||
Path testnodeStore = Paths.get(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks").toURI());
|
||||
sslService = new SSLService(settingsBuilder()
|
||||
.put("shield.ssl.keystore.path", testnodeStore)
|
||||
.put("shield.ssl.keystore.password", "testnode")
|
||||
.build());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatSSLCanBeDisabledByProfile() throws Exception {
|
||||
Settings settings = ImmutableSettings.builder().put("shield.transport.ssl", true).build();
|
||||
NettySecuredTransport transport = new NettySecuredTransport(settings, mock(ThreadPool.class), mock(NetworkService.class), mock(BigArrays.class), Version.CURRENT, null, sslService);
|
||||
setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", ImmutableSettings.builder().put("shield.ssl", false).build());
|
||||
assertThat(factory.getPipeline().get(SslHandler.class), nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatSSLCanBeEnabledByProfile() throws Exception {
|
||||
Settings settings = ImmutableSettings.builder().put("shield.transport.ssl", false).build();
|
||||
NettySecuredTransport transport = new NettySecuredTransport(settings, mock(ThreadPool.class), mock(NetworkService.class), mock(BigArrays.class), Version.CURRENT, null, sslService);
|
||||
setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", ImmutableSettings.builder().put("shield.ssl", true).build());
|
||||
assertThat(factory.getPipeline().get(SslHandler.class), notNullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatProfileTakesDefaultSSLSetting() throws Exception {
|
||||
Settings settings = ImmutableSettings.builder().put("shield.transport.ssl", true).build();
|
||||
NettySecuredTransport transport = new NettySecuredTransport(settings, mock(ThreadPool.class), mock(NetworkService.class), mock(BigArrays.class), Version.CURRENT, null, sslService);
|
||||
setOpenChannelsHandlerToMock(transport);
|
||||
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", ImmutableSettings.EMPTY);
|
||||
assertThat(factory.getPipeline().get(SslHandler.class), notNullValue());
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't really need to start Netty for these tests, but we can't create a pipeline
|
||||
* with a null handler. So we set it to a mock for this test using reflection.
|
||||
*/
|
||||
private void setOpenChannelsHandlerToMock(NettyTransport transport) throws Exception {
|
||||
Field serverOpenChannels = NettyTransport.class.getDeclaredField("serverOpenChannels");
|
||||
serverOpenChannels.setAccessible(true);
|
||||
serverOpenChannels.set(transport, mock(OpenChannelsHandler.class));
|
||||
}
|
||||
}
|
|
@ -23,21 +23,26 @@ import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilde
|
|||
import static org.elasticsearch.shield.transport.support.TransportProfileUtil.getProfilePort;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
|
||||
import static org.elasticsearch.test.ShieldSettingsSource.DEFAULT_USER_NAME;
|
||||
import static org.elasticsearch.test.ShieldSettingsSource.DEFAULT_PASSWORD;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
@ClusterScope(scope = Scope.SUITE)
|
||||
public class SslMultiPortTests extends ShieldIntegrationTest {
|
||||
|
||||
private static int randomClientPort;
|
||||
private static int randomNonSslPort;
|
||||
|
||||
@BeforeClass
|
||||
public static void getRandomPort() {
|
||||
randomClientPort = randomIntBetween(49000, 65500); // ephemeral port
|
||||
randomNonSslPort = randomIntBetween(49000, 65500);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
String randomClientPortRange = randomClientPort + "-" + (randomClientPort+100);
|
||||
String randomNonSslPortRange = randomNonSslPort + "-" + (randomNonSslPort+100);
|
||||
|
||||
File store;
|
||||
try {
|
||||
|
@ -54,6 +59,9 @@ public class SslMultiPortTests extends ShieldIntegrationTest {
|
|||
.put("transport.profiles.client.bind_host", "localhost") // make sure this is "localhost", no matter if ipv4 or ipv6, but be consistent
|
||||
.put("transport.profiles.client.shield.truststore.path", store.getAbsolutePath()) // settings for client truststore
|
||||
.put("transport.profiles.client.shield.truststore.password", "testnode-client-profile")
|
||||
.put("transport.profiles.no_ssl.port", randomNonSslPortRange)
|
||||
.put("transport.profiles.no_ssl.bind_host", "localhost")
|
||||
.put("transport.profiles.no_ssl.shield.ssl", "false")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -102,4 +110,24 @@ public class SslMultiPortTests extends ShieldIntegrationTest {
|
|||
transportClient.admin().cluster().prepareHealth().get();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatTransportClientCanConnectToNoSslProfile() throws Exception {
|
||||
Settings settings = ImmutableSettings.builder()
|
||||
.put("shield.user", DEFAULT_USER_NAME + ":" + DEFAULT_PASSWORD)
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.build();
|
||||
try (TransportClient transportClient = new TransportClient(settings, false)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", getProfilePort("no_ssl", internalCluster())));
|
||||
assertGreenClusterState(transportClient);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = NoNodeAvailableException.class)
|
||||
public void testThatStandardTransportClientCannotConnectToNoSslProfile() throws Exception {
|
||||
try (TransportClient transportClient = createTransportClient(ImmutableSettings.EMPTY)) {
|
||||
transportClient.addTransportAddress(new InetSocketTransportAddress("localhost", getProfilePort("no_ssl", internalCluster())));
|
||||
assertGreenClusterState(transportClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue