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":

Reply via email to