Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
18a1bca
KAFKA-9320: Initial commit.
nizhikov May 19, 2020
1076e51
KAFKA-9320: Initial commit.
nizhikov May 19, 2020
7dec0d6
KAFKA-9320: Test added
nizhikov May 20, 2020
f6afbb9
KAFKA-9320: Test added
nizhikov May 20, 2020
142e487
KAFKA-9320: Test added
nizhikov May 20, 2020
ac448d1
KAFKA-9320: Test added
nizhikov May 20, 2020
e1287c6
KAFKA-9320: SslVersionsTransportLayerTest added.
nizhikov May 25, 2020
b310e60
KAFKA-9320: Tests fix.
nizhikov May 26, 2020
518eb77
KAFKA-9320: system tests updated.
nizhikov May 26, 2020
5b5f37e
KAFKA-9320: system tests updated.
nizhikov May 27, 2020
c7000d9
KAFKA-9320: system tests updated.
nizhikov May 27, 2020
862f7ae
KAFKA-9320: code review fixes
nizhikov May 28, 2020
d1dd114
Merge branch 'trunk' into KAFKA-9320
nizhikov May 28, 2020
5578192
KAFKA-9320: code review fixes
nizhikov May 28, 2020
c1847e7
KAFKA-9320: code review fixes
nizhikov May 28, 2020
c901254
KAFKA-9320: code review fixes
nizhikov May 28, 2020
61cd6c5
KAFKA-9320: code review fixes
nizhikov May 28, 2020
fd1f48b
KAFKA-9320: code review fixes
nizhikov May 29, 2020
e1a2fe4
Merge branch 'trunk' into KAFKA-9320
nizhikov May 29, 2020
4e7eaec
KAFKA-9320: test fix.
nizhikov May 29, 2020
c756720
KAFKA-9320: code review fixes.
nizhikov May 29, 2020
a231e2f
KAFKA-9320: code review fixes.
nizhikov May 29, 2020
7ab2f39
KAFKA-9320: code review fixes.
nizhikov Jun 1, 2020
17612ac
KAFKA-9320: code review fixes.
nizhikov Jun 1, 2020
ebb20e1
KAFKA-9320: revert test changes.
nizhikov Jun 1, 2020
1b55587
KAFKA-9320: fix test duration.
nizhikov Jun 1, 2020
9da1c21
KAFKA-9320: unused code removed.
nizhikov Jun 1, 2020
3e6c445
KAFKA-9320: code review fixes.
nizhikov Jun 1, 2020
14bf85a
KAFKA-9320: TLSv1.3 vs TLSv1.2 explanation comments.
nizhikov Jun 2, 2020
67f0ef9
Merge branch 'trunk' into KAFKA-9320
nizhikov Jun 2, 2020
869e342
KAFKA-9320: code review fixes.
nizhikov Jun 2, 2020
ca81fcd
KAFKA-9320: code review fixes.
nizhikov Jun 2, 2020
6a82441
KAFKA-9320: SSL_PROTOCOL_DOC updated.
nizhikov Jun 2, 2020
ce7505f
Documentation tweaks
ijuma Jun 2, 2020
b293578
Merge branch 'trunk' into KAFKA-9320
nizhikov Jun 2, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.kafka.common.config;

import org.apache.kafka.common.config.internals.BrokerSecurityConfigs;
import org.apache.kafka.common.utils.Java;
import org.apache.kafka.common.utils.Utils;

import javax.net.ssl.KeyManagerFactory;
Expand Down Expand Up @@ -49,11 +50,15 @@ public class SslConfigs {

public static final String SSL_PROTOCOL_CONFIG = "ssl.protocol";
public static final String SSL_PROTOCOL_DOC = "The SSL protocol used to generate the SSLContext. "
+ "Default setting is TLSv1.2, which is fine for most cases. "
+ "Allowed values in recent JVMs are TLSv1.2 and TLSv1.3. TLS, TLSv1.1, SSL, SSLv2 and SSLv3 "
+ "may be supported in older JVMs, but their usage is discouraged due to known security vulnerabilities.";
+ "The default is 'TLSv1.3' when running with Java 11 or newer, 'TLSv1.2' otherwise. "
+ "This value should be fine for most use cases. "
+ "Allowed values in recent JVMs are 'TLSv1.2' and 'TLSv1.3'. 'TLS', 'TLSv1.1', 'SSL', 'SSLv2' and 'SSLv3' "
+ "may be supported in older JVMs, but their usage is discouraged due to known security vulnerabilities. "
+ "With the default value for this config and 'ssl.enabled.protocols', clients will downgrade to 'TLSv1.2' if "
+ "the server does not support 'TLSv1.3'. If this config is set to 'TLSv1.2', clients will not use 'TLSv1.3' even "
+ "if it is one of the values in ssl.enabled.protocols and the server only supports 'TLSv1.3'.";

public static final String DEFAULT_SSL_PROTOCOL = "TLSv1.2";
public static final String DEFAULT_SSL_PROTOCOL;

public static final String SSL_PROVIDER_CONFIG = "ssl.provider";
public static final String SSL_PROVIDER_DOC = "The name of the security provider used for SSL connections. Default value is the default security provider of the JVM.";
Expand All @@ -63,8 +68,22 @@ public class SslConfigs {
+ "By default all the available cipher suites are supported.";

public static final String SSL_ENABLED_PROTOCOLS_CONFIG = "ssl.enabled.protocols";
public static final String SSL_ENABLED_PROTOCOLS_DOC = "The list of protocols enabled for SSL connections.";
public static final String DEFAULT_SSL_ENABLED_PROTOCOLS = "TLSv1.2";
public static final String SSL_ENABLED_PROTOCOLS_DOC = "The list of protocols enabled for SSL connections. "
+ "The default is 'TLSv1.2,TLSv1.3' when running with Java 11 or newer, 'TLSv1.2' otherwise. With the "
+ "default value for Java 11, clients and servers will prefer TLSv1.3 if both support it and fallback "
+ "to TLSv1.2 otherwise (assuming both support at least TLSv1.2). This default should be fine for most "
+ "cases. Also see the config documentation for `ssl.protocol`.";
public static final String DEFAULT_SSL_ENABLED_PROTOCOLS;

static {
if (Java.IS_JAVA11_COMPATIBLE) {
DEFAULT_SSL_PROTOCOL = "TLSv1.3";
DEFAULT_SSL_ENABLED_PROTOCOLS = "TLSv1.2,TLSv1.3";
} else {
DEFAULT_SSL_PROTOCOL = "TLSv1.2";
DEFAULT_SSL_ENABLED_PROTOCOLS = "TLSv1.2";
}
}

public static final String SSL_KEYSTORE_TYPE_CONFIG = "ssl.keystore.type";
public static final String SSL_KEYSTORE_TYPE_DOC = "The file format of the key store file. "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocketFactory;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetAddress;
Expand Down Expand Up @@ -578,26 +577,6 @@ public void testTLSDefaults() throws Exception {
server.verifyAuthenticationMetrics(1, 2);
}

@Test
public void testUnsupportedCipher() throws Exception {
String[] cipherSuites = ((SSLServerSocketFactory) SSLServerSocketFactory.getDefault()).getSupportedCipherSuites();
if (cipherSuites != null && cipherSuites.length > 1) {
sslServerConfigs = serverCertStores.getTrustingConfig(clientCertStores);
sslServerConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuites[0]));
sslClientConfigs = clientCertStores.getTrustingConfig(serverCertStores);
sslClientConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuites[1]));

server = createEchoServer(SecurityProtocol.SSL);
createSelector(sslClientConfigs);

checkAuthentiationFailed("1", "TLSv1.1");
server.verifyAuthenticationMetrics(0, 1);

checkAuthentiationFailed("2", "TLSv1");
server.verifyAuthenticationMetrics(0, 2);
Comment thread
nizhikov marked this conversation as resolved.
}
}

/** Checks connection failed using the specified {@code tlsVersion}. */
private void checkAuthentiationFailed(String node, String tlsVersion) throws IOException {
sslClientConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Arrays.asList(tlsVersion));
Expand Down Expand Up @@ -627,7 +606,6 @@ public void testUnsupportedTLSVersion() throws Exception {
*/
@Test
public void testUnsupportedCiphers() throws Exception {
String node = "0";
SSLContext context = SSLContext.getInstance(tlsProtocol);
context.init(null, null, null);
String[] cipherSuites = context.getDefaultSSLParameters().getCipherSuites();
Expand All @@ -636,10 +614,8 @@ public void testUnsupportedCiphers() throws Exception {

sslClientConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Arrays.asList(cipherSuites[1]));
createSelector(sslClientConfigs);
InetSocketAddress addr = new InetSocketAddress("localhost", server.port());
selector.connect(node, addr, BUFFER_SIZE, BUFFER_SIZE);

NetworkTestUtils.waitForChannelClose(selector, node, ChannelState.State.AUTHENTICATION_FAILED);
checkAuthentiationFailed("1", tlsProtocol);
server.verifyAuthenticationMetrics(0, 1);
Comment thread
nizhikov marked this conversation as resolved.
}

Expand Down Expand Up @@ -1250,7 +1226,7 @@ private interface FailureAction {
void run() throws IOException;
}

private static class TestSslChannelBuilder extends SslChannelBuilder {
static class TestSslChannelBuilder extends SslChannelBuilder {

private Integer netReadBufSizeOverride;
private Integer netWriteBufSizeOverride;
Expand Down Expand Up @@ -1361,7 +1337,7 @@ private void resetDelayedFlush() {
}
}

private static class ResizeableBufferSize {
static class ResizeableBufferSize {
private Integer bufSizeOverride;
ResizeableBufferSize(Integer bufSizeOverride) {
this.bufSizeOverride = bufSizeOverride;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.kafka.common.network;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import org.apache.kafka.common.config.SslConfigs;
import org.apache.kafka.common.metrics.Metrics;
import org.apache.kafka.common.security.TestSecurityConfig;
import org.apache.kafka.common.security.auth.SecurityProtocol;
import org.apache.kafka.common.utils.Java;
import org.apache.kafka.common.utils.LogContext;
import org.apache.kafka.common.utils.Time;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assume.assumeTrue;

public class SslTransportTls12Tls13Test {
private static final int BUFFER_SIZE = 4 * 1024;
private static final Time TIME = Time.SYSTEM;

private NioEchoServer server;
private Selector selector;
private Map<String, Object> sslClientConfigs;
private Map<String, Object> sslServerConfigs;

@Before
public void setup() throws Exception {
// Create certificates for use by client and server. Add server cert to client truststore and vice versa.
CertStores serverCertStores = new CertStores(true, "server", "localhost");
CertStores clientCertStores = new CertStores(false, "client", "localhost");
sslServerConfigs = serverCertStores.getTrustingConfig(clientCertStores);
sslClientConfigs = clientCertStores.getTrustingConfig(serverCertStores);

LogContext logContext = new LogContext();
ChannelBuilder channelBuilder = new SslChannelBuilder(Mode.CLIENT, null, false, logContext);
channelBuilder.configure(sslClientConfigs);
this.selector = new Selector(5000, new Metrics(), TIME, "MetricGroup", channelBuilder, logContext);
}

@After
public void teardown() throws Exception {
if (selector != null)
this.selector.close();
if (server != null)
this.server.close();
}

/**
* Tests that connections fails if TLSv1.3 enabled but cipher suite suitable only for TLSv1.2 used.
*/
@Test
public void testCiphersSuiteForTls12FailsForTls13() throws Exception {
assumeTrue(Java.IS_JAVA11_COMPATIBLE);

String cipherSuite = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";

sslServerConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Collections.singletonList("TLSv1.3"));
sslServerConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuite));
server = NetworkTestUtils.createEchoServer(ListenerName.forSecurityProtocol(SecurityProtocol.SSL),
SecurityProtocol.SSL, new TestSecurityConfig(sslServerConfigs), null, TIME);

sslClientConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Collections.singletonList("TLSv1.3"));
sslClientConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuite));

checkAuthentiationFailed();
}

/**
* Tests that connections can't be made if server uses TLSv1.2 with custom cipher suite and client uses TLSv1.3.
*/
@Test
public void testCiphersSuiteFailForServerTls12ClientTls13() throws Exception {
assumeTrue(Java.IS_JAVA11_COMPATIBLE);

String tls12CipherSuite = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
String tls13CipherSuite = "TLS_AES_128_GCM_SHA256";

sslServerConfigs.put(SslConfigs.SSL_PROTOCOL_CONFIG, "TLSv1.2");
sslServerConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Collections.singletonList("TLSv1.2"));
sslServerConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(tls12CipherSuite));
server = NetworkTestUtils.createEchoServer(ListenerName.forSecurityProtocol(SecurityProtocol.SSL),
SecurityProtocol.SSL, new TestSecurityConfig(sslServerConfigs), null, TIME);

sslClientConfigs.put(SslConfigs.SSL_PROTOCOL_CONFIG, "TLSv1.3");
sslClientConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(tls13CipherSuite));

checkAuthentiationFailed();
}

/**
* Tests that connections can be made with TLSv1.3 cipher suite.
*/
@Test
public void testCiphersSuiteForTls13() throws Exception {
assumeTrue(Java.IS_JAVA11_COMPATIBLE);

String cipherSuite = "TLS_AES_128_GCM_SHA256";

sslServerConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuite));
server = NetworkTestUtils.createEchoServer(ListenerName.forSecurityProtocol(SecurityProtocol.SSL),
SecurityProtocol.SSL, new TestSecurityConfig(sslServerConfigs), null, TIME);

sslClientConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuite));
checkAuthenticationSucceed();
}

/**
* Tests that connections can be made with TLSv1.2 cipher suite.
*/
@Test
public void testCiphersSuiteForTls12() throws Exception {
String cipherSuite = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";

sslServerConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Arrays.asList(SslConfigs.DEFAULT_SSL_ENABLED_PROTOCOLS.split(",")));
sslServerConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuite));
server = NetworkTestUtils.createEchoServer(ListenerName.forSecurityProtocol(SecurityProtocol.SSL),
SecurityProtocol.SSL, new TestSecurityConfig(sslServerConfigs), null, TIME);

sslClientConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Arrays.asList(SslConfigs.DEFAULT_SSL_ENABLED_PROTOCOLS.split(",")));
sslClientConfigs.put(SslConfigs.SSL_CIPHER_SUITES_CONFIG, Collections.singletonList(cipherSuite));
checkAuthenticationSucceed();
}

/** Checks connection failed using the specified {@code tlsVersion}. */
private void checkAuthentiationFailed() throws IOException, InterruptedException {
sslClientConfigs.put(SslConfigs.SSL_ENABLED_PROTOCOLS_CONFIG, Arrays.asList("TLSv1.3"));
createSelector(sslClientConfigs);
InetSocketAddress addr = new InetSocketAddress("localhost", server.port());
selector.connect("0", addr, BUFFER_SIZE, BUFFER_SIZE);

NetworkTestUtils.waitForChannelClose(selector, "0", ChannelState.State.AUTHENTICATION_FAILED);
server.verifyAuthenticationMetrics(0, 1);
}

private void checkAuthenticationSucceed() throws IOException, InterruptedException {
createSelector(sslClientConfigs);
InetSocketAddress addr = new InetSocketAddress("localhost", server.port());
selector.connect("0", addr, BUFFER_SIZE, BUFFER_SIZE);
NetworkTestUtils.waitForChannelReady(selector, "0");
server.verifyAuthenticationMetrics(1, 0);
}

private void createSelector(Map<String, Object> sslClientConfigs) {
SslTransportLayerTest.TestSslChannelBuilder channelBuilder = new SslTransportLayerTest.TestSslChannelBuilder(Mode.CLIENT);
channelBuilder.configureBufferSizes(null, null, null);
channelBuilder.configure(sslClientConfigs);
this.selector = new Selector(100 * 5000, new Metrics(), TIME, "MetricGroup", channelBuilder, new LogContext());
}
}
Loading