Explorar o código

HUE-1749 [core] thrift ssl support

Starting with Beeswax.
Added configs for SSL in the beeswax config section.
get ca certs, private key, cert, and validate from config.
use new SSLSocket in thrift utils.
Abraham Elmahrek %!s(int64=12) %!d(string=hai) anos
pai
achega
2c16cb2

+ 41 - 1
apps/beeswax/src/beeswax/conf.py

@@ -20,7 +20,7 @@ import sys
 
 from django.utils.translation import ugettext_lazy as _t, ugettext as _
 
-from desktop.lib.conf import Config
+from desktop.lib.conf import ConfigSection, Config, coerce_bool
 
 from beeswax.settings import NICE_NAME
 
@@ -66,6 +66,46 @@ BROWSE_PARTITIONED_TABLE_LIMIT = Config(
   type=int,
   help=_t('Set a LIMIT clause when browsing a partitioned table. A positive value will be set as the LIMIT. If 0 or negative, do not set any limit.'))
 
+SSL = ConfigSection(
+  key='ssl',
+  help=_t('SSL configuration for the server.'),
+  members=dict(
+    ENABLED = Config(
+      key="enabled",
+      help=_t("SSL communication enabled for this server."),
+      type=coerce_bool,
+      default=False
+    ),
+
+    CACERTS = Config(
+      key="cacerts",
+      help=_t("Path to Certificate Authority certificates."),
+      type=str,
+      default=""
+    ),
+
+    KEY = Config(
+      key="key",
+      help=_t("Path to the private key file."),
+      type=str,
+      default=""
+    ),
+
+    CERT = Config(
+      key="cert",
+      help=_t("Path to the public certificate file."),
+      type=str,
+      default=""
+    ),
+
+    VALIDATE = Config(
+      key="validate",
+      help=_t("Choose whether Hue should validate certificates received from the server."),
+      type=coerce_bool,
+      default=True
+    )
+  )
+)
 
 def config_validator(user):
   # dbms is dependent on beeswax.conf (this file)

+ 6 - 1
apps/beeswax/src/beeswax/server/hive_server2_lib.py

@@ -309,7 +309,12 @@ class HiveServerClient:
                                           use_sasl=use_sasl,
                                           mechanism=mechanism,
                                           username=user.username,
-                                          timeout_seconds=conf.SERVER_CONN_TIMEOUT.get())
+                                          timeout_seconds=conf.SERVER_CONN_TIMEOUT.get(),
+                                          use_ssl=conf.SSL.ENABLED.get(),
+                                          ca_certs=conf.SSL.CACERTS.get(),
+                                          keyfile=conf.SSL.KEY.get(),
+                                          certfile=conf.SSL.CERT.get(),
+                                          validate=conf.SSL.VALIDATE.get())
 
 
   def get_security(self):

+ 16 - 0
desktop/conf.dist/hue.ini

@@ -444,6 +444,22 @@
   # A positive value will be set as the LIMIT. If 0 or negative, do not set any limit.
   ## browse_partitioned_table_limit=250
 
+  [[ssl]]
+    # SSL communication enabled for this server.
+    ## enabled=false
+
+    # Path to Certificate Authority certificates.
+    ## cacerts=
+
+    # Path to the private key file.
+    ## key=
+
+    # Path to the public certificate file.
+    ## cert=
+
+    # Choose whether Hue should validate certificates received from the server.
+    ## validate=
+
 
 ###########################################################################
 # Settings to configure Pig

+ 16 - 0
desktop/conf/pseudo-distributed.ini.tmpl

@@ -485,6 +485,22 @@
   # A positive value will be set as the LIMIT. If 0 or negative, do not set any limit.
   ## browse_partitioned_table_limit=250
 
+  [[ssl]]
+    # SSL communication enabled for this server.
+    ## enabled=false
+
+    # Path to Certificate Authority certificates.
+    ## cacerts=
+
+    # Path to the private key file.
+    ## key=
+
+    # Path to the public certificate file.
+    ## cert=
+
+    # Choose whether Hue should validate certificates received from the server.
+    ## validate=
+
 
 ###########################################################################
 # Settings to configure Pig

+ 21 - 3
desktop/core/src/desktop/lib/thrift_util.py

@@ -19,7 +19,6 @@
 
 import Queue
 import logging
-import select
 import socket
 import threading
 import time
@@ -28,6 +27,7 @@ import sys
 
 from thrift.Thrift import TType, TApplicationException
 from thrift.transport.TSocket import TSocket
+from thrift.transport.TSSLSocket import TSSLSocket
 from thrift.transport.TTransport import TBufferedTransport, TMemoryBuffer,\
                                         TTransportException
 from thrift.protocol.TBinaryProtocol import TBinaryProtocol
@@ -70,9 +70,14 @@ class ConnectionConfig(object):
   """ Struct-like class encapsulating the configuration of a Thrift client. """
   def __init__(self, klass, host, port, service_name,
                use_sasl=False,
+               use_ssl=False,
                kerberos_principal="thrift",
                mechanism='GSSAPI',
                username='hue',
+               ca_certs=None,
+               keyfile=None,
+               certfile=None,
+               validate=False,
                timeout_seconds=45):
     """
     @param klass The thrift client class
@@ -80,11 +85,16 @@ class ConnectionConfig(object):
     @param port Port to connect to
     @param service_name A human-readable name to describe the service
     @param use_sasl If true, will use KERBEROS or PLAIN over SASL to authenticate
+    @param use_ssl If true, will use ca_certs, keyfile, and certfile to create TLS connection
     @param mechanism: GSSAPI or PLAIN if SASL
     @param username: username if PLAIN SASL only
     @param kerberos_principal The Kerberos service name to connect to.
               NOTE: for a service like fooservice/foo.blah.com@REALM only
               specify "fooservice", NOT the full principal name.
+    @param ca_certs certificate authority certificates
+    @param keyfile private key file
+    @param certfile certificate file
+    @param validate Validate the certificate received from server
     @param timeout_seconds Timeout for thrift calls
     """
     self.klass = klass
@@ -92,14 +102,19 @@ class ConnectionConfig(object):
     self.port = port
     self.service_name = service_name
     self.use_sasl = use_sasl
+    self.use_ssl = use_ssl
     self.mechanism = mechanism
     self.username = username
     self.kerberos_principal = kerberos_principal
+    self.ca_certs = ca_certs
+    self.keyfile = keyfile
+    self.certfile = certfile
+    self.validate = validate
     self.timeout_seconds = timeout_seconds
 
   def __str__(self):
     return ', '.join(map(str, [self.klass, self.host, self.port, self.service_name, self.use_sasl, self.kerberos_principal, self.timeout_seconds,
-                               self.mechanism, self.username]))
+                               self.mechanism, self.username, self.use_ssl, self.ca_certs, self.keyfile, self.certfile, self.validate]))
 
 class ConnectionPooler(object):
   """
@@ -213,7 +228,10 @@ def connect_to_thrift(conf):
 
   Returns a tuple of (service, protocol, transport)
   """
-  sock = TSocket(conf.host, conf.port)
+  if conf.use_ssl:
+    sock = TSSLSocket(conf.host, conf.port, validate=conf.validate, ca_certs=conf.ca_certs, keyfile=conf.keyfile, certfile=conf.certfile)
+  else:
+    sock = TSocket(conf.host, conf.port)
   if conf.timeout_seconds:
     # Thrift trivia: You can do this after the fact with
     # _grab_transport_from_wrapper(self.wrapped.transport).setTimeout(seconds*1000)