diff --git a/salt/auth/ldap.py b/salt/auth/ldap.py index 4ca3514028..7fdfc9aece 100644 --- a/salt/auth/ldap.py +++ b/salt/auth/ldap.py @@ -24,7 +24,8 @@ except ImportError: HAS_LDAP = False # Defaults, override in master config -__defopts__ = {'auth.ldap.server': 'localhost', +__defopts__ = {'auth.ldap.uri': '', + 'auth.ldap.server': 'localhost', 'auth.ldap.port': '389', 'auth.ldap.tls': False, 'auth.ldap.no_verify': False, @@ -66,38 +67,43 @@ class _LDAPConnection(object): Setup an LDAP connection. ''' - def __init__(self, server, port, tls, no_verify, binddn, bindpw, + def __init__(self, uri, server, port, tls, no_verify, binddn, bindpw, anonymous): ''' Bind to an LDAP directory using passed credentials. ''' + self.uri = uri self.server = server self.port = port self.tls = tls self.binddn = binddn self.bindpw = bindpw - schema = 'ldap' if not HAS_LDAP: raise CommandExecutionError('Failed to connect to LDAP, module ' 'not loaded') + if self.uri == '': + self.uri = 'ldap://{0}:{1}'.format(self.server, self.port) + try: if no_verify: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) - if self.tls: - schema = 'ldaps' + self.ldap = ldap.initialize( - '{0}://{1}:{2}'.format(schema, self.server, self.port) + '{0}'.format(self.uri) ) self.ldap.protocol_version = 3 # ldap.VERSION3 self.ldap.set_option(ldap.OPT_REFERRALS, 0) # Needed for AD + if self.tls: + self.ldap.start_tls_s() + if not anonymous: self.ldap.simple_bind_s(self.binddn, self.bindpw) except Exception as ldap_error: raise CommandExecutionError( - 'Failed to bind to LDAP server {0}:{1} as {2}: {3}'.format( - self.server, self.port, self.binddn, ldap_error + 'Failed to bind to LDAP server {0} as {1}: {2}'.format( + self.uri, self.binddn, ldap_error ) ) @@ -112,7 +118,7 @@ def _bind(username, password): connargs = {} # config params (auth.ldap.*) params = { - 'mandatory': ['server', 'port', 'tls', 'no_verify', 'anonymous'], + 'mandatory': ['uri', 'server', 'port', 'tls', 'no_verify', 'anonymous'], 'additional': ['binddn', 'bindpw', 'filter'], } diff --git a/salt/modules/config.py b/salt/modules/config.py index 5ba171d09b..c7af1cf7df 100644 --- a/salt/modules/config.py +++ b/salt/modules/config.py @@ -38,9 +38,12 @@ DEFAULTS = {'mongo.db': 'salt', 'solr.num_backups': 1, 'poudriere.config': '/usr/local/etc/poudriere.conf', 'poudriere.config_dir': '/usr/local/etc/poudriere.d', + 'ldap.uri': '', 'ldap.server': 'localhost', 'ldap.port': '389', 'ldap.tls': False, + 'ldap.no_verify': False, + 'ldap.anonymous': True, 'ldap.scope': 2, 'ldap.attrs': None, 'ldap.binddn': '', diff --git a/salt/modules/ldapmod.py b/salt/modules/ldapmod.py index 266e34c930..2c60dda8f8 100644 --- a/salt/modules/ldapmod.py +++ b/salt/modules/ldapmod.py @@ -11,6 +11,7 @@ Salt interface to LDAP commands If your LDAP server requires authentication then you must also set:: + ldap.anonymous: False ldap.binddn: admin ldap.bindpw: password @@ -19,6 +20,8 @@ Salt interface to LDAP commands ldap.server: localhost (default=localhost, see warning below) ldap.port: 389 (default=389, standard port) ldap.tls: False (default=False, no TLS) + ldap.no_verify: False (default=False, verify TLS) + ldap.anonymous: True (default=True, bind anonymous) ldap.scope: 2 (default=2, ldap.SCOPE_SUBTREE) ldap.attrs: [saltAttr] (default=None, return all attributes) @@ -84,7 +87,8 @@ def _connect(**kwargs): Instantiate LDAP Connection class and return an LDAP connection object ''' connargs = {} - for name in ['server', 'port', 'tls', 'binddn', 'bindpw']: + for name in ['uri', 'server', 'port', 'tls', 'no_verify', 'binddn', + 'bindpw', 'anonymous']: connargs[name] = _config(name, **kwargs) return _LDAPConnection(**connargs).ldap @@ -156,29 +160,43 @@ def search(filter, # pylint: disable=C0103 class _LDAPConnection(object): ''' - Setup a LDAP connection. + Setup an LDAP connection. ''' - def __init__(self, server, port, tls, binddn, bindpw): + + def __init__(self, uri, server, port, tls, no_verify, binddn, bindpw, + anonymous): ''' - Bind to a LDAP directory using passed credentials.""" + Bind to an LDAP directory using passed credentials. ''' + self.uri = uri self.server = server self.port = port self.tls = tls self.binddn = binddn self.bindpw = bindpw + + if self.uri == '': + self.uri = 'ldap://{0}:{1}'.format(self.server, self.port) + try: - # TODO: Support ldaps:// and possibly ldapi:// - self.ldap = ldap.initialize('ldap://{0}:{1}'.format( - self.server, self.port - )) + if no_verify: + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, + ldap.OPT_X_TLS_NEVER) + + self.ldap = ldap.initialize( + '{0}'.format(self.uri) + ) self.ldap.protocol_version = 3 # ldap.VERSION3 + self.ldap.set_option(ldap.OPT_REFERRALS, 0) # Needed for AD + if self.tls: self.ldap.start_tls_s() - self.ldap.simple_bind_s(self.binddn, self.bindpw) - except Exception: + + if not anonymous: + self.ldap.simple_bind_s(self.binddn, self.bindpw) + except Exception as ldap_error: raise CommandExecutionError( - 'Failed to bind to LDAP server {0}:{1} as {2}'.format( - self.server, self.port, self.binddn + 'Failed to bind to LDAP server {0} as {1}: {2}'.format( + self.uri, self.binddn, ldap_error ) )