Make security tests transport agnostic (#39411)

Currently there are two security tests that specifically target the
netty security transport. This PR moves the client authentication tests
into `AbstractSimpleSecurityTransportTestCase` so that the nio transport
will also be tested.

Additionally the work to build transport configurations is moved out of
the netty transport and tested independently.
This commit is contained in:
Tim Brooks 2019-02-26 18:54:38 -07:00
parent 30687cbe7f
commit f24dae302d
No known key found for this signature in database
GPG Key ID: C2AA3BB91A889E77
10 changed files with 272 additions and 292 deletions

View File

@ -1113,6 +1113,10 @@ public abstract class TcpTransport extends AbstractLifecycleComponent implements
return handshaker.getNumHandshakes();
}
final Set<TcpChannel> getAcceptedChannels() {
return Collections.unmodifiableSet(acceptedChannels);
}
/**
* Ensures this transport is still started / open
*

View File

@ -29,6 +29,7 @@ import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListenerResponseHandler;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
@ -38,6 +39,7 @@ import org.elasticsearch.common.network.CloseableChannel;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
@ -105,10 +107,10 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
private static final Version CURRENT_VERSION = Version.fromString(String.valueOf(Version.CURRENT.major) + ".0.0");
protected static final Version version0 = CURRENT_VERSION.minimumCompatibilityVersion();
private ClusterSettings clusterSettings;
protected volatile DiscoveryNode nodeA;
protected volatile MockTransportService serviceA;
protected ClusterSettings clusterSettingsA;
protected static final Version version1 = Version.fromId(CURRENT_VERSION.id + 1);
protected volatile DiscoveryNode nodeB;
@ -121,12 +123,16 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
return 6;
}
protected Set<Setting<?>> getSupportedSettings() {
return ClusterSettings.BUILT_IN_CLUSTER_SETTINGS;
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
threadPool = new TestThreadPool(getClass().getName());
clusterSettings = new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
clusterSettingsA = new ClusterSettings(Settings.EMPTY, getSupportedSettings());
Settings connectionSettings = Settings.builder()
.put(TransportSettings.CONNECTIONS_PER_NODE_RECOVERY.getKey(), 1)
.put(TransportSettings.CONNECTIONS_PER_NODE_BULK.getKey(), 1)
@ -135,7 +141,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
.put(TransportSettings.CONNECTIONS_PER_NODE_PING.getKey(), 1)
.build();
serviceA = buildService("TS_A", version0, clusterSettings, connectionSettings); // this one supports dynamic tracer updates
serviceA = buildService("TS_A", version0, clusterSettingsA, connectionSettings); // this one supports dynamic tracer updates
nodeA = serviceA.getLocalNode();
serviceB = buildService("TS_B", version1, null, connectionSettings); // this one doesn't support dynamic tracer updates
nodeB = serviceB.getLocalNode();
@ -166,25 +172,24 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
serviceB.removeConnectionListener(waitForConnection);
}
private MockTransportService buildService(final String name, final Version version, ClusterSettings clusterSettings,
private MockTransportService buildService(final String name, final Version version, @Nullable ClusterSettings clusterSettings,
Settings settings, boolean acceptRequests, boolean doHandshake) {
MockTransportService service = build(
Settings.builder()
.put(settings)
.put(Node.NODE_NAME_SETTING.getKey(), name)
.put(TransportSettings.TRACE_LOG_INCLUDE_SETTING.getKey(), "")
.put(TransportSettings.TRACE_LOG_EXCLUDE_SETTING.getKey(), "NOTHING")
.build(),
version,
clusterSettings, doHandshake);
Settings updatedSettings = Settings.builder()
.put(settings)
.put(Node.NODE_NAME_SETTING.getKey(), name)
.build();
if (clusterSettings == null) {
clusterSettings = new ClusterSettings(updatedSettings, getSupportedSettings());
}
MockTransportService service = build(updatedSettings, version, clusterSettings, doHandshake);
if (acceptRequests) {
service.acceptIncomingRequests();
}
return service;
}
protected MockTransportService buildService(final String name, final Version version, ClusterSettings clusterSettings) {
return buildService(name, version, clusterSettings, Settings.EMPTY);
protected MockTransportService buildService(final String name, final Version version, Settings settings) {
return buildService(name, version, null, settings);
}
protected MockTransportService buildService(final String name, final Version version, ClusterSettings clusterSettings,
@ -500,7 +505,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testVoidMessageCompressed() {
try (MockTransportService serviceC = build(Settings.EMPTY, CURRENT_VERSION, null, true)) {
try (MockTransportService serviceC = buildService("TS_C", CURRENT_VERSION, Settings.EMPTY)) {
serviceC.start();
serviceC.acceptIncomingRequests();
@ -553,7 +558,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testHelloWorldCompressed() throws IOException {
try (MockTransportService serviceC = build(Settings.EMPTY, CURRENT_VERSION, null, true)) {
try (MockTransportService serviceC = buildService("TS_C", CURRENT_VERSION, Settings.EMPTY)) {
serviceC.start();
serviceC.acceptIncomingRequests();
@ -767,7 +772,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
if (i % 3 == 0) {
// simulate restart of nodeB
serviceB.close();
MockTransportService newService = buildService("TS_B_" + i, version1, null);
MockTransportService newService = buildService("TS_B_" + i, version1, Settings.EMPTY);
newService.registerRequestHandler("internal:test", TestRequest::new, ThreadPool.Names.SAME, ignoringRequestHandler);
serviceB = newService;
nodeB = newService.getLocalDiscoNode();
@ -1050,7 +1055,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
includeSettings = "internal:test";
excludeSettings = "DOESN'T_MATCH";
}
clusterSettings.applySettings(Settings.builder()
clusterSettingsA.applySettings(Settings.builder()
.put(TransportSettings.TRACE_LOG_INCLUDE_SETTING.getKey(), includeSettings)
.put(TransportSettings.TRACE_LOG_EXCLUDE_SETTING.getKey(), excludeSettings)
.build());
@ -1732,14 +1737,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testSendRandomRequests() throws InterruptedException {
TransportService serviceC = build(
Settings.builder()
.put("name", "TS_TEST")
.put(TransportSettings.TRACE_LOG_INCLUDE_SETTING.getKey(), "")
.put(TransportSettings.TRACE_LOG_EXCLUDE_SETTING.getKey(), "NOTHING")
.build(),
version0,
null, true);
TransportService serviceC = buildService("TS_C", version0, Settings.EMPTY);
DiscoveryNode nodeC = serviceC.getLocalNode();
serviceC.acceptIncomingRequests();
@ -1970,7 +1968,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
public void testHandshakeWithIncompatVersion() {
assumeTrue("only tcp transport has a handshake method", serviceA.getOriginalTransport() instanceof TcpTransport);
Version version = Version.fromString("2.0.0");
try (MockTransportService service = build(Settings.EMPTY, version, null, true)) {
try (MockTransportService service = buildService("TS_C", version, Settings.EMPTY)) {
service.start();
service.acceptIncomingRequests();
TransportAddress address = service.boundAddress().publishAddress();
@ -1989,7 +1987,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
public void testHandshakeUpdatesVersion() throws IOException {
assumeTrue("only tcp transport has a handshake method", serviceA.getOriginalTransport() instanceof TcpTransport);
Version version = VersionUtils.randomVersionBetween(random(), Version.CURRENT.minimumCompatibilityVersion(), Version.CURRENT);
try (MockTransportService service = build(Settings.EMPTY, version, null, true)) {
try (MockTransportService service = buildService("TS_C", version, Settings.EMPTY)) {
service.start();
service.acceptIncomingRequests();
TransportAddress address = service.boundAddress().publishAddress();
@ -2015,7 +2013,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
ConnectionProfile connectionProfile = new ConnectionProfile.Builder(defaultProfile)
.setPingInterval(TimeValue.timeValueMillis(50))
.build();
try (TransportService service = buildService("TS_TPC", Version.CURRENT, null)) {
try (TransportService service = buildService("TS_TPC", Version.CURRENT, Settings.EMPTY)) {
PlainActionFuture<Transport.Connection> future = PlainActionFuture.newFuture();
DiscoveryNode node = new DiscoveryNode("TS_TPC", "TS_TPC", service.boundAddress().publishAddress(), emptyMap(), emptySet(),
version0);
@ -2062,7 +2060,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
ConnectionProfile connectionProfile = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY);
try (TransportService service = buildService("TS_TPC", Version.CURRENT, null)) {
try (TransportService service = buildService("TS_TPC", Version.CURRENT, Settings.EMPTY)) {
DiscoveryNode node = new DiscoveryNode("TS_TPC", "TS_TPC", service.boundAddress().publishAddress(), emptyMap(), emptySet(),
version0);
PlainActionFuture<Transport.Connection> future = PlainActionFuture.newFuture();
@ -2193,7 +2191,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
public void testHandlerIsInvokedOnConnectionClose() throws IOException, InterruptedException {
List<String> executors = new ArrayList<>(ThreadPool.THREAD_POOL_TYPES.keySet());
CollectionUtil.timSort(executors); // makes sure it's reproducible
TransportService serviceC = build(Settings.builder().put("name", "TS_TEST").build(), version0, null, true);
TransportService serviceC = buildService("TS_C", CURRENT_VERSION, Settings.EMPTY);
serviceC.registerRequestHandler("internal:action", TestRequest::new, ThreadPool.Names.SAME,
(request, channel, task) -> {
// do nothing
@ -2251,7 +2249,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testConcurrentDisconnectOnNonPublishedConnection() throws IOException, InterruptedException {
MockTransportService serviceC = build(Settings.builder().put("name", "TS_TEST").build(), version0, null, true);
MockTransportService serviceC = buildService("TS_C", version0, Settings.EMPTY);
CountDownLatch receivedLatch = new CountDownLatch(1);
CountDownLatch sendResponseLatch = new CountDownLatch(1);
serviceC.registerRequestHandler("internal:action", TestRequest::new, ThreadPool.Names.SAME,
@ -2319,7 +2317,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testTransportStats() throws Exception {
MockTransportService serviceC = build(Settings.builder().put("name", "TS_TEST").build(), version0, null, true);
MockTransportService serviceC = buildService("TS_C", version0, Settings.EMPTY);
CountDownLatch receivedLatch = new CountDownLatch(1);
CountDownLatch sendResponseLatch = new CountDownLatch(1);
serviceB.registerRequestHandler("internal:action", TestRequest::new, ThreadPool.Names.SAME,
@ -2430,7 +2428,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testTransportStatsWithException() throws Exception {
MockTransportService serviceC = build(Settings.builder().put("name", "TS_TEST").build(), version0, null, true);
MockTransportService serviceC = buildService("TS_C", version0, Settings.EMPTY);
CountDownLatch receivedLatch = new CountDownLatch(1);
CountDownLatch sendResponseLatch = new CountDownLatch(1);
Exception ex = new RuntimeException("boom");
@ -2541,15 +2539,14 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
} else {
hosts = Arrays.asList("_local:ipv4_");
}
try (MockTransportService serviceC = build(Settings.builder()
.put("name", "TS_TEST")
try (MockTransportService serviceC = buildService("TS_C", version0, Settings.builder()
.put("transport.profiles.default.bind_host", "_local:ipv4_")
.put("transport.profiles.some_profile.port", "8900-9000")
.put("transport.profiles.some_profile.bind_host", "_local:ipv4_")
.put("transport.profiles.some_other_profile.port", "8700-8800")
.putList("transport.profiles.some_other_profile.bind_host", hosts)
.putList("transport.profiles.some_other_profile.publish_host", "_local:ipv4_")
.build(), version0, null, true)) {
.build())) {
serviceC.start();
serviceC.acceptIncomingRequests();
@ -2706,7 +2703,7 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
}
public void testChannelCloseWhileConnecting() {
try (MockTransportService service = build(Settings.builder().put("name", "close").build(), version0, null, true)) {
try (MockTransportService service = buildService("TS_C", version0, Settings.EMPTY)) {
AtomicBoolean connectionClosedListenerCalled = new AtomicBoolean(false);
service.addConnectionListener(new TransportConnectionListener() {
@Override
@ -2748,4 +2745,8 @@ public abstract class AbstractSimpleTransportTestCase extends ESTestCase {
protected InetSocketAddress getLocalEphemeral() throws UnknownHostException {
return new InetSocketAddress(InetAddress.getLocalHost(), 0);
}
protected Set<TcpChannel> getAcceptedChannels(TcpTransport transport) {
return transport.getAcceptedChannels();
}
}

View File

@ -21,7 +21,7 @@ package org.elasticsearch.transport;
import org.elasticsearch.common.settings.Settings;
final class TestProfiles {
public final class TestProfiles {
private TestProfiles() {}
@ -29,7 +29,7 @@ final class TestProfiles {
* A pre-built light connection profile that shares a single connection across all
* types.
*/
static final ConnectionProfile LIGHT_PROFILE;
public static final ConnectionProfile LIGHT_PROFILE;
static {
ConnectionProfile source = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY);

View File

@ -0,0 +1,45 @@
/*
* 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.xpack.core.security.transport;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.TransportSettings;
import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
import org.elasticsearch.xpack.core.ssl.SSLService;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.xpack.core.security.SecurityField.setting;
public final class ProfileConfigurations {
private ProfileConfigurations() {}
public static Map<String, SSLConfiguration> get(Settings settings, SSLService sslService, SSLConfiguration defaultConfiguration) {
Set<String> profileNames = settings.getGroups("transport.profiles.", true).keySet();
Map<String, SSLConfiguration> profileConfiguration = new HashMap<>(profileNames.size() + 1);
for (String profileName : profileNames) {
if (profileName.equals(TransportSettings.DEFAULT_PROFILE)) {
// don't attempt to parse ssl settings from the profile;
// profiles need to be killed with fire
if (settings.getByPrefix("transport.profiles.default.xpack.security.ssl.").isEmpty()) {
continue;
} else {
throw new IllegalArgumentException("SSL settings should not be configured for the default profile. " +
"Use the [xpack.security.transport.ssl] settings instead.");
}
}
SSLConfiguration configuration = sslService.getSSLConfiguration("transport.profiles." + profileName + "." + setting("ssl"));
profileConfiguration.put(profileName, configuration);
}
assert profileConfiguration.containsKey(TransportSettings.DEFAULT_PROFILE) == false;
profileConfiguration.put(TransportSettings.DEFAULT_PROFILE, defaultConfiguration);
return profileConfiguration;
}
}

View File

@ -25,9 +25,9 @@ import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.ConnectTransportException;
import org.elasticsearch.transport.TcpChannel;
import org.elasticsearch.transport.TransportSettings;
import org.elasticsearch.transport.netty4.Netty4Transport;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.transport.ProfileConfigurations;
import org.elasticsearch.xpack.core.security.transport.SSLExceptionHelper;
import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
import org.elasticsearch.xpack.core.ssl.SSLService;
@ -39,9 +39,7 @@ import javax.net.ssl.SSLParameters;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static org.elasticsearch.xpack.core.security.SecurityField.setting;
@ -70,7 +68,7 @@ public class SecurityNetty4Transport extends Netty4Transport {
this.sslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings);
if (sslEnabled) {
this.sslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl."));
Map<String, SSLConfiguration> profileConfiguration = getTransportProfileConfigurations(settings, sslService, sslConfiguration);
Map<String, SSLConfiguration> profileConfiguration = ProfileConfigurations.get(settings, sslService, sslConfiguration);
this.profileConfiguration = Collections.unmodifiableMap(profileConfiguration);
} else {
this.profileConfiguration = Collections.emptyMap();
@ -78,30 +76,6 @@ public class SecurityNetty4Transport extends Netty4Transport {
}
}
public static Map<String, SSLConfiguration> getTransportProfileConfigurations(Settings settings, SSLService sslService,
SSLConfiguration defaultConfiguration) {
Set<String> profileNames = settings.getGroups("transport.profiles.", true).keySet();
Map<String, SSLConfiguration> profileConfiguration = new HashMap<>(profileNames.size() + 1);
for (String profileName : profileNames) {
if (profileName.equals(TransportSettings.DEFAULT_PROFILE)) {
// don't attempt to parse ssl settings from the profile;
// profiles need to be killed with fire
if (settings.getByPrefix("transport.profiles.default.xpack.security.ssl.").isEmpty()) {
continue;
} else {
throw new IllegalArgumentException("SSL settings should not be configured for the default profile. " +
"Use the [xpack.security.transport.ssl] settings instead.");
}
}
SSLConfiguration configuration = sslService.getSSLConfiguration("transport.profiles." + profileName + "." + setting("ssl"));
profileConfiguration.put(profileName, configuration);
}
assert profileConfiguration.containsKey(TransportSettings.DEFAULT_PROFILE) == false;
profileConfiguration.put(TransportSettings.DEFAULT_PROFILE, defaultConfiguration);
return profileConfiguration;
}
@Override
protected void doStart() {
super.doStart();

View File

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.security.transport.netty4;
package org.elasticsearch.xpack.core.security.transport;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
@ -17,9 +17,7 @@ import org.hamcrest.Matchers;
import java.util.Map;
import static org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport.getTransportProfileConfigurations;
public class SecurityNetty4TransportTests extends ESTestCase {
public class ProfileConfigurationsTests extends ESTestCase {
public void testGetSecureTransportProfileConfigurations() {
final Settings settings = Settings.builder()
@ -31,7 +29,7 @@ public class SecurityNetty4TransportTests extends ESTestCase {
final Environment env = TestEnvironment.newEnvironment(settings);
SSLService sslService = new SSLService(settings, env);
final SSLConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl");
final Map<String, SSLConfiguration> profileConfigurations = getTransportProfileConfigurations(settings, sslService, defaultConfig);
final Map<String, SSLConfiguration> profileConfigurations = ProfileConfigurations.get(settings, sslService, defaultConfig);
assertThat(profileConfigurations.size(), Matchers.equalTo(3));
assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("full", "cert", "default"));
assertThat(profileConfigurations.get("full").verificationMode(), Matchers.equalTo(VerificationMode.FULL));
@ -49,7 +47,7 @@ public class SecurityNetty4TransportTests extends ESTestCase {
final Environment env = TestEnvironment.newEnvironment(settings);
SSLService sslService = new SSLService(settings, env);
final SSLConfiguration defaultConfig = sslService.getSSLConfiguration("xpack.security.transport.ssl");
final Map<String, SSLConfiguration> profileConfigurations = getTransportProfileConfigurations(settings, sslService, defaultConfig);
final Map<String, SSLConfiguration> profileConfigurations = ProfileConfigurations.get(settings, sslService, defaultConfig);
assertThat(profileConfigurations.size(), Matchers.equalTo(2));
assertThat(profileConfigurations.keySet(), Matchers.containsInAnyOrder("none", "default"));
assertThat(profileConfigurations.get("none").verificationMode(), Matchers.equalTo(VerificationMode.NONE));

View File

@ -33,7 +33,7 @@ import org.elasticsearch.transport.TransportService;
import org.elasticsearch.transport.TransportService.ContextRestoreResponseHandler;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.SecurityContext;
import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.core.security.transport.ProfileConfigurations;
import org.elasticsearch.xpack.core.security.user.SystemUser;
import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
import org.elasticsearch.xpack.core.ssl.SSLService;
@ -172,10 +172,9 @@ public class SecurityServerTransportInterceptor implements TransportInterceptor
licenseState, threadPool);
}
protected Map<String, ServerTransportFilter> initializeProfileFilters(DestructiveOperations destructiveOperations) {
final SSLConfiguration transportSslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl"));
final Map<String, SSLConfiguration> profileConfigurations = SecurityNetty4Transport.getTransportProfileConfigurations(settings,
sslService, transportSslConfiguration);
private Map<String, ServerTransportFilter> initializeProfileFilters(DestructiveOperations destructiveOperations) {
final SSLConfiguration sslConfiguration = sslService.getSSLConfiguration(setting("transport.ssl"));
final Map<String, SSLConfiguration> profileConfigurations = ProfileConfigurations.get(settings, sslService, sslConfiguration);
Map<String, ServerTransportFilter> profileFilters = new HashMap<>(profileConfigurations.size() + 1);

View File

@ -35,8 +35,8 @@ import org.elasticsearch.transport.nio.NioTcpServerChannel;
import org.elasticsearch.transport.nio.NioTransport;
import org.elasticsearch.transport.nio.TcpReadWriteHandler;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.security.transport.ProfileConfigurations;
import org.elasticsearch.xpack.core.security.transport.SSLExceptionHelper;
import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
@ -85,8 +85,7 @@ public class SecurityNioTransport extends NioTransport {
this.sslEnabled = XPackSettings.TRANSPORT_SSL_ENABLED.get(settings);
if (sslEnabled) {
final SSLConfiguration transportConfiguration = sslService.getSSLConfiguration(setting("transport.ssl."));
Map<String, SSLConfiguration> profileConfiguration = SecurityNetty4Transport.getTransportProfileConfigurations(settings,
sslService, transportConfiguration);
Map<String, SSLConfiguration> profileConfiguration = ProfileConfigurations.get(settings, sslService, transportConfiguration);
this.profileConfiguration = Collections.unmodifiableMap(profileConfiguration);
} else {
profileConfiguration = Collections.emptyMap();

View File

@ -10,24 +10,27 @@ import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.stream.OutputStreamStreamOutput;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.node.Node;
import org.elasticsearch.test.transport.MockTransportService;
import org.elasticsearch.test.transport.StubbableTransport;
import org.elasticsearch.transport.AbstractSimpleTransportTestCase;
import org.elasticsearch.transport.BindTransportException;
import org.elasticsearch.transport.ConnectTransportException;
import org.elasticsearch.transport.ConnectionProfile;
import org.elasticsearch.transport.TcpChannel;
import org.elasticsearch.transport.TcpTransport;
import org.elasticsearch.transport.TestProfiles;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportRequestOptions;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.transport.TransportSettings;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.common.socket.SocketAccess;
import org.elasticsearch.xpack.core.ssl.SSLClientAuth;
import org.elasticsearch.xpack.core.ssl.SSLConfiguration;
import org.elasticsearch.xpack.core.ssl.SSLService;
@ -37,6 +40,7 @@ import javax.net.ssl.SNIHostName;
import javax.net.ssl.SNIMatcher;
import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
@ -51,30 +55,24 @@ import java.nio.file.Path;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSimpleTransportTestCase {
private static final ConnectionProfile SINGLE_CHANNEL_PROFILE;
static {
ConnectionProfile.Builder builder = new ConnectionProfile.Builder();
builder.addConnections(1,
TransportRequestOptions.Type.BULK,
TransportRequestOptions.Type.PING,
TransportRequestOptions.Type.RECOVERY,
TransportRequestOptions.Type.REG,
TransportRequestOptions.Type.STATE);
SINGLE_CHANNEL_PROFILE = builder.build();
}
protected SSLService createSSLService() {
private SSLService createSSLService() {
return createSSLService(Settings.EMPTY);
}
@ -83,6 +81,8 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
Path testnodeKey = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
// Some tests use a client profile. Put the passphrase in the secure settings for the profile (secure settings cannot be set twice)
secureSettings.setString("transport.profiles.client.xpack.security.ssl.secure_key_passphrase", "testnode");
Settings settings1 = Settings.builder()
.put("xpack.security.transport.ssl.enabled", true)
.put("xpack.security.transport.ssl.key", testnodeKey)
@ -98,6 +98,13 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
}
}
@Override
protected Set<Setting<?>> getSupportedSettings() {
HashSet<Setting<?>> availableSettings = new HashSet<>(super.getSupportedSettings());
availableSettings.addAll(XPackSettings.getAllSettings());
return availableSettings;
}
public void testConnectException() throws UnknownHostException {
try {
serviceA.connectToNode(new DiscoveryNode("C", new TransportAddress(InetAddress.getByName("localhost"), 9876),
@ -115,14 +122,10 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
// this is on a lower level since it needs access to the TransportService before it's started
int port = serviceA.boundAddress().publishAddress().getPort();
Settings settings = Settings.builder()
.put(Node.NODE_NAME_SETTING.getKey(), "foobar")
.put(TransportSettings.TRACE_LOG_INCLUDE_SETTING.getKey(), "")
.put(TransportSettings.TRACE_LOG_EXCLUDE_SETTING.getKey(), "NOTHING")
.put(TransportSettings.PORT.getKey(), port)
.build();
ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
BindTransportException bindTransportException = expectThrows(BindTransportException.class, () -> {
MockTransportService transportService = build(settings, Version.CURRENT, clusterSettings, true);
MockTransportService transportService = buildService("TS_C", Version.CURRENT, settings);
try {
transportService.start();
} finally {
@ -139,7 +142,7 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
TcpTransport originalTransport = (TcpTransport) serviceA.getOriginalTransport();
ConnectionProfile connectionProfile = ConnectionProfile.buildDefaultConnectionProfile(Settings.EMPTY);
try (TransportService service = buildService("TS_TPC", Version.CURRENT, null)) {
try (TransportService service = buildService("TS_TPC", Version.CURRENT, Settings.EMPTY)) {
DiscoveryNode node = new DiscoveryNode("TS_TPC", "TS_TPC", service.boundAddress().publishAddress(), emptyMap(), emptySet(),
version0);
PlainActionFuture<Transport.Connection> future = PlainActionFuture.newFuture();
@ -245,10 +248,10 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
InetSocketAddress serverAddress = (InetSocketAddress) SocketAccess.doPrivileged(sslServerSocket::getLocalSocketAddress);
Settings settings = Settings.builder().put("name", "TS_TEST")
Settings settings = Settings.builder()
.put("xpack.security.transport.ssl.verification_mode", "none")
.build();
try (MockTransportService serviceC = build(settings, version0, null, true)) {
try (MockTransportService serviceC = buildService("TS_C", version0, settings)) {
serviceC.acceptIncomingRequests();
HashMap<String, String> attributes = new HashMap<>();
@ -258,7 +261,7 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
new Thread(() -> {
try {
serviceC.connectToNode(node, SINGLE_CHANNEL_PROFILE);
serviceC.connectToNode(node, TestProfiles.LIGHT_PROFILE);
} catch (ConnectTransportException ex) {
// Ignore. The other side is not setup to do the ES handshake. So this will fail.
}
@ -292,10 +295,10 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
InetSocketAddress serverAddress = (InetSocketAddress) SocketAccess.doPrivileged(sslServerSocket::getLocalSocketAddress);
Settings settings = Settings.builder().put("name", "TS_TEST")
Settings settings = Settings.builder()
.put("xpack.security.transport.ssl.verification_mode", "none")
.build();
try (MockTransportService serviceC = build(settings, version0, null, true)) {
try (MockTransportService serviceC = buildService("TS_C", version0, settings)) {
serviceC.acceptIncomingRequests();
HashMap<String, String> attributes = new HashMap<>();
@ -304,10 +307,147 @@ public abstract class AbstractSimpleSecurityTransportTestCase extends AbstractSi
EnumSet.allOf(DiscoveryNode.Role.class), Version.CURRENT);
ConnectTransportException connectException = expectThrows(ConnectTransportException.class,
() -> serviceC.connectToNode(node, SINGLE_CHANNEL_PROFILE));
() -> serviceC.connectToNode(node, TestProfiles.LIGHT_PROFILE));
assertThat(connectException.getMessage(), containsString("invalid DiscoveryNode server_name [invalid_hostname]"));
}
}
}
public void testSecurityClientAuthenticationConfigs() throws Exception {
Path testnodeCert = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
Path testnodeKey = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
Transport.Connection connection1 = serviceA.getConnection(serviceB.getLocalNode());
SSLEngine sslEngine = getSSLEngine(connection1);
assertThat(sslEngine, notNullValue());
// test client authentication is default
assertThat(sslEngine.getNeedClientAuth(), is(true));
assertThat(sslEngine.getWantClientAuth(), is(false));
// test required client authentication
String value = randomFrom(SSLClientAuth.REQUIRED.name(), SSLClientAuth.REQUIRED.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder().put("xpack.security.transport.ssl.client_authentication", value).build();
try (MockTransportService service = buildService("TS_REQUIRED_CLIENT_AUTH", Version.CURRENT, settings)) {
TcpTransport originalTransport = (TcpTransport) service.getOriginalTransport();
try (Transport.Connection connection2 = serviceA.openConnection(service.getLocalNode(), TestProfiles.LIGHT_PROFILE)) {
sslEngine = getEngineFromAcceptedChannel(originalTransport, connection2);
assertThat(sslEngine.getNeedClientAuth(), is(true));
assertThat(sslEngine.getWantClientAuth(), is(false));
}
}
// test no client authentication
value = randomFrom(SSLClientAuth.NONE.name(), SSLClientAuth.NONE.name().toLowerCase(Locale.ROOT));
settings = Settings.builder().put("xpack.security.transport.ssl.client_authentication", value).build();
try (MockTransportService service = buildService("TS_NO_CLIENT_AUTH", Version.CURRENT, settings)) {
TcpTransport originalTransport = (TcpTransport) service.getOriginalTransport();
try (Transport.Connection connection2 = serviceA.openConnection(service.getLocalNode(), TestProfiles.LIGHT_PROFILE)) {
sslEngine = getEngineFromAcceptedChannel(originalTransport, connection2);
assertThat(sslEngine.getNeedClientAuth(), is(false));
assertThat(sslEngine.getWantClientAuth(), is(false));
}
}
// test optional client authentication
value = randomFrom(SSLClientAuth.OPTIONAL.name(), SSLClientAuth.OPTIONAL.name().toLowerCase(Locale.ROOT));
settings = Settings.builder().put("xpack.security.transport.ssl.client_authentication", value).build();
try (MockTransportService service = buildService("TS_OPTIONAL_CLIENT_AUTH", Version.CURRENT, settings)) {
TcpTransport originalTransport = (TcpTransport) service.getOriginalTransport();
try (Transport.Connection connection2 = serviceA.openConnection(service.getLocalNode(), TestProfiles.LIGHT_PROFILE)) {
sslEngine = getEngineFromAcceptedChannel(originalTransport, connection2);
assertThat(sslEngine.getNeedClientAuth(), is(false));
assertThat(sslEngine.getWantClientAuth(), is(true));
}
}
// test profile required client authentication
value = randomFrom(SSLClientAuth.REQUIRED.name(), SSLClientAuth.REQUIRED.name().toLowerCase(Locale.ROOT));
settings = Settings.builder()
.put("transport.profiles.client.port", "8000-9000")
.put("transport.profiles.client.xpack.security.ssl.enabled", true)
.put("transport.profiles.client.xpack.security.ssl.certificate", testnodeCert)
.put("transport.profiles.client.xpack.security.ssl.key", testnodeKey)
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
try (MockTransportService service = buildService("TS_PROFILE_REQUIRE_CLIENT_AUTH", Version.CURRENT, settings)) {
TcpTransport originalTransport = (TcpTransport) service.getOriginalTransport();
TransportAddress clientAddress = originalTransport.profileBoundAddresses().get("client").publishAddress();
DiscoveryNode node = new DiscoveryNode(service.getLocalNode().getId(), clientAddress, service.getLocalNode().getVersion());
try (Transport.Connection connection2 = serviceA.openConnection(node, TestProfiles.LIGHT_PROFILE)) {
sslEngine = getEngineFromAcceptedChannel(originalTransport, connection2);
assertEquals("client", getAcceptedChannel(originalTransport, connection2).getProfile());
assertThat(sslEngine.getNeedClientAuth(), is(true));
assertThat(sslEngine.getWantClientAuth(), is(false));
}
}
// test profile no client authentication
value = randomFrom(SSLClientAuth.NONE.name(), SSLClientAuth.NONE.name().toLowerCase(Locale.ROOT));
settings = Settings.builder()
.put("transport.profiles.client.port", "8000-9000")
.put("transport.profiles.client.xpack.security.ssl.enabled", true)
.put("transport.profiles.client.xpack.security.ssl.certificate", testnodeCert)
.put("transport.profiles.client.xpack.security.ssl.key", testnodeKey)
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
try (MockTransportService service = buildService("TS_PROFILE_NO_CLIENT_AUTH", Version.CURRENT, settings)) {
TcpTransport originalTransport = (TcpTransport) service.getOriginalTransport();
TransportAddress clientAddress = originalTransport.profileBoundAddresses().get("client").publishAddress();
DiscoveryNode node = new DiscoveryNode(service.getLocalNode().getId(), clientAddress, service.getLocalNode().getVersion());
try (Transport.Connection connection2 = serviceA.openConnection(node, TestProfiles.LIGHT_PROFILE)) {
sslEngine = getEngineFromAcceptedChannel(originalTransport, connection2);
assertEquals("client", getAcceptedChannel(originalTransport, connection2).getProfile());
assertThat(sslEngine.getNeedClientAuth(), is(false));
assertThat(sslEngine.getWantClientAuth(), is(false));
}
}
// test profile optional client authentication
value = randomFrom(SSLClientAuth.OPTIONAL.name(), SSLClientAuth.OPTIONAL.name().toLowerCase(Locale.ROOT));
settings = Settings.builder()
.put("transport.profiles.client.port", "8000-9000")
.put("transport.profiles.client.xpack.security.ssl.enabled", true)
.put("transport.profiles.client.xpack.security.ssl.certificate", testnodeCert)
.put("transport.profiles.client.xpack.security.ssl.key", testnodeKey)
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
try (MockTransportService service = buildService("TS_PROFILE_OPTIONAL_CLIENT_AUTH", Version.CURRENT, settings)) {
TcpTransport originalTransport = (TcpTransport) service.getOriginalTransport();
TransportAddress clientAddress = originalTransport.profileBoundAddresses().get("client").publishAddress();
DiscoveryNode node = new DiscoveryNode(service.getLocalNode().getId(), clientAddress, service.getLocalNode().getVersion());
try (Transport.Connection connection2 = serviceA.openConnection(node, TestProfiles.LIGHT_PROFILE)) {
sslEngine = getEngineFromAcceptedChannel(originalTransport, connection2);
assertEquals("client", getAcceptedChannel(originalTransport, connection2).getProfile());
assertThat(sslEngine.getNeedClientAuth(), is(false));
assertThat(sslEngine.getWantClientAuth(), is(true));
}
}
}
private SSLEngine getEngineFromAcceptedChannel(TcpTransport transport, Transport.Connection connection) throws Exception {
return SSLEngineUtils.getSSLEngine(getAcceptedChannel(transport, connection));
}
private TcpChannel getAcceptedChannel(TcpTransport transport, Transport.Connection connection) throws Exception {
InetSocketAddress localAddress = getSingleChannel(connection).getLocalAddress();
AtomicReference<TcpChannel> accepted = new AtomicReference<>();
assertBusy(() -> {
Optional<TcpChannel> maybeAccepted = getAcceptedChannels(transport)
.stream().filter(c -> c.getRemoteAddress().equals(localAddress)).findFirst();
assertTrue(maybeAccepted.isPresent());
accepted.set(maybeAccepted.get());
});
return accepted.get();
}
private SSLEngine getSSLEngine(Transport.Connection connection) {
return SSLEngineUtils.getSSLEngine(getSingleChannel(connection));
}
private TcpChannel getSingleChannel(Transport.Connection connection) {
StubbableTransport.WrappedConnection wrappedConnection = (StubbableTransport.WrappedConnection) connection;
TcpTransport.NodeChannels nodeChannels = (TcpTransport.NodeChannels) wrappedConnection.getConnection();
return nodeChannels.getChannels().get(0);
}
}

View File

@ -1,180 +0,0 @@
/*
* 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.xpack.security.transport.netty4;
import io.netty.channel.ChannelHandler;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.ssl.SslHandler;
import org.elasticsearch.Version;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.MockSecureSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.PageCacheRecycler;
import org.elasticsearch.env.Environment;
import org.elasticsearch.env.TestEnvironment;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.core.ssl.SSLClientAuth;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.junit.Before;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Locale;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.mockito.Mockito.mock;
public class SecurityNetty4ServerTransportTests extends ESTestCase {
private Environment env;
private SSLService sslService;
@Before
public void createSSLService() throws Exception {
Path testnodeCert = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.crt");
Path testnodeKey = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.pem");
MockSecureSettings secureSettings = new MockSecureSettings();
secureSettings.setString("xpack.security.transport.ssl.secure_key_passphrase", "testnode");
Settings settings = Settings.builder()
.put("xpack.security.transport.ssl.enabled", true)
.put("xpack.security.transport.ssl.key", testnodeKey)
.put("xpack.security.transport.ssl.certificate", testnodeCert)
.setSecureSettings(secureSettings)
.put("path.home", createTempDir())
.build();
env = TestEnvironment.newEnvironment(settings);
sslService = new SSLService(settings, env);
}
private SecurityNetty4Transport createTransport() {
return createTransport(Settings.builder().put("xpack.security.transport.ssl.enabled", true).build());
}
private SecurityNetty4Transport createTransport(Settings additionalSettings) {
final Settings settings =
Settings.builder()
.put("xpack.security.transport.ssl.enabled", true)
.put(additionalSettings)
.build();
return new SecurityNetty4ServerTransport(
settings,
Version.CURRENT,
mock(ThreadPool.class),
new NetworkService(Collections.emptyList()),
mock(PageCacheRecycler.class),
mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class),
null,
sslService);
}
public void testThatProfileTakesDefaultSSLSetting() throws Exception {
SecurityNetty4Transport transport = createTransport();
ChannelHandler handler = transport.getServerChannelInitializer("default");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine(), notNullValue());
}
public void testDefaultClientAuth() throws Exception {
SecurityNetty4Transport transport = createTransport();
ChannelHandler handler = transport.getServerChannelInitializer("default");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(true));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(false));
}
public void testRequiredClientAuth() throws Exception {
String value = randomFrom(SSLClientAuth.REQUIRED.name(), SSLClientAuth.REQUIRED.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.transport.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty4Transport transport = createTransport(settings);
ChannelHandler handler = transport.getServerChannelInitializer("default");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(true));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(false));
}
public void testNoClientAuth() throws Exception {
String value = randomFrom(SSLClientAuth.NONE.name(), SSLClientAuth.NONE.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.transport.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty4Transport transport = createTransport(settings);
ChannelHandler handler = transport.getServerChannelInitializer("default");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(false));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(false));
}
public void testOptionalClientAuth() throws Exception {
String value = randomFrom(SSLClientAuth.OPTIONAL.name(), SSLClientAuth.OPTIONAL.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.transport.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty4Transport transport = createTransport(settings);
ChannelHandler handler = transport.getServerChannelInitializer("default");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(false));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(true));
}
public void testProfileRequiredClientAuth() throws Exception {
String value = randomFrom(SSLClientAuth.REQUIRED.name(), SSLClientAuth.REQUIRED.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder()
.put(env.settings())
.put("transport.profiles.client.port", "8000-9000")
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty4Transport transport = createTransport(settings);
ChannelHandler handler = transport.getServerChannelInitializer("client");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(true));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(false));
}
public void testProfileNoClientAuth() throws Exception {
String value = randomFrom(SSLClientAuth.NONE.name(), SSLClientAuth.NONE.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder()
.put(env.settings())
.put("transport.profiles.client.port", "8000-9000")
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty4Transport transport = createTransport(settings);
ChannelHandler handler = transport.getServerChannelInitializer("client");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(false));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(false));
}
public void testProfileOptionalClientAuth() throws Exception {
String value = randomFrom(SSLClientAuth.OPTIONAL.name(), SSLClientAuth.OPTIONAL.name().toLowerCase(Locale.ROOT));
Settings settings = Settings.builder()
.put(env.settings())
.put("transport.profiles.client.port", "8000-9000")
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty4Transport transport = createTransport(settings);
final ChannelHandler handler = transport.getServerChannelInitializer("client");
final EmbeddedChannel ch = new EmbeddedChannel(handler);
assertThat(ch.pipeline().get(SslHandler.class).engine().getNeedClientAuth(), is(false));
assertThat(ch.pipeline().get(SslHandler.class).engine().getWantClientAuth(), is(true));
}
}