Repository: incubator-impala Updated Branches: refs/heads/master 8149dbfc9 -> 294d42adc
IMPALA-5775: Allow shell to support TLSv1, v1.1 and v1.2 The shell uses Thrift's TSSLSocket to negotiate secure connections to Impala. This socket uses a variable SSL_VERSION to determine which SSL and TLS protocol versions it will connect to. SSL_VERSION was hardcoded to be PROTOCOL_TLSv1, which only supports TLSv1 servers and no other protocol version. Change the allowed version to be PROTOCOL_SSLv23, which supports any TLS or SSL protocol. We rely on the server not to allow SSLv2 or v3 connections. Testing: Added a new custom cluster test to confirm that the shell can connect to a TLSv1.2 cluster. Confirmed that the test is correctly skipped on machines with an old version of OpenSSL that does not support TLSv1.2. Change-Id: I5487f82d110676b9c3c7a5305931da00c7f68ca0 Reviewed-on: http://gerrit.cloudera.org:8080/7675 Reviewed-by: Tim Armstrong <[email protected]> Tested-by: Impala Public Jenkins Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/e4a0e2f3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/e4a0e2f3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/e4a0e2f3 Branch: refs/heads/master Commit: e4a0e2f391bce3b8411ce7e5010856a54dc52991 Parents: 8149dbf Author: Henry Robinson <[email protected]> Authored: Mon Aug 14 18:04:55 2017 -0700 Committer: Impala Public Jenkins <[email protected]> Committed: Wed Aug 16 08:10:02 2017 +0000 ---------------------------------------------------------------------- shell/TSSLSocketWithWildcardSAN.py | 7 ++++++ tests/custom_cluster/test_client_ssl.py | 33 ++++++++++++++++++++++++++-- tests/util/thrift_util.py | 3 +++ 3 files changed, 41 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/e4a0e2f3/shell/TSSLSocketWithWildcardSAN.py ---------------------------------------------------------------------- diff --git a/shell/TSSLSocketWithWildcardSAN.py b/shell/TSSLSocketWithWildcardSAN.py old mode 100644 new mode 100755 index 7e15ac8..d65cc68 --- a/shell/TSSLSocketWithWildcardSAN.py +++ b/shell/TSSLSocketWithWildcardSAN.py @@ -18,6 +18,7 @@ # under the License. import re +import ssl from thrift.transport import TSSLSocket from thrift.transport.TTransport import TTransportException @@ -42,6 +43,12 @@ class TSSLSocketWithWildcardSAN(TSSLSocket.TSSLSocket): ca_certs=None, unix_socket=None): TSSLSocket.TSSLSocket.__init__(self, host, port, validate, ca_certs, unix_socket) + # Set client protocol choice to be very permissive, as we rely on servers to enforce + # good protocol selection. This value is forwarded to the ssl.wrap_socket() API during + # open(). See https://docs.python.org/2/library/ssl.html#socket-creation for a table + # that shows a better option is not readily available for sockets that use + # wrap_socket(). + self.SSL_VERSION = ssl.PROTOCOL_SSLv23 def _validate_cert(self): cert = self.handle.getpeercert() http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/e4a0e2f3/tests/custom_cluster/test_client_ssl.py ---------------------------------------------------------------------- diff --git a/tests/custom_cluster/test_client_ssl.py b/tests/custom_cluster/test_client_ssl.py index 9d19234..4858ce0 100644 --- a/tests/custom_cluster/test_client_ssl.py +++ b/tests/custom_cluster/test_client_ssl.py @@ -20,6 +20,7 @@ import logging import os import pytest import signal +import ssl import socket import time @@ -28,6 +29,17 @@ from tests.common.impala_service import ImpaladService from tests.shell.util import run_impala_shell_cmd, run_impala_shell_cmd_no_expect, \ ImpalaShell +REQUIRED_MIN_OPENSSL_VERSION = 0x10001000L +HAS_LEGACY_OPENSSL = True +SKIP_SSL_MSG = "Legacy OpenSSL module detected" +try: + HAS_LEGACY_OPENSSL = ssl.OPENSSL_VERSION_NUMBER < REQUIRED_MIN_OPENSSL_VERSION + SKIP_SSL_MSG = "Only have OpenSSL version %X, but test requires %X" % ( + ssl.OPENSSL_VERSION_NUMBER, REQUIRED_MIN_OPENSSL_VERSION) +except AttributeError: + # Old ssl module versions don't even have OPENSSL_VERSION_NUMBER as a member. + pass + class TestClientSsl(CustomClusterTestSuite): """Tests for a client using SSL (particularly, the Impala Shell) """ @@ -92,11 +104,28 @@ class TestClientSsl(CustomClusterTestSuite): assert "Query Status: Cancelled" in result.stdout assert impalad.wait_for_num_in_flight_queries(0) + # Test that the shell can connect to a TLS1.2 only cluster, and for good measure + # restrict the cipher suite to just one choice. + TLS_V12_ARGS = ("--ssl_server_certificate=%s/wildcard-cert.pem " + "--ssl_private_key=%s/wildcard-cert.key " + "--ssl_minimum_version=tlsv1.2 " + "--ssl_client_ca_certificate=%s/wildcardCA.pem " + "--ssl_cipher_list=AES128-GCM-SHA256 " + % (CERT_DIR, CERT_DIR, CERT_DIR)) + + @pytest.mark.execute_serially + @CustomClusterTestSuite.with_args(impalad_args=TLS_V12_ARGS, + statestored_args=TLS_V12_ARGS, + catalogd_args=TLS_V12_ARGS) + @pytest.mark.skipif(HAS_LEGACY_OPENSSL, reason=SKIP_SSL_MSG) + def test_tls_v12(self, vector): + self._validate_positive_cases("%s/wildcardCA.pem" % self.CERT_DIR) + @pytest.mark.execute_serially @CustomClusterTestSuite.with_args(impalad_args=SSL_WILDCARD_ARGS, statestored_args=SSL_WILDCARD_ARGS, catalogd_args=SSL_WILDCARD_ARGS) - @pytest.mark.xfail(run=True, reason="IMPALA-4295 on Centos6") + @pytest.mark.skipif(HAS_LEGACY_OPENSSL, reason=SKIP_SSL_MSG) def test_wildcard_ssl(self, vector): """ Test for IMPALA-3159: Test with a certificate which has a wildcard for the CommonName. @@ -109,7 +138,7 @@ class TestClientSsl(CustomClusterTestSuite): @CustomClusterTestSuite.with_args(impalad_args=SSL_WILDCARD_SAN_ARGS, statestored_args=SSL_WILDCARD_SAN_ARGS, catalogd_args=SSL_WILDCARD_SAN_ARGS) - @pytest.mark.xfail(run=True, reason="IMPALA-4295") + @pytest.mark.skipif(HAS_LEGACY_OPENSSL, reason=SKIP_SSL_MSG) def test_wildcard_san_ssl(self, vector): """ Test for IMPALA-3159: Test with a certificate which has a wildcard as a SAN. """ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/e4a0e2f3/tests/util/thrift_util.py ---------------------------------------------------------------------- diff --git a/tests/util/thrift_util.py b/tests/util/thrift_util.py index 6f5871b..24e5fd7 100644 --- a/tests/util/thrift_util.py +++ b/tests/util/thrift_util.py @@ -42,6 +42,9 @@ def create_transport(host, port, service, transport_type="buffered", user=None, sock = TSSLSocket.TSSLSocket(host, port, validate=False) else: sock = TSSLSocket.TSSLSocket(host, port, validate=True, ca_certs=ssl_cert) + # Set allowed SSL / TLS protocols to a permissive set to connect to any Impala server. + import ssl + sock.SSL_VERSION = ssl.PROTOCOL_SSLv23 else: sock = TSocket(host, port) if transport_type.lower() == "buffered":
