Simplied SSL keystores and truststores
This puts one keystore in the SSLService. An optional truststore can be configured but the keystore defaults as the truststore. This change also removed the ability to do certificate authentication with clients. Resolves https://github.com/elasticsearch/elasticsearch-shield/issues/292 Original commit: elastic/x-pack-elasticsearch@59920db32a
This commit is contained in:
parent
90d4c43a6d
commit
a224b54973
4
.esvmrc
4
.esvmrc
|
@ -17,9 +17,7 @@
|
|||
"http.ssl": true,
|
||||
"ssl" : {
|
||||
"keystore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
|
||||
"keystore_password" : "testnode",
|
||||
"truststore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
|
||||
"truststore_password" : "testnode"
|
||||
"keystore_password" : "testnode"
|
||||
},
|
||||
"authc": {
|
||||
"esusers.files" : {
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
"http.ssl": true,
|
||||
"ssl" : {
|
||||
"keystore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
|
||||
"keystore_password" : "testnode",
|
||||
"truststore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
|
||||
"truststore_password" : "testnode"
|
||||
"keystore_password" : "testnode"
|
||||
},
|
||||
"authc": {
|
||||
"esusers.files" : {
|
||||
|
@ -30,8 +28,6 @@
|
|||
"mode" : "active_directory",
|
||||
"domain_name" : "ad.test.elasticsearch.com",
|
||||
"url" : "ldaps://ad.test.elasticsearch.com:636",
|
||||
"truststore" : "src/test/resources/org/elasticsearch/shield/authc/ldap/ldaptrust.jks",
|
||||
"truststore_password" : "changeit",
|
||||
"unmapped_groups_as_roles" : "false",
|
||||
"files" : {
|
||||
"role_mapping": ".esvm-shield-config/role_mapping.yml"
|
||||
|
|
|
@ -17,9 +17,7 @@
|
|||
"http.ssl": true,
|
||||
"ssl" : {
|
||||
"keystore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
|
||||
"keystore_password" : "testnode",
|
||||
"truststore" : "src/test/resources/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks",
|
||||
"truststore_password" : "testnode"
|
||||
"keystore_password" : "testnode"
|
||||
},
|
||||
"authc": {
|
||||
"ldap" : {
|
||||
|
@ -28,8 +26,6 @@
|
|||
"user_dn_templates": ["uid={0},ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com"],
|
||||
"group_search.group_search_dn" : "ou=people,dc=oldap,dc=test,dc=elasticsearch,dc=com",
|
||||
"group_search.subtree_search" : false,
|
||||
"truststore" : "src/test/resources/org/elasticsearch/shield/authc/ldap/ldaptrust.jks",
|
||||
"truststore_password" : "changeit",
|
||||
"unmapped_groups_as_roles" : "false",
|
||||
"files" : {
|
||||
"role_mapping": ".esvm-shield-config/role_mapping.yml"
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.shield.audit.AuditTrailModule;
|
|||
import org.elasticsearch.shield.authc.AuthenticationModule;
|
||||
import org.elasticsearch.shield.authz.AuthorizationModule;
|
||||
import org.elasticsearch.shield.key.KeyModule;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.shield.support.AbstractShieldModule;
|
||||
import org.elasticsearch.shield.transport.SecuredRestModule;
|
||||
import org.elasticsearch.shield.transport.SecuredTransportModule;
|
||||
|
@ -62,5 +63,8 @@ public class ShieldModule extends AbstractShieldModule.Spawn implements PreProce
|
|||
|
||||
@Override
|
||||
protected void configure(boolean clientMode) {
|
||||
if (SSLService.isSSLEnabled(settings)) {
|
||||
bind(SSLService.class).asEagerSingleton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ public class LdapModule extends AbstractShieldModule.Node {
|
|||
protected void configureNode() {
|
||||
if (enabled) {
|
||||
/* This socket factory needs to be configured before any LDAP connections are created. LDAP configuration
|
||||
for JNDI invokes a static getSocketFactory method from LdapSslSocketFactory. This doesn't mesh well with
|
||||
guice so we set the factory here during startup. See LdapSslSocketFactory for more details. */
|
||||
LdapSslSocketFactory.init(settings);
|
||||
for JNDI invokes a static getSocketFactory method from LdapSslSocketFactory. */
|
||||
requestStaticInjection(LdapSslSocketFactory.class);
|
||||
|
||||
bind(Realm.class).annotatedWith(named(LdapRealm.TYPE)).to(LdapRealm.class).asEagerSingleton();
|
||||
bind(LdapGroupToRoleMapper.class).asEagerSingleton();
|
||||
String mode = settings.getComponentSettings(LdapModule.class).get("mode", StandardLdapConnectionFactory.MODE_NAME);
|
||||
|
||||
if (StandardLdapConnectionFactory.MODE_NAME.equals(mode)) {
|
||||
bind(LdapConnectionFactory.class).to(StandardLdapConnectionFactory.class);
|
||||
} else if (ActiveDirectoryConnectionFactory.MODE_NAME.equals(mode)) {
|
||||
|
@ -49,7 +49,7 @@ public class LdapModule extends AbstractShieldModule.Node {
|
|||
}
|
||||
}
|
||||
|
||||
static boolean enabled(Settings settings) {
|
||||
public static boolean enabled(Settings settings) {
|
||||
Settings authcSettings = settings.getAsSettings("shield.authc");
|
||||
if (!authcSettings.names().contains("ldap")) {
|
||||
return false;
|
||||
|
|
|
@ -7,11 +7,11 @@ package org.elasticsearch.shield.authc.ldap;
|
|||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.ShieldSettingsException;
|
||||
import org.elasticsearch.shield.transport.ssl.SSLTrustConfig;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import java.io.IOException;
|
||||
|
@ -32,24 +32,23 @@ public class LdapSslSocketFactory extends SocketFactory {
|
|||
|
||||
static final String JAVA_NAMING_LDAP_FACTORY_SOCKET = "java.naming.ldap.factory.socket";
|
||||
private static ESLogger logger = ESLoggerFactory.getLogger(LdapSslSocketFactory.class.getName());
|
||||
|
||||
private static LdapSslSocketFactory instance;
|
||||
|
||||
/**
|
||||
* This should only be invoked once to establish a static instance that will be used for each constructor.
|
||||
*/
|
||||
public static void init(Settings settings) {
|
||||
@Inject
|
||||
public static void init(SSLService ssl) {
|
||||
if (instance != null) {
|
||||
logger.error("LdapSslSocketFactory already configured, this change could lead to threading issues");
|
||||
}
|
||||
|
||||
Settings componentSettings = settings.getComponentSettings(LdapSslSocketFactory.class);
|
||||
Settings generalSslSettings = settings.getByPrefix("shield.ssl.");
|
||||
if (generalSslSettings.get("truststore") == null && componentSettings.get("truststore") == null){
|
||||
logger.warn("No truststore has been configured for LDAP");
|
||||
if (ssl == null) {
|
||||
logger.warn("no keystore has been configured for LDAP");
|
||||
} else {
|
||||
SSLTrustConfig sslConfig = new SSLTrustConfig(componentSettings, generalSslSettings);
|
||||
instance = new LdapSslSocketFactory(sslConfig.createSSLSocketFactory());
|
||||
instance = new LdapSslSocketFactory(ssl.getSSLSocketFactory());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,14 +99,7 @@ public class LdapSslSocketFactory extends SocketFactory {
|
|||
* @throws org.elasticsearch.shield.ShieldSettingsException if URLs have mixed protocols.
|
||||
*/
|
||||
public static void configureJndiSSL(String[] ldapUrls, ImmutableMap.Builder<String, Serializable> builder) {
|
||||
boolean secureProtocol = ldapUrls[0].toLowerCase(Locale.getDefault()).startsWith("ldaps://");
|
||||
for(String url: ldapUrls){
|
||||
if (secureProtocol != url.toLowerCase(Locale.getDefault()).startsWith("ldaps://")) {
|
||||
//this is because LdapSSLSocketFactory produces only SSL sockets and not clear text sockets
|
||||
throw new ShieldSettingsException("Configured ldap protocols are not all equal " +
|
||||
"(ldaps://.. and ldap://..): [" + Strings.arrayToCommaDelimitedString(ldapUrls) + "]");
|
||||
}
|
||||
}
|
||||
boolean secureProtocol = secureUrls(ldapUrls);
|
||||
if (secureProtocol && instance != null) {
|
||||
builder.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, LdapSslSocketFactory.class.getName());
|
||||
} else {
|
||||
|
@ -117,4 +109,23 @@ public class LdapSslSocketFactory extends SocketFactory {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ldapUrls URLS in the form of "ldap://..." or "ldaps://..."
|
||||
* @return true if all URLS are ldaps, also true it ldapUrls is empty. False otherwise
|
||||
*/
|
||||
public static boolean secureUrls(String[] ldapUrls) {
|
||||
if (ldapUrls.length == 0) {
|
||||
return true;
|
||||
}
|
||||
boolean secureProtocol = ldapUrls[0].toLowerCase(Locale.getDefault()).startsWith("ldaps://");
|
||||
for(String url: ldapUrls){
|
||||
if (secureProtocol != url.toLowerCase(Locale.getDefault()).startsWith("ldaps://")) {
|
||||
//this is because LdapSSLSocketFactory produces only SSL sockets and not clear text sockets
|
||||
throw new ShieldSettingsException("Configured ldap protocols are not all equal " +
|
||||
"(ldaps://.. and ldap://..): [" + Strings.arrayToCommaDelimitedString(ldapUrls) + "]");
|
||||
}
|
||||
}
|
||||
return secureProtocol;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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.ssl;
|
||||
package org.elasticsearch.shield.ssl;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.rest.RestStatus;
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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 org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.ShieldSettingsException;
|
||||
import org.elasticsearch.shield.authc.ldap.LdapModule;
|
||||
import org.elasticsearch.shield.authc.ldap.LdapSslSocketFactory;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This service houses the private key and trust managers needed for SSL/TLS negotiation. It is the central place to
|
||||
* get SSLEngines and SocketFactories.
|
||||
*/
|
||||
public class SSLService extends AbstractComponent {
|
||||
static final String[] DEFAULT_CIPHERS = new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" };
|
||||
private final TrustManagerFactory trustFactory;
|
||||
private final SSLContext sslContext;
|
||||
private final String[] ciphers;
|
||||
|
||||
@Inject
|
||||
public SSLService(Settings settings) {
|
||||
super(settings);
|
||||
|
||||
String keyStore = componentSettings.get("keystore", System.getProperty("javax.net.ssl.keyStore"));
|
||||
String keyStorePassword = componentSettings.get("keystore_password", System.getProperty("javax.net.ssl.keyStorePassword"));
|
||||
String keyStoreAlgorithm = componentSettings.get("keystore_algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm", KeyManagerFactory.getDefaultAlgorithm()));
|
||||
|
||||
String trustStore = componentSettings.get("truststore", System.getProperty("javax.net.ssl.trustStore"));
|
||||
String trustStorePassword = componentSettings.get("truststore_password", System.getProperty("javax.net.ssl.trustStorePassword"));
|
||||
String trustStoreAlgorithm = componentSettings.get("truststore_algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm()));
|
||||
|
||||
if (trustStore == null) {
|
||||
//the keystore will also be the truststore
|
||||
trustStore = keyStore;
|
||||
trustStorePassword = keyStorePassword;
|
||||
}
|
||||
|
||||
if (keyStore == null) {
|
||||
throw new ShieldSettingsException("No keystore configured");
|
||||
}
|
||||
if (keyStorePassword == null) {
|
||||
throw new ShieldSettingsException("No keystore password configured");
|
||||
}
|
||||
|
||||
this.ciphers = componentSettings.getAsArray("ciphers", DEFAULT_CIPHERS);
|
||||
//protocols supported: https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
|
||||
String sslProtocol = componentSettings.get("protocol", "TLS");
|
||||
|
||||
logger.debug("using keyStore[{}], keyAlgorithm[{}], trustStore[{}], truststoreAlgorithm[{}], ciphersuites[{}], TLS protocol[{}]",
|
||||
keyStore, keyStoreAlgorithm, trustStore, trustStoreAlgorithm, ciphers, sslProtocol);
|
||||
|
||||
try (FileInputStream in = new FileInputStream(trustStore)) {
|
||||
// Load TrustStore
|
||||
KeyStore ks = KeyStore.getInstance("jks");
|
||||
ks.load(in, trustStorePassword == null ? null : trustStorePassword.toCharArray());
|
||||
|
||||
// Initialize a trust manager factory with the trusted store
|
||||
trustFactory = TrustManagerFactory.getInstance(trustStoreAlgorithm);
|
||||
trustFactory.init(ks);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("Failed to initialize a TrustManagerFactory", e);
|
||||
}
|
||||
|
||||
KeyStore ks = null;
|
||||
KeyManagerFactory kmf = null;
|
||||
try (FileInputStream in = new FileInputStream(keyStore)){
|
||||
// Load KeyStore
|
||||
ks = KeyStore.getInstance("jks");
|
||||
ks.load(in, keyStorePassword.toCharArray());
|
||||
|
||||
// Initialize KeyManagerFactory
|
||||
kmf = KeyManagerFactory.getInstance(keyStoreAlgorithm);
|
||||
kmf.init(ks, keyStorePassword.toCharArray());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchSSLException("Failed to initialize a KeyManagerFactory", e);
|
||||
}
|
||||
|
||||
// Initialize sslContext
|
||||
try {
|
||||
sslContext = SSLContext.getInstance(sslProtocol);
|
||||
sslContext.init(kmf.getKeyManagers(), trustFactory.getTrustManagers(), null);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchSSLException("Failed to initialize the SSLContext", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An SSLSocketFactory (for client-side SSL handshaking)
|
||||
*/
|
||||
public SSLSocketFactory getSSLSocketFactory() {
|
||||
return sslContext.getSocketFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* This engine is configured with a trust manager and a keystore that should have only one private key.
|
||||
* Four possible usages for elasticsearch exist:
|
||||
* Node-to-Node outbound:
|
||||
* - sslEngine.setUseClientMode(true)
|
||||
* Node-to-Node inbound:
|
||||
* - sslEngine.setUseClientMode(false)
|
||||
* - sslEngine.setNeedClientAuth(true)
|
||||
* Client-to-Node:
|
||||
* - sslEngine.setUseClientMode(true)
|
||||
* Node-from-Client (inbound):
|
||||
* - sslEngine.setUserClientMode(false)
|
||||
* - sslEngine.setNeedClientAuth(false)
|
||||
* @return
|
||||
*/
|
||||
public SSLEngine createSSLEngine() {
|
||||
SSLEngine sslEngine = sslContext.createSSLEngine();
|
||||
try {
|
||||
sslEngine.setEnabledCipherSuites(ciphers);
|
||||
} catch (Throwable t) {
|
||||
throw new ElasticsearchSSLException("Error loading cipher suites ["+ Arrays.asList(ciphers)+"]", t);
|
||||
}
|
||||
return sslEngine;
|
||||
}
|
||||
|
||||
public static boolean isSSLEnabled(Settings settings) {
|
||||
return settings.getAsBoolean("shield.transport.ssl", false) ||
|
||||
settings.getAsBoolean("shield.http.ssl", false) ||
|
||||
(LdapSslSocketFactory.secureUrls(settings.getAsArray("shield.authc.ldap.url")) &&
|
||||
LdapModule.enabled(settings));
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import org.elasticsearch.common.network.NetworkService;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.http.netty.NettyHttpServerTransport;
|
||||
import org.elasticsearch.shield.transport.ssl.SSLConfig;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
|
@ -25,12 +25,14 @@ public class NettySecuredHttpServerTransport extends NettyHttpServerTransport {
|
|||
|
||||
private final boolean ssl;
|
||||
private final N2NNettyUpstreamHandler shieldUpstreamHandler;
|
||||
private final SSLService sslService;
|
||||
|
||||
@Inject
|
||||
public NettySecuredHttpServerTransport(Settings settings, NetworkService networkService, BigArrays bigArrays,
|
||||
@Nullable N2NNettyUpstreamHandler shieldUpstreamHandler) {
|
||||
@Nullable N2NNettyUpstreamHandler shieldUpstreamHandler, SSLService sslService) {
|
||||
super(settings, networkService, bigArrays);
|
||||
this.ssl = settings.getAsBoolean("shield.http.ssl", false);
|
||||
this.sslService = sslService;
|
||||
this.shieldUpstreamHandler = shieldUpstreamHandler;
|
||||
}
|
||||
|
||||
|
@ -41,25 +43,18 @@ public class NettySecuredHttpServerTransport extends NettyHttpServerTransport {
|
|||
|
||||
private class HttpSslChannelPipelineFactory extends HttpChannelPipelineFactory {
|
||||
|
||||
private final SSLConfig sslConfig;
|
||||
|
||||
public HttpSslChannelPipelineFactory(NettyHttpServerTransport transport) {
|
||||
super(transport);
|
||||
if (ssl) {
|
||||
sslConfig = new SSLConfig(settings.getByPrefix("shield.http.ssl."), settings.getByPrefix("shield.ssl."), false);
|
||||
// try to create an SSL engine, so that exceptions lead to early exit
|
||||
sslConfig.createSSLEngine();
|
||||
} else {
|
||||
sslConfig = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = super.getPipeline();
|
||||
if (ssl) {
|
||||
SSLEngine engine = sslConfig.createSSLEngine();
|
||||
SSLEngine engine = sslService.createSSLEngine();
|
||||
engine.setUseClientMode(false);
|
||||
engine.setNeedClientAuth(false);
|
||||
|
||||
pipeline.addFirst("ssl", new SslHandler(engine));
|
||||
}
|
||||
if (shieldUpstreamHandler != null) {
|
||||
|
|
|
@ -14,7 +14,7 @@ import org.elasticsearch.common.netty.handler.ssl.SslHandler;
|
|||
import org.elasticsearch.common.network.NetworkService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.BigArrays;
|
||||
import org.elasticsearch.shield.transport.ssl.SSLConfig;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.netty.NettyTransport;
|
||||
|
||||
|
@ -27,13 +27,15 @@ public class NettySecuredTransport extends NettyTransport {
|
|||
|
||||
private final boolean ssl;
|
||||
private final N2NNettyUpstreamHandler shieldUpstreamHandler;
|
||||
private final SSLService sslService;
|
||||
|
||||
@Inject
|
||||
public NettySecuredTransport(Settings settings, ThreadPool threadPool, NetworkService networkService, BigArrays bigArrays, Version version,
|
||||
@Nullable N2NNettyUpstreamHandler shieldUpstreamHandler) {
|
||||
@Nullable N2NNettyUpstreamHandler shieldUpstreamHandler, SSLService sslService) {
|
||||
super(settings, threadPool, networkService, bigArrays, version);
|
||||
this.shieldUpstreamHandler = shieldUpstreamHandler;
|
||||
this.ssl = settings.getAsBoolean("shield.transport.ssl", false);
|
||||
this.sslService = sslService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -48,25 +50,17 @@ public class NettySecuredTransport extends NettyTransport {
|
|||
|
||||
private class SslServerChannelPipelineFactory extends ServerChannelPipelineFactory {
|
||||
|
||||
private final SSLConfig sslConfig;
|
||||
|
||||
public SslServerChannelPipelineFactory(NettyTransport nettyTransport, String name, Settings settings, Settings profileSettings) {
|
||||
super(nettyTransport, name, settings);
|
||||
if (ssl) {
|
||||
sslConfig = new SSLConfig(this.settings.getByPrefix("shield.transport.ssl."), this.settings.getByPrefix("shield.ssl."), true);
|
||||
// try to create an SSL engine, so that exceptions lead to early exit
|
||||
sslConfig.createSSLEngine();
|
||||
} else {
|
||||
sslConfig = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = super.getPipeline();
|
||||
if (ssl) {
|
||||
SSLEngine serverEngine = sslConfig.createSSLEngine();
|
||||
SSLEngine serverEngine = sslService.createSSLEngine();
|
||||
serverEngine.setUseClientMode(false);
|
||||
serverEngine.setNeedClientAuth(true);
|
||||
|
||||
pipeline.addFirst("ssl", new SslHandler(serverEngine));
|
||||
pipeline.replace("dispatcher", "dispatcher", new SecuredMessageChannelHandler(nettyTransport, logger));
|
||||
|
@ -80,24 +74,15 @@ public class NettySecuredTransport extends NettyTransport {
|
|||
|
||||
private class SslClientChannelPipelineFactory extends ClientChannelPipelineFactory {
|
||||
|
||||
private final SSLConfig sslConfig;
|
||||
|
||||
public SslClientChannelPipelineFactory(NettyTransport transport) {
|
||||
super(transport);
|
||||
if (ssl) {
|
||||
sslConfig = new SSLConfig(settings.getByPrefix("shield.transport.ssl."), settings.getByPrefix("shield.ssl."), true);
|
||||
// try to create an SSL engine, so that exceptions lead to early exit
|
||||
sslConfig.createSSLEngine();
|
||||
} else {
|
||||
sslConfig = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline getPipeline() throws Exception {
|
||||
ChannelPipeline pipeline = super.getPipeline();
|
||||
if (ssl) {
|
||||
SSLEngine clientEngine = sslConfig.createSSLEngine();
|
||||
SSLEngine clientEngine = sslService.createSSLEngine();
|
||||
clientEngine.setUseClientMode(true);
|
||||
|
||||
pipeline.addFirst("ssl", new SslHandler(clientEngine));
|
||||
|
|
|
@ -11,7 +11,6 @@ import org.elasticsearch.common.netty.channel.ChannelFutureListener;
|
|||
import org.elasticsearch.common.netty.channel.ChannelHandlerContext;
|
||||
import org.elasticsearch.common.netty.channel.ChannelStateEvent;
|
||||
import org.elasticsearch.common.netty.handler.ssl.SslHandler;
|
||||
import org.elasticsearch.shield.transport.ssl.ElasticsearchSSLException;
|
||||
import org.elasticsearch.transport.netty.MessageChannelHandler;
|
||||
|
||||
public class SecuredMessageChannelHandler extends MessageChannelHandler {
|
||||
|
|
|
@ -1,93 +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.shield.transport.ssl;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SSLConfig {
|
||||
|
||||
private static final ESLogger logger = Loggers.getLogger(SSLConfig.class);
|
||||
static final String[] DEFAULT_CIPHERS = new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" };
|
||||
private final boolean clientAuth;
|
||||
|
||||
private SSLContext sslContext;
|
||||
private String[] ciphers;
|
||||
|
||||
public SSLConfig(Settings componentSettings, Settings defaultSettings, boolean defaultRequireClientAuth) {
|
||||
this.clientAuth = componentSettings.getAsBoolean("require.client.auth", defaultSettings.getAsBoolean("require.client.auth", defaultRequireClientAuth));
|
||||
TrustManager[] trustManagers = null;
|
||||
if (clientAuth) {
|
||||
trustManagers = new SSLTrustConfig(componentSettings, defaultSettings).getTrustManagers();
|
||||
}
|
||||
|
||||
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")));
|
||||
String keyStoreAlgorithm = componentSettings.get("keystore_algorithm", defaultSettings.get("keystore_algorithm", System.getProperty("ssl.KeyManagerFactory.algorithm")));
|
||||
this.ciphers = componentSettings.getAsArray("ciphers", defaultSettings.getAsArray("ciphers", DEFAULT_CIPHERS));
|
||||
|
||||
if (keyStore == null) {
|
||||
throw new ElasticsearchException("SSL Enabled, but keystore unconfigured");
|
||||
}
|
||||
|
||||
if (keyStoreAlgorithm == null) {
|
||||
keyStoreAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
|
||||
}
|
||||
|
||||
logger.debug("using keyStore[{}], keyAlgorithm[{}], ", keyStore, keyStoreAlgorithm);
|
||||
|
||||
if (!new File(keyStore).exists()) {
|
||||
throw new ElasticsearchSSLException("Keystore at path ["+ keyStore +"] does not exist");
|
||||
}
|
||||
|
||||
KeyStore ks = null;
|
||||
KeyManagerFactory kmf = null;
|
||||
try (FileInputStream in = new FileInputStream(keyStore)){
|
||||
// Load KeyStore
|
||||
ks = KeyStore.getInstance("jks");
|
||||
ks.load(in, keyStorePassword.toCharArray());
|
||||
|
||||
// Initialize KeyManagerFactory
|
||||
kmf = KeyManagerFactory.getInstance(keyStoreAlgorithm);
|
||||
kmf.init(ks, keyStorePassword.toCharArray());
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchSSLException("Failed to initialize a KeyManagerFactory", e);
|
||||
}
|
||||
|
||||
// Initialize sslContext
|
||||
try {
|
||||
String algorithm = componentSettings.get("context_algorithm", defaultSettings.get("shield.ssl.context_algorithm", "TLS"));
|
||||
sslContext = SSLContext.getInstance(algorithm);
|
||||
sslContext.init(kmf.getKeyManagers(), trustManagers, null);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchSSLException("Failed to initialize the SSLContext", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SSLEngine createSSLEngine() {
|
||||
SSLEngine sslEngine = sslContext.createSSLEngine();
|
||||
try {
|
||||
sslEngine.setEnabledCipherSuites(ciphers);
|
||||
} catch (Throwable t) {
|
||||
throw new ElasticsearchSSLException("Error loading cipher suites ["+Arrays.asList(ciphers)+"]", t);
|
||||
}
|
||||
sslEngine.setNeedClientAuth(clientAuth);
|
||||
return sslEngine;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,82 +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.shield.transport.ssl;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.security.KeyStore;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SSLTrustConfig {
|
||||
|
||||
private static final ESLogger logger = Loggers.getLogger(SSLTrustConfig.class);
|
||||
private final TrustManager[] trustManagers;
|
||||
private final String sslContextAlgorithm;
|
||||
|
||||
private SSLContext sslContext;
|
||||
|
||||
public SSLTrustConfig(Settings componentSettings, Settings defaultSettings) {
|
||||
this.sslContextAlgorithm = componentSettings.get("context_algorithm", defaultSettings.get("shield.ssl.context_algorithm", "TLS"));
|
||||
String trustStore = componentSettings.get("truststore", defaultSettings.get("truststore", System.getProperty("javax.net.ssl.trustStore")));
|
||||
String trustStorePassword = componentSettings.get("truststore_password", defaultSettings.get("truststore_password", System.getProperty("javax.net.ssl.trustStorePassword")));
|
||||
String trustStoreAlgorithm = componentSettings.get("truststore_algorithm", defaultSettings.get("truststore_algorithm", System.getProperty("ssl.TrustManagerFactory.algorithm")));
|
||||
|
||||
if (trustStore == null) {
|
||||
throw new ElasticsearchException("SSL Enabled, but truststore unconfigured");
|
||||
}
|
||||
|
||||
if (trustStoreAlgorithm == null) {
|
||||
trustStoreAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
||||
}
|
||||
|
||||
logger.debug("using trustStore[{}], trustAlgorithm[{}]", trustStore, trustStoreAlgorithm);
|
||||
|
||||
if (!new File(trustStore).exists()) {
|
||||
throw new ElasticsearchSSLException("Truststore at path ["+ trustStore +"] does not exist");
|
||||
}
|
||||
|
||||
try (FileInputStream in = new FileInputStream(trustStore)) {
|
||||
// Load TrustStore
|
||||
KeyStore ks = KeyStore.getInstance("jks");
|
||||
ks.load(in, trustStorePassword == null ? null : trustStorePassword.toCharArray());
|
||||
|
||||
// Initialize a trust manager factory with the trusted store
|
||||
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(trustStoreAlgorithm);
|
||||
trustFactory.init(ks);
|
||||
|
||||
// Retrieve the trust managers from the factory
|
||||
trustManagers = trustFactory.getTrustManagers();
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchException("Failed to initialize a TrustManagerFactory", e);
|
||||
}
|
||||
}
|
||||
|
||||
public SSLSocketFactory createSSLSocketFactory() {
|
||||
// Initialize sslContext
|
||||
try {
|
||||
sslContext = SSLContext.getInstance(sslContextAlgorithm);
|
||||
sslContext.init(null, trustManagers, null);
|
||||
} catch (Exception e) {
|
||||
throw new ElasticsearchSSLException("Failed to initialize the SSLContext", e);
|
||||
}
|
||||
return sslContext.getSocketFactory();
|
||||
}
|
||||
|
||||
public TrustManager[] getTrustManagers() {
|
||||
return trustManagers;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.shield.authc.ldap;
|
|||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.test.junit.annotations.Network;
|
||||
import org.hamcrest.Matchers;
|
||||
|
@ -29,9 +30,11 @@ public class ActiveDirectoryFactoryTests extends ElasticsearchTestCase {
|
|||
|
||||
@BeforeClass
|
||||
public static void setTrustStore() throws URISyntaxException {
|
||||
LdapSslSocketFactory.init(ImmutableSettings.builder()
|
||||
.put(SETTINGS_PREFIX + "truststore", new File(LdapConnectionTests.class.getResource("ldaptrust.jks").toURI()))
|
||||
.build());
|
||||
File filename = new File(LdapConnectionTests.class.getResource("ldaptrust.jks").toURI()).getAbsoluteFile();
|
||||
LdapSslSocketFactory.init(new SSLService(ImmutableSettings.builder()
|
||||
.put("shield.ssl.keystore", filename)
|
||||
.put("shield.ssl.keystore_password", "changeit")
|
||||
.build()));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.shield.authc.ldap;
|
|||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.shield.ShieldSettingsException;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -23,10 +24,11 @@ public class LdapSslSocketFactoryTests extends ElasticsearchTestCase {
|
|||
|
||||
@BeforeClass
|
||||
public static void setTrustStore() throws URISyntaxException {
|
||||
//LdapModule will set this up as a singleton normally
|
||||
LdapSslSocketFactory.init(ImmutableSettings.builder()
|
||||
.put("shield.authc.ldap.truststore", new File(LdapConnectionTests.class.getResource("ldaptrust.jks").toURI()))
|
||||
.build());
|
||||
File filename = new File(LdapConnectionTests.class.getResource("ldaptrust.jks").toURI()).getAbsoluteFile();
|
||||
LdapSslSocketFactory.init(new SSLService(ImmutableSettings.builder()
|
||||
.put("shield.ssl.keystore", filename)
|
||||
.put("shield.ssl.keystore_password", "changeit")
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.shield.authc.ldap;
|
|||
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.shield.authc.support.SecuredStringTests;
|
||||
import org.elasticsearch.shield.ssl.SSLService;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.elasticsearch.test.junit.annotations.Network;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -26,10 +27,11 @@ public class OpenLdapTests extends ElasticsearchTestCase {
|
|||
|
||||
@BeforeClass
|
||||
public static void setTrustStore() throws URISyntaxException {
|
||||
//LdapModule will set this up as a singleton normally
|
||||
LdapSslSocketFactory.init(ImmutableSettings.builder()
|
||||
.put(SETTINGS_PREFIX + "truststore", new File(LdapConnectionTests.class.getResource("ldaptrust.jks").toURI()))
|
||||
.build());
|
||||
File filename = new File(LdapConnectionTests.class.getResource("ldaptrust.jks").toURI()).getAbsoluteFile();
|
||||
LdapSslSocketFactory.init(new SSLService(ImmutableSettings.builder()
|
||||
.put("shield.ssl.keystore", filename)
|
||||
.put("shield.ssl.keystore_password", "changeit")
|
||||
.build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* 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 org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
public class SSLServiceTests extends ElasticsearchTestCase {
|
||||
|
||||
File testnodeStore;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
testnodeStore = new File(getClass().getResource("/org/elasticsearch/shield/transport/ssl/certs/simple/testnode.jks").toURI());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatInvalidProtocolThrowsException() throws Exception {
|
||||
try {
|
||||
new SSLService(settingsBuilder()
|
||||
.put("shield.ssl.protocol", "non-existing")
|
||||
.put("shield.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.ssl.keystore_password", "testnode")
|
||||
.put("shield.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.ssl.truststore_password", "testnode")
|
||||
.build());
|
||||
} catch (ElasticsearchSSLException e) {
|
||||
Assert.assertThat(e.getRootCause(), Matchers.instanceOf(NoSuchAlgorithmException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Ignore //TODO it appears that setting a specific protocol doesn't make a difference
|
||||
public void testSpecificProtocol() {
|
||||
SSLService ssl = new SSLService(settingsBuilder()
|
||||
.put("shield.ssl.protocol", "TLSv1.2")
|
||||
.put("shield.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.ssl.keystore_password", "testnode")
|
||||
.put("shield.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.ssl.truststore_password", "testnode")
|
||||
.build());
|
||||
Assert.assertThat(ssl.createSSLEngine().getSSLParameters().getProtocols(), Matchers.arrayContaining("TLSv1.2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSSLEnabled_allDefaults(){
|
||||
Settings settings = settingsBuilder().build();
|
||||
assertThat(SSLService.isSSLEnabled(settings), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSSLEnabled_transportOffHttpOffLdapOff(){
|
||||
|
||||
Settings settings = settingsBuilder()
|
||||
.put("shield.transport.ssl", false)
|
||||
.put("shield.http.ssl", false)
|
||||
.put("shield.authc.ldap.mode", "ldap")
|
||||
.put("shield.authc.ldap.url", "ldap://example.com:389")
|
||||
.build();
|
||||
assertThat(SSLService.isSSLEnabled(settings), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSSLEnabled_transportOffHttpOffLdapMissingUrl() {
|
||||
Settings settings = settingsBuilder()
|
||||
.put("shield.transport.ssl", false)
|
||||
.put("shield.http.ssl", false)
|
||||
.put("shield.authc.ldap.mode", "active_dir") //default for missing URL is
|
||||
.build();
|
||||
assertThat(SSLService.isSSLEnabled(settings), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSSLEnabled_transportOffHttpOffLdapOn(){
|
||||
Settings settings = settingsBuilder()
|
||||
.put("shield.transport.ssl", false)
|
||||
.put("shield.http.ssl", false)
|
||||
.put("shield.authc.ldap.mode", "ldap")
|
||||
.put("shield.authc.ldap.url", "ldaps://example.com:636")
|
||||
.build();
|
||||
assertThat(SSLService.isSSLEnabled(settings), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSSLEnabled_transportOffHttpOnLdapOff(){
|
||||
|
||||
Settings settings = settingsBuilder()
|
||||
.put("shield.transport.ssl", false)
|
||||
.put("shield.http.ssl", true)
|
||||
.put("shield.authc.ldap.mode", "ldap")
|
||||
.put("shield.authc.ldap.url", "ldap://example.com:389")
|
||||
.build();
|
||||
assertThat(SSLService.isSSLEnabled(settings), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSSLEnabled_transportOnHttpOffLdapOff(){
|
||||
Settings settings = settingsBuilder()
|
||||
.put("shield.transport.ssl", true)
|
||||
.put("shield.http.ssl", false)
|
||||
.put("shield.authc.ldap.mode", "ldap")
|
||||
.put("shield.authc.ldap.url", "ldap://example.com:389")
|
||||
.build();
|
||||
assertThat(SSLService.isSSLEnabled(settings), is(true));
|
||||
}
|
||||
}
|
|
@ -158,15 +158,11 @@ public abstract class ShieldIntegrationTest extends ElasticsearchIntegrationTest
|
|||
|
||||
ImmutableSettings.Builder builder = settingsBuilder()
|
||||
.put("shield.transport.ssl", true)
|
||||
.put("shield.transport.ssl.keystore", store.getPath())
|
||||
.put("shield.transport.ssl.keystore_password", password)
|
||||
.put("shield.transport.ssl.truststore", store.getPath())
|
||||
.put("shield.transport.ssl.truststore_password", password)
|
||||
.put("shield.http.ssl", true)
|
||||
.put("shield.http.ssl.keystore", store.getPath())
|
||||
.put("shield.http.ssl.keystore_password", password)
|
||||
.put("shield.http.ssl.truststore", store.getPath())
|
||||
.put("shield.http.ssl.truststore_password", password);
|
||||
.put("shield.ssl.keystore", store.getPath())
|
||||
.put("shield.ssl.keystore_password", password)
|
||||
.put("shield.ssl.truststore", store.getPath())
|
||||
.put("shield.ssl.truststore_password", password)
|
||||
.put("shield.http.ssl", true);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
@ -1,69 +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.shield.transport.ssl;
|
||||
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import java.io.File;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class SSLConfigTests extends ElasticsearchTestCase {
|
||||
|
||||
File testnodeStore;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
testnodeStore = new File(getClass().getResource("certs/simple/testnode.jks").toURI());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatInvalidContextAlgoThrowsException() throws Exception {
|
||||
try {
|
||||
new SSLConfig(ImmutableSettings.EMPTY,
|
||||
settingsBuilder()
|
||||
.put("context_algorithm", "non-existing")
|
||||
.put("keystore", testnodeStore.getPath())
|
||||
.put("keystore_password", "testnode")
|
||||
.put("truststore", testnodeStore.getPath())
|
||||
.put("truststore_password", "testnode")
|
||||
.build(), false);
|
||||
} catch (ElasticsearchSSLException e) {
|
||||
assertThat(e.getRootCause(), instanceOf(NoSuchAlgorithmException.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThatExactConfigOverwritesDefaultConfig() throws Exception {
|
||||
//
|
||||
Settings concreteSettings = settingsBuilder()
|
||||
.put("ciphers", "TLS_RSA_WITH_AES_128_CBC_SHA")
|
||||
.build();
|
||||
|
||||
Settings genericSettings = settingsBuilder()
|
||||
.putArray("shield.ssl.ciphers", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA")
|
||||
.put("shield.ssl.keystore", testnodeStore.getPath())
|
||||
.put("shield.ssl.keystore_password", "testnode")
|
||||
.put("shield.ssl.truststore", testnodeStore.getPath())
|
||||
.put("shield.ssl.truststore_password", "testnode")
|
||||
.build();
|
||||
|
||||
SSLConfig sslConfig = new SSLConfig(concreteSettings, genericSettings.getByPrefix("shield.ssl."), false);
|
||||
SSLEngine sslEngine = sslConfig.createSSLEngine();
|
||||
assertThat(sslEngine.getEnabledCipherSuites().length, is(1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -82,7 +82,7 @@ public class SslIntegrationTests extends ShieldIntegrationTest {
|
|||
.put(transportClientSettings())
|
||||
.put("name", "programmatic_transport_client")
|
||||
.put("cluster.name", internalCluster().getClusterName())
|
||||
.putArray("shield.transport.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"})
|
||||
.putArray("shield.ssl.ciphers", new String[]{"TLS_ECDH_anon_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA"})
|
||||
.build())) {
|
||||
|
||||
TransportAddress transportAddress = internalCluster().getInstance(Transport.class).boundAddress().boundAddress();
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.elasticsearch.http.HttpServerTransport;
|
|||
import org.elasticsearch.node.internal.InternalNode;
|
||||
import org.elasticsearch.shield.authc.support.UsernamePasswordToken;
|
||||
import org.elasticsearch.shield.test.ShieldIntegrationTest;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.net.ssl.*;
|
||||
|
@ -66,6 +67,7 @@ public class SslRequireAuthTests extends ShieldIntegrationTest {
|
|||
}
|
||||
|
||||
|
||||
@Ignore //clients-certs are no longer configured for http
|
||||
@Test(expected = SSLHandshakeException.class)
|
||||
public void testThatRequireClientAuthRejectsWithoutCert() throws Exception {
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue