Remove netty_3 support from xpack (elastic/elasticsearch#4097)

This is a followup from elastic/elasticsearchelastic/elasticsearch#21590 and needs to be
committed first or at the same time since netty_3 is removed

Original commit: elastic/x-pack-elasticsearch@131d74dd6b
This commit is contained in:
Simon Willnauer 2016-11-17 12:44:24 +01:00 committed by GitHub
parent a5e410ba59
commit 92040ef72e
53 changed files with 479 additions and 1836 deletions

View File

@ -31,7 +31,6 @@ licenseHeaders {
dependencies {
// security deps
compile project(path: ':modules:transport-netty3', configuration: 'runtime')
compile project(path: ':modules:transport-netty4', configuration: 'runtime')
compile 'com.unboundid:unboundid-ldapsdk:3.2.0'
compile 'org.bouncycastle:bcprov-jdk15on:1.55'

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.common.http;
import io.netty.handler.codec.http.HttpHeaders;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseFieldMatcher;
@ -21,7 +22,6 @@ import org.elasticsearch.xpack.common.http.auth.HttpAuthRegistry;
import org.elasticsearch.xpack.common.text.TextTemplate;
import org.elasticsearch.xpack.common.text.TextTemplateEngine;
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import java.io.IOException;
import java.net.URI;

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.common.http;
import io.netty.handler.codec.http.HttpHeaders;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
@ -16,7 +17,6 @@ import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import java.io.IOException;
import java.util.ArrayList;

View File

@ -114,8 +114,6 @@ import org.elasticsearch.xpack.security.rest.action.user.RestPutUserAction;
import org.elasticsearch.xpack.security.rest.action.user.RestSetEnabledAction;
import org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3HttpServerTransport;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4HttpServerTransport;
import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.security.user.AnonymousUser;
@ -145,7 +143,6 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
private static final Logger logger = Loggers.getLogger(XPackPlugin.class);
public static final String NAME3 = XPackPlugin.SECURITY + "3";
public static final String NAME4 = XPackPlugin.SECURITY + "4";
public static final Setting<Optional<String>> USER_SETTING =
new Setting<>(setting("user"), (String) null, Optional::ofNullable, Property.NodeScope);
@ -354,9 +351,9 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
if (NetworkModule.TRANSPORT_TYPE_SETTING.exists(settings)) {
final String transportType = NetworkModule.TRANSPORT_TYPE_SETTING.get(settings);
if (NAME3.equals(transportType) == false && NAME4.equals(transportType) == false) {
throw new IllegalArgumentException("transport type setting [" + NetworkModule.TRANSPORT_TYPE_KEY + "] must be one of [" +
NAME3 + "," + NAME4 + "]");
if (NAME4.equals(transportType) == false) {
throw new IllegalArgumentException("transport type setting [" + NetworkModule.TRANSPORT_TYPE_KEY + "] must be [" + NAME4
+ "]");
}
} else {
// default to security4
@ -365,13 +362,10 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
if (NetworkModule.HTTP_TYPE_SETTING.exists(settings)) {
final String httpType = NetworkModule.HTTP_TYPE_SETTING.get(settings);
if (httpType.equals(NAME3)) {
SecurityNetty3HttpServerTransport.overrideSettings(settingsBuilder, settings);
} else if (httpType.equals(NAME4)) {
if (httpType.equals(NAME4)) {
SecurityNetty4HttpServerTransport.overrideSettings(settingsBuilder, settings);
} else {
throw new IllegalArgumentException("http type setting [" + NetworkModule.HTTP_TYPE_KEY + "] must be one of [" +
NAME3 + "," + NAME4 + "]");
throw new IllegalArgumentException("http type setting [" + NetworkModule.HTTP_TYPE_KEY + "] must be [" + NAME4 + "]");
}
} else {
// default to security4
@ -714,13 +708,8 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
if (enabled == false) { // don't register anything if we are not enabled
return Collections.emptyMap();
}
Map<String, Supplier<Transport>> map = new HashMap<>();
map.put(Security.NAME3, () -> new SecurityNetty3Transport(settings, threadPool, networkService, bigArrays, ipFilter.get(),
sslService, namedWriteableRegistry, circuitBreakerService));
map.put(Security.NAME4, () -> new SecurityNetty4Transport(settings, threadPool, networkService, bigArrays,
return Collections.singletonMap(Security.NAME4, () -> new SecurityNetty4Transport(settings, threadPool, networkService, bigArrays,
namedWriteableRegistry, circuitBreakerService, ipFilter.get(), sslService));
return Collections.unmodifiableMap(map);
}
@Override
@ -731,12 +720,9 @@ public class Security implements ActionPlugin, IngestPlugin, NetworkPlugin {
if (enabled == false) { // don't register anything if we are not enabled
return Collections.emptyMap();
}
Map<String, Supplier<HttpServerTransport>> map = new HashMap<>();
map.put(Security.NAME3, () -> new SecurityNetty3HttpServerTransport(settings, networkService, bigArrays, ipFilter.get(), sslService,
return Collections.singletonMap(Security.NAME4, () -> new SecurityNetty4HttpServerTransport(settings, networkService, bigArrays,
ipFilter.get(), sslService,
threadPool));
map.put(Security.NAME4, () -> new SecurityNetty4HttpServerTransport(settings, networkService, bigArrays, ipFilter.get(), sslService,
threadPool));
return Collections.unmodifiableMap(map);
}
}

View File

@ -16,6 +16,7 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.security.Security;
import org.elasticsearch.xpack.security.authc.Realms;
import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.ssl.CertUtils;
import org.elasticsearch.xpack.ssl.SSLService;
import org.elasticsearch.xpack.security.user.User;
@ -23,7 +24,6 @@ import org.elasticsearch.xpack.security.authc.AuthenticationToken;
import org.elasticsearch.xpack.security.authc.Realm;
import org.elasticsearch.xpack.security.authc.RealmConfig;
import org.elasticsearch.xpack.security.authc.support.DnRoleMapper;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
@ -226,9 +226,9 @@ public class PkiRealm extends Realm {
Map<String, Settings> groupedSettings = settings.getGroups("transport.profiles.");
for (Map.Entry<String, Settings> entry : groupedSettings.entrySet()) {
Settings profileSettings = entry.getValue().getByPrefix(Security.settingPrefix());
if (SecurityNetty3Transport.PROFILE_SSL_SETTING.get(profileSettings)
if (SecurityNetty4Transport.PROFILE_SSL_SETTING.get(profileSettings)
&& sslService.isSSLClientAuthEnabled(
SecurityNetty3Transport.profileSslSettings(profileSettings), transportSSLSettings)) {
SecurityNetty4Transport.profileSslSettings(profileSettings), transportSSLSettings)) {
return;
}
}

View File

@ -5,16 +5,14 @@
*/
package org.elasticsearch.xpack.security.rest;
import io.netty.handler.ssl.SslHandler;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.http.netty3.Netty3HttpRequest;
import org.elasticsearch.http.netty4.Netty4HttpRequest;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.rest.RestChannel;
@ -25,14 +23,9 @@ import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestRequest.Method;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import org.elasticsearch.xpack.security.transport.ServerTransportFilter;
import org.elasticsearch.xpack.ssl.SSLService;
import org.jboss.netty.handler.ssl.SslHandler;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLPeerUnverifiedException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import static org.elasticsearch.xpack.XPackSettings.HTTP_SSL_ENABLED;
@ -70,7 +63,10 @@ public class SecurityRestFilter extends RestFilter {
if (licenseState.isAuthAllowed() && request.method() != Method.OPTIONS) {
// CORS - allow for preflight unauthenticated OPTIONS request
if (extractClientCertificate) {
putClientCertificateInContext(request, threadContext, logger);
Netty4HttpRequest nettyHttpRequest = (Netty4HttpRequest) request;
SslHandler handler = nettyHttpRequest.getChannel().pipeline().get(SslHandler.class);
assert handler != null;
ServerTransportFilter.extactClientCertificates(logger, threadContext, handler.engine(), nettyHttpRequest.getChannel());
}
service.authenticate(request, ActionListener.wrap((authentication) -> {
RemoteHostHeader.process(request, threadContext);
@ -80,42 +76,4 @@ public class SecurityRestFilter extends RestFilter {
filterChain.continueProcessing(request, channel, client);
}
}
static void putClientCertificateInContext(RestRequest request, ThreadContext threadContext, Logger logger) throws Exception {
assert request instanceof Netty3HttpRequest || request instanceof Netty4HttpRequest;
if (request instanceof Netty3HttpRequest) {
Netty3HttpRequest nettyHttpRequest = (Netty3HttpRequest) request;
SslHandler handler = nettyHttpRequest.getChannel().getPipeline().get(SslHandler.class);
assert handler != null;
extractClientCerts(handler.getEngine(), nettyHttpRequest.getChannel(), threadContext, logger);
} else if (request instanceof Netty4HttpRequest) {
Netty4HttpRequest nettyHttpRequest = (Netty4HttpRequest) request;
io.netty.handler.ssl.SslHandler handler = nettyHttpRequest.getChannel().pipeline().get(io.netty.handler.ssl.SslHandler.class);
assert handler != null;
extractClientCerts(handler.engine(), nettyHttpRequest.getChannel(), threadContext, logger);
}
}
private static void extractClientCerts(SSLEngine sslEngine, Object channel, ThreadContext threadContext, Logger logger) {
try {
Certificate[] certs = sslEngine.getSession().getPeerCertificates();
if (certs instanceof X509Certificate[]) {
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, certs);
}
} catch (SSLPeerUnverifiedException e) {
// this happens when client authentication is optional and the client does not provide credentials. If client
// authentication was required then this connection should be closed before ever getting into this class
assert sslEngine.getNeedClientAuth() == false;
assert sslEngine.getWantClientAuth();
if (logger.isTraceEnabled()) {
logger.trace(
(Supplier<?>) () -> new ParameterizedMessage("SSL Peer did not present a certificate on channel [{}]", channel), e);
} else if (logger.isDebugEnabled()) {
logger.debug("SSL Peer did not present a certificate on channel [{}]", channel);
}
}
}
}

View File

@ -5,7 +5,8 @@
*/
package org.elasticsearch.xpack.security.transport;
import org.jboss.netty.handler.ssl.NotSslRecordException;
import io.netty.handler.ssl.NotSslRecordException;
import javax.net.ssl.SSLException;

View File

@ -28,7 +28,7 @@ import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.AuthorizationUtils;
import org.elasticsearch.xpack.security.authz.accesscontrol.RequestContext;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
import org.elasticsearch.xpack.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.security.user.SystemUser;
import org.elasticsearch.xpack.ssl.SSLService;
@ -125,8 +125,8 @@ public class SecurityServerTransportInterceptor implements TransportInterceptor
final Settings transportSSLSettings = settings.getByPrefix(setting("transport.ssl."));
for (Map.Entry<String, Settings> entry : profileSettingsMap.entrySet()) {
Settings profileSettings = entry.getValue();
final boolean profileSsl = SecurityNetty3Transport.PROFILE_SSL_SETTING.get(profileSettings);
final Settings profileSslSettings = SecurityNetty3Transport.profileSslSettings(profileSettings);
final boolean profileSsl = SecurityNetty4Transport.PROFILE_SSL_SETTING.get(profileSettings);
final Settings profileSslSettings = SecurityNetty4Transport.profileSslSettings(profileSettings);
final boolean clientAuth = sslService.isSSLClientAuthEnabled(profileSslSettings, transportSSLSettings);
final boolean extractClientCert = profileSsl && clientAuth;
String type = entry.getValue().get(SETTING_NAME, "node");
@ -152,10 +152,6 @@ public class SecurityServerTransportInterceptor implements TransportInterceptor
return Collections.unmodifiableMap(profileFilters);
}
ServerTransportFilter transportFilter(String profile) {
return profileFilters.get(profile);
}
public static class ProfileSecuredRequestHandler<T extends TransportRequest> implements TransportRequestHandler<T> {
protected final String action;

View File

@ -5,6 +5,8 @@
*/
package org.elasticsearch.xpack.security.transport;
import io.netty.channel.Channel;
import io.netty.handler.ssl.SslHandler;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
@ -25,8 +27,6 @@ import org.elasticsearch.xpack.security.authc.AuthenticationService;
import org.elasticsearch.xpack.security.authc.pki.PkiRealm;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.AuthorizationUtils;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.handler.ssl.SslHandler;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLPeerUnverifiedException;
@ -100,19 +100,13 @@ public interface ServerTransportFilter {
unwrappedChannel = ((DelegatingTransportChannel) unwrappedChannel).getChannel();
}
if (extractClientCert && (unwrappedChannel instanceof TcpTransportChannel)) {
if (((TcpTransportChannel) unwrappedChannel).getChannel() instanceof Channel) {
Channel channel = (Channel) ((TcpTransportChannel) unwrappedChannel).getChannel();
SslHandler sslHandler = channel.getPipeline().get(SslHandler.class);
assert sslHandler != null;
extactClientCertificates(sslHandler.getEngine(), channel);
} else if (((TcpTransportChannel) unwrappedChannel).getChannel() instanceof io.netty.channel.Channel) {
io.netty.channel.Channel channel = (io.netty.channel.Channel) ((TcpTransportChannel) unwrappedChannel).getChannel();
io.netty.handler.ssl.SslHandler sslHandler = channel.pipeline().get(io.netty.handler.ssl.SslHandler.class);
if (channel.isOpen()) {
assert sslHandler != null : "channel [" + channel + "] did not have a ssl handler. pipeline " + channel.pipeline();
extactClientCertificates(sslHandler.engine(), channel);
}
if (extractClientCert && (unwrappedChannel instanceof TcpTransportChannel) &&
((TcpTransportChannel) unwrappedChannel).getChannel() instanceof io.netty.channel.Channel) {
Channel channel = (io.netty.channel.Channel) ((TcpTransportChannel) unwrappedChannel).getChannel();
SslHandler sslHandler = channel.pipeline().get(SslHandler.class);
if (channel.isOpen()) {
assert sslHandler != null : "channel [" + channel + "] did not have a ssl handler. pipeline " + channel.pipeline();
extactClientCertificates(logger, threadContext, sslHandler.engine(), channel);
}
}
@ -125,25 +119,25 @@ public interface ServerTransportFilter {
asyncAuthorizer.authorize(authzService);
}, listener::onFailure));
}
}
private void extactClientCertificates(SSLEngine sslEngine, Object channel) {
try {
Certificate[] certs = sslEngine.getSession().getPeerCertificates();
if (certs instanceof X509Certificate[]) {
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, certs);
}
} catch (SSLPeerUnverifiedException e) {
// this happens when client authentication is optional and the client does not provide credentials. If client
// authentication was required then this connection should be closed before ever getting into this class
assert sslEngine.getNeedClientAuth() == false;
assert sslEngine.getWantClientAuth();
if (logger.isTraceEnabled()) {
logger.trace(
(Supplier<?>) () -> new ParameterizedMessage(
"SSL Peer did not present a certificate on channel [{}]", channel), e);
} else if (logger.isDebugEnabled()) {
logger.debug("SSL Peer did not present a certificate on channel [{}]", channel);
}
static void extactClientCertificates(Logger logger, ThreadContext threadContext, SSLEngine sslEngine, Object channel) {
try {
Certificate[] certs = sslEngine.getSession().getPeerCertificates();
if (certs instanceof X509Certificate[]) {
threadContext.putTransient(PkiRealm.PKI_CERT_HEADER_NAME, certs);
}
} catch (SSLPeerUnverifiedException e) {
// this happens when client authentication is optional and the client does not provide credentials. If client
// authentication was required then this connection should be closed before ever getting into this class
assert sslEngine.getNeedClientAuth() == false;
assert sslEngine.getWantClientAuth();
if (logger.isTraceEnabled()) {
logger.trace(
(Supplier<?>) () -> new ParameterizedMessage(
"SSL Peer did not present a certificate on channel [{}]", channel), e);
} else if (logger.isDebugEnabled()) {
logger.debug("SSL Peer did not present a certificate on channel [{}]", channel);
}
}
}

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.security.transport.filter;
import io.netty.handler.ipfilter.IpFilterRuleType;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.util.SetOnce;
import org.elasticsearch.common.collect.MapBuilder;
@ -22,6 +23,7 @@ import org.elasticsearch.transport.TransportSettings;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -76,19 +78,15 @@ public class IPFilter {
.immutableMap();
public static final SecurityIpFilterRule DEFAULT_PROFILE_ACCEPT_ALL = new SecurityIpFilterRule(true, "default:accept_all") {
@Override
public boolean contains(InetAddress inetAddress) {
public boolean matches(InetSocketAddress remoteAddress) {
return true;
}
@Override
public boolean isAllowRule() {
return true;
}
@Override
public boolean isDenyRule() {
return false;
public IpFilterRuleType ruleType() {
return IpFilterRuleType.ACCEPT;
}
};
@ -179,7 +177,7 @@ public class IPFilter {
updateRules();
}
public boolean accept(String profile, InetAddress peerAddress) {
public boolean accept(String profile, InetSocketAddress peerAddress) {
if (licenseState.isIpFilteringAllowed() == false) {
return true;
}
@ -190,18 +188,18 @@ public class IPFilter {
}
for (SecurityIpFilterRule rule : rules.get(profile)) {
if (rule.contains(peerAddress)) {
boolean isAllowed = rule.isAllowRule();
if (rule.matches(peerAddress)) {
boolean isAllowed = rule.ruleType() == IpFilterRuleType.ACCEPT;
if (isAllowed) {
auditTrail.connectionGranted(peerAddress, profile, rule);
auditTrail.connectionGranted(peerAddress.getAddress(), profile, rule);
} else {
auditTrail.connectionDenied(peerAddress, profile, rule);
auditTrail.connectionDenied(peerAddress.getAddress(), profile, rule);
}
return isAllowed;
}
}
auditTrail.connectionGranted(peerAddress, profile, DEFAULT_PROFILE_ACCEPT_ALL);
auditTrail.connectionGranted(peerAddress.getAddress(), profile, DEFAULT_PROFILE_ACCEPT_ALL);
return true;
}

View File

@ -0,0 +1,159 @@
/*
* 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.filter;
import io.netty.handler.ipfilter.IpFilterRule;
import io.netty.handler.ipfilter.IpFilterRuleType;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.network.NetworkAddress;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.regex.Pattern;
/**
* The Class PatternRule represents an IP filter rule using string patterns.
* <br>
* Rule Syntax:
* <br>
* <pre>
* Rule ::= [n|i]:address n stands for computer name, i for ip address
* address ::= &lt;regex&gt; | localhost
* regex is a regular expression with '*' as multi character and '?' as single character wild card
* </pre>
* <br>
* Example: allow localhost:
* <br>
* new PatternRule(true, "n:localhost")
* <br>
* Example: allow local lan:
* <br>
* new PatternRule(true, "i:192.168.0.*")
* <br>
* Example: block all
* <br>
* new PatternRule(false, "n:*")
* <br>
*/
// this has been adopted from Netty3 there is no replacement in netty4 for this.
final class PatternRule implements IpFilterRule {
private final Pattern ipPattern;
private final Pattern namePattern;
private final IpFilterRuleType ruleType;
private final boolean localhost;
private final String pattern;
/**
* Instantiates a new pattern rule.
*
* @param ruleType indicates if this is an allow or block rule
* @param pattern the filter pattern
*/
PatternRule(IpFilterRuleType ruleType, String pattern) {
this.ruleType = ruleType;
this.pattern = pattern;
Pattern namePattern = null;
Pattern ipPattern = null;
boolean localhost = false;
if (pattern != null) {
String[] acls = pattern.split(",");
String ip = "";
String name = "";
for (String c : acls) {
c = c.trim();
if ("n:localhost".equals(c)) {
localhost = true;
} else if (c.startsWith("n:")) {
name = addRule(name, c.substring(2));
} else if (c.startsWith("i:")) {
ip = addRule(ip, c.substring(2));
}
}
if (ip.length() != 0) {
ipPattern = Pattern.compile(ip);
}
if (name.length() != 0) {
namePattern = Pattern.compile(name);
}
}
this.ipPattern = ipPattern;
this.namePattern = namePattern;
this.localhost = localhost;
}
/**
* returns the pattern.
*
* @return the pattern
*/
String getPattern() {
return pattern;
}
private static String addRule(String pattern, String rule) {
if (rule == null || rule.length() == 0) {
return pattern;
}
if (pattern.length() != 0) {
pattern += "|";
}
rule = rule.replaceAll("\\.", "\\\\.");
rule = rule.replaceAll("\\*", ".*");
rule = rule.replaceAll("\\?", ".");
pattern += '(' + rule + ')';
return pattern;
}
private boolean isLocalhost(InetAddress address) {
try {
return address.isAnyLocalAddress() || address.isLoopbackAddress() || NetworkInterface.getByInetAddress(address) != null;
} catch (SocketException e) {
// not defined - ie. it's not a local address
return false;
}
}
@Override
public boolean matches(InetSocketAddress remoteAddress) {
InetAddress inetAddress = remoteAddress.getAddress();
if (localhost) {
if (isLocalhost(inetAddress)) {
return true;
}
}
if (ipPattern != null) {
String format = NetworkAddress.format(inetAddress);
if (ipPattern.matcher(format).matches()) {
return true;
}
}
return checkHostName(inetAddress);
}
@SuppressForbidden(reason = "we compare the hostname of the address this is how netty3 did it and we keep it for BWC")
private boolean checkHostName(InetAddress address) {
if (namePattern != null) {
if (namePattern.matcher(address.getHostName()).matches()) {
return true;
}
}
return false;
}
@Override
public IpFilterRuleType ruleType() {
return ruleType;
}
boolean isLocalhost() {
return localhost;
}
}

View File

@ -5,17 +5,24 @@
*/
package org.elasticsearch.xpack.security.transport.filter;
import io.netty.handler.ipfilter.IpFilterRule;
import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.jboss.netty.handler.ipfilter.IpFilterRule;
import org.jboss.netty.handler.ipfilter.IpSubnetFilterRule;
import org.jboss.netty.handler.ipfilter.PatternRule;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringJoiner;
import java.util.StringTokenizer;
/**
* decorator class to have a useful toString() method for an IpFilterRule
@ -25,36 +32,25 @@ public class SecurityIpFilterRule implements IpFilterRule {
public static final SecurityIpFilterRule ACCEPT_ALL = new SecurityIpFilterRule(true, "accept_all") {
@Override
public boolean contains(InetAddress inetAddress) {
public boolean matches(InetSocketAddress remoteAddress) {
return true;
}
@Override
public boolean isAllowRule() {
return true;
}
@Override
public boolean isDenyRule() {
return false;
public IpFilterRuleType ruleType() {
return IpFilterRuleType.ACCEPT;
}
};
public static final SecurityIpFilterRule DENY_ALL = new SecurityIpFilterRule(true, "deny_all") {
@Override
public boolean contains(InetAddress inetAddress) {
public boolean matches(InetSocketAddress remoteAddress) {
return true;
}
@Override
public boolean isAllowRule() {
return false;
}
@Override
public boolean isDenyRule() {
return true;
public IpFilterRuleType ruleType() {
return IpFilterRuleType.REJECT;
}
};
@ -71,25 +67,10 @@ public class SecurityIpFilterRule implements IpFilterRule {
this.ipFilterRule = getRule(isAllowRule, ruleSpec);
}
@Override
public boolean contains(InetAddress inetAddress) {
return ipFilterRule.contains(inetAddress);
}
@Override
public boolean isAllowRule() {
return ipFilterRule.isAllowRule();
}
@Override
public boolean isDenyRule() {
return ipFilterRule.isDenyRule();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (isAllowRule()) {
if (ruleType() == IpFilterRuleType.ACCEPT) {
builder.append("allow ");
} else {
builder.append("deny ");
@ -99,7 +80,76 @@ public class SecurityIpFilterRule implements IpFilterRule {
return builder.toString();
}
static Tuple<InetAddress, Integer> parseSubnetMask(String address) throws UnknownHostException {
int p = address.indexOf('/');
if (p < 0) {
throw new UnknownHostException("Invalid CIDR notation used: " + address);
}
if (p == address.length() -1) {
throw new IllegalArgumentException("address must not end with a '/");
}
String addrString = address.substring(0, p);
String maskString = address.substring(p + 1);
InetAddress addr = InetAddress.getByName(addrString);
int mask;
if (maskString.indexOf('.') < 0) {
mask = parseInt(maskString, -1);
} else {
mask = getNetMask(maskString);
if (addr instanceof Inet6Address) {
mask += 96;
}
}
if (mask < 0) {
throw new UnknownHostException("Invalid mask length used: " + maskString);
}
return new Tuple<>(addr, mask);
}
/**
* Get the Subnet's Netmask in Decimal format.<BR>
* i.e.: getNetMask("255.255.255.0") returns the integer CIDR mask
*
* @param netMask a network mask
* @return the integer CIDR mask
*/
private static int getNetMask(String netMask) {
StringTokenizer nm = new StringTokenizer(netMask, ".");
int i = 0;
int[] netmask = new int[4];
while (nm.hasMoreTokens()) {
netmask[i] = Integer.parseInt(nm.nextToken());
i++;
}
int mask1 = 0;
for (i = 0; i < 4; i++) {
mask1 += Integer.bitCount(netmask[i]);
}
return mask1;
}
/**
* @param intstr a string containing an integer.
* @param def the default if the string does not contain a valid
* integer.
* @return the inetAddress from the integer
*/
private static int parseInt(String intstr, int def) {
Integer res;
if (intstr == null) {
return def;
}
try {
res = Integer.decode(intstr);
} catch (Exception e) {
res = def;
}
return res.intValue();
}
static IpFilterRule getRule(boolean isAllowRule, String value) {
IpFilterRuleType filterRuleType = isAllowRule ? IpFilterRuleType.ACCEPT : IpFilterRuleType.REJECT;
String[] values = value.split(",");
int allRuleIndex = Arrays.binarySearch(values, 0, values.length, "_all");
if (allRuleIndex >= 0) {
@ -111,36 +161,34 @@ public class SecurityIpFilterRule implements IpFilterRule {
}
if (value.contains("/")) {
// subnet rule...
if (values.length != 1) {
throw new IllegalArgumentException("multiple subnet filters cannot be specified in a single rule!");
}
try {
return new IpSubnetFilterRule(isAllowRule, value);
Tuple<InetAddress, Integer> inetAddressIntegerTuple = parseSubnetMask(value);
return new IpSubnetFilterRule(inetAddressIntegerTuple.v1(), inetAddressIntegerTuple.v2(), filterRuleType);
} catch (UnknownHostException e) {
String ruleType = (isAllowRule ? "allow " : "deny ");
throw new ElasticsearchException("unable to create ip filter for rule [" + ruleType + " " + value + "]", e);
}
}
boolean firstAdded = false;
StringBuilder ruleSpec = new StringBuilder();
for (String singleValue : values) {
if (firstAdded) {
ruleSpec.append(",");
} else {
firstAdded = true;
} else {
// pattern rule - not netmask
StringJoiner rules = new StringJoiner(",");
for (String pattern : values) {
if (InetAddresses.isInetAddress(pattern)) {
// we want the inet addresses to be normalized especially in the IPv6 case where :0:0: is equivalent to ::
// that's why we convert the address here and then format since PatternRule also uses the formatting to normalize
// the value we are matching against
InetAddress inetAddress = InetAddresses.forString(pattern);
pattern = "i:" + NetworkAddress.format(inetAddress);
} else {
pattern = "n:" + pattern;
}
rules.add(pattern);
}
boolean isInetAddress = InetAddresses.isInetAddress(singleValue);
if (isInetAddress) {
ruleSpec.append("i:");
} else {
ruleSpec.append("n:");
}
ruleSpec.append(singleValue);
return new PatternRule(filterRuleType, rules.toString());
}
return new PatternRule(isAllowRule, ruleSpec.toString());
}
static String getRuleSpec(TransportAddress... addresses) {
@ -157,4 +205,14 @@ public class SecurityIpFilterRule implements IpFilterRule {
}
return ruleSpec.toString();
}
@Override
public boolean matches(InetSocketAddress remoteAddress) {
return ipFilterRule.matches(remoteAddress);
}
@Override
public IpFilterRuleType ruleType() {
return ipFilterRule.ruleType();
}
}

View File

@ -1,34 +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.netty3;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.ipfilter.IpFilteringHandlerImpl;
import java.net.InetSocketAddress;
@ChannelHandler.Sharable
public class IPFilterNetty3UpstreamHandler extends IpFilteringHandlerImpl {
private final IPFilter filter;
private final String profile;
public IPFilterNetty3UpstreamHandler(IPFilter filter, String profile) {
this.filter = filter;
this.profile = profile;
}
@Override
protected boolean accept(ChannelHandlerContext channelHandlerContext, ChannelEvent channelEvent, InetSocketAddress inetSocketAddress)
throws Exception {
// at this stage no auth has happened, so we do not have any principal anyway
return filter.accept(profile, inetSocketAddress.getAddress());
}
}

View File

@ -1,129 +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.netty3;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.DownstreamMessageEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.handler.ssl.SslHandler;
import java.util.LinkedList;
import java.util.Queue;
/**
* Netty requires that nothing be written to the channel prior to the handshake. Writing before the handshake
* completes, results in odd SSLExceptions being thrown. Channel writes can happen from any thread that
* can access the channel and Netty does not provide a way to ensure the handshake has occurred before the
* application writes to the channel. This handler will queue up writes until the handshake has occurred and
* then will pass the writes through the pipeline. After all writes have been completed, this handler removes
* itself from the pipeline.
*
* NOTE: This class assumes that the transport will not use a closed channel again or attempt to reconnect, which
* is the way that Netty3Transport currently works
*/
public class Netty3HandshakeWaitingHandler extends SimpleChannelHandler {
private final Logger logger;
private boolean handshaken = false;
private Queue<MessageEvent> pendingWrites = new LinkedList<>();
/**
* @param logger We pass a context aware logger here (logger that is aware of the node name &amp; env)
*/
public Netty3HandshakeWaitingHandler(Logger logger) {
this.logger = logger;
}
@Override
public void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception {
SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
final ChannelFuture handshakeFuture = sslHandler.handshake();
handshakeFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (handshakeFuture.isSuccess()) {
logger.debug("SSL/TLS handshake completed for channel");
// We synchronize here to allow all pending writes to be processed prior to any writes coming from
// another thread
synchronized (Netty3HandshakeWaitingHandler.this) {
handshaken = true;
while (!pendingWrites.isEmpty()) {
MessageEvent event = pendingWrites.remove();
ctx.sendDownstream(event);
}
ctx.getPipeline().remove(Netty3HandshakeWaitingHandler.class);
}
ctx.sendUpstream(e);
} else {
Throwable cause = handshakeFuture.getCause();
if (logger.isDebugEnabled()) {
logger.debug(
(Supplier<?>) () -> new ParameterizedMessage(
"SSL/TLS handshake failed, closing channel: {}", cause.getMessage()), cause);
} else {
logger.error("SSL/TLS handshake failed, closing channel: {}", cause.getMessage());
}
synchronized (Netty3HandshakeWaitingHandler.this) {
// Set failure on the futures of each message so that listeners are called
while (!pendingWrites.isEmpty()) {
DownstreamMessageEvent event = (DownstreamMessageEvent) pendingWrites.remove();
event.getFuture().setFailure(cause);
}
// Some writes may be waiting to acquire lock, if so the SetFailureOnAddQueue will set
// failure on their futures
pendingWrites = new SetFailureOnAddQueue(cause);
handshakeFuture.getChannel().close();
}
}
}
});
}
@Override
public synchronized void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
// Writes can come from any thread so we need to ensure that we do not let any through
// until handshake has completed
if (!handshaken) {
pendingWrites.add(e);
return;
}
ctx.sendDownstream(e);
}
synchronized boolean hasPendingWrites() {
return !pendingWrites.isEmpty();
}
private static class SetFailureOnAddQueue extends LinkedList<MessageEvent> {
private final Throwable cause;
SetFailureOnAddQueue(Throwable cause) {
super();
this.cause = cause;
}
@Override
public boolean add(MessageEvent messageEvent) {
DownstreamMessageEvent event = (DownstreamMessageEvent) messageEvent;
event.getFuture().setFailure(cause);
return false;
}
}
}

View File

@ -1,115 +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.netty3;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.http.netty3.Netty3HttpServerTransport;
import org.elasticsearch.xpack.ssl.SSLService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.handler.ssl.SslHandler;
import javax.net.ssl.SSLEngine;
import static org.elasticsearch.http.HttpTransportSettings.SETTING_HTTP_COMPRESSION;
import static org.elasticsearch.xpack.security.transport.SSLExceptionHelper.isCloseDuringHandshakeException;
import static org.elasticsearch.xpack.security.transport.SSLExceptionHelper.isNotSslRecordException;
import static org.elasticsearch.xpack.XPackSettings.HTTP_SSL_ENABLED;
public class SecurityNetty3HttpServerTransport extends Netty3HttpServerTransport {
private final IPFilter ipFilter;
private final SSLService sslService;
private final boolean ssl;
public SecurityNetty3HttpServerTransport(Settings settings, NetworkService networkService, BigArrays bigArrays, IPFilter ipFilter,
SSLService sslService, ThreadPool threadPool) {
super(settings, networkService, bigArrays, threadPool);
this.ipFilter = ipFilter;
this.sslService = sslService;
this.ssl = HTTP_SSL_ENABLED.get(settings);
}
@Override
protected void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
if (!lifecycle.started()) {
return;
}
Throwable t = e.getCause();
if (isNotSslRecordException(t)) {
if (logger.isTraceEnabled()) {
logger.trace(
(Supplier<?>) () -> new ParameterizedMessage(
"received plaintext http traffic on a https channel, closing connection {}",
ctx.getChannel()),
t);
} else {
logger.warn("received plaintext http traffic on a https channel, closing connection {}", ctx.getChannel());
}
ctx.getChannel().close();
} else if (isCloseDuringHandshakeException(t)) {
if (logger.isTraceEnabled()) {
logger.trace((Supplier<?>) () -> new ParameterizedMessage("connection {} closed during handshake", ctx.getChannel()), t);
} else {
logger.warn("connection {} closed during handshake", ctx.getChannel());
}
ctx.getChannel().close();
} else {
super.exceptionCaught(ctx, e);
}
}
@Override
protected void doStart() {
super.doStart();
ipFilter.setBoundHttpTransportAddress(this.boundAddress());
}
@Override
public ChannelPipelineFactory configureServerChannelPipelineFactory() {
return new HttpSslChannelPipelineFactory(this);
}
private class HttpSslChannelPipelineFactory extends HttpChannelPipelineFactory {
private final Settings sslSettings;
public HttpSslChannelPipelineFactory(Netty3HttpServerTransport transport) {
super(transport, detailedErrorsEnabled, threadPool.getThreadContext());
this.sslSettings = SSLService.getHttpTransportSSLSettings(settings);
if (ssl && sslService.isConfigurationValidForServerUsage(sslSettings, Settings.EMPTY) == false) {
throw new IllegalArgumentException("a key must be provided to run as a server. the key should be configured using the " +
"[xpack.security.http.ssl.key] or [xpack.security.http.ssl.keystore.path] setting");
}
}
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = super.getPipeline();
if (ssl) {
SSLEngine engine = sslService.createSSLEngine(sslSettings, Settings.EMPTY);
pipeline.addFirst("ssl", new SslHandler(engine));
}
pipeline.addFirst("ipfilter", new IPFilterNetty3UpstreamHandler(ipFilter, IPFilter.HTTP_PROFILE_NAME));
return pipeline;
}
}
public static void overrideSettings(Settings.Builder settingsBuilder, Settings settings) {
if (HTTP_SSL_ENABLED.get(settings) && SETTING_HTTP_COMPRESSION.exists(settings) == false) {
settingsBuilder.put(SETTING_HTTP_COMPRESSION.getKey(), false);
}
}
}

View File

@ -1,186 +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.netty3;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.logging.log4j.util.Supplier;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.inject.internal.Nullable;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.transport.TransportSettings;
import org.elasticsearch.xpack.ssl.SSLService;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.netty3.Netty3Transport;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.handler.ssl.SslHandler;
import javax.net.ssl.SSLEngine;
import java.io.IOException;
import java.net.InetSocketAddress;
import static org.elasticsearch.xpack.security.Security.setting;
import static org.elasticsearch.xpack.security.transport.SSLExceptionHelper.isCloseDuringHandshakeException;
import static org.elasticsearch.xpack.security.transport.SSLExceptionHelper.isNotSslRecordException;
import static org.elasticsearch.xpack.XPackSettings.TRANSPORT_SSL_ENABLED;
public class SecurityNetty3Transport extends Netty3Transport {
public static final Setting<Boolean> PROFILE_SSL_SETTING = Setting.boolSetting(setting("ssl.enabled"), false);
private final SSLService sslService;
@Nullable private final IPFilter authenticator;
private final Settings transportSSLSettings;
private final boolean ssl;
@Inject
public SecurityNetty3Transport(Settings settings, ThreadPool threadPool, NetworkService networkService, BigArrays bigArrays,
@Nullable IPFilter authenticator, SSLService sslService, NamedWriteableRegistry namedWriteableRegistry,
CircuitBreakerService circuitBreakerService) {
super(settings, threadPool, networkService, bigArrays, namedWriteableRegistry, circuitBreakerService);
this.authenticator = authenticator;
this.ssl = TRANSPORT_SSL_ENABLED.get(settings);
this.sslService = sslService;
this.transportSSLSettings = settings.getByPrefix(setting("transport.ssl."));
}
@Override
protected void doStart() {
super.doStart();
if (authenticator != null) {
authenticator.setBoundTransportAddress(boundAddress(), profileBoundAddresses());
}
}
@Override
public ChannelPipelineFactory configureClientChannelPipelineFactory() {
return new SslClientChannelPipelineFactory(this);
}
@Override
public ChannelPipelineFactory configureServerChannelPipelineFactory(String name, Settings profileSettings) {
return new SslServerChannelPipelineFactory(this, name, settings, profileSettings);
}
@Override
protected void onException(Channel channel, Exception e) throws IOException {
if (isNotSslRecordException(e)) {
if (logger.isTraceEnabled()) {
logger.trace(
(Supplier<?>) () -> new ParameterizedMessage(
"received plaintext traffic on a encrypted channel, closing connection {}", channel), e);
} else {
logger.warn("received plaintext traffic on a encrypted channel, closing connection {}", channel);
}
disconnectFromNodeChannel(channel, e);
} else if (isCloseDuringHandshakeException(e)) {
if (logger.isTraceEnabled()) {
logger.trace((Supplier<?>) () -> new ParameterizedMessage("connection {} closed during handshake", channel), e);
} else {
logger.warn("connection {} closed during handshake", channel);
}
disconnectFromNodeChannel(channel, e);
} else {
super.onException(channel, e);
}
}
public static Settings profileSslSettings(Settings profileSettings) {
return profileSettings.getByPrefix(setting("ssl."));
}
private class SslServerChannelPipelineFactory extends ServerChannelPipelineFactory {
private final boolean profileSsl;
private final Settings profileSslSettings;
SslServerChannelPipelineFactory(Netty3Transport nettyTransport, String name, Settings settings, Settings profileSettings) {
super(nettyTransport, name, settings);
this.profileSsl = PROFILE_SSL_SETTING.exists(profileSettings) ? PROFILE_SSL_SETTING.get(profileSettings) : ssl;
this.profileSslSettings = profileSslSettings(profileSettings);
if (profileSsl && sslService.isConfigurationValidForServerUsage(profileSslSettings, transportSSLSettings) == false) {
if (TransportSettings.DEFAULT_PROFILE.equals(name)) {
throw new IllegalArgumentException("a key must be provided to run as a server. the key should be configured using the "
+ "[xpack.security.transport.ssl.key] or [xpack.security.transport.ssl.keystore.path] setting");
}
throw new IllegalArgumentException("a key must be provided to run as a server. the key should be configured using the "
+ "[transport.profiles." + name + ".xpack.security.ssl.key] or [transport.profiles." + name
+ ".xpack.security.ssl.keystore.path] setting");
}
}
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = super.getPipeline();
if (profileSsl) {
final SSLEngine serverEngine = sslService.createSSLEngine(profileSslSettings, transportSSLSettings);
serverEngine.setUseClientMode(false);
pipeline.addFirst("ssl", new SslHandler(serverEngine));
}
if (authenticator != null) {
pipeline.addFirst("ipfilter", new IPFilterNetty3UpstreamHandler(authenticator, name));
}
return pipeline;
}
}
private class SslClientChannelPipelineFactory extends ClientChannelPipelineFactory {
private final boolean hostnameVerificationEnabled;
SslClientChannelPipelineFactory(Netty3Transport transport) {
super(transport);
this.hostnameVerificationEnabled =
sslService.getVerificationMode(transportSSLSettings, Settings.EMPTY).isHostnameVerificationEnabled();
}
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = super.getPipeline();
if (ssl) {
pipeline.addFirst("sslInitializer", new ClientSslHandlerInitializer());
}
return pipeline;
}
/**
* Handler that waits until connect is called to create a SSLEngine with the proper parameters in order to
* perform hostname verification
*/
private class ClientSslHandlerInitializer extends SimpleChannelHandler {
@Override
public void connectRequested(ChannelHandlerContext ctx, ChannelStateEvent e) {
SSLEngine sslEngine;
if (hostnameVerificationEnabled) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) e.getValue();
// we create the socket based on the name given. don't reverse DNS
sslEngine = sslService.createSSLEngine(transportSSLSettings, Settings.EMPTY, inetSocketAddress.getHostString(),
inetSocketAddress.getPort());
} else {
sslEngine = sslService.createSSLEngine(transportSSLSettings, Settings.EMPTY);
}
sslEngine.setUseClientMode(true);
ctx.getPipeline().replace(this, "ssl", new SslHandler(sslEngine));
ctx.getPipeline().addAfter("ssl", "handshake", new Netty3HandshakeWaitingHandler(logger));
ctx.sendDownstream(e);
}
}
}
}

View File

@ -26,7 +26,7 @@ class IpFilterRemoteAddressFilter extends AbstractRemoteAddressFilter<InetSocket
@Override
protected boolean accept(final ChannelHandlerContext ctx, final InetSocketAddress remoteAddress) throws Exception {
// at this stage no auth has happened, so we do not have any principal anyway
return filter.accept(profile, remoteAddress.getAddress());
return filter.accept(profile, remoteAddress);
}
}

View File

@ -39,7 +39,7 @@ import static org.elasticsearch.xpack.XPackSettings.TRANSPORT_SSL_ENABLED;
*/
public class SecurityNetty4Transport extends Netty4Transport {
private static final Setting<Boolean> PROFILE_SSL_SETTING = Setting.boolSetting(setting("ssl.enabled"), false);
public static final Setting<Boolean> PROFILE_SSL_SETTING = Setting.boolSetting(setting("ssl.enabled"), false);
private final SSLService sslService;
@Nullable private final IPFilter authenticator;
@ -157,4 +157,9 @@ public class SecurityNetty4Transport extends Netty4Transport {
super.connect(ctx, remoteAddress, localAddress, promise);
}
}
public static Settings profileSslSettings(Settings profileSettings) {
return profileSettings.getByPrefix(setting("ssl."));
}
}

View File

@ -1,22 +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.http.netty3;
import org.elasticsearch.transport.netty3.Netty3OpenChannelsHandler;
import static org.mockito.Mockito.mock;
/** Allows setting a mock into Netty3HttpServerTransport */
public class Netty3HttpMockUtil {
/**
* We don't really need to start Netty for these tests, but we can't create a pipeline
* with a null handler. So we set it to a mock for tests.
*/
public static void setOpenChannelsHandlerToMock(Netty3HttpServerTransport transport) throws Exception {
transport.serverOpenChannels = mock(Netty3OpenChannelsHandler.class);
}
}

View File

@ -11,7 +11,6 @@ import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.security.authc.support.SecuredString;
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
@ -138,7 +137,6 @@ public class IndexPrivilegeTests extends AbstractPrivilegeTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -11,7 +11,6 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.env.Environment;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.XPackPlugin;
@ -48,7 +47,7 @@ public class LicenseServiceClusterTests extends AbstractLicensesIntegrationTestC
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(XPackPlugin.class, Netty3Plugin.class, Netty4Plugin.class);
return Arrays.asList(XPackPlugin.class, Netty4Plugin.class);
}
@Override

View File

@ -7,6 +7,7 @@ package org.elasticsearch.license;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.ElasticsearchSecurityException;
@ -29,7 +30,6 @@ import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.SecurityIntegTestCase;
import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.xpack.XPackPlugin;
@ -108,7 +108,6 @@ public class LicensingTests extends SecurityIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -14,7 +14,6 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase.Scope;
import org.elasticsearch.test.discovery.ClusterDiscoveryConfiguration;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.XPackPlugin;
import org.elasticsearch.xpack.XPackSettings;
@ -151,7 +150,8 @@ public class SecuritySettingsSource extends ClusterDiscoveryConfiguration.Unicas
@Override
public Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(xpackPluginClass(), Netty3Plugin.class, Netty4Plugin.class);
return Arrays.asList(xpackPluginClass(),
Netty4Plugin.class);
}
@Override

View File

@ -1,19 +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.transport.netty3;
import static org.mockito.Mockito.mock;
/** Allows setting a mock into Netty3Transport */
public class Netty3MockUtil {
/**
* We don't really need to start Netty for these tests, but we can't create a pipeline
* with a null handler. So we set it to a mock for tests.
*/
public static void setOpenChannelsHandlerToMock(Netty3Transport transport) throws Exception {
transport.serverOpenChannels = mock(Netty3OpenChannelsHandler.class);
}
}

View File

@ -5,9 +5,6 @@
*/
package org.elasticsearch.transport.netty4;
import org.elasticsearch.transport.netty3.Netty3OpenChannelsHandler;
import org.elasticsearch.transport.netty3.Netty3Transport;
import static org.mockito.Mockito.mock;
/** Allows setting a mock into Netty3Transport */

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.common.http;
import io.netty.handler.codec.http.HttpHeaders;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ToXContent;
@ -18,7 +19,6 @@ import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
import org.elasticsearch.xpack.common.http.auth.basic.BasicAuthFactory;
import org.elasticsearch.xpack.common.text.TextTemplate;
import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import java.util.Collections;

View File

@ -12,13 +12,13 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
@ -48,7 +48,6 @@ public class MonitoringSettingsIntegTests extends MonitoringIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -12,7 +12,6 @@ import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
@ -20,6 +19,7 @@ import org.elasticsearch.xpack.security.authc.support.SecuredString;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue;
@ -51,7 +51,6 @@ public class MonitoringSettingsFilterTests extends MonitoringIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.monitoring.test;
import io.netty.util.internal.SystemPropertyUtil;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.node.NodeClient;
@ -42,7 +43,6 @@ import org.elasticsearch.xpack.security.authc.support.SecuredString;
import org.elasticsearch.xpack.security.crypto.CryptoService;
import org.elasticsearch.xpack.watcher.WatcherLifeCycleService;
import org.hamcrest.Matcher;
import org.jboss.netty.util.internal.SystemPropertyUtil;
import org.junit.After;
import org.junit.Before;

View File

@ -149,29 +149,6 @@ public class SecurityTests extends ESTestCase {
assertEquals(Security.NAME4, NetworkModule.HTTP_TYPE_SETTING.get(defaultSettings));
}
public void testTransportSettingNetty3Transport() {
Settings baseSettings = Settings.builder().put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME3).build();
Settings transport3 = Security.additionalSettings(baseSettings, false);
assertFalse(NetworkModule.TRANSPORT_TYPE_SETTING.exists(transport3));
assertEquals(Security.NAME4, NetworkModule.HTTP_TYPE_SETTING.get(transport3));
}
public void testTransportSettingNetty3Http() {
Settings baseSettings = Settings.builder().put(NetworkModule.HTTP_TYPE_KEY, Security.NAME3).build();
Settings http3 = Security.additionalSettings(baseSettings, false);
assertEquals(Security.NAME4, NetworkModule.TRANSPORT_TYPE_SETTING.get(http3));
assertFalse(NetworkModule.HTTP_TYPE_SETTING.exists(http3));
}
public void testTransportSettingNetty3Both() {
Settings both3 = Security.additionalSettings(Settings.builder()
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME3)
.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME3)
.build(), false);
assertFalse(NetworkModule.TRANSPORT_TYPE_SETTING.exists(both3));
assertFalse(NetworkModule.HTTP_TYPE_SETTING.exists(both3));
}
public void testTransportSettingNetty4Both() {
Settings both4 = Security.additionalSettings(Settings.builder()
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4)
@ -182,18 +159,16 @@ public class SecurityTests extends ESTestCase {
}
public void testTransportSettingValidation() {
final String badType = randomFrom("netty3", "netty4", "other", "security1");
final String badType = randomFrom("netty4", "other", "security1");
Settings settingsTransport = Settings.builder().put(NetworkModule.TRANSPORT_TYPE_KEY, badType).build();
IllegalArgumentException badTransport = expectThrows(IllegalArgumentException.class,
() -> Security.additionalSettings(settingsTransport, false));
assertThat(badTransport.getMessage(), containsString(Security.NAME3));
assertThat(badTransport.getMessage(), containsString(Security.NAME4));
assertThat(badTransport.getMessage(), containsString(NetworkModule.TRANSPORT_TYPE_KEY));
Settings settingsHttp = Settings.builder().put(NetworkModule.HTTP_TYPE_KEY, badType).build();
IllegalArgumentException badHttp = expectThrows(IllegalArgumentException.class,
() -> Security.additionalSettings(settingsHttp, false));
assertThat(badHttp.getMessage(), containsString(Security.NAME3));
assertThat(badHttp.getMessage(), containsString(Security.NAME4));
assertThat(badHttp.getMessage(), containsString(NetworkModule.HTTP_TYPE_KEY));
}

View File

@ -18,7 +18,6 @@ import org.elasticsearch.test.SecuritySettingsSource;
import org.elasticsearch.xpack.security.SecurityTemplateService;
import org.elasticsearch.xpack.security.authz.permission.FieldPermissions;
import org.elasticsearch.xpack.security.client.SecurityClient;
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3HttpServerTransport;
import org.junit.BeforeClass;
import java.util.HashSet;

View File

@ -26,6 +26,7 @@ import org.junit.Before;
import org.mockito.ArgumentCaptor;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -223,7 +224,7 @@ public class IPFilterTests extends ESTestCase {
// don't use the assert helper because we don't want the audit trail to be invoked here
String message = String.format(Locale.ROOT, "Expected address %s to be allowed", "8.8.8.8");
InetAddress address = InetAddresses.forString("8.8.8.8");
assertThat(message, ipFilter.accept("default", address), is(true));
assertThat(message, ipFilter.accept("default", new InetSocketAddress(address, 0)), is(true));
verifyZeroInteractions(auditTrail);
// for sanity enable license and check that it is denied
@ -249,7 +250,7 @@ public class IPFilterTests extends ESTestCase {
for (String inetAddress : inetAddresses) {
String message = String.format(Locale.ROOT, "Expected address %s to be allowed", inetAddress);
InetAddress address = InetAddresses.forString(inetAddress);
assertThat(message, ipFilter.accept(profile, address), is(true));
assertTrue(message, ipFilter.accept(profile, new InetSocketAddress(address, 0)));
ArgumentCaptor<SecurityIpFilterRule> ruleCaptor = ArgumentCaptor.forClass(SecurityIpFilterRule.class);
verify(auditTrail).connectionGranted(eq(address), eq(profile), ruleCaptor.capture());
assertNotNull(ruleCaptor.getValue());
@ -264,7 +265,7 @@ public class IPFilterTests extends ESTestCase {
for (String inetAddress : inetAddresses) {
String message = String.format(Locale.ROOT, "Expected address %s to be denied", inetAddress);
InetAddress address = InetAddresses.forString(inetAddress);
assertThat(message, ipFilter.accept(profile, address), is(false));
assertFalse(message, ipFilter.accept(profile, new InetSocketAddress(address, 0)));
ArgumentCaptor<SecurityIpFilterRule> ruleCaptor = ArgumentCaptor.forClass(SecurityIpFilterRule.class);
verify(auditTrail).connectionDenied(eq(address), eq(profile), ruleCaptor.capture());
assertNotNull(ruleCaptor.getValue());

View File

@ -13,6 +13,7 @@ import org.elasticsearch.test.SecurityIntegTestCase;
import org.junit.BeforeClass;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Locale;
@ -162,7 +163,7 @@ public class IpFilteringUpdateTests extends SecurityIntegTestCase {
IPFilter ipFilter = internalCluster().getDataNodeInstance(IPFilter.class);
String message = String.format(Locale.ROOT, "Expected allowed connection for profile %s against host %s", profile, host);
assertThat(message, ipFilter.accept(profile, InetAddress.getByName(host)), is(true));
assertThat(message, ipFilter.accept(profile, new InetSocketAddress(InetAddress.getByName(host), 0)), is(true));
}
private void assertConnectionRejected(String profile, String host) throws UnknownHostException {
@ -173,6 +174,6 @@ public class IpFilteringUpdateTests extends SecurityIntegTestCase {
IPFilter ipFilter = internalCluster().getDataNodeInstance(IPFilter.class);
String message = String.format(Locale.ROOT, "Expected rejection for profile %s against host %s", profile, host);
assertThat(message, ipFilter.accept(profile, InetAddress.getByName(host)), is(false));
assertThat(message, ipFilter.accept(profile, new InetSocketAddress(InetAddress.getByName(host), 0)), is(false));
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.filter;
import io.netty.handler.ipfilter.IpFilterRuleType;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.test.ESTestCase;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
public class PatternRuleTests extends ESTestCase {
public void testSingleIpRule() throws UnknownHostException {
PatternRule rule = new PatternRule(IpFilterRuleType.REJECT, "i:127.0.0.1");
assertFalse(rule.isLocalhost());
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0)));
assertEquals(IpFilterRuleType.REJECT, rule.ruleType());
rule = new PatternRule(IpFilterRuleType.REJECT, "i:192.168.*");
assertFalse(rule.isLocalhost());
assertFalse(rule.matches(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0)));
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("192.168.2.1"), 0)));
assertEquals(IpFilterRuleType.REJECT, rule.ruleType());
}
public void testSingleLocalHostRule() throws UnknownHostException {
PatternRule rule = new PatternRule(IpFilterRuleType.ACCEPT, "n:localhost");
assertTrue(rule.isLocalhost());
assertTrue(rule.matches(new InetSocketAddress(getLocalHost(), 0)));
assertEquals(IpFilterRuleType.ACCEPT, rule.ruleType());
}
public void testMultiRules() throws UnknownHostException {
PatternRule rule = new PatternRule(IpFilterRuleType.ACCEPT, "n:localhost,i:127.0.0.1,i:192.168.9.*");
assertTrue(rule.isLocalhost());
assertTrue(rule.matches(new InetSocketAddress(getLocalHost(), 0)));
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("192.168.9.1"), 0)));
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0)));
assertFalse(rule.matches(new InetSocketAddress(InetAddress.getByName("192.168.11.1"), 0)));
assertEquals(IpFilterRuleType.ACCEPT, rule.ruleType());
}
public void testAll() throws UnknownHostException {
PatternRule rule = new PatternRule(IpFilterRuleType.ACCEPT, "n:*");
assertFalse(rule.isLocalhost());
assertTrue(rule.matches(new InetSocketAddress(getLocalHost(), 0)));
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("192.168.9.1"), 0)));
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0)));
assertTrue(rule.matches(new InetSocketAddress(InetAddress.getByName("192.168.11.1"), 0)));
assertEquals(IpFilterRuleType.ACCEPT, rule.ruleType());
}
@SuppressForbidden(reason = "just for this test")
private static InetAddress getLocalHost() throws UnknownHostException {
return InetAddress.getLocalHost();
}
}

View File

@ -5,15 +5,20 @@
*/
package org.elasticsearch.xpack.security.transport.filter;
import io.netty.handler.ipfilter.IpFilterRule;
import io.netty.handler.ipfilter.IpFilterRuleType;
import io.netty.handler.ipfilter.IpSubnetFilterRule;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.network.NetworkAddress;
import org.elasticsearch.test.ESTestCase;
import org.jboss.netty.handler.ipfilter.IpFilterRule;
import org.jboss.netty.handler.ipfilter.IpSubnetFilterRule;
import org.jboss.netty.handler.ipfilter.PatternRule;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import static org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule.ACCEPT_ALL;
import static org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule.DENY_ALL;
import static org.elasticsearch.xpack.security.transport.filter.SecurityIpFilterRule.getRule;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.sameInstance;
@ -43,9 +48,13 @@ public class SecurityIpFilterRuleTests extends ESTestCase {
final boolean allow = randomBoolean();
IpFilterRule rule = getRule(allow, "127.0.0.0/24");
assertThat(rule, instanceOf(IpSubnetFilterRule.class));
assertThat(rule.isAllowRule(), equalTo(allow));
if (allow) {
assertEquals(rule.ruleType(), IpFilterRuleType.ACCEPT);
} else {
assertEquals(rule.ruleType(), IpFilterRuleType.REJECT);
}
IpSubnetFilterRule ipSubnetFilterRule = (IpSubnetFilterRule) rule;
assertThat(ipSubnetFilterRule.contains("127.0.0.1"), equalTo(true));
assertTrue(ipSubnetFilterRule.matches(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0)));
}
public void testParseIpSubnetFilterRuleWithOtherValues() throws Exception {
@ -62,6 +71,27 @@ public class SecurityIpFilterRuleTests extends ESTestCase {
String ruleSpec = "127.0.0.1,::1,192.168.0.*,name*,specific_name";
IpFilterRule rule = getRule(allow, ruleSpec);
assertThat(rule, instanceOf(PatternRule.class));
assertThat(rule.isAllowRule(), equalTo(allow));
if (allow) {
assertEquals(rule.ruleType(), IpFilterRuleType.ACCEPT);
} else {
assertEquals(rule.ruleType(), IpFilterRuleType.REJECT);
}
}
public void testParseSubnetMask() throws UnknownHostException {
Tuple<InetAddress, Integer> result = SecurityIpFilterRule.parseSubnetMask("2001:0db8:85a3:0000:0000:8a2e:0370:7334/24");
assertEquals(NetworkAddress.format(result.v1()), "2001:db8:85a3::8a2e:370:7334");
assertEquals(24, result.v2().intValue());
result = SecurityIpFilterRule.parseSubnetMask("127.0.0.0/24");
assertEquals(NetworkAddress.format(result.v1()), "127.0.0.0");
assertEquals(24, result.v2().intValue());
result = SecurityIpFilterRule.parseSubnetMask("127.0.0.1/255.255.255.0");
assertEquals(NetworkAddress.format(result.v1()), "127.0.0.1");
assertEquals(24, result.v2().intValue());
expectThrows(UnknownHostException.class, () -> SecurityIpFilterRule.parseSubnetMask("127.0.0.1"));
expectThrows(IllegalArgumentException.class, () -> SecurityIpFilterRule.parseSubnetMask("127.0.0.1/"));
}
}

View File

@ -1,300 +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.netty3;
import org.elasticsearch.common.component.Lifecycle;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.BoundTransportAddress;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.security.audit.AuditTrailService;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportSettings;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelConfig;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.UpstreamMessageEvent;
import org.junit.Before;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class IPFilterNetty3UpstreamHandlerTests extends ESTestCase {
private IPFilterNetty3UpstreamHandler nettyUpstreamHandler;
@Before
public void init() throws Exception {
Settings settings = Settings.builder()
.put("xpack.security.transport.filter.allow", "127.0.0.1")
.put("xpack.security.transport.filter.deny", "10.0.0.0/8")
.build();
boolean isHttpEnabled = randomBoolean();
Transport transport = mock(Transport.class);
TransportAddress address = new TransportAddress(InetAddress.getLoopbackAddress(), 9300);
when(transport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { address }, address));
when(transport.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, new HashSet<>(Arrays.asList(
IPFilter.HTTP_FILTER_ALLOW_SETTING,
IPFilter.HTTP_FILTER_DENY_SETTING,
IPFilter.IP_FILTER_ENABLED_HTTP_SETTING,
IPFilter.IP_FILTER_ENABLED_SETTING,
IPFilter.TRANSPORT_FILTER_ALLOW_SETTING,
IPFilter.TRANSPORT_FILTER_DENY_SETTING,
TransportSettings.TRANSPORT_PROFILES_SETTING)));
XPackLicenseState licenseState = mock(XPackLicenseState.class);
when(licenseState.isIpFilteringAllowed()).thenReturn(true);
AuditTrailService auditTrailService = new AuditTrailService(settings, Collections.emptyList(), licenseState);
IPFilter ipFilter = new IPFilter(settings, auditTrailService, clusterSettings, licenseState);
ipFilter.setBoundTransportAddress(transport.boundAddress(), transport.profileBoundAddresses());
if (isHttpEnabled) {
HttpServerTransport httpTransport = mock(HttpServerTransport.class);
TransportAddress httpAddress = new TransportAddress(InetAddress.getLoopbackAddress(), 9200);
when(httpTransport.boundAddress()).thenReturn(new BoundTransportAddress(new TransportAddress[] { httpAddress }, httpAddress));
when(httpTransport.lifecycleState()).thenReturn(Lifecycle.State.STARTED);
ipFilter.setBoundHttpTransportAddress(httpTransport.boundAddress());
}
if (isHttpEnabled) {
nettyUpstreamHandler = new IPFilterNetty3UpstreamHandler(ipFilter, IPFilter.HTTP_PROFILE_NAME);
} else {
nettyUpstreamHandler = new IPFilterNetty3UpstreamHandler(ipFilter, "default");
}
}
public void testThatFilteringWorksByIp() throws Exception {
InetSocketAddress localhostAddr = new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 12345);
assertThat(nettyUpstreamHandler.accept(new NullChannelHandlerContext(), new UpstreamMessageEvent(
new NullChannel(), "my message", localhostAddr), localhostAddr), is(true));
InetSocketAddress remoteAddr = new InetSocketAddress(InetAddresses.forString("10.0.0.8"), 12345);
assertThat(nettyUpstreamHandler.accept(new NullChannelHandlerContext(), new UpstreamMessageEvent(
new NullChannel(), "my message", remoteAddr), remoteAddr), is(false));
}
private static class NullChannelHandlerContext implements ChannelHandlerContext {
@Override
public boolean canHandleDownstream() {
return false;
}
@Override
public boolean canHandleUpstream() {
return false;
}
@Override
public Object getAttachment() {
return null;
}
@Override
public Channel getChannel() {
return null;
}
@Override
public ChannelHandler getHandler() {
return null;
}
@Override
public String getName() {
return null;
}
@Override
public ChannelPipeline getPipeline() {
return null;
}
@Override
public void sendDownstream(ChannelEvent e) {
// NOOP
}
@Override
public void sendUpstream(ChannelEvent e) {
// NOOP
}
@Override
public void setAttachment(Object attachment) {
// NOOP
}
}
private static class NullChannel implements Channel {
@Override
public ChannelFuture bind(SocketAddress localAddress) {
return null;
}
@Override
public ChannelFuture close() {
return null;
}
@Override
public ChannelFuture connect(SocketAddress remoteAddress) {
return null;
}
@Override
public ChannelFuture disconnect() {
return null;
}
@Override
public ChannelFuture getCloseFuture() {
return null;
}
@Override
public ChannelConfig getConfig() {
return null;
}
@Override
public ChannelFactory getFactory() {
return null;
}
@Override
public Integer getId() {
return null;
}
@Override
public int getInterestOps() {
return 0;
}
@Override
public SocketAddress getLocalAddress() {
return null;
}
@Override
public Channel getParent() {
return null;
}
@Override
public ChannelPipeline getPipeline() {
return null;
}
@Override
public SocketAddress getRemoteAddress() {
return null;
}
@Override
public boolean isBound() {
return false;
}
@Override
public boolean isConnected() {
return false;
}
@Override
public boolean isOpen() {
return false;
}
@Override
public boolean isReadable() {
return false;
}
@Override
public boolean isWritable() {
return false;
}
@Override
public ChannelFuture setInterestOps(int interestOps) {
return null;
}
@Override
public ChannelFuture setReadable(boolean readable) {
return null;
}
@Override
public boolean getUserDefinedWritability(int i) {
return false;
}
@Override
public void setUserDefinedWritability(int i, boolean b) {
}
@Override
public ChannelFuture unbind() {
return null;
}
@Override
public ChannelFuture write(Object message) {
return null;
}
@Override
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
return null;
}
@Override
public int compareTo(Channel o) {
return 0;
}
@Override
public int hashCode() {
return 0;
}
@Override
public boolean equals(Object o) {
return this == o;
}
@Override
public Object getAttachment() {
return null;
}
@Override
public void setAttachment(Object attachment) {
// NOOP
}
}
}

View File

@ -1,266 +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.netty3;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.ssl.SSLService;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslHandler;
import org.junit.After;
import org.junit.Before;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.BindException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class Netty3HandshakeWaitingHandlerTests extends ESTestCase {
private static final int CONCURRENT_CLIENT_REQUESTS = 20;
private int iterations;
private int randomPort;
private ServerBootstrap serverBootstrap;
private ClientBootstrap clientBootstrap;
private SSLService sslService;
private final AtomicReference<Throwable> failureCause = new AtomicReference<>();
private ExecutorService threadPoolExecutor;
@Before
public void setup() throws Exception {
randomPort = randomIntBetween(49000, 65500);
iterations = randomIntBetween(10, 100);
Settings settings = Settings.builder()
.put("xpack.ssl.keystore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
.put("xpack.ssl.keystore.password", "testnode")
.build();
Environment env = new Environment(Settings.builder().put("path.home", createTempDir()).build());
sslService = new SSLService(settings, env);
startBootstrap();
clientBootstrap = new ClientBootstrap(new NioClientSocketChannelFactory());
threadPoolExecutor = Executors.newFixedThreadPool(CONCURRENT_CLIENT_REQUESTS);
}
@After
public void reset() throws InterruptedException {
terminate(threadPoolExecutor);
clientBootstrap.shutdown();
clientBootstrap.releaseExternalResources();
serverBootstrap.shutdown();
serverBootstrap.releaseExternalResources();
failureCause.set(null);
}
public void testWriteBeforeHandshakeFailsWithoutHandler() throws Exception {
clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
final SSLEngine engine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY);
engine.setUseClientMode(true);
return Channels.pipeline(
new SslHandler(engine));
}
});
List<Callable<ChannelFuture>> callables = new ArrayList<>(CONCURRENT_CLIENT_REQUESTS);
for (int i = 0; i < CONCURRENT_CLIENT_REQUESTS; i++) {
callables.add(new WriteBeforeHandshakeCompletedCallable(clientBootstrap, randomPort));
}
for (int i = 0; i < iterations; i++) {
List<Future<ChannelFuture>> futures = threadPoolExecutor.invokeAll(callables);
for (Future<ChannelFuture> future : futures) {
ChannelFuture handshakeFuture = future.get();
handshakeFuture.await();
handshakeFuture.getChannel().close();
}
if (failureCause.get() != null) {
logger.info("run [{}] produced a failure", i);
assertThat(failureCause.get(), anyOf(instanceOf(SSLException.class), instanceOf(AssertionError.class)));
break;
} else {
logger.warn("run [{}] did not produce a failure", i);
}
}
assertThat("Expected this test to fail with an SSLException or AssertionError", failureCause.get(), notNullValue());
}
public void testWriteBeforeHandshakePassesWithHandshakeWaitingHandler() throws Exception {
clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
final SSLEngine engine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY);
engine.setUseClientMode(true);
return Channels.pipeline(
new SslHandler(engine),
new Netty3HandshakeWaitingHandler(Loggers.getLogger(Netty3HandshakeWaitingHandler.class)));
}
});
List<Callable<ChannelFuture>> callables = new ArrayList<>(CONCURRENT_CLIENT_REQUESTS);
for (int i = 0; i < CONCURRENT_CLIENT_REQUESTS; i++) {
callables.add(new WriteBeforeHandshakeCompletedCallable(clientBootstrap, randomPort));
}
for (int i = 0; i < iterations; i++) {
List<Future<ChannelFuture>> futures = threadPoolExecutor.invokeAll(callables);
for (Future<ChannelFuture> future : futures) {
ChannelFuture handshakeFuture = future.get();
handshakeFuture.await();
// Wait for pending writes to prevent IOExceptions
Channel channel = handshakeFuture.getChannel();
Netty3HandshakeWaitingHandler handler = channel.getPipeline().get(Netty3HandshakeWaitingHandler.class);
if (handler != null) {
boolean noMoreWrites = awaitBusy(() -> handler.hasPendingWrites() == false);
assertTrue(noMoreWrites);
}
channel.close();
}
assertNotFailed();
logger.info("run [{}] succeeded", i);
}
}
private void assertNotFailed() {
if (failureCause.get() != null) {
StringWriter writer = new StringWriter();
if (failureCause.get() != null) {
failureCause.get().printStackTrace(new PrintWriter(writer));
}
assertThat("Expected this test to always pass with the HandshakeWaitingHandler in pipeline\n" + writer.toString(),
failureCause.get(), nullValue());
}
}
private void startBootstrap() {
serverBootstrap = new ServerBootstrap(new NioServerSocketChannelFactory());
serverBootstrap.setPipelineFactory(getServerFactory());
int tries = 1;
int maxTries = 10;
while (tries <= maxTries) {
try {
serverBootstrap.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), randomPort));
break;
} catch (Exception e) {
if (e.getCause() instanceof BindException) {
logger.error("Tried to bind to port [{}], going to retry", randomPort);
randomPort = randomIntBetween(49000, 65500);
}
if (tries >= maxTries) {
throw new RuntimeException("Failed to start server bootstrap [" + tries + "] times, stopping", e);
}
tries++;
}
}
}
private ChannelPipelineFactory getServerFactory() {
return new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
final SSLEngine sslEngine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY);
sslEngine.setUseClientMode(false);
return Channels.pipeline(new SslHandler(sslEngine),
new SimpleChannelHandler() {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Sink the message
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
Throwable cause = e.getCause();
// Only save first cause
failureCause.compareAndSet(null, cause);
ctx.getChannel().close();
}
});
}
};
}
private static class WriteBeforeHandshakeCompletedCallable implements Callable<ChannelFuture> {
private final ClientBootstrap bootstrap;
private final int port;
WriteBeforeHandshakeCompletedCallable(ClientBootstrap bootstrap, int port) {
this.bootstrap = bootstrap;
this.port = port;
}
@Override
public ChannelFuture call() throws Exception {
ChannelBuffer buffer = ChannelBuffers.buffer(8);
buffer.writeLong(SecureRandom.getInstance("SHA1PRNG").nextLong());
// Connect and wait, then immediately start writing
ChannelFuture future = bootstrap.connect(new InetSocketAddress(InetAddress.getLoopbackAddress(), port));
future.awaitUninterruptibly();
Channel channel = future.getChannel();
// Do not call handshake before writing as it will most likely succeed before a write begins
// in the test
ChannelFuture handshakeFuture = null;
for (int i = 0; i < 100; i++) {
if (handshakeFuture == null) {
handshakeFuture = channel.getPipeline().get(SslHandler.class).handshake();
}
channel.write(buffer);
}
return handshakeFuture;
}
}
}

View File

@ -1,190 +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.netty3;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.env.Environment;
import org.elasticsearch.http.HttpTransportSettings;
import org.elasticsearch.http.netty3.Netty3HttpMockUtil;
import org.elasticsearch.xpack.ssl.SSLService;
import org.elasticsearch.xpack.ssl.SSLClientAuth;
import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.ssl.SslHandler;
import org.junit.Before;
import javax.net.ssl.SSLEngine;
import java.nio.file.Path;
import java.util.Locale;
import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.mockito.Mockito.mock;
public class SecurityNetty3HttpServerTransportTests extends ESTestCase {
private SSLService sslService;
private Environment env;
@Before
public void createSSLService() throws Exception {
Path testnodeStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
Settings settings = Settings.builder()
.put("xpack.ssl.keystore.path", testnodeStore)
.put("xpack.ssl.keystore.password", "testnode")
.put("path.home", createTempDir())
.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
}
public void testDefaultClientAuth() throws Exception {
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.http.ssl.enabled", true).build();
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
Netty3HttpMockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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.http.ssl.enabled", true)
.put("xpack.security.http.ssl.client_authentication", value).build();
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
Netty3HttpMockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getWantClientAuth(), is(true));
}
public void testRequiredClientAuth() throws Exception {
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.http.ssl.enabled", true)
.put("xpack.security.http.ssl.client_authentication", SSLClientAuth.REQUIRED).build();
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
Netty3HttpMockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(true));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getWantClientAuth(), is(false));
}
public void testNoClientAuth() throws Exception {
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.http.ssl.enabled", true)
.put("xpack.security.http.ssl.client_authentication", SSLClientAuth.NONE).build();
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
Netty3HttpMockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getWantClientAuth(), is(false));
}
public void testCustomSSLConfiguration() throws Exception {
Settings settings = Settings.builder()
.put(env.settings())
.put("xpack.security.http.ssl.enabled", true).build();
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
Netty3HttpMockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory();
SSLEngine defaultEngine = factory.getPipeline().get(SslHandler.class).getEngine();
settings = Settings.builder()
.put(env.settings())
.put("xpack.security.http.ssl.enabled", true)
.put("xpack.security.http.ssl.supported_protocols", "TLSv1.2")
.build();
sslService = new SSLService(settings, new Environment(settings));
transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
Netty3HttpMockUtil.setOpenChannelsHandlerToMock(transport);
factory = transport.configureServerChannelPipelineFactory();
SSLEngine customEngine = factory.getPipeline().get(SslHandler.class).getEngine();
assertThat(customEngine.getEnabledProtocols(), arrayContaining("TLSv1.2"));
assertThat(customEngine.getEnabledProtocols(), not(equalTo(defaultEngine.getEnabledProtocols())));
}
public void testDisablesCompressionByDefaultForSsl() throws Exception {
Settings settings = Settings.builder()
.put("xpack.security.http.ssl.enabled", true).build();
Settings.Builder pluginSettingsBuilder = Settings.builder();
SecurityNetty3HttpServerTransport.overrideSettings(pluginSettingsBuilder, settings);
assertThat(HttpTransportSettings.SETTING_HTTP_COMPRESSION.get(pluginSettingsBuilder.build()), is(false));
}
public void testLeavesCompressionOnIfNotSsl() throws Exception {
Settings settings = Settings.builder()
.put("xpack.security.http.ssl.enabled", false).build();
Settings.Builder pluginSettingsBuilder = Settings.builder();
SecurityNetty3HttpServerTransport.overrideSettings(pluginSettingsBuilder, settings);
assertThat(pluginSettingsBuilder.build().isEmpty(), is(true));
}
public void testDoesNotChangeExplicitlySetCompression() throws Exception {
Settings settings = Settings.builder()
.put("xpack.security.http.ssl.enabled", true)
.put(HttpTransportSettings.SETTING_HTTP_COMPRESSION.getKey(), true)
.build();
Settings.Builder pluginSettingsBuilder = Settings.builder();
SecurityNetty3HttpServerTransport.overrideSettings(pluginSettingsBuilder, settings);
assertThat(pluginSettingsBuilder.build().isEmpty(), is(true));
}
public void testThatExceptionIsThrownWhenConfiguredWithoutSslKey() throws Exception {
Settings settings = Settings.builder()
.put("xpack.ssl.truststore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
.put("xpack.ssl.truststore.password", "testnode")
.put("xpack.security.http.ssl.enabled", true)
.put("path.home", createTempDir())
.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, transport::configureServerChannelPipelineFactory);
assertThat(e.getMessage(), containsString("key must be provided"));
}
public void testNoExceptionWhenConfiguredWithoutSslKeySSLDisabled() throws Exception {
Settings settings = Settings.builder()
.put("xpack.ssl.truststore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
.put("xpack.ssl.truststore.password", "testnode")
.put("path.home", createTempDir())
.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
SecurityNetty3HttpServerTransport transport = new SecurityNetty3HttpServerTransport(settings, mock(NetworkService.class),
mock(BigArrays.class), mock(IPFilter.class), sslService, mock(ThreadPool.class));
assertNotNull(transport.configureServerChannelPipelineFactory());
}
}

View File

@ -1,262 +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.netty3;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.env.Environment;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.xpack.XPackSettings;
import org.elasticsearch.xpack.ssl.SSLService;
import org.elasticsearch.xpack.ssl.SSLClientAuth;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.netty3.Netty3MockUtil;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.ssl.SslHandler;
import org.junit.Before;
import javax.net.ssl.SSLEngine;
import java.nio.file.Path;
import java.util.Locale;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Mockito.mock;
public class SecurityNetty3TransportTests extends ESTestCase {
private Environment env;
private SSLService sslService;
@Before
public void createSSLService() throws Exception {
Path testnodeStore = getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks");
Settings settings = Settings.builder()
.put("path.home", createTempDir())
.put("xpack.ssl.keystore.path", testnodeStore)
.put("xpack.ssl.keystore.password", "testnode")
.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
}
public void testThatSSLCanBeDisabledByProfile() throws Exception {
Settings settings = Settings.builder().put("xpack.security.transport.ssl.enabled", true).build();
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client",
Settings.builder().put("xpack.security.ssl.enabled", false).build());
assertThat(factory.getPipeline().get(SslHandler.class), nullValue());
}
public void testThatSSLCanBeEnabledByProfile() throws Exception {
Settings settings = Settings.builder().put("xpack.security.transport.ssl.enabled", false).build();
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client",
Settings.builder().put("xpack.security.ssl.enabled", true).build());
assertThat(factory.getPipeline().get(SslHandler.class), notNullValue());
}
public void testThatProfileTakesDefaultSSLSetting() throws Exception {
Settings settings = Settings.builder().put("xpack.security.transport.ssl.enabled", true).build();
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", Settings.EMPTY);
assertThat(factory.getPipeline().get(SslHandler.class).getEngine(), notNullValue());
}
public void testDefaultClientAuth() throws Exception {
Settings settings = Settings.builder().put("xpack.security.transport.ssl.enabled", true).build();
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", Settings.EMPTY);
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(true));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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.enabled", true)
.put("xpack.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", Settings.EMPTY);
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(true));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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.enabled", true)
.put("xpack.ssl.client_authentication", value).build();
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", Settings.EMPTY);
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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.enabled", true)
.put("xpack.ssl.client_authentication", value).build();
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client", Settings.EMPTY);
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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("xpack.security.transport.ssl.enabled", true)
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client",
Settings.builder().put("xpack.security.ssl.client_authentication", value).build());
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(true));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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("xpack.security.transport.ssl.enabled", true)
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class), mock(NetworkService.class),
mock(BigArrays.class), null, sslService, mock(NamedWriteableRegistry.class),
mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client",
Settings.builder().put("xpack.security.ssl.client_authentication", value).build());
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().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("xpack.security.transport.ssl.enabled", true)
.put("transport.profiles.client.xpack.security.ssl.client_authentication", value)
.build();
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class),
mock(NetworkService.class), mock(BigArrays.class), null, sslService,
mock(NamedWriteableRegistry.class), mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("client",
Settings.builder().put("xpack.security.ssl.client_authentication", value).build());
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getNeedClientAuth(), is(false));
assertThat(factory.getPipeline().get(SslHandler.class).getEngine().getWantClientAuth(), is(true));
}
public void testThatExceptionIsThrownWhenConfiguredWithoutSslKey() throws Exception {
Settings settings = Settings.builder()
.put("xpack.ssl.truststore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
.put("xpack.ssl.truststore.password", "testnode")
.put(XPackSettings.TRANSPORT_SSL_ENABLED.getKey(), true)
.put("path.home", createTempDir())
.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class),
mock(NetworkService.class), mock(BigArrays.class), null, sslService,
mock(NamedWriteableRegistry.class), mock(CircuitBreakerService.class));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> transport.configureServerChannelPipelineFactory(randomAsciiOfLength(6), Settings.EMPTY));
assertThat(e.getMessage(), containsString("key must be provided"));
}
public void testNoExceptionWhenConfiguredWithoutSslKeySSLDisabled() throws Exception {
Settings settings = Settings.builder()
.put("xpack.ssl.truststore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
.put("xpack.ssl.truststore.password", "testnode")
.put(XPackSettings.TRANSPORT_SSL_ENABLED.getKey(), false)
.put("path.home", createTempDir())
.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class),
mock(NetworkService.class), mock(BigArrays.class), null, sslService,
mock(NamedWriteableRegistry.class), mock(CircuitBreakerService.class));
assertNotNull(transport.configureServerChannelPipelineFactory(randomAsciiOfLength(6), Settings.EMPTY));
}
public void testTransportSSLOverridesGlobalSSL() throws Exception {
final boolean useGlobalKeystoreWithoutKey = randomBoolean();
Settings.Builder builder = Settings.builder()
.put("xpack.security.transport.ssl.keystore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/testnode.jks"))
.put("xpack.security.transport.ssl.keystore.password", "testnode")
.put("xpack.security.transport.ssl.client_authentication", "none")
.put(XPackSettings.TRANSPORT_SSL_ENABLED.getKey(), true)
.put("path.home", createTempDir());
if (useGlobalKeystoreWithoutKey) {
builder.put("xpack.ssl.keystore.path",
getDataPath("/org/elasticsearch/xpack/security/transport/ssl/certs/simple/truststore-testnode-only.jks"))
.put("xpack.ssl.keystore.password", "truststore-testnode-only");
}
Settings settings = builder.build();
env = new Environment(settings);
sslService = new SSLService(settings, env);
SecurityNetty3Transport transport = new SecurityNetty3Transport(settings, mock(ThreadPool.class),
mock(NetworkService.class), mock(BigArrays.class), null, sslService,
mock(NamedWriteableRegistry.class), mock(CircuitBreakerService.class));
Netty3MockUtil.setOpenChannelsHandlerToMock(transport);
ChannelPipelineFactory factory = transport.configureServerChannelPipelineFactory("default", Settings.EMPTY);
final SSLEngine engine = factory.getPipeline().get(SslHandler.class).getEngine();
assertFalse(engine.getNeedClientAuth());
assertFalse(engine.getWantClientAuth());
// get the global and verify that it is different in that it requires client auth
final SSLEngine globalEngine = sslService.createSSLEngine(Settings.EMPTY, Settings.EMPTY);
assertTrue(globalEngine.getNeedClientAuth());
assertFalse(globalEngine.getWantClientAuth());
}
}

View File

@ -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.xpack.security.transport.netty3;
package org.elasticsearch.xpack.security.transport.netty4;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;

View File

@ -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.xpack.security.transport.netty3;
package org.elasticsearch.xpack.security.transport.netty4;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.NoNodeAvailableException;

View File

@ -15,7 +15,6 @@ import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
@ -48,7 +47,7 @@ public class WatcherPluginDisableTests extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Arrays.asList(XPackPlugin.class, Netty3Plugin.class, Netty4Plugin.class);
return Arrays.asList(XPackPlugin.class, Netty4Plugin.class);
}
@Override

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.watcher.actions.email;
import io.netty.handler.codec.http.HttpHeaders;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.MapBuilder;
@ -45,7 +46,6 @@ import org.elasticsearch.xpack.watcher.support.xcontent.WatcherParams;
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine;
import org.elasticsearch.xpack.watcher.watch.Payload;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Before;

View File

@ -10,7 +10,6 @@ import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.common.http.HttpRequestTemplate;
import org.elasticsearch.xpack.common.http.auth.basic.BasicAuth;
@ -48,7 +47,6 @@ public class ChainIntegrationTests extends AbstractWatcherIntegrationTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -12,7 +12,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.watcher.client.WatcherClient;
import org.elasticsearch.xpack.watcher.condition.CompareCondition;
@ -54,7 +53,6 @@ public class HttpInputIntegrationTests extends AbstractWatcherIntegrationTestCas
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.watcher.input.http;
import io.netty.handler.codec.http.HttpHeaders;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.settings.Settings;
@ -39,7 +40,6 @@ import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent;
import org.elasticsearch.xpack.watcher.watch.Payload;
import org.elasticsearch.xpack.watcher.watch.Watch;
import org.elasticsearch.xpack.watcher.watch.WatchStatus;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.joda.time.DateTime;
import org.junit.Before;

View File

@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.watcher.test;
import io.netty.util.internal.SystemPropertyUtil;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
@ -73,7 +74,6 @@ import org.elasticsearch.xpack.watcher.trigger.TriggerService;
import org.elasticsearch.xpack.watcher.watch.Watch;
import org.elasticsearch.xpack.watcher.watch.WatchStore;
import org.hamcrest.Matcher;
import org.jboss.netty.util.internal.SystemPropertyUtil;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@ -123,13 +123,6 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
private static String scheduleEngineName;
private boolean useSecurity3;
@Before
public void setUseSecurity3() {
useSecurity3 = randomBoolean();
}
@Override
protected TestCluster buildTestCluster(Scope scope, long seed) throws IOException {
if (securityEnabled == null) {
@ -150,7 +143,7 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
.put("index.store.mock.check_index_on_close", false)
.put("xpack.watcher.execution.scroll.size", randomIntBetween(1, 100))
.put("xpack.watcher.watch.scroll.size", randomIntBetween(1, 100))
.put(SecuritySettings.settings(securityEnabled, useSecurity3))
.put(SecuritySettings.settings(securityEnabled))
.put("xpack.watcher.trigger.schedule.engine", scheduleEngineName)
.put("script.inline", "true")
.build();
@ -274,8 +267,8 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
return Settings.builder()
.put("client.transport.sniff", false)
.put(Security.USER_SETTING.getKey(), "admin:changeme")
.put(NetworkModule.TRANSPORT_TYPE_KEY, useSecurity3 ? Security.NAME3 : Security.NAME4)
.put(NetworkModule.HTTP_TYPE_KEY, useSecurity3 ? Security.NAME3 : Security.NAME4)
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4)
.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME4)
.build();
}
@ -743,7 +736,7 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
;
public static Settings settings(boolean enabled, boolean useSecurity3) {
public static Settings settings(boolean enabled) {
Settings.Builder builder = Settings.builder();
if (!enabled) {
return builder.put("xpack.security.enabled", false).build();
@ -763,15 +756,10 @@ public abstract class AbstractWatcherIntegrationTestCase extends ESIntegTestCase
.put("xpack.security.authc.sign_user_header", false)
.put("xpack.security.audit.enabled", auditLogsEnabled)
.put(Environment.PATH_CONF_SETTING.getKey(), conf);
if (useSecurity3) {
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME3);
builder.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME3);
} else {
// security should always use one of its transports so if it is enabled explicitly declare one otherwise a local
// transport could be used
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4);
builder.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME4);
}
// security should always use one of its transports so if it is enabled explicitly declare one otherwise a local
// transport could be used
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4);
builder.put(NetworkModule.HTTP_TYPE_KEY, Security.NAME4);
return builder.build();
} catch (IOException ex) {
throw new RuntimeException("failed to build settings for security", ex);

View File

@ -15,7 +15,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.transport.Netty3Plugin;
import org.elasticsearch.transport.Netty4Plugin;
import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase;
import org.elasticsearch.xpack.security.authc.support.SecuredString;
@ -55,7 +54,6 @@ public class WatcherSettingsFilterTests extends AbstractWatcherIntegrationTestCa
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
ArrayList<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(Netty3Plugin.class); // for http
plugins.add(Netty4Plugin.class); // for http
return plugins;
}

View File

@ -114,7 +114,7 @@ public class IndexAuditIT extends ESIntegTestCase {
protected Settings externalClusterClientSettings() {
return Settings.builder()
.put(Security.USER_SETTING.getKey(), USER + ":" + PASS)
.put(NetworkModule.TRANSPORT_TYPE_KEY, randomFrom("security3", "security4"))
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
.build();
}

View File

@ -23,14 +23,6 @@ import java.util.Collections;
public class ReindexWithSecurityIT extends SecurityIntegTestCase {
private boolean useSecurity3;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
useSecurity3 = randomBoolean();
}
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
@ -49,11 +41,7 @@ public class ReindexWithSecurityIT extends SecurityIntegTestCase {
@Override
protected Settings externalClusterClientSettings() {
Settings.Builder builder = Settings.builder().put(super.externalClusterClientSettings());
if (useSecurity3) {
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME3);
} else {
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4);
}
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4);
builder.put(Security.USER_SETTING.getKey(), "test_admin:changeme");
return builder.build();
}

View File

@ -40,7 +40,7 @@ public class SecurityTransportClientIT extends ESIntegTestCase {
protected Settings externalClusterClientSettings() {
return Settings.builder()
.put(Security.USER_SETTING.getKey(), ADMIN_USER_PW)
.put(NetworkModule.TRANSPORT_TYPE_KEY, randomFrom("security3", "security4"))
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
.build();
}

View File

@ -39,7 +39,7 @@ public class CustomRealmIT extends ESIntegTestCase {
return Settings.builder()
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
.put(NetworkModule.TRANSPORT_TYPE_KEY, randomFrom("security3", "security4"))
.put(NetworkModule.TRANSPORT_TYPE_KEY, "security4")
.build();
}

View File

@ -45,16 +45,6 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo;
* indexed in the cluster.
*/
public class SmokeTestMonitoringWithSecurityIT extends ESIntegTestCase {
private boolean useSecurity3;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
useSecurity3 = randomBoolean();
}
private static final String USER = "test_user";
private static final String PASS = "changeme";
private static final String KEYSTORE_PASS = "keypass";
@ -67,18 +57,12 @@ public class SmokeTestMonitoringWithSecurityIT extends ESIntegTestCase {
@Override
protected Settings externalClusterClientSettings() {
final Settings.Builder builder =
Settings.builder()
return Settings.builder()
.put(Security.USER_SETTING.getKey(), USER + ":" + PASS)
.put("xpack.security.transport.ssl.enabled", true)
.put("xpack.ssl.keystore.path", clientKeyStore)
.put("xpack.ssl.keystore.password", KEYSTORE_PASS);
if (useSecurity3) {
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME3);
} else {
builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4);
}
return builder.build();
.put("xpack.ssl.keystore.password", KEYSTORE_PASS)
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4).build();
}
@Before