mirror of https://github.com/apache/kafka.git
KAFKA-4050; Allow configuration of the PRNG used for SSL
Add an optional configuration for the SecureRandom PRNG implementation, with the default behavior being the same (use the default implementation in the JDK/JRE). Author: Todd Palino <Todd Palino> Reviewers: Grant Henke <granthenke@gmail.com>, Ismael Juma <ismael@juma.me.uk>, Joel Koshy <jjkoshy@gmail.com>, Jiangjie Qin <becket.qin@gmail.com>, Rajini Sivaram <rajinisivaram@googlemail.com> Closes #1747 from toddpalino/trunk
This commit is contained in:
parent
79d3fd2bf0
commit
104d2154b6
|
@ -85,6 +85,9 @@ public class SslConfigs {
|
||||||
public static final String SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG = "ssl.endpoint.identification.algorithm";
|
public static final String SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG = "ssl.endpoint.identification.algorithm";
|
||||||
public static final String SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_DOC = "The endpoint identification algorithm to validate server hostname using server certificate. ";
|
public static final String SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_DOC = "The endpoint identification algorithm to validate server hostname using server certificate. ";
|
||||||
|
|
||||||
|
public static final String SSL_SECURE_RANDOM_IMPLEMENTATION_CONFIG = "ssl.secure.random.implementation";
|
||||||
|
public static final String SSL_SECURE_RANDOM_IMPLEMENTATION_DOC = "The SecureRandom PRNG implementation to use for SSL cryptography operations. ";
|
||||||
|
|
||||||
public static final String SSL_CLIENT_AUTH_CONFIG = "ssl.client.auth";
|
public static final String SSL_CLIENT_AUTH_CONFIG = "ssl.client.auth";
|
||||||
public static final String SSL_CLIENT_AUTH_DOC = "Configures kafka broker to request client authentication."
|
public static final String SSL_CLIENT_AUTH_DOC = "Configures kafka broker to request client authentication."
|
||||||
+ " The following settings are common: "
|
+ " The following settings are common: "
|
||||||
|
@ -109,6 +112,7 @@ public class SslConfigs {
|
||||||
.define(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, ConfigDef.Type.PASSWORD, null, ConfigDef.Importance.HIGH, SslConfigs.SSL_TRUSTSTORE_PASSWORD_DOC)
|
.define(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG, ConfigDef.Type.PASSWORD, null, ConfigDef.Importance.HIGH, SslConfigs.SSL_TRUSTSTORE_PASSWORD_DOC)
|
||||||
.define(SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG, ConfigDef.Type.STRING, SslConfigs.DEFAULT_SSL_KEYMANGER_ALGORITHM, ConfigDef.Importance.LOW, SslConfigs.SSL_KEYMANAGER_ALGORITHM_DOC)
|
.define(SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG, ConfigDef.Type.STRING, SslConfigs.DEFAULT_SSL_KEYMANGER_ALGORITHM, ConfigDef.Importance.LOW, SslConfigs.SSL_KEYMANAGER_ALGORITHM_DOC)
|
||||||
.define(SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_CONFIG, ConfigDef.Type.STRING, SslConfigs.DEFAULT_SSL_TRUSTMANAGER_ALGORITHM, ConfigDef.Importance.LOW, SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_DOC)
|
.define(SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_CONFIG, ConfigDef.Type.STRING, SslConfigs.DEFAULT_SSL_TRUSTMANAGER_ALGORITHM, ConfigDef.Importance.LOW, SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_DOC)
|
||||||
.define(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, ConfigDef.Type.STRING, null, ConfigDef.Importance.LOW, SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_DOC);
|
.define(SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, ConfigDef.Type.STRING, null, ConfigDef.Importance.LOW, SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_DOC)
|
||||||
|
.define(SslConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_CONFIG, ConfigDef.Type.STRING, null, ConfigDef.Importance.LOW, SslConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_DOC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ public class SslFactory implements Configurable {
|
||||||
private String[] cipherSuites;
|
private String[] cipherSuites;
|
||||||
private String[] enabledProtocols;
|
private String[] enabledProtocols;
|
||||||
private String endpointIdentification;
|
private String endpointIdentification;
|
||||||
|
private SecureRandom secureRandomImplementation;
|
||||||
private SSLContext sslContext;
|
private SSLContext sslContext;
|
||||||
private boolean needClientAuth;
|
private boolean needClientAuth;
|
||||||
private boolean wantClientAuth;
|
private boolean wantClientAuth;
|
||||||
|
@ -83,6 +85,15 @@ public class SslFactory implements Configurable {
|
||||||
if (endpointIdentification != null)
|
if (endpointIdentification != null)
|
||||||
this.endpointIdentification = endpointIdentification;
|
this.endpointIdentification = endpointIdentification;
|
||||||
|
|
||||||
|
String secureRandomImplementation = (String) configs.get(SslConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_CONFIG);
|
||||||
|
if (secureRandomImplementation != null) {
|
||||||
|
try {
|
||||||
|
this.secureRandomImplementation = SecureRandom.getInstance(secureRandomImplementation);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
throw new KafkaException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String clientAuthConfig = clientAuthConfigOverride;
|
String clientAuthConfig = clientAuthConfigOverride;
|
||||||
if (clientAuthConfig == null)
|
if (clientAuthConfig == null)
|
||||||
clientAuthConfig = (String) configs.get(SslConfigs.SSL_CLIENT_AUTH_CONFIG);
|
clientAuthConfig = (String) configs.get(SslConfigs.SSL_CLIENT_AUTH_CONFIG);
|
||||||
|
@ -134,7 +145,7 @@ public class SslFactory implements Configurable {
|
||||||
KeyStore ts = truststore == null ? null : truststore.load();
|
KeyStore ts = truststore == null ? null : truststore.load();
|
||||||
tmf.init(ts);
|
tmf.init(ts);
|
||||||
|
|
||||||
sslContext.init(keyManagers, tmf.getTrustManagers(), null);
|
sslContext.init(keyManagers, tmf.getTrustManagers(), this.secureRandomImplementation);
|
||||||
return sslContext;
|
return sslContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,22 @@ public class SslTransportLayerTest {
|
||||||
|
|
||||||
NetworkTestUtils.checkClientConnection(selector, node, 100, 10);
|
NetworkTestUtils.checkClientConnection(selector, node, 100, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that an invalid SecureRandom implementation cannot be configured
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testInvalidSecureRandomImplementation() throws Exception {
|
||||||
|
SslChannelBuilder channelBuilder = new SslChannelBuilder(Mode.CLIENT);
|
||||||
|
try {
|
||||||
|
sslClientConfigs.put(SslConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_CONFIG, "invalid");
|
||||||
|
channelBuilder.configure(sslClientConfigs);
|
||||||
|
fail("SSL channel configured with invalid SecureRandom implementation");
|
||||||
|
} catch (KafkaException e) {
|
||||||
|
// Expected exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests that channels cannot be created if truststore cannot be loaded
|
* Tests that channels cannot be created if truststore cannot be loaded
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -336,6 +336,7 @@ object KafkaConfig {
|
||||||
val SslKeyManagerAlgorithmProp = SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG
|
val SslKeyManagerAlgorithmProp = SslConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG
|
||||||
val SslTrustManagerAlgorithmProp = SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_CONFIG
|
val SslTrustManagerAlgorithmProp = SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_CONFIG
|
||||||
val SslEndpointIdentificationAlgorithmProp = SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG
|
val SslEndpointIdentificationAlgorithmProp = SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG
|
||||||
|
val SslSecureRandomImplementationProp = SslConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_CONFIG
|
||||||
val SslClientAuthProp = SslConfigs.SSL_CLIENT_AUTH_CONFIG
|
val SslClientAuthProp = SslConfigs.SSL_CLIENT_AUTH_CONFIG
|
||||||
|
|
||||||
/** ********* SASL Configuration ****************/
|
/** ********* SASL Configuration ****************/
|
||||||
|
@ -544,6 +545,7 @@ object KafkaConfig {
|
||||||
val SslKeyManagerAlgorithmDoc = SslConfigs.SSL_KEYMANAGER_ALGORITHM_DOC
|
val SslKeyManagerAlgorithmDoc = SslConfigs.SSL_KEYMANAGER_ALGORITHM_DOC
|
||||||
val SslTrustManagerAlgorithmDoc = SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_DOC
|
val SslTrustManagerAlgorithmDoc = SslConfigs.SSL_TRUSTMANAGER_ALGORITHM_DOC
|
||||||
val SslEndpointIdentificationAlgorithmDoc = SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_DOC
|
val SslEndpointIdentificationAlgorithmDoc = SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_DOC
|
||||||
|
val SslSecureRandomImplementationDoc = SslConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_DOC
|
||||||
val SslClientAuthDoc = SslConfigs.SSL_CLIENT_AUTH_DOC
|
val SslClientAuthDoc = SslConfigs.SSL_CLIENT_AUTH_DOC
|
||||||
|
|
||||||
/** ********* Sasl Configuration ****************/
|
/** ********* Sasl Configuration ****************/
|
||||||
|
@ -716,6 +718,7 @@ object KafkaConfig {
|
||||||
.define(SslKeyManagerAlgorithmProp, STRING, Defaults.SslKeyManagerAlgorithm, MEDIUM, SslKeyManagerAlgorithmDoc)
|
.define(SslKeyManagerAlgorithmProp, STRING, Defaults.SslKeyManagerAlgorithm, MEDIUM, SslKeyManagerAlgorithmDoc)
|
||||||
.define(SslTrustManagerAlgorithmProp, STRING, Defaults.SslTrustManagerAlgorithm, MEDIUM, SslTrustManagerAlgorithmDoc)
|
.define(SslTrustManagerAlgorithmProp, STRING, Defaults.SslTrustManagerAlgorithm, MEDIUM, SslTrustManagerAlgorithmDoc)
|
||||||
.define(SslEndpointIdentificationAlgorithmProp, STRING, null, LOW, SslEndpointIdentificationAlgorithmDoc)
|
.define(SslEndpointIdentificationAlgorithmProp, STRING, null, LOW, SslEndpointIdentificationAlgorithmDoc)
|
||||||
|
.define(SslSecureRandomImplementationProp, STRING, null, LOW, SslSecureRandomImplementationDoc)
|
||||||
.define(SslClientAuthProp, STRING, Defaults.SslClientAuth, in(Defaults.SslClientAuthRequired, Defaults.SslClientAuthRequested, Defaults.SslClientAuthNone), MEDIUM, SslClientAuthDoc)
|
.define(SslClientAuthProp, STRING, Defaults.SslClientAuth, in(Defaults.SslClientAuthRequired, Defaults.SslClientAuthRequested, Defaults.SslClientAuthNone), MEDIUM, SslClientAuthDoc)
|
||||||
.define(SslCipherSuitesProp, LIST, null, MEDIUM, SslCipherSuitesDoc)
|
.define(SslCipherSuitesProp, LIST, null, MEDIUM, SslCipherSuitesDoc)
|
||||||
|
|
||||||
|
|
|
@ -547,6 +547,7 @@ class KafkaConfigTest {
|
||||||
case KafkaConfig.SslTrustManagerAlgorithmProp =>
|
case KafkaConfig.SslTrustManagerAlgorithmProp =>
|
||||||
case KafkaConfig.SslClientAuthProp => // ignore string
|
case KafkaConfig.SslClientAuthProp => // ignore string
|
||||||
case KafkaConfig.SslEndpointIdentificationAlgorithmProp => // ignore string
|
case KafkaConfig.SslEndpointIdentificationAlgorithmProp => // ignore string
|
||||||
|
case KafkaConfig.SslSecureRandomImplementationProp => // ignore string
|
||||||
case KafkaConfig.SslCipherSuitesProp => // ignore string
|
case KafkaConfig.SslCipherSuitesProp => // ignore string
|
||||||
|
|
||||||
//Sasl Configs
|
//Sasl Configs
|
||||||
|
|
|
@ -145,6 +145,7 @@ Apache Kafka allows clients to connect over SSL. By default SSL is disabled but
|
||||||
<li>ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1 (list out the SSL protocols that you are going to accept from clients. Do note that SSL is deprecated in favor of TLS and using SSL in production is not recommended)</li>
|
<li>ssl.enabled.protocols=TLSv1.2,TLSv1.1,TLSv1 (list out the SSL protocols that you are going to accept from clients. Do note that SSL is deprecated in favor of TLS and using SSL in production is not recommended)</li>
|
||||||
<li>ssl.keystore.type=JKS</li>
|
<li>ssl.keystore.type=JKS</li>
|
||||||
<li>ssl.truststore.type=JKS</li>
|
<li>ssl.truststore.type=JKS</li>
|
||||||
|
<li>ssl.secure.random.implementation=SHA1PRNG</li>
|
||||||
</ol>
|
</ol>
|
||||||
If you want to enable SSL for inter-broker communication, add the following to the broker properties file (it defaults to PLAINTEXT)
|
If you want to enable SSL for inter-broker communication, add the following to the broker properties file (it defaults to PLAINTEXT)
|
||||||
<pre>
|
<pre>
|
||||||
|
@ -155,6 +156,14 @@ Apache Kafka allows clients to connect over SSL. By default SSL is disabled but
|
||||||
<a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html">JCA Providers Documentation</a> for more information.
|
<a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html">JCA Providers Documentation</a> for more information.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The JRE/JDK will have a default pseudo-random number generator (PRNG) that is used for cryptography operations, so it is not required to configure the
|
||||||
|
implementation used with the <pre>ssl.secure.random.implementation</pre>. However, there are performance issues with some implementations (notably, the
|
||||||
|
default chosen on Linux systems, <pre>NativePRNG</pre>, utilizes a global lock). In cases where performance of SSL connections becomes an issue,
|
||||||
|
consider explicitly setting the implementation to be used. The <pre>SHA1PRNG</pre> implementation is non-blocking, and has shown very good performance
|
||||||
|
characteristics under heavy load (50 MB/sec of produced messages, plus replication traffic, per-broker).
|
||||||
|
</p>
|
||||||
|
|
||||||
Once you start the broker you should be able to see in the server.log
|
Once you start the broker you should be able to see in the server.log
|
||||||
<pre>
|
<pre>
|
||||||
with addresses: PLAINTEXT -> EndPoint(192.168.64.1,9092,PLAINTEXT),SSL -> EndPoint(192.168.64.1,9093,SSL)</pre>
|
with addresses: PLAINTEXT -> EndPoint(192.168.64.1,9092,PLAINTEXT),SSL -> EndPoint(192.168.64.1,9093,SSL)</pre>
|
||||||
|
|
|
@ -173,6 +173,7 @@ From KafkaConfig.scala
|
||||||
val SSLKeyManagerAlgorithmProp = SSLConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG
|
val SSLKeyManagerAlgorithmProp = SSLConfigs.SSL_KEYMANAGER_ALGORITHM_CONFIG
|
||||||
val SSLTrustManagerAlgorithmProp = SSLConfigs.SSL_TRUSTMANAGER_ALGORITHM_CONFIG
|
val SSLTrustManagerAlgorithmProp = SSLConfigs.SSL_TRUSTMANAGER_ALGORITHM_CONFIG
|
||||||
val SSLEndpointIdentificationAlgorithmProp = SSLConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG
|
val SSLEndpointIdentificationAlgorithmProp = SSLConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG
|
||||||
|
val SSLSecureRandomImplementationProp = SSLConfigs.SSL_SECURE_RANDOM_IMPLEMENTATION_CONFIG
|
||||||
val SSLClientAuthProp = SSLConfigs.SSL_CLIENT_AUTH_CONFIG
|
val SSLClientAuthProp = SSLConfigs.SSL_CLIENT_AUTH_CONFIG
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue