浏览代码

[core] Make search bind authentication optional for LDAP

Abraham Elmahrek 12 年之前
父节点
当前提交
23933dd

+ 12 - 1
apps/useradmin/src/useradmin/ldap_access.py

@@ -37,14 +37,25 @@ def get_connection():
     return CACHED_LDAP_CONN
 
   ldap_url = desktop.conf.LDAP.LDAP_URL.get()
+  nt_domain = desktop.conf.LDAP.NT_DOMAIN.get()
   username = desktop.conf.LDAP.BIND_DN.get()
   password = desktop.conf.LDAP.BIND_PASSWORD.get()
   ldap_cert = desktop.conf.LDAP.LDAP_CERT.get()
+  search_bind_authentication = desktop.conf.LDAP.SEARCH_BIND_AUTHENTICATION.get()
 
   if ldap_url is None:
     raise Exception('No LDAP URL was specified')
 
-  return LdapConnection(ldap_url, username, password, ldap_cert)
+  if search_bind_authentication:
+    return LdapConnection(ldap_url, username, password, ldap_cert)
+  else:
+    return LdapConnection(ldap_url, get_ldap_username(username, nt_domain), password, ldap_cert)
+
+def get_ldap_username(username, nt_domain):
+  if nt_domain:
+    return '%s@%s' % (username, nt_domain)
+  else:
+    return username
 
 class LdapConnection(object):
   """

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

@@ -116,6 +116,9 @@
     # The search base for finding users and groups
     ## base_dn="DC=mycompany,DC=com"
 
+    # The NT domain to connect to (only for use with Active Directory)
+    ## nt_domain=mycompany.com
+
     # URL of the LDAP server
     ## ldap_url=ldap://auth.mycompany.com
 
@@ -135,10 +138,17 @@
     # anonymous searches
     ## bind_password=
 
+    # Pattern for searching for usernames -- Use <username> for the parameter
+    # For use when using LdapBackend for Hue authentication
+    ## ldap_username_pattern="uid=<username>,ou=People,dc=mycompany,dc=com"
+
     # Create users in Hue when they try to login with their LDAP credentials
     # For use when using LdapBackend for Hue authentication
     ## create_users_on_login = true
 
+    # Use search bind authentication.
+    ## search_bind_authentication=true
+
     [[[users]]]
 
       # Base filter for searching for users

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

@@ -125,6 +125,9 @@
     # The search base for finding users and groups
     ## base_dn="DC=mycompany,DC=com"
 
+    # The NT domain to connect to (only for use with Active Directory)
+    ## nt_domain=mycompany.com
+
     # URL of the LDAP server
     ## ldap_url=ldap://auth.mycompany.com
 
@@ -144,10 +147,17 @@
     # anonymous searches
     ## bind_password=
 
+    # Pattern for searching for usernames -- Use <username> for the parameter
+    # For use when using LdapBackend for Hue authentication
+    ## ldap_username_pattern="uid=<username>,ou=People,dc=mycompany,dc=com"
+
     # Create users in Hue when they try to login with their LDAP credentials
     # For use when using LdapBackend for Hue authentication
     ## create_users_on_login = true
 
+    # Use search bind authentication.
+    ## search_bind_authentication=true
+
     [[[users]]]
 
       # Base filter for searching for users

+ 21 - 11
desktop/core/src/desktop/auth/backend.py

@@ -290,20 +290,30 @@ class LdapBackend(object):
       LOG.warn("Could not find LDAP URL required for authentication.")
       return None
 
-    # New Search/Bind Auth
-    base_dn = desktop.conf.LDAP.BASE_DN.get()
-    user_name_attr = desktop.conf.LDAP.USERS.USER_NAME_ATTR.get()
+    if desktop.conf.LDAP.SEARCH_BIND_AUTHENTICATION.get():
+      # New Search/Bind Auth
+      base_dn = desktop.conf.LDAP.BASE_DN.get()
+      user_name_attr = desktop.conf.LDAP.USERS.USER_NAME_ATTR.get()
 
-    if desktop.conf.LDAP.BIND_DN.get():
-      bind_dn = desktop.conf.LDAP.BIND_DN.get()
-      ldap_settings.AUTH_LDAP_BIND_DN = bind_dn
-      bind_password = desktop.conf.LDAP.BIND_PASSWORD.get()
-      ldap_settings.AUTH_LDAP_BIND_PASSWORD = bind_password
+      if desktop.conf.LDAP.BIND_DN.get():
+        bind_dn = desktop.conf.LDAP.BIND_DN.get()
+        ldap_settings.AUTH_LDAP_BIND_DN = bind_dn
+        bind_password = desktop.conf.LDAP.BIND_PASSWORD.get()
+        ldap_settings.AUTH_LDAP_BIND_PASSWORD = bind_password
 
-    search_bind_results = LDAPSearch(base_dn,
-        ldap.SCOPE_SUBTREE, "(" + user_name_attr + "=%(user)s)")
+      search_bind_results = LDAPSearch(base_dn,
+          ldap.SCOPE_SUBTREE, "(" + user_name_attr + "=%(user)s)")
 
-    ldap_settings.AUTH_LDAP_USER_SEARCH = search_bind_results
+      ldap_settings.AUTH_LDAP_USER_SEARCH = search_bind_results
+    else:
+      nt_domain = desktop.conf.LDAP.NT_DOMAIN.get()
+      if nt_domain is None:
+        pattern = desktop.conf.LDAP.LDAP_USERNAME_PATTERN.get()
+        pattern = pattern.replace('<username>', '%(user)s')
+        ldap_settings.AUTH_LDAP_USER_DN_TEMPLATE = pattern
+      else:
+        # %(user)s is a special string that will get replaced during the authentication process
+        ldap_settings.AUTH_LDAP_USER_DN_TEMPLATE = "%(user)s@" + nt_domain
 
     # Certificate-related config settings
     if desktop.conf.LDAP.LDAP_CERT.get():

+ 37 - 7
desktop/core/src/desktop/conf.py

@@ -344,6 +344,9 @@ LDAP = ConfigSection(
     BASE_DN=Config("base_dn",
                    default=None,
                    help=_("The base LDAP distinguished name to use for LDAP search.")),
+    NT_DOMAIN=Config("nt_domain",
+                     default=None,
+                     help=_("The NT domain used for LDAP authentication.")),
     LDAP_URL=Config("ldap_url",
                      default=None,
                      help=_("The LDAP URL to connect to.")),
@@ -354,12 +357,19 @@ LDAP = ConfigSection(
     LDAP_CERT=Config("ldap_cert",
                      default=None,
                      help=_("A PEM-format file containing certificates for the CA's that Hue will trust for authentication over TLS. The certificate for the CA that signed the LDAP server certificate must be included among these certificates. See more here http://www.openldap.org/doc/admin24/tls.html.")),
+    LDAP_USERNAME_PATTERN=Config("ldap_username_pattern",
+                                 default=None,
+                                 help=_("A pattern to use for constructing LDAP usernames.")),
     BIND_DN=Config("bind_dn",
                    default=None,
                    help=_("The distinguished name to bind as, when importing from LDAP.")),
     BIND_PASSWORD=Config("bind_password",
                    default=None,
                    help=_("The password for the bind user.")),
+    SEARCH_BIND_AUTHENTICATION=Config("search_bind_authentication",
+                   default=True,
+                   type=coerce_bool,
+                   help=_("Use search bind authentication.")),
     CREATE_USERS_ON_LOGIN = Config("create_users_on_login",
       help=_("Create users when they login with their LDAP credentials."),
       type=coerce_bool,
@@ -554,13 +564,33 @@ def config_validator(user):
     res.extend(validate_path(KERBEROS.KINIT_PATH, is_dir=False))
     res.extend(validate_path(KERBEROS.CCACHE_PATH, is_dir=False))
 
-  if LDAP.LDAP_URL.get() is None != LDAP.BASE_DN.get() is None:
-    res.append((LDAP.LDAP_URL,
-                force_unicode(_("LDAP is only partially configured. An LDAP URL and BASE DN must be provided."))))
+  if LDAP.SEARCH_BIND_AUTHENTICATION.get():
+    if LDAP.LDAP_URL.get() is None:
+      res.append((LDAP.LDAP_URL,
+                  unicode(_("LDAP is only partially configured. An LDAP URL must be provided."))))
 
-  if LDAP.BIND_DN.get():
-    if LDAP.BIND_PASSWORD.get() is None:
-      res.append((LDAP.BIND_PASSWORD,
-                  force_unicode(_("If you set bind_dn, then you must set bind_password."))))
+    if LDAP.BIND_DN.get():
+      if LDAP.BIND_PASSWORD.get() is None:
+        res.append((LDAP.BIND_PASSWORD,
+                    unicode(_("If you set bind_dn, then you must set bind_password."))))
+  else:
+    if LDAP.NT_DOMAIN.get() is not None or \
+        LDAP.LDAP_USERNAME_PATTERN.get() is not None:
+      if LDAP.LDAP_URL.get() is None:
+        res.append((LDAP.LDAP_URL,
+                    unicode(_("LDAP is only partially configured. An LDAP URL must be provided."))))
+
+    if LDAP.LDAP_URL.get() is not None:
+      if LDAP.NT_DOMAIN.get() is None and \
+          LDAP.LDAP_USERNAME_PATTERN.get() is None:
+        res.append((LDAP.LDAP_URL,
+                    unicode(_("LDAP is only partially configured. An NT Domain or username "
+                    "search pattern must be provided."))))
+
+    if LDAP.LDAP_USERNAME_PATTERN.get() is not None and \
+        '<username>' not in LDAP.LDAP_USERNAME_PATTERN.get():
+        res.append((LDAP.LDAP_USERNAME_PATTERN,
+                   unicode(_("The LDAP username pattern should contain the special"
+                   "<username> replacement string for authentication."))))
 
   return res