Explorar o código

HUE-1545 [core] Improve SAML configuration parameters

acs, ls, and entity id are generated.
acs and ls urls can be generated because they are URLs in Hue.
entity id is generated because it's common to use
subdomain plus the url to the metadata view.
A hostname of 0.0.0.0 in hue.ini will result in
FQDN being used in acs, ls, and entity id.
Abraham Elmahrek %!s(int64=12) %!d(string=hai) anos
pai
achega
464eb31

+ 2 - 1
desktop/Makefile

@@ -41,7 +41,8 @@ include $(ROOT)/Makefile.vars.priv
 
 
 APPS := core \
 APPS := core \
 	libs/hadoop \
 	libs/hadoop \
-	libs/liboozie
+	libs/liboozie \
+	libs/libsaml
 
 
 .PHONY: default
 .PHONY: default
 default:: hue syncdb
 default:: hue syncdb

+ 5 - 12
desktop/conf.dist/hue.ini

@@ -91,7 +91,7 @@
     # - desktop.auth.backend.SpnegoDjangoBackend
     # - desktop.auth.backend.SpnegoDjangoBackend
     # - desktop.auth.backend.RemoteUserDjangoBackend
     # - desktop.auth.backend.RemoteUserDjangoBackend
     # - desktop.auth.backend.OAuthBackend
     # - desktop.auth.backend.OAuthBackend
-    # - huesaml.backend.SAML2Backend
+    # - libsaml.backend.SAML2Backend
     ## backend=desktop.auth.backend.AllowFirstUserDjangoBackend
     ## backend=desktop.auth.backend.AllowFirstUserDjangoBackend
 
 
     # Backend to synchronize user-group membership with
     # Backend to synchronize user-group membership with
@@ -227,27 +227,20 @@
   # Settings to configure SAML
   # Settings to configure SAML
   ###########################################################################
   ###########################################################################
 
 
-  [saml]
+  [libsaml]
     # Xmlsec1 binary path. This program should be executable by the user running Hue.
     # Xmlsec1 binary path. This program should be executable by the user running Hue.
     ## xmlsec_binary=/usr/local/bin/xmlsec1
     ## xmlsec_binary=/usr/local/bin/xmlsec1
 
 
     # Create users from SSO on login.
     # Create users from SSO on login.
     ## create_users_on_login=true
     ## create_users_on_login=true
 
 
-    # Globally unique identifier of the entity.
-    ## entity_id=http://localhost:8888/saml2/metadata/
-
-    # Consumes assertions sent back from IdP.
-    ## assertion_consumer_service_uri=http://localhost:8888/saml2/acs/
-
-    # Logout using the SSO provider.
-    ## single_logout_service=http://localhost:8888/saml2/ls/
-
     # Required attributes to ask for from IdP.
     # Required attributes to ask for from IdP.
+    # This requires a comma separated list.
     ## required_attributes=uid
     ## required_attributes=uid
 
 
     # Optional attributes to ask for from IdP.
     # Optional attributes to ask for from IdP.
-    ## optional_attributes=true
+    # This requires a comma separated list.
+    ## optional_attributes=
 
 
     # IdP metadata in the form of a file. This is generally an XML file containing metadata that the Identity Provider generates.
     # IdP metadata in the form of a file. This is generally an XML file containing metadata that the Identity Provider generates.
     ## metadata_file=
     ## metadata_file=

+ 5 - 12
desktop/conf/pseudo-distributed.ini.tmpl

@@ -100,7 +100,7 @@
     # - desktop.auth.backend.SpnegoDjangoBackend
     # - desktop.auth.backend.SpnegoDjangoBackend
     # - desktop.auth.backend.RemoteUserDjangoBackend
     # - desktop.auth.backend.RemoteUserDjangoBackend
     # - desktop.auth.backend.OAuthBackend
     # - desktop.auth.backend.OAuthBackend
-    # - huesaml.backend.SAML2Backend
+    # - libsaml.backend.SAML2Backend
     ## backend=desktop.auth.backend.AllowFirstUserDjangoBackend
     ## backend=desktop.auth.backend.AllowFirstUserDjangoBackend
 
 
     # Backend to synchronize user-group membership with
     # Backend to synchronize user-group membership with
@@ -233,27 +233,20 @@
 # Settings to configure SAML
 # Settings to configure SAML
 ###########################################################################
 ###########################################################################
 
 
-[saml]
+[libsaml]
   # Xmlsec1 binary path. This program should be executable by the user running Hue.
   # Xmlsec1 binary path. This program should be executable by the user running Hue.
   ## xmlsec_binary=/usr/local/bin/xmlsec1
   ## xmlsec_binary=/usr/local/bin/xmlsec1
 
 
   # Create users from SSO on login.
   # Create users from SSO on login.
   ## create_users_on_login=true
   ## create_users_on_login=true
 
 
-  # Globally unique identifier of the entity.
-  ## entity_id=http://localhost:8888/saml2/metadata/
-
-  # Consumes assertions sent back from IdP.
-  ## assertion_consumer_service_uri=http://localhost:8888/saml2/acs/
-
-  # Logout using the SSO provider.
-  ## single_logout_service=http://localhost:8888/saml2/ls/
-
   # Required attributes to ask for from IdP.
   # Required attributes to ask for from IdP.
+  # This requires a comma separated list.
   ## required_attributes=uid
   ## required_attributes=uid
 
 
   # Optional attributes to ask for from IdP.
   # Optional attributes to ask for from IdP.
-  ## optional_attributes=true
+  # This requires a comma separated list.
+  ## optional_attributes=
 
 
   # IdP metadata in the form of a file. This is generally an XML file containing metadata that the Identity Provider generates.
   # IdP metadata in the form of a file. This is generally an XML file containing metadata that the Identity Provider generates.
   ## metadata_file=
   ## metadata_file=

+ 3 - 3
desktop/core/src/desktop/settings.py

@@ -272,10 +272,10 @@ if SECRET_KEY == "":
   logging.warning("secret_key should be configured")
   logging.warning("secret_key should be configured")
 
 
 # SAML
 # SAML
-SAML_AUTHENTICATION = 'huesaml.backend.SAML2Backend' in AUTHENTICATION_BACKENDS
+SAML_AUTHENTICATION = 'libsaml.backend.SAML2Backend' in AUTHENTICATION_BACKENDS
 if SAML_AUTHENTICATION:
 if SAML_AUTHENTICATION:
-  from huesaml.saml_settings import *
-  INSTALLED_APPS.append('huesaml')
+  from libsaml.saml_settings import *
+  INSTALLED_APPS.append('libsaml')
   LOGIN_URL = '/saml2/login/'
   LOGIN_URL = '/saml2/login/'
   SESSION_EXPIRE_AT_BROWSER_CLOSE = True
   SESSION_EXPIRE_AT_BROWSER_CLOSE = True
 
 

+ 1 - 1
desktop/core/src/desktop/urls.py

@@ -78,7 +78,7 @@ static_patterns = []
 
 
 # SAML specific
 # SAML specific
 if settings.SAML_AUTHENTICATION:
 if settings.SAML_AUTHENTICATION:
-  static_patterns.append((r'^saml2/', include('huesaml.urls')))
+  static_patterns.append((r'^saml2/', include('libsaml.urls')))
 
 
 # Root each app at /appname if they have a "urls" module
 # Root each app at /appname if they have a "urls" module
 for app in appmanager.DESKTOP_APPS:
 for app in appmanager.DESKTOP_APPS:

+ 0 - 0
desktop/libs/huesaml/Makefile → desktop/libs/libsaml/Makefile


+ 0 - 0
desktop/libs/huesaml/attribute-maps/SAML2.py → desktop/libs/libsaml/attribute-maps/SAML2.py


+ 2 - 2
desktop/libs/huesaml/setup.py → desktop/libs/libsaml/setup.py

@@ -17,7 +17,7 @@
 from setuptools import setup, find_packages
 from setuptools import setup, find_packages
 
 
 setup(
 setup(
-      name = "huesaml",
+      name = "libsaml",
       version = "3.0.0",
       version = "3.0.0",
       url = 'http://github.com/cloudera/hue',
       url = 'http://github.com/cloudera/hue',
       description = "SAML Libraries",
       description = "SAML Libraries",
@@ -26,5 +26,5 @@ setup(
       install_requires = ['setuptools', 'desktop'],
       install_requires = ['setuptools', 'desktop'],
       # Even libraries need to be registered as desktop_apps,
       # Even libraries need to be registered as desktop_apps,
       # if they have configuration, like this one.
       # if they have configuration, like this one.
-      entry_points = { 'desktop.sdk.lib': 'huesaml=huesaml' },
+      entry_points = { 'desktop.sdk.lib': 'libsaml=libsaml' },
 )
 )

+ 0 - 0
desktop/libs/huesaml/src/huesaml/__init__.py → desktop/libs/libsaml/src/libsaml/__init__.py


+ 0 - 0
desktop/libs/huesaml/src/huesaml/backend.py → desktop/libs/libsaml/src/libsaml/backend.py


+ 3 - 21
desktop/libs/huesaml/src/huesaml/conf.py → desktop/libs/libsaml/src/libsaml/conf.py

@@ -53,12 +53,6 @@ CREATE_USERS_ON_LOGIN = Config(
   type=coerce_bool,
   type=coerce_bool,
   help=_t("Create users from IdP on login."))
   help=_t("Create users from IdP on login."))
 
 
-ENTITY_ID = Config(
-  key="entity_id",
-  default="http://localhost:8888/saml2/metadata/",
-  type=str,
-  help=_t("Globally unique identifier of the entity."))
-
 ATTRIBUTE_MAP_DIR = Config(
 ATTRIBUTE_MAP_DIR = Config(
   key="attribute_map_dir",
   key="attribute_map_dir",
   default=os.path.abspath( os.path.join(BASEDIR, '..', '..', 'attribute-maps') ),
   default=os.path.abspath( os.path.join(BASEDIR, '..', '..', 'attribute-maps') ),
@@ -66,18 +60,6 @@ ATTRIBUTE_MAP_DIR = Config(
   private=True,
   private=True,
   help=_t("Attribute map directory contains files that map SAML attributes to pysaml2 attributes."))
   help=_t("Attribute map directory contains files that map SAML attributes to pysaml2 attributes."))
 
 
-ASSERTION_CONSUMER_SERVICE_URI = Config(
-  key="assertion_consumer_service_uri",
-  default="http://localhost:8888/saml2/acs/",
-  type=str,
-  help=_t("Consumes assertions sent back from IdP."))
-
-SINGLE_LOGOUT_SERVICE = Config(
-  key="single_logout_service",
-  default="http://localhost:8888/saml2/ls/",
-  type=str,
-  help=_t("Logout using the IdP."))
-
 ALLOW_UNSOLICITED = Config(
 ALLOW_UNSOLICITED = Config(
   key="allow_unsolicited",
   key="allow_unsolicited",
   default=True,
   default=True,
@@ -87,7 +69,7 @@ ALLOW_UNSOLICITED = Config(
 
 
 REQUIRED_ATTRIBUTES = Config(
 REQUIRED_ATTRIBUTES = Config(
   key="required_attributes",
   key="required_attributes",
-  default=[],
+  default=['uid'],
   type=csv,
   type=csv,
   help=_t("Required attributes to ask for from IdP."))
   help=_t("Required attributes to ask for from IdP."))
 
 
@@ -105,13 +87,13 @@ METADATA_FILE = Config(
 
 
 KEY_FILE = Config(
 KEY_FILE = Config(
   key="key_file",
   key="key_file",
-  default=os.path.abspath( os.path.join(BASEDIR, '..', '..', 'examples', 'key.pem') ),
+  default="",
   type=str,
   type=str,
   help=_t("key_file is the name of a PEM formatted file that contains the private key of the Hue service. This is presently used both to encrypt/sign assertions and as client key in a HTTPS session."))
   help=_t("key_file is the name of a PEM formatted file that contains the private key of the Hue service. This is presently used both to encrypt/sign assertions and as client key in a HTTPS session."))
 
 
 CERT_FILE = Config(
 CERT_FILE = Config(
   key="cert_file",
   key="cert_file",
-  default=os.path.abspath( os.path.join(BASEDIR, '..', '..', 'examples', 'cert.pem') ),
+  default="",
   type=str,
   type=str,
   help=_t("This is the public part of the service private/public key pair. cert_file must be a PEM formatted certificate chain file."))
   help=_t("This is the public part of the service private/public key pair. cert_file must be a PEM formatted certificate chain file."))
 
 

+ 24 - 14
desktop/libs/huesaml/src/huesaml/saml_settings.py → desktop/libs/libsaml/src/libsaml/saml_settings.py

@@ -15,20 +15,30 @@
 # limitations under the License.
 # limitations under the License.
 
 
 import saml2
 import saml2
-import huesaml.conf
+import desktop.conf
+import libsaml.conf
+
+from desktop.lib import security_util
+
 
 
 __all__ = ['SAML_CONFIG', 'SAML_ATTRIBUTE_MAPPING', 'SAML_CREATE_UNKNOWN_USER']
 __all__ = ['SAML_CONFIG', 'SAML_ATTRIBUTE_MAPPING', 'SAML_CREATE_UNKNOWN_USER']
 
 
 
 
+BASE_URL = "%(protocol)s%(host)s:%(port)d" % {
+  'protocol': desktop.conf.is_https_enabled() and 'https://' or 'http://',
+  'host':  desktop.conf.HTTP_HOST.get() == '0.0.0.0' and security_util.get_localhost_name() or desktop.conf.HTTP_HOST.get(),
+  'port':  desktop.conf.HTTP_PORT.get()
+}
+
 SAML_CONFIG = {
 SAML_CONFIG = {
   # full path to the xmlsec1 binary programm
   # full path to the xmlsec1 binary programm
-  'xmlsec_binary': huesaml.conf.XMLSEC_BINARY.get(),
+  'xmlsec_binary': libsaml.conf.XMLSEC_BINARY.get(),
 
 
   # your entity id, usually your subdomain plus the url to the metadata view
   # your entity id, usually your subdomain plus the url to the metadata view
-  'entityid': huesaml.conf.ENTITY_ID.get(),
+  'entityid': "%s/saml2/metadata/" % BASE_URL,
 
 
   # directory with attribute mapping
   # directory with attribute mapping
-  'attribute_map_dir': huesaml.conf.ATTRIBUTE_MAP_DIR.get(),
+  'attribute_map_dir': libsaml.conf.ATTRIBUTE_MAP_DIR.get(),
 
 
   # this block states what services we provide
   # this block states what services we provide
   'service': {
   'service': {
@@ -38,37 +48,37 @@ SAML_CONFIG = {
         # url and binding to the assetion consumer service view
         # url and binding to the assetion consumer service view
         # do not change the binding or service name
         # do not change the binding or service name
         'assertion_consumer_service': [
         'assertion_consumer_service': [
-          (huesaml.conf.ASSERTION_CONSUMER_SERVICE_URI.get(), saml2.BINDING_HTTP_POST),
+          ("%s/saml2/acs/" % BASE_URL, saml2.BINDING_HTTP_POST),
         ],
         ],
         # url and binding to the single logout service view
         # url and binding to the single logout service view
         # do not change the binding or service name
         # do not change the binding or service name
         'single_logout_service': [
         'single_logout_service': [
-          (huesaml.conf.SINGLE_LOGOUT_SERVICE_URI.get(), saml2.BINDING_HTTP_REDIRECT),
+          ("%s/saml2/ls/" % BASE_URL, saml2.BINDING_HTTP_REDIRECT),
         ],
         ],
       },
       },
 
 
-      'allow_unsolicited': huesaml.conf.ALLOW_UNSOLICITED.get(),
+      'allow_unsolicited': libsaml.conf.ALLOW_UNSOLICITED.get(),
 
 
       # attributes that this project need to identify a user
       # attributes that this project need to identify a user
-      'required_attributes': huesaml.conf.REQUIRED_ATTRIBUTES.get(),
+      'required_attributes': libsaml.conf.REQUIRED_ATTRIBUTES.get(),
 
 
       # attributes that may be useful to have but not required
       # attributes that may be useful to have but not required
-      'optional_attributes': huesaml.conf.OPTIONAL_ATTRIBUTES.get(),
+      'optional_attributes': libsaml.conf.OPTIONAL_ATTRIBUTES.get(),
     },
     },
   },
   },
 
 
   # where the remote metadata is stored
   # where the remote metadata is stored
   'metadata': {
   'metadata': {
-    'local': huesaml.conf.METADATA_FILE.get(),
+    'local': [ libsaml.conf.METADATA_FILE.get() ],
   },
   },
 
 
   # set to 1 to output debugging information
   # set to 1 to output debugging information
   'debug': 1,
   'debug': 1,
 
 
   # certificate
   # certificate
-  'key_file': huesaml.conf.KEY_FILE.get(),
-  'cert_file': huesaml.conf.CERT_FILE.get()
+  'key_file': libsaml.conf.KEY_FILE.get(),
+  'cert_file': libsaml.conf.CERT_FILE.get()
 }
 }
 
 
-SAML_ATTRIBUTE_MAPPING = huesaml.conf.USER_ATTRIBUTE_MAPPING.get()
-SAML_CREATE_UNKNOWN_USER = huesaml.conf.CREATE_USERS_ON_LOGIN.get()
+SAML_ATTRIBUTE_MAPPING = libsaml.conf.USER_ATTRIBUTE_MAPPING.get()
+SAML_CREATE_UNKNOWN_USER = libsaml.conf.CREATE_USERS_ON_LOGIN.get()

+ 1 - 1
desktop/libs/huesaml/src/huesaml/urls.py → desktop/libs/libsaml/src/libsaml/urls.py

@@ -23,7 +23,7 @@ urlpatterns = patterns(
     url(r'^ls/$', 'logout_service', name='saml2_ls')
     url(r'^ls/$', 'logout_service', name='saml2_ls')
 )
 )
 
 
-urlpatterns += patterns('huesaml.views',
+urlpatterns += patterns('libsaml.views',
                         url(r'^acs/$', 'assertion_consumer_service', name='saml2_acs'),
                         url(r'^acs/$', 'assertion_consumer_service', name='saml2_acs'),
                         url(r'^login/$', 'login', name='saml2_login'),
                         url(r'^login/$', 'login', name='saml2_login'),
                         url(r'^metadata/$', 'metadata', name='saml2_metadata'),
                         url(r'^metadata/$', 'metadata', name='saml2_metadata'),

+ 0 - 0
desktop/libs/huesaml/src/huesaml/views.py → desktop/libs/libsaml/src/libsaml/views.py