You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by sa...@apache.org on 2016/07/26 03:47:18 UTC

[2/2] incubator-impala git commit: IMPALA-3159: impala-shell does not accept wildcard or SAN certificates

IMPALA-3159: impala-shell does not accept wildcard or SAN certificates

The impala-shell could not accept wildcard or SAN certificates
previously as the thrift library it depended on did not support them.
This patch subclasses TSSLSocket and adds the logic to take care of
the above mentioned cases by introducing the new
TSSLSocketWithWildcardSAN class.

The certificate matching logic is based on the python-ssl source code.

Added custom cluster tests to test both wildcard matching and SAN
matching.

Added be/src/testutil/certificates-info.txt which contains all the
information about the certificates which are added for the tests.

This has been tested with Python2.4 and Python2.6.

Change-Id: I75e37012eeeb0bcf87a5edf875f0ff915daf8b89
Reviewed-on: http://gerrit.cloudera.org:8080/3765
Reviewed-by: Sailesh Mukil <sa...@cloudera.com>
Tested-by: Internal 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/45ff0f9e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/45ff0f9e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/45ff0f9e

Branch: refs/heads/master
Commit: 45ff0f9e674f54b35afb2b5eced0d6ec346890d6
Parents: fbed1c9
Author: Sailesh Mukil <sa...@cloudera.com>
Authored: Mon Jul 11 15:21:34 2016 -0700
Committer: Internal Jenkins <cl...@gerrit.cloudera.org>
Committed: Tue Jul 26 02:44:25 2016 +0000

----------------------------------------------------------------------
 be/src/testutil/certificates-info.txt         |  73 ++++++++++
 be/src/testutil/incorrect-commonname-cert.key |  27 ++++
 be/src/testutil/incorrect-commonname-cert.pem |  22 +++
 be/src/testutil/wildcard-cert.key             |  27 ++++
 be/src/testutil/wildcard-cert.pem             |  21 +++
 be/src/testutil/wildcard-san-cert.key         |  27 ++++
 be/src/testutil/wildcard-san-cert.pem         |  21 +++
 be/src/testutil/wildcardCA.key                |  27 ++++
 be/src/testutil/wildcardCA.pem                |  23 ++++
 shell/TSSLSocketWithWildcardSAN.py            | 149 +++++++++++++++++++++
 shell/impala_client.py                        |   6 +-
 tests/custom_cluster/test_client_ssl.py       |  83 ++++++++++--
 tests/shell/util.py                           |  17 ++-
 13 files changed, 509 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/certificates-info.txt
----------------------------------------------------------------------
diff --git a/be/src/testutil/certificates-info.txt b/be/src/testutil/certificates-info.txt
new file mode 100644
index 0000000..43647e9
--- /dev/null
+++ b/be/src/testutil/certificates-info.txt
@@ -0,0 +1,73 @@
+The following SSL certificates are used in our tests. This lists what each certificate is
+responsible for and how they were created:
+
+  1) wildcardCA.pem & wildcardCA.key:
+
+    This is a root certificate and its key which was used to sign wildcard-cert.pem and
+    wildcard-san-cert.pem. (Added as a part of IMPALA-3159)
+
+    This was created using the following commands:
+
+      openssl genrsa -out wildcardCA.key 2048
+
+      openssl req -x509 -new -nodes -key wildcardCA.key -sha256 -days 10000 \
+          -out wildcardCA.pem
+        (Fill in all the details according to prompts)
+
+-------------
+  2) wildcard-cert.pem & wildcard-cert.key:
+
+    This is a wildcard certificate and its corresponding key which has its commonName as
+    "*". This means it should match with any host. (Added as a part of IMPALA-3159)
+
+    This was created using the following commands:
+
+      openssl genrsa -out wildcard-cert.key 2048
+
+      openssl req -new -key wildcard-cert.key -out wildcard-cert.csr
+        (Fill in all the details according to prompts)
+
+      openssl x509 -req -in wildcard-cert.csr -CA wildcardCA.pem -CAkey wildcardCA.key \
+          -CAcreateserial -out wildcard-cert.pem -days 10000 -sha256
+
+-------------
+  3) wildcard-san-cert.pem & wildcard-san-cert.key:
+
+    This is a certificate and its corresponding key which has 2 SANs
+    (subjectAlternativeName). One is "localhost" and the other is a wildcard ("*").
+    (Added as a part of IMPALA-3159)
+
+    This was created using the following commands:
+
+      openssl genrsa -out wildcard-san-cert.key 2048
+
+      openssl req -new -sha256 -key wildcard-san-cert.key \
+          -subj "/C=US/ST=CA/L=SF/O=Cloudera/CN=badCN" -reqexts SAN \
+          -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:localhost,DNS:*")) \
+          -out wildcard-san-cert.csr
+
+      openssl x509 -req -in wildcard-san-cert.csr -CA wildcardCA.pem \
+          -CAkey wildcardCA.key -CAcreateserial \
+          -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:localhost,DNS:*")) \
+          -extensions SAN -out wildcard-san-cert.pem -days 10000 -sha256
+
+-------------
+  4) server-cert.pem & server-cert.key:
+
+    This is a self-signed certificate and its corresponding key which has the commonName
+    as "localhost".
+
+      This was created the same as 1) with a different commonName.
+
+-------------
+  5) incorrect-commonname-cert.pem & incorrect-commonname-cert.key:
+
+    This is a certificate and its corresponding key that has an incorrect commonName,
+    which means that it should not match with any host. (Added as a part of IMPALA-3159)
+
+      This was created the same as 1) with a different commonName.
+
+-------------
+To verify the contents of any certificate, do the following:
+
+  openssl x509 -in <certificate_name> -text

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/incorrect-commonname-cert.key
----------------------------------------------------------------------
diff --git a/be/src/testutil/incorrect-commonname-cert.key b/be/src/testutil/incorrect-commonname-cert.key
new file mode 100644
index 0000000..30e84f1
--- /dev/null
+++ b/be/src/testutil/incorrect-commonname-cert.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA4ULEO7tY9Ujpk4oN7JMWEwBXGZloPJ+v6Ldl3O41Uhym2B6V
+1nikx1uhDbWTwS4+UBvLX0NcMBLWPpYJcATNDUt8tpFR+kTOCXWz49FFTPdEzXa4
+8kFCvfuu5yc/l2Fq4jjt7LUWtFlATGFHdUSL+0PrGaIA7qqIYIRLIUI9Ygppy7SY
+37Pr3LGBRkPjWWLh//LxSEhf0L1jIXKrFCSKMBoVxzXpM841PGB6xQGRIer19c9B
+QIhsXqI1Ojp/rd29epmiBsrLai3OKSdZU0Ea0YtiSm+HfOBukfQbdvusYX+sEsrW
+ZMpVCDju4ni9yWhi9pLpGslnNb+SJ3kJpM5XeQIDAQABAoIBACnccYE0MLTshtOv
+PSUwtFJ1proQIynY9yTFKD3lWq1Wu76/+FJx+xU9NvHIQ5wLzvKuJ54dc31Pktbw
+pPJXQg/tblCzMsvSi4OAhxyYIEvMS9Hu9TG35QJPSlKUnaGxLd66e6SYho6fY26O
+SWxGf8kC9ya9T3UK5eshyqB0odmdAoi0VcL6SjBDgd7w8IFCQNtDJwRHKLdqv5+4
+TW885wvXPxZrSI+HCr0aenXcKdwdpav+1QrTvkcP++0RAeCwKwIu+7IiOxZRLmhK
+x+BnqKxQdNctnq99DN8h35bj5xoHosYyMVfrBxrm8Dhsu5XtzPRjPf+iA20pNIkF
+ieFChgECgYEA8dqlvjhMUs4wxPa71A0OpvCT3kaeVQ7aaKu3Uk6VgSz3XgXoQcF4
+KWHg+0O2vonAdCkBYpz0lSRDKgrr9RV6K25YKdhGF0/t8Clt9lbi3aUpFmNELfuV
+YPTs5pgm49lV49UgJ2Bm6zskWBoJfvoK07rWuxSGu/2C4L2Fdj60p7kCgYEA7m+p
+t9atVonVFc2yPLJdOYko6+EvWYGj8GxxT9OyrcVPbarYrey4v+fs1MZ0jYR7GfLh
+pgTRzgvkGWSiqevQxlETH5SydX58uaqx9o/U6kA5U19p8w1lRz7tjBYlGaCthG9A
+y6+Q0MdMj+bfR9WpzPxLEG5kZ4Li1v4TjIeTjcECgYEApXt/sLoArx/aCsrwFdWh
+UuSFqK8VIwn4s2nbE3wlm69SyoisNGHWgCoysHnSjmjewBxWkEzopSucsSWr8ZPy
+dckYlfkfbFAKdCtEzCsDK7kYdfMR8YyU1zR+7ADrizdoJ23qhEbX5NggtA+Ms88O
+nXTX/EW9Mt/xLyk+KnwZTDECgYAwqDzcNUT+SfZgEq/yzvtTSHg/Wp7NBzWrVJXz
+EmJ+L6u714eMRqiVEQE1kqIqVwTAEN6XgJhIEgkkXXMMdgEO13Ctmyyn6X4ObZUP
+md57R0vrhacbYHpwhZj4Y3SCvFVslz+D0XoeAO3Q1+5svF+AY2P2IHEA5qbf9M2M
+egZUgQKBgH7dY106NWHk4CeusuQ9ACMknx/4NYWmA2cU4KrwfQs/9/poCcHVylgc
+4wV95surNPnef6x3o+WJDUSltLSdm7feSOt6eZpISxks51pH+dFqaxuzIb5e02HA
+gVude9Whb4oPCJWgCdTE9bifrf/v8dloLXG44BHXX9WrEMx53i6E
+-----END RSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/incorrect-commonname-cert.pem
----------------------------------------------------------------------
diff --git a/be/src/testutil/incorrect-commonname-cert.pem b/be/src/testutil/incorrect-commonname-cert.pem
new file mode 100644
index 0000000..7edbdff
--- /dev/null
+++ b/be/src/testutil/incorrect-commonname-cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnYCCQDDWZz2iHv/ODANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjERMA8GA1UECgwIQ2xvdWRlcmEx
+DzANBgNVBAsMBkltcGFsYTEWMBQGA1UEAwwNYmFkQ29tbW9uTmFtZTEjMCEGCSqG
+SIb3DQEJARYUc2FpbGVzaEBjbG91ZGVyYS5jb20wHhcNMTYwNzEyMTgyMjA4WhcN
+NDMxMTI4MTgyMjA4WjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYD
+VQQHDAJTRjERMA8GA1UECgwIQ2xvdWRlcmExDzANBgNVBAsMBkltcGFsYTEWMBQG
+A1UEAwwNYmFkQ29tbW9uTmFtZTEjMCEGCSqGSIb3DQEJARYUc2FpbGVzaEBjbG91
+ZGVyYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhQsQ7u1j1
+SOmTig3skxYTAFcZmWg8n6/ot2Xc7jVSHKbYHpXWeKTHW6ENtZPBLj5QG8tfQ1ww
+EtY+lglwBM0NS3y2kVH6RM4JdbPj0UVM90TNdrjyQUK9+67nJz+XYWriOO3stRa0
+WUBMYUd1RIv7Q+sZogDuqohghEshQj1iCmnLtJjfs+vcsYFGQ+NZYuH/8vFISF/Q
+vWMhcqsUJIowGhXHNekzzjU8YHrFAZEh6vX1z0FAiGxeojU6On+t3b16maIGystq
+Lc4pJ1lTQRrRi2JKb4d84G6R9Bt2+6xhf6wSytZkylUIOO7ieL3JaGL2kukayWc1
+v5IneQmkzld5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAGgamvYR6LECHTU3rUIt
+Z0ecca6RsspGN6UUwfX9t44TmEJ4DkHG7w/1Z+BH45jLJljsNOLK+m7w/w1ypL6/
+zGSqAOa02VgjRoOJY7k7Jwk1OAsHbxc5bAxSOXnAaZ6dgBf4lI05dFUWkRB1ZZd1
+TrVdqjlIwJpD5hlY9a3hGM02ltGR/rupWKSmvAUehXZrZduTVbyMiEmUM8/W59TX
+LhfzlBbHm6XwxLUm2VM25Uu9HFNOgVFEM6+rtrpwwHHLVACWhPv2VZTJBGdzFrFW
+OpqlfHm5EMwxZIgHHRQtOeo70lEO+Sg82i6AVUnv+LzNPyZLl0YtcakjIfWCA5rS
+WI0=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/wildcard-cert.key
----------------------------------------------------------------------
diff --git a/be/src/testutil/wildcard-cert.key b/be/src/testutil/wildcard-cert.key
new file mode 100644
index 0000000..5281170
--- /dev/null
+++ b/be/src/testutil/wildcard-cert.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA9BvJTBTYBznKDuvyGz+qZlqOVcC4lbDVq2pjUkbo09NCj/rE
+OVL30+XHOUhzzXjjUHkmBFMLMQjHQg0pIdDxIzV7UqXl4d46WC1Q0W4fJNXp59Dp
+YzK7Y95aCp5HNogcY3xZehNbPgrIv8bWYCofBrRoe9y76aKWuM2HxKL+9Ke1WftH
+8qUvesAclMpywq5XENCCjdk+af19VW5VzCTWdymrkD2xXnB4CXv9Mjq0KYG4cixY
+OPyWXPVou9oe9ZoESZARyWMUkaJdzYEk2LKItGmybt3TcPWG5Zur4qCtTRv2UGW1
+elps732l4cBGA7kvcxX/VEtqaTp22Ns3/9hemwIDAQABAoIBAQCIrfI09krLKPFZ
+D4Vc+nXXn4aovyLbNcs9knEQRYHh8R0I7vjlu+3lqHe3PDkS6Egm6958d18B0o93
+DVVliM8rzqtBaIBhyoNSkfT5frZTcq7oTJIRJ/vCfGJgJaVsBCQZFCwpbSMehv1G
+W/f2mj8LCwKhr8NLmuzXhsUpNbaZlyHBgKOfoBbzncImNT1IPcKMQpYBZZa0MKI9
+TJGrgZ/RSZKSwx7h9Jww+N0BAb2ITlsTtk9jXF2GxpyO1iGH87yc7/EC+O/V2ZTw
+RGgJ7XfSYvNoZHQg04ae1EwWrAjDbCqMZPNBbtqsDjmBdkAeRDjCOK1swMjCqJuW
+ZCxSMzcJAoGBAPvhZSJI+HdpgAxjXDKSu6TA162wC5k2S8HY35d8TKD/ejZUawH3
+xSfibbALrDzCsA/jN/nCTpme0vyDBznQdA5upzzc3qH/SvUwGTa8kPWae+XV8UKe
+ub0hWqZ6SnxkFjB7TrUyscZ5E3VKa8R8mbS9Xxa+jabZifCOiXRx4QjlAoGBAPgZ
+2dFNTwyqZE6zvZqrD41xG+2Vgmkr232CKTc2fXwx9dK6u7psW8fiijzeWGU08DSd
+39uL10K3HX67+dBjwLxGIiEmIQqxspP9BcF1WyqxbjrNNNZ+K4XiLSx7lXNET0F1
+LnG/s4+GUmAWvgcBE1VMk6GW/RQQ8HKm1BewCtF/AoGBAKY9TrhgHM0DLmX+tf0S
+5xGHzVFvHViTg1B/SKL8gL7Jnul4sd9sng0C3o4QRi8b94Ok3W7UFXhCYNIT0JMR
+x2c3FN2QkMeubNSCWEHOFoZi3V8F4uOrSr9O4jt5/us2S4bX+0yQFtD9XCBPa+0U
+p4WobrfeMDNs5COGj6Xw+ysZAoGAF5O9U1qZbIa0yZXjKtOewr5A/S78GaqFTUQV
+Tp3rBuZoigIc3PZ3MmOg52/pzpRdT2LBZ0e+ySRFtUl/0AHqyvmPPL823KFOaync
+ZioU49XAt+3QW6HZ2PtJd7S22yFetsXACCdDlRwar+75WAkOIUkJro1+t210rDCW
+bznXjVkCgYAirTLnwdpoXEuXBZstPdaEZKiJLqQKi3w8ATQopYna3Zrh4aZsUWkj
+UQu+w/ev7/oZOW7UDBF6jUhWhDX97APXOSNAgfBCN6oahxTfeTF2evoj+WDRBgGT
+qvCdseYyWPOyLhhFN7Kjk/2yH8IpfQ4i7rKD7RvpxhX/x+CG3tA+YA==
+-----END RSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/wildcard-cert.pem
----------------------------------------------------------------------
diff --git a/be/src/testutil/wildcard-cert.pem b/be/src/testutil/wildcard-cert.pem
new file mode 100644
index 0000000..9425ee3
--- /dev/null
+++ b/be/src/testutil/wildcard-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAmwCCQC/dhp+NzzLKzANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjERMA8GA1UECgwIQ2xvdWRlcmEx
+DzANBgNVBAsMBkltcGFsYTEZMBcGA1UEAwwQV2lsZGNhcmQgUm9vdCBDQTEjMCEG
+CSqGSIb3DQEJARYUc2FpbGVzaEBjbG91ZGVyYS5jb20wHhcNMTYwNzExMjMwMDIx
+WhcNNDMxMTI3MjMwMDIxWjB8MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJ
+BgNVBAcMAlNGMREwDwYDVQQKDAhDbG91ZGVyYTEPMA0GA1UECwwGSW1wYWxhMQow
+CAYDVQQDDAEqMSMwIQYJKoZIhvcNAQkBFhRzYWlsZXNoQGNsb3VkZXJhLmNvbTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPQbyUwU2Ac5yg7r8hs/qmZa
+jlXAuJWw1atqY1JG6NPTQo/6xDlS99PlxzlIc81441B5JgRTCzEIx0INKSHQ8SM1
+e1Kl5eHeOlgtUNFuHyTV6efQ6WMyu2PeWgqeRzaIHGN8WXoTWz4KyL/G1mAqHwa0
+aHvcu+milrjNh8Si/vSntVn7R/KlL3rAHJTKcsKuVxDQgo3ZPmn9fVVuVcwk1ncp
+q5A9sV5weAl7/TI6tCmBuHIsWDj8llz1aLvaHvWaBEmQEcljFJGiXc2BJNiyiLRp
+sm7d03D1huWbq+KgrU0b9lBltXpabO99peHARgO5L3MV/1RLamk6dtjbN//YXpsC
+AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfeA/dt2eIlLPvOTqowwXyS8Fm69G09wJ
+eR3cPZELJONbIRs8AicxNyglj3d2QkwLc+kMPighEqjBaGjXFxEMnY/nncw+DTtN
+eLKu+QtXtKMaVxigmXx7fkdITy3OHUiEJcwzNjTj68XycgvSol5QQ3GtjvECGQgG
+6bGle+kHrkYRRMqnnLAzoRTeTvkbGHNyoszl5Ix6iPWzCBfP/Vo+Swa+BUlDTLZs
+4I+c/ORT69vIbU8b8EI+3DA1hf+6m8Pf8gXGCSPJyB8guUBuUPdd6wUemjLCbvM9
+R6gTEr1XDEAdjPryDL3pE84AF2u4bkoPTYosM9YOO2ZGYW2/wHT/0A==
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/wildcard-san-cert.key
----------------------------------------------------------------------
diff --git a/be/src/testutil/wildcard-san-cert.key b/be/src/testutil/wildcard-san-cert.key
new file mode 100644
index 0000000..4a5cf1e
--- /dev/null
+++ b/be/src/testutil/wildcard-san-cert.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAqdaaAYAb9wd19eZbuipPcTzyr4wOL2AFqS8jbYzb55IqRb/G
+yAm60aBnL91R/LG+VFTGuPWhcxWyvsrix0lK7YhsZS4hkOO5ggW2aUmklxDszTsj
+QvVj7Jr6Sb8bXnOqYl9zA8eEVsaRookpveGJ0hKm2ZozBF71epSyTSzAxBGx3wS8
+thj+NJbAu93gWW5kHOa4657HJAmJ9Mz8rEdWnNksZhR6DtcWOQF4Mxpp+5PzgngE
+Kn+1/cmInzFs2DoehK1LkiuTVn5fXeMZ4tYxZKAn9wzk+U2VuREycVp/ZiQBGr73
+iU5mkAQDztWUQa4WRlK1A6CX8b4mZgamx00MyQIDAQABAoIBAQCYaG8dZ5Qw0u4l
+M4oe/rb5nEMAC4PzOYz67MUzGtN/9Geg3d8JRcnzMalHh6l6RRrSXJ1T/4DZYKBd
+nH1zbq8hh2oWRhZzChg/uNaflylvMw39gdM71C/OdKikIy3xTYSZ8KOqwZFduaWZ
+INNnhQyDip9V6I1dn8VUMjnrDX0StIQX/zqRBg5gtQQPsdWftwspwR0Xnqn2lMic
+hEcV+PBC1As+YeS7bnPjtJ8UW3RvpbUlyL6P4C5/5XVCYsx74qOdyKW7GwYlPs38
+CUBFkaBbveOOWJl/ESf9LSYKvN3rO3O0JMwyElnH4Jpx7xqKutZhUmSuMGxV+HwI
+2G0vQHmdAoGBANEL08gYIZGD2DZ90RSaVcQon70VsvdFKyoSbeLqcNj5Z1ZvlNvG
+7Z/dmpJSneLuKEQYGo7Yrg4lTWlGxCJVzixdgH6Ot8Zvp7AZzfUy7EyjyRhMhXcB
+ff9vacWtms/AgX1piXIuFrCobAeaoWGw8LgNZSMe9ljBRYxykmzUfZ3nAoGBAM/8
+UPgHVckbwmFbSf8kuJhtytobIAJ/l8cm3GWhyGUdddKgbozKGBpAtSNuhkQVCsAy
+v4l0G6vS6c1uxkvBekYIN0EbbMuiQ0fMLQNvmX7NQOj3s45NkcVZoO8Gx6dJ+T8s
+r7XhA/jpoi/hKSSzuPibYQ/OzMEqgQdTV7btQMnPAoGAL9FDxV53t0BwYa6P9+WB
+vtgICgl/oX4p7HrAtgoofAk4sRXe+BLd4haft968DN+rSEA3OvunfMbdmTo9vRjh
+i1ZsAQcGVJbPxcFxUigu0y0X374JPXqS5q4GhNg8NE91j0lnzj1qpUgxReACEEWY
+GpG907XOZej3zrOaeNh2T3sCgYEAk+J9lA5rIecaDG2DrOZoVwHiNbkJxp0Ax7tL
+BPzG55bN+yjV0ke0YZ5W7c2drHUlwsmSxWKIdmEum0LDvoPgtEENQL8GWbiTjE6S
+RxooEzBQkhXmVy2yk5eKRcsVVU7U6eWVPoazc150UwUPYyhjQmoA1uOdVVAqlJHf
+EZOa+KMCgYBQV5PntIQK5b2xWZ5jzJOYFadz49T5ZYXdv2V4QaRLbCYN0sLUKe9q
+wCHRbQ79Pbu16a07QGubXcWtBuSrikHShS8j+0dMRawnwUDLFGtQ0pn6NkLLQaBD
+ZPxn0R1zfJWN10ZphB/2By/WOBjwMznG2s3QP+JSq8r9bJeC2so60A==
+-----END RSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/wildcard-san-cert.pem
----------------------------------------------------------------------
diff --git a/be/src/testutil/wildcard-san-cert.pem b/be/src/testutil/wildcard-san-cert.pem
new file mode 100644
index 0000000..c64b342
--- /dev/null
+++ b/be/src/testutil/wildcard-san-cert.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDdDCCAlygAwIBAgIJAKQejNj+hCJGMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMREwDwYDVQQKDAhDbG91
+ZGVyYTEPMA0GA1UECwwGSW1wYWxhMRkwFwYDVQQDDBBXaWxkY2FyZCBSb290IENB
+MSMwIQYJKoZIhvcNAQkBFhRzYWlsZXNoQGNsb3VkZXJhLmNvbTAeFw0xNjA3MTIw
+MjQwNDdaFw00MzExMjgwMjQwNDdaMEoxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD
+QTELMAkGA1UEBwwCU0YxETAPBgNVBAoMCENsb3VkZXJhMQ4wDAYDVQQDDAViYWRD
+TjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKnWmgGAG/cHdfXmW7oq
+T3E88q+MDi9gBakvI22M2+eSKkW/xsgJutGgZy/dUfyxvlRUxrj1oXMVsr7K4sdJ
+Su2IbGUuIZDjuYIFtmlJpJcQ7M07I0L1Y+ya+km/G15zqmJfcwPHhFbGkaKJKb3h
+idISptmaMwRe9XqUsk0swMQRsd8EvLYY/jSWwLvd4FluZBzmuOuexyQJifTM/KxH
+VpzZLGYUeg7XFjkBeDMaafuT84J4BCp/tf3JiJ8xbNg6HoStS5Irk1Z+X13jGeLW
+MWSgJ/cM5PlNlbkRMnFaf2YkARq+94lOZpAEA87VlEGuFkZStQOgl/G+JmYGpsdN
+DMkCAwEAAaMbMBkwFwYDVR0RBBAwDoIJbG9jYWxob3N0ggEqMA0GCSqGSIb3DQEB
+CwUAA4IBAQCbKVWv0j0JmK6dCbmWlEdbjpyr0ABgGCggvHmzjJeSIA+stmyDp/JD
+BNO8bQTydc6EWMhOS8+9egVTevbYO6Kv9u4up/ZJ/noaEz3UnNeKAW7qWdElwM5q
+GRm29g0wQ+tz63KMzWLGLMngM3gH3Omy0xtJ9sOZgV0SWxppujaK9RNkJaikLiIw
+4uQ2WbJTiDG9U/5itOoQIroXOQF4+RugWJgkfXcuzb3fsOh9LRIOczW097E6lmWh
+QYnBeGyYUuRBvD28xTXMeAUnR3dRyUrSbzUmUI2XvLyeeEC5uvAgsvr60bvluzZ+
+msvMXVQ/eq5FNnL9eRVVNCKz+Z+zrfHt
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/wildcardCA.key
----------------------------------------------------------------------
diff --git a/be/src/testutil/wildcardCA.key b/be/src/testutil/wildcardCA.key
new file mode 100644
index 0000000..59b1f61
--- /dev/null
+++ b/be/src/testutil/wildcardCA.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAxF0t8Bg3db+lJYQAJIFNvqbhux3YHgdwD8xaUaC58ECfHh47
+fORSVVvSlFYp36eIOp3elnYDXHrndzdCLyzWDXvP58Zshf8nX05vtqBewQSTCD9L
+4QY2Q/YGhAnbJZUTCXDoYQ/ZDXEI6GCUxgaY9dj5CuhmLwVSr9eYHkS+j5aK1mHr
+DMxdAb7L7AmxLbwUQAe3XStLgG08oofQoiETa5MqlcjNeNqzZyhQ8uoT9uE17TIx
+U+D/C6DDYOo2wgFtti2U25EV6sUyTGC4SwGJ9tfgyKo8NnYvjDzHf7164bTtY6vV
+Hgn2ieokMeZyCvHGMusa/t9BRZK1yvUQP24m5QIDAQABAoIBADnHgUDon0kSfzGu
+yav0MEAtMrawbWtInPzJELp8JLpBCZD/LFnvhRqAzlG/mMqqrTcyRNDZINwRfhJi
+PCNNeh61k9OLW1uCXL96gPyn67m38tu2ZEluXoFY30ny7Hz+hH9+raIB28hMvmZC
+JQSv5EpS8dT31Tl4w3/iXGxrpfbxvJMTifuqKdC9DQtOUvDIr4yGyeUrAwfsfHzH
+JZiRoEEcfFhv6OhYPrk1NM6KBlmNYMCK/8toQSmAzG5lq8YpG0k0IKk9opAU87ql
+rlgelRoGpgtpzawWgUL/UEEOubfQtINFYM9oWm8SbFOk37vPWvFvzd85xPFbflAL
+8RLPzfECgYEA9sH/Hn/KIKeTSh01bvrSMGgf0WLlj58gWC8zZysZJU6GDub+ctCr
+AZKi7c7vqIoDQmT1RRkdSaJMFDAgDgB16fEXs/g61yULyTi18hZ4QbhX3X01sSb2
+UwYvEyljKeb4cAB/QtMeCgM2dRdMMKehH/12WH96CNzXnkNNjL9ApasCgYEAy7f9
+GLVPemOH4REAWw/fNlilEKviHR9GkWI8bpEB+M21XazSg4qX/1aelWCilCjLjDmm
+2tVk3NeYd/nojqi8MGx3uAkCFSvlpWeneARBUGnjC5qvGWY2CHiqGMys55fiFLnB
+uyuF/6Zx5lrJJuGnigBswCyQBHznRr4ovyZRta8CgYAk6t9NY9cMzaV2qCoPYY1C
+2sEv5Xjs5OTE7MLnA4aukzHxVtPov5lmEdc4dwZaE9PrAgnD/b7o/lQdjRmunpkF
+mCFwtomvGIbL4yUtg/kX9AmJRKtcxrSBtWIjnsSMR1cSArEHgWh0HQjvub2XZezw
+SU6EbQYH/2pu7ijTDuYQIwKBgCo2ec+A4nMt5J4Sc8xqwYn1XF7T/wqhzHGbtYID
+sjDoD0jV4tk3Ar/6Juo1F/szaNopqBV4WmoYkpNpyXKmLDisgTI1S6Uvb2qSy/Tm
+jNIo3s8swlO1BkVDG5v/7WQf6Mz6oNYz8pRC3R8qeLwBzkGeTOqVUVJcv1+9T5ws
+SIopAoGADMumT6YSnPdMUIx3B7aekM29/eZFjthjxCoFX6XRul2frxwPhUFQgW9m
+g0wqOmty+oaXYLDb1hxYYMolh56thyB3WcmTUt+ns83TeMDJ8ucp0KMtYpJS6e+W
+sYnVDG5VUmeFV96hHve6x6Z4b1z2N6qW+FAVIh+hAFF2hcoFoBM=
+-----END RSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/be/src/testutil/wildcardCA.pem
----------------------------------------------------------------------
diff --git a/be/src/testutil/wildcardCA.pem b/be/src/testutil/wildcardCA.pem
new file mode 100644
index 0000000..2505197
--- /dev/null
+++ b/be/src/testutil/wildcardCA.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6zCCAtOgAwIBAgIJAIHi0TcUStMuMA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMREwDwYDVQQKDAhDbG91
+ZGVyYTEPMA0GA1UECwwGSW1wYWxhMRkwFwYDVQQDDBBXaWxkY2FyZCBSb290IENB
+MSMwIQYJKoZIhvcNAQkBFhRzYWlsZXNoQGNsb3VkZXJhLmNvbTAeFw0xNjA3MTEy
+MjU4MTJaFw00MzExMjcyMjU4MTJaMIGLMQswCQYDVQQGEwJVUzELMAkGA1UECAwC
+Q0ExCzAJBgNVBAcMAlNGMREwDwYDVQQKDAhDbG91ZGVyYTEPMA0GA1UECwwGSW1w
+YWxhMRkwFwYDVQQDDBBXaWxkY2FyZCBSb290IENBMSMwIQYJKoZIhvcNAQkBFhRz
+YWlsZXNoQGNsb3VkZXJhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMRdLfAYN3W/pSWEACSBTb6m4bsd2B4HcA/MWlGgufBAnx4eO3zkUlVb0pRW
+Kd+niDqd3pZ2A1x653c3Qi8s1g17z+fGbIX/J19Ob7agXsEEkwg/S+EGNkP2BoQJ
+2yWVEwlw6GEP2Q1xCOhglMYGmPXY+QroZi8FUq/XmB5Evo+WitZh6wzMXQG+y+wJ
+sS28FEAHt10rS4BtPKKH0KIhE2uTKpXIzXjas2coUPLqE/bhNe0yMVPg/wugw2Dq
+NsIBbbYtlNuRFerFMkxguEsBifbX4MiqPDZ2L4w8x3+9euG07WOr1R4J9onqJDHm
+cgrxxjLrGv7fQUWStcr1ED9uJuUCAwEAAaNQME4wHQYDVR0OBBYEFCEEu9Mtdc0u
+ZTcujaXZDHDwg1MGMB8GA1UdIwQYMBaAFCEEu9Mtdc0uZTcujaXZDHDwg1MGMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACgUQveK0WK5mVw+NfnoYqTg
+MqP33udt358tZx97xyiLOcnEd69OKKD8yLnSHB6lgiN6JvBRpXaK15K1T4sC3fNw
+fN9j3BkSVshBWOTgaHsaAuP9QuySh5nUnwvO0QM9ehuh1tfBVYVluShJb6UV3T+v
+gFTMT+6pDozfmkx8+3HeUne5jGoWg38eVOYFQyzFp1T19+x9VPw8bYmZ3wGShpQF
+FLLbTUXn462bk6pSYeQ8SUzFezrcLfbBh6iY/51IHZxgysyXbb5v9X1m8yZfdj3n
+tUBxq6QumAv4CU7rT0lZ+CMhX8nrSvicvPhudduCvhAHSThDJvTZRCT6WFgTlqA=
+-----END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/shell/TSSLSocketWithWildcardSAN.py
----------------------------------------------------------------------
diff --git a/shell/TSSLSocketWithWildcardSAN.py b/shell/TSSLSocketWithWildcardSAN.py
new file mode 100644
index 0000000..a13dd25
--- /dev/null
+++ b/shell/TSSLSocketWithWildcardSAN.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+# Copyright 2016 Cloudera Inc.
+#
+# Licensed 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.
+
+import re
+
+from thrift.transport import TSSLSocket
+from thrift.transport.TTransport import TTransportException
+
+class CertificateError(ValueError):
+  """Convenience class to raise errors"""
+  pass
+
+class TSSLSocketWithWildcardSAN(TSSLSocket.TSSLSocket):
+  """
+  This is a subclass of thrift's TSSLSocket which has been extended to add the missing
+  functionality of validating wildcard certificates and certificates with SANs
+  (subjectAlternativeName).
+
+  The core of the validation logic is based on the python-ssl library:
+  See <https://svn.python.org/projects/python/tags/r32/Lib/ssl.py>
+  """
+  def __init__(self,
+      host='localhost',
+      port=9090,
+      validate=True,
+      ca_certs=None,
+      unix_socket=None):
+    TSSLSocket.TSSLSocket.__init__(self, host, port, validate, ca_certs, unix_socket)
+
+  def _validate_cert(self):
+    cert = self.handle.getpeercert()
+    self.peercert = cert
+    if 'subject' not in cert:
+      raise TTransportException(
+        type=TTransportException.NOT_OPEN,
+        message='No SSL certificate found from %s:%s' % (self.host, self.port))
+    try:
+      self._match_hostname(cert, self.host)
+      self.is_valid = True
+      return
+    except CertificateError, ce:
+      raise TTransportException(
+        type=TTransportException.UNKNOWN,
+        message='Certificate error with remote host: %s' % (ce))
+    raise TTransportException(
+      type=TTransportException.UNKNOWN,
+      message='Could not validate SSL certificate from '
+              'host "%s".  Cert=%s' % (self.host, cert))
+
+  def _match_hostname(self, cert, hostname):
+    """Verify that *cert* (in decoded format as returned by
+    SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 and RFC 6125
+    rules are followed, but IP addresses are not accepted for *hostname*.
+
+    CertificateError is raised on failure. On success, the function
+    returns nothing.
+    """
+    dnsnames = []
+    san = cert.get('subjectAltName', ())
+    for key, value in san:
+      if key == 'DNS':
+        if self._dnsname_match(value, hostname):
+          return
+        dnsnames.append(value)
+    if not dnsnames:
+      # The subject is only checked when there is no dNSName entry
+      # in subjectAltName
+      for sub in cert.get('subject', ()):
+        for key, value in sub:
+          # XXX according to RFC 2818, the most specific Common Name
+          # must be used.
+          if key == 'commonName':
+            if self._dnsname_match(value, hostname):
+              return
+            dnsnames.append(value)
+    if len(dnsnames) > 1:
+      raise CertificateError("hostname %r "
+        "doesn't match either of %s"
+        % (hostname, ', '.join(map(repr, dnsnames))))
+    elif len(dnsnames) == 1:
+      raise CertificateError("hostname %r "
+        "doesn't match %r"
+        % (hostname, dnsnames[0]))
+    else:
+      raise CertificateError("no appropriate commonName or "
+        "subjectAltName fields were found")
+
+  def _dnsname_match(self, dn, hostname, max_wildcards=1):
+    """Matching according to RFC 6125, section 6.4.3
+    http://tools.ietf.org/html/rfc6125#section-6.4.3
+    """
+    pats = []
+    if not dn:
+      return False
+
+    # Ported from python3-syntax:
+    # leftmost, *remainder = dn.split(r'.')
+    parts = dn.split(r'.')
+    leftmost = parts[0]
+    remainder = parts[1:]
+
+    wildcards = leftmost.count('*')
+    if wildcards > max_wildcards:
+      # Issue #17980: avoid denials of service by refusing more
+      # than one wildcard per fragment.  A survey of established
+      # policy among SSL implementations showed it to be a
+      # reasonable choice.
+      raise CertificateError(
+        "too many wildcards in certificate DNS name: " + repr(dn))
+
+    # speed up common case w/o wildcards
+    if not wildcards:
+      return dn.lower() == hostname.lower()
+
+    # RFC 6125, section 6.4.3, subitem 1.
+    # The client SHOULD NOT attempt to match a presented identifier in which
+    # the wildcard character comprises a label other than the left-most label.
+    if leftmost == '*':
+      # When '*' is a fragment by itself, it matches a non-empty dotless
+      # fragment.
+      pats.append('[^.]+')
+    elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
+      # RFC 6125, section 6.4.3, subitem 3.
+      # The client SHOULD NOT attempt to match a presented identifier
+      # where the wildcard character is embedded within an A-label or
+      # U-label of an internationalized domain name.
+      pats.append(re.escape(leftmost))
+    else:
+      # Otherwise, '*' matches any dotless string, e.g. www*
+      pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
+
+    # add the remaining fragments, ignore any wildcards
+    for frag in remainder:
+      pats.append(re.escape(frag))
+
+    pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
+    return pat.match(hostname)

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/shell/impala_client.py
----------------------------------------------------------------------
diff --git a/shell/impala_client.py b/shell/impala_client.py
index 63195f0..58e3245 100755
--- a/shell/impala_client.py
+++ b/shell/impala_client.py
@@ -253,16 +253,16 @@ class ImpalaClient(object):
     if self.use_ssl:
       # TSSLSocket needs the ssl module, which may not be standard on all Operating
       # Systems. Only attempt to import TSSLSocket if the user wants an SSL connection.
-      from thrift.transport import TSSLSocket
+      from TSSLSocketWithWildcardSAN import TSSLSocketWithWildcardSAN
 
     # sasl does not accept unicode strings, explicitly encode the string into ascii.
     host, port = self.impalad[0].encode('ascii', 'ignore'), int(self.impalad[1])
     if self.use_ssl:
       if self.ca_cert is None:
         # No CA cert means don't try to verify the certificate
-        sock = TSSLSocket.TSSLSocket(host, port, validate=False)
+        sock = TSSLSocketWithWildcardSAN(host, port, validate=False)
       else:
-        sock = TSSLSocket.TSSLSocket(host, port, validate=True, ca_certs=self.ca_cert)
+        sock = TSSLSocketWithWildcardSAN(host, port, validate=True, ca_certs=self.ca_cert)
     else:
       sock = TSocket(host, port)
     if not (self.use_ldap or self.use_kerberos):

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/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 4276505..f20b107 100644
--- a/tests/custom_cluster/test_client_ssl.py
+++ b/tests/custom_cluster/test_client_ssl.py
@@ -22,7 +22,8 @@ import time
 
 from tests.common.custom_cluster_test_suite import CustomClusterTestSuite
 from tests.common.impala_service import ImpaladService
-from tests.shell.util import run_impala_shell_cmd, ImpalaShell
+from tests.shell.util import run_impala_shell_cmd, run_impala_shell_cmd_no_expect, \
+    ImpalaShell
 
 class TestClientSsl(CustomClusterTestSuite):
   """Tests for a client using SSL (particularly, the Impala Shell) """
@@ -32,23 +33,32 @@ class TestClientSsl(CustomClusterTestSuite):
   SSL_ENABLED = "SSL is enabled"
   CONNECTED = "Connected to"
   FETCHED = "Fetched 1 row"
+  SAN_UNSUPPORTED_ERROR = ("Certificate error with remote host: hostname "
+                          "'localhost' doesn't match u'badCN'")
+
+  SSL_WILDCARD_ARGS = ("--ssl_client_ca_certificate=%s/wildcardCA.pem "
+                      "--ssl_server_certificate=%s/wildcard-cert.pem "
+                      "--ssl_private_key=%s/wildcard-cert.key"
+                      % (CERT_DIR, CERT_DIR, CERT_DIR))
+
+  SSL_WILDCARD_SAN_ARGS = ("--ssl_client_ca_certificate=%s/wildcardCA.pem "
+                          "--ssl_server_certificate=%s/wildcard-san-cert.pem "
+                          "--ssl_private_key=%s/wildcard-san-cert.key"
+                          % (CERT_DIR, CERT_DIR, CERT_DIR))
 
   @pytest.mark.execute_serially
   @CustomClusterTestSuite.with_args("--ssl_server_certificate=%s/server-cert.pem "
                                     "--ssl_private_key=%s/server-key.pem"
                                     % (CERT_DIR, CERT_DIR))
   def test_ssl(self, vector):
+
+    self._verify_negative_cases()
     # TODO: This is really two different tests, but the custom cluster takes too long to
     # start. Make it so that custom clusters can be specified across test suites.
-    result = run_impala_shell_cmd("--ssl --ca_cert=%s/server-cert.pem -q 'select 1 + 2'"
-                                  % self.CERT_DIR)
-    for msg in [self.SSL_ENABLED, self.CONNECTED, self.FETCHED]:
-      assert msg in result.stderr
+    self._validate_positive_cases("%s/server-cert.pem" % self.CERT_DIR)
 
     # No certificate checking: will accept any cert.
-    result = run_impala_shell_cmd("--ssl -q 'select 1 + 2'")
-    for msg in [self.SSL_ENABLED, self.CONNECTED, self.FETCHED]:
-      assert msg in result.stderr
+    self._validate_positive_cases()
 
     # Test cancelling a query
     impalad = ImpaladService(socket.getfqdn())
@@ -78,3 +88,60 @@ class TestClientSsl(CustomClusterTestSuite):
     assert result.rc == 0
     assert "Query Status: Cancelled" in result.stdout
     assert impalad.wait_for_num_in_flight_queries(0)
+
+  @pytest.mark.execute_serially
+  @CustomClusterTestSuite.with_args(impalad_args=SSL_WILDCARD_ARGS,
+                                    statestored_args=SSL_WILDCARD_ARGS,
+                                    catalogd_args=SSL_WILDCARD_ARGS)
+  def test_wildcard_ssl(self, vector):
+    """ Test for IMPALA-3159: Test with a certificate which has a wildcard for the
+    CommonName.
+    """
+    self._verify_negative_cases()
+
+    self._validate_positive_cases("%s/wildcardCA.pem" % self.CERT_DIR)
+
+  @pytest.mark.execute_serially
+  @CustomClusterTestSuite.with_args(impalad_args=SSL_WILDCARD_SAN_ARGS,
+                                    statestored_args=SSL_WILDCARD_SAN_ARGS,
+                                    catalogd_args=SSL_WILDCARD_SAN_ARGS)
+  def test_wildcard_san_ssl(self, vector):
+    """ Test for IMPALA-3159: Test with a certificate which has a wildcard as a SAN. """
+
+    # This block of code is the same as _validate_positive_cases() but we want to check
+    # if retrieving the SAN is supported first.
+    args = "--ssl -q 'select 1 + 2' --ca_cert=%s/wildcardCA.pem" \
+        % self.CERT_DIR
+    result = run_impala_shell_cmd_no_expect(args)
+    if self.SAN_UNSUPPORTED_ERROR in result.stderr:
+      pytest.xfail("Running with a RHEL/Python combination that has a bug where Python "
+          "cannot retrieve SAN from certificate: "
+          "https://bugzilla.redhat.com/show_bug.cgi?id=928390")
+
+    self._verify_negative_cases()
+
+    self._validate_positive_cases("%s/wildcardCA.pem" % self.CERT_DIR)
+
+  def _verify_negative_cases(self):
+    # Expect the shell to not start successfully if we point --ca_cert to an incorrect
+    # certificate.
+    args = "--ssl -q 'select 1 + 2' --ca_cert=%s/incorrect-commonname-cert.pem" \
+        % self.CERT_DIR
+    run_impala_shell_cmd(args, expect_success=False)
+
+    # Expect the shell to not start successfully if we don't specify the --ssl option
+    args = "-q 'select 1 + 2'"
+    run_impala_shell_cmd(args, expect_success=False)
+
+  def _validate_positive_cases(self, ca_cert=""):
+    shell_options = "--ssl -q 'select 1 + 2'"
+
+    result = run_impala_shell_cmd(shell_options)
+    for msg in [self.SSL_ENABLED, self.CONNECTED, self.FETCHED]:
+      assert msg in result.stderr
+
+    if ca_cert != "":
+      shell_options = shell_options + (" --ca_cert=%s" % ca_cert)
+      result = run_impala_shell_cmd(shell_options)
+      for msg in [self.SSL_ENABLED, self.CONNECTED, self.FETCHED]:
+        assert msg in result.stderr

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/45ff0f9e/tests/shell/util.py
----------------------------------------------------------------------
diff --git a/tests/shell/util.py b/tests/shell/util.py
index 36cb729..c037c0b 100755
--- a/tests/shell/util.py
+++ b/tests/shell/util.py
@@ -85,15 +85,26 @@ def run_impala_shell_cmd(shell_args, expect_success=True, stdin_input=None):
   'shell_args' is a string which represents the commandline options.
   Returns a ImpalaShellResult.
   """
-  p = ImpalaShell(shell_args)
-  result = p.get_result(stdin_input)
-  cmd = "%s %s" % (SHELL_CMD, shell_args)
+  result = run_impala_shell_cmd_no_expect(shell_args, stdin_input)
   if expect_success:
     assert result.rc == 0, "Cmd %s was expected to succeed: %s" % (cmd, result.stderr)
   else:
     assert result.rc != 0, "Cmd %s was expected to fail" % cmd
   return result
 
+def run_impala_shell_cmd_no_expect(shell_args, stdin_input=None):
+  """Runs the Impala shell on the commandline.
+
+  'shell_args' is a string which represents the commandline options.
+  Returns a ImpalaShellResult.
+
+  Does not assert based on success or failure of command.
+  """
+  p = ImpalaShell(shell_args)
+  result = p.get_result(stdin_input)
+  cmd = "%s %s" % (SHELL_CMD, shell_args)
+  return result
+
 class ImpalaShellResult(object):
   def __init__(self):
     self.rc = 0