add more tls configs to enable/disable specific cipher suites and protocols (#4902)

* add more tls configs to enable/disable specific cipher suites and protocols

* fix doc, allow empty list
This commit is contained in:
Parag Jain 2017-10-09 15:53:12 -05:00 committed by Jonathan Wei
parent 797b54d283
commit 7cc18226cd
4 changed files with 111 additions and 18 deletions

View File

@ -30,8 +30,17 @@ values for the below mentioned configs among others provided by Java implementat
|`druid.server.https.keyStoreType`|The type of the key store.|none|yes|
|`druid.server.https.certAlias`|Alias of TLS/SSL certificate for the connector.|none|yes|
|`druid.server.https.keyStorePassword`|The [Password Provider](../operations/password-provider.html) or String password for the Key Store.|none|yes|
Following table contains non-mandatory advanced configuration options, use caution.
|Property|Description|Default|Required|
|--------|-----------|-------|--------|
|`druid.server.https.keyManagerFactoryAlgorithm`|Algorithm to use for creating KeyManager, more details [here](https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#KeyManager).|`javax.net.ssl.KeyManagerFactory.getDefaultAlgorithm()`|no|
|`druid.server.https.keyManagerPassword`|The [Password Provider](../operations/password-provider.html) or String password for the Key Manager.|none|no|
|`druid.server.https.includeCipherSuites`|List of cipher suite names to include. You can either use the exact cipher suite name or a regular expression.|Jetty's default include cipher list|no|
|`druid.server.https.excludeCipherSuites`|List of cipher suite names to exclude. You can either use the exact cipher suite name or a regular expression.|Jetty's default exclude cipher list|no|
|`druid.server.https.includeProtocols`|List of exact protocols names to include.|Jetty's default include protocol list|no|
|`druid.server.https.excludeProtocols`|List of exact protocols names to exclude.|Jetty's default exclude protocol list|no|
# Druid's internal communication over TLS

View File

@ -21,6 +21,8 @@ package io.druid.server.initialization;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.druid.metadata.PasswordProvider;
import java.util.List;
public class TLSServerConfig
{
@JsonProperty
@ -32,15 +34,27 @@ public class TLSServerConfig
@JsonProperty
private String certAlias;
@JsonProperty
private String keyManagerFactoryAlgorithm;
@JsonProperty("keyStorePassword")
private PasswordProvider keyStorePasswordProvider;
@JsonProperty("keyManagerPassword")
private PasswordProvider keyManagerPasswordProvider;
@JsonProperty
private String keyManagerFactoryAlgorithm;
@JsonProperty
private List<String> includeCipherSuites;
@JsonProperty
private List<String> excludeCipherSuites;
@JsonProperty
private List<String> includeProtocols;
@JsonProperty
private List<String> excludeProtocols;
public String getKeyStorePath()
{
return keyStorePath;
@ -71,6 +85,26 @@ public class TLSServerConfig
return keyManagerFactoryAlgorithm;
}
public List<String> getIncludeCipherSuites()
{
return includeCipherSuites;
}
public List<String> getExcludeCipherSuites()
{
return excludeCipherSuites;
}
public List<String> getIncludeProtocols()
{
return includeProtocols;
}
public List<String> getExcludeProtocols()
{
return excludeProtocols;
}
@Override
public String toString()
{
@ -79,6 +113,10 @@ public class TLSServerConfig
", keyStoreType='" + keyStoreType + '\'' +
", certAlias='" + certAlias + '\'' +
", keyManagerFactoryAlgorithm='" + keyManagerFactoryAlgorithm + '\'' +
", includeCipherSuites=" + includeCipherSuites +
", excludeCipherSuites=" + excludeCipherSuites +
", includeProtocols=" + includeProtocols +
", excludeProtocols=" + excludeProtocols +
'}';
}
}

View File

@ -120,13 +120,13 @@ public class ChatHandlerServerModule implements Module
@RemoteChatHandler TLSServerConfig TLSServerConfig
)
{
final Server server = JettyServerModule.makeJettyServer(
return JettyServerModule.makeAndInitializeServer(
injector,
lifecycle,
node,
config,
TLSServerConfig,
injector.getExistingBinding(Key.get(SslContextFactory.class))
);
JettyServerModule.initializeServer(injector, lifecycle, server);
return server;
}
}

View File

@ -22,6 +22,7 @@ package io.druid.server.initialization.jetty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.fasterxml.jackson.jaxrs.smile.JacksonSmileProvider;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Ints;
import com.google.inject.Binder;
import com.google.inject.Binding;
@ -48,6 +49,7 @@ import io.druid.guice.annotations.JSR311Resource;
import io.druid.guice.annotations.Json;
import io.druid.guice.annotations.Self;
import io.druid.guice.annotations.Smile;
import io.druid.java.util.common.ISE;
import io.druid.java.util.common.RE;
import io.druid.java.util.common.lifecycle.Lifecycle;
import io.druid.java.util.common.logger.Logger;
@ -72,8 +74,10 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLEngine;
import javax.servlet.ServletException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -147,14 +151,14 @@ public class JettyServerModule extends JerseyServletModule
final TLSServerConfig TLSServerConfig
)
{
final Server server = makeJettyServer(
return makeAndInitializeServer(
injector,
lifecycle,
node,
config,
TLSServerConfig,
injector.getExistingBinding(Key.get(SslContextFactory.class))
);
initializeServer(injector, lifecycle, server);
return server;
}
@Provides
@ -175,7 +179,9 @@ public class JettyServerModule extends JerseyServletModule
return provider;
}
static Server makeJettyServer(
static Server makeAndInitializeServer(
Injector injector,
Lifecycle lifecycle,
DruidNode node,
ServerConfig config,
TLSServerConfig tlsServerConfig,
@ -216,9 +222,10 @@ public class JettyServerModule extends JerseyServletModule
connector.setPort(node.getPlaintextPort());
serverConnectors.add(connector);
}
final SslContextFactory sslContextFactory;
if (node.isEnableTlsPort()) {
log.info("Creating https connector with port [%d]", node.getTlsPort());
final SslContextFactory sslContextFactory;
if (sslContextFactoryBinding == null) {
// Never trust all certificates by default
sslContextFactory = new SslContextFactory(false);
@ -229,8 +236,26 @@ public class JettyServerModule extends JerseyServletModule
sslContextFactory.setKeyManagerFactoryAlgorithm(tlsServerConfig.getKeyManagerFactoryAlgorithm() == null
? KeyManagerFactory.getDefaultAlgorithm()
: tlsServerConfig.getKeyManagerFactoryAlgorithm());
sslContextFactory.setKeyManagerPassword(tlsServerConfig.getKeyManagerPasswordProvider() == null ? null
: tlsServerConfig.getKeyManagerPasswordProvider().getPassword());
sslContextFactory.setKeyManagerPassword(tlsServerConfig.getKeyManagerPasswordProvider() == null ?
null : tlsServerConfig.getKeyManagerPasswordProvider().getPassword());
if (tlsServerConfig.getIncludeCipherSuites() != null) {
sslContextFactory.setIncludeCipherSuites(
tlsServerConfig.getIncludeCipherSuites()
.toArray(new String[tlsServerConfig.getIncludeCipherSuites().size()]));
}
if (tlsServerConfig.getExcludeCipherSuites() != null) {
sslContextFactory.setExcludeCipherSuites(
tlsServerConfig.getExcludeCipherSuites()
.toArray(new String[tlsServerConfig.getExcludeCipherSuites().size()]));
}
if (tlsServerConfig.getIncludeProtocols() != null) {
sslContextFactory.setIncludeProtocols(
tlsServerConfig.getIncludeProtocols().toArray(new String[tlsServerConfig.getIncludeProtocols().size()]));
}
if (tlsServerConfig.getExcludeProtocols() != null) {
sslContextFactory.setExcludeProtocols(
tlsServerConfig.getExcludeProtocols().toArray(new String[tlsServerConfig.getExcludeProtocols().size()]));
}
} else {
sslContextFactory = sslContextFactoryBinding.getProvider().get();
}
@ -246,6 +271,8 @@ public class JettyServerModule extends JerseyServletModule
);
connector.setPort(node.getTlsPort());
serverConnectors.add(connector);
} else {
sslContextFactory = null;
}
final ServerConnector[] connectors = new ServerConnector[serverConnectors.size()];
@ -266,11 +293,7 @@ public class JettyServerModule extends JerseyServletModule
server.setConnectors(connectors);
return server;
}
static void initializeServer(Injector injector, Lifecycle lifecycle, final Server server)
{
// initialize server
JettyServerInitializer initializer = injector.getInstance(JettyServerInitializer.class);
try {
initializer.initialize(server, injector);
@ -286,6 +309,27 @@ public class JettyServerModule extends JerseyServletModule
public void start() throws Exception
{
server.start();
if (node.isEnableTlsPort()) {
// Perform validation
Preconditions.checkNotNull(sslContextFactory);
final SSLEngine sslEngine = sslContextFactory.newSSLEngine();
if (sslEngine.getEnabledCipherSuites() == null || sslEngine.getEnabledCipherSuites().length == 0) {
throw new ISE(
"No supported cipher suites found, supported suites [%s], configured suites include list: [%s] exclude list: [%s]",
Arrays.toString(sslEngine.getSupportedCipherSuites()),
tlsServerConfig.getIncludeCipherSuites(),
tlsServerConfig.getExcludeCipherSuites()
);
}
if (sslEngine.getEnabledProtocols() == null || sslEngine.getEnabledProtocols().length == 0) {
throw new ISE(
"No supported protocols found, supported protocols [%s], configured protocols include list: [%s] exclude list: [%s]",
Arrays.toString(sslEngine.getSupportedProtocols()),
tlsServerConfig.getIncludeProtocols(),
tlsServerConfig.getExcludeProtocols()
);
}
}
}
@Override
@ -300,6 +344,8 @@ public class JettyServerModule extends JerseyServletModule
}
}
);
return server;
}
private static int getMaxJettyAcceptorsSelectorsNum(DruidNode druidNode)