Browse Source

[core] Make search bind authentication optional for LDAP

Abraham Elmahrek 12 years ago
parent
commit
23933dd

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

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

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

@@ -116,6 +116,9 @@
     # The search base for finding users and groups
     # The search base for finding users and groups
     ## base_dn="DC=mycompany,DC=com"
     ## 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
     # URL of the LDAP server
     ## ldap_url=ldap://auth.mycompany.com
     ## ldap_url=ldap://auth.mycompany.com
 
 
@@ -135,10 +138,17 @@
     # anonymous searches
     # anonymous searches
     ## bind_password=
     ## 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
     # Create users in Hue when they try to login with their LDAP credentials
     # For use when using LdapBackend for Hue authentication
     # For use when using LdapBackend for Hue authentication
     ## create_users_on_login = true
     ## create_users_on_login = true
 
 
+    # Use search bind authentication.
+    ## search_bind_authentication=true
+
     [[[users]]]
     [[[users]]]
 
 
       # Base filter for searching for 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
     # The search base for finding users and groups
     ## base_dn="DC=mycompany,DC=com"
     ## 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
     # URL of the LDAP server
     ## ldap_url=ldap://auth.mycompany.com
     ## ldap_url=ldap://auth.mycompany.com
 
 
@@ -144,10 +147,17 @@
     # anonymous searches
     # anonymous searches
     ## bind_password=
     ## 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
     # Create users in Hue when they try to login with their LDAP credentials
     # For use when using LdapBackend for Hue authentication
     # For use when using LdapBackend for Hue authentication
     ## create_users_on_login = true
     ## create_users_on_login = true
 
 
+    # Use search bind authentication.
+    ## search_bind_authentication=true
+
     [[[users]]]
     [[[users]]]
 
 
       # Base filter for searching for 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.")
       LOG.warn("Could not find LDAP URL required for authentication.")
       return None
       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
     # Certificate-related config settings
     if desktop.conf.LDAP.LDAP_CERT.get():
     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",
     BASE_DN=Config("base_dn",
                    default=None,
                    default=None,
                    help=_("The base LDAP distinguished name to use for LDAP search.")),
                    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",
     LDAP_URL=Config("ldap_url",
                      default=None,
                      default=None,
                      help=_("The LDAP URL to connect to.")),
                      help=_("The LDAP URL to connect to.")),
@@ -354,12 +357,19 @@ LDAP = ConfigSection(
     LDAP_CERT=Config("ldap_cert",
     LDAP_CERT=Config("ldap_cert",
                      default=None,
                      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.")),
                      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",
     BIND_DN=Config("bind_dn",
                    default=None,
                    default=None,
                    help=_("The distinguished name to bind as, when importing from LDAP.")),
                    help=_("The distinguished name to bind as, when importing from LDAP.")),
     BIND_PASSWORD=Config("bind_password",
     BIND_PASSWORD=Config("bind_password",
                    default=None,
                    default=None,
                    help=_("The password for the bind user.")),
                    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",
     CREATE_USERS_ON_LOGIN = Config("create_users_on_login",
       help=_("Create users when they login with their LDAP credentials."),
       help=_("Create users when they login with their LDAP credentials."),
       type=coerce_bool,
       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.KINIT_PATH, is_dir=False))
     res.extend(validate_path(KERBEROS.CCACHE_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
   return res