PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ldapmod.py |
""" Salt interface to LDAP commands :depends: - ldap Python module :configuration: In order to connect to LDAP, certain configuration is required in the minion config on the LDAP server. The minimum configuration items that must be set are: .. code-block:: yaml ldap.basedn: dc=acme,dc=com (example values, adjust to suit) If your LDAP server requires authentication then you must also set: .. code-block:: yaml ldap.anonymous: False ldap.binddn: admin ldap.bindpw: password In addition, the following optional values may be set: .. code-block:: yaml 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) .. warning:: At the moment this module only recommends connection to LDAP services listening on ``localhost``. This is deliberate to avoid the potentially dangerous situation of multiple minions sending identical update commands to the same LDAP server. It's easy enough to override this behavior, but badness may ensue - you have been warned. """ import logging import time import salt.utils.data from salt.exceptions import CommandExecutionError try: import ldap import ldap.modlist # pylint: disable=no-name-in-module HAS_LDAP = True except ImportError: HAS_LDAP = False log = logging.getLogger(__name__) # Define the module's virtual name __virtualname__ = "ldap" def __virtual__(): """ Only load this module if the ldap config is set """ # These config items must be set in the minion config if HAS_LDAP: return __virtualname__ return ( False, "The ldapmod execution module cannot be loaded: ldap config not present.", ) def _config(name, key=None, **kwargs): """ Return a value for 'name' from command line args then config file options. Specify 'key' if the config file option is not the same as 'name'. """ if key is None: key = name if name in kwargs: value = kwargs[name] else: value = __salt__["config.option"](f"ldap.{key}") return salt.utils.data.decode(value, to_str=True) def _connect(**kwargs): """ Instantiate LDAP Connection class and return an LDAP connection object """ connargs = {} for name in [ "uri", "server", "port", "tls", "no_verify", "binddn", "bindpw", "anonymous", ]: connargs[name] = _config(name, **kwargs) return _LDAPConnection(**connargs).ldap def search( filter, # pylint: disable=C0103 dn=None, # pylint: disable=C0103 scope=None, attrs=None, **kwargs, ): """ Run an arbitrary LDAP query and return the results. CLI Example: .. code-block:: bash salt 'ldaphost' ldap.search "filter=cn=myhost" Return data: .. code-block:: python {'myhost': {'count': 1, 'results': [['cn=myhost,ou=hosts,o=acme,c=gb', {'saltKeyValue': ['ntpserver=ntp.acme.local', 'foo=myfoo'], 'saltState': ['foo', 'bar']}]], 'time': {'human': '1.2ms', 'raw': '0.00123'}}} Search and connection options can be overridden by specifying the relevant option as key=value pairs, for example: .. code-block:: bash salt 'ldaphost' ldap.search filter=cn=myhost dn=ou=hosts,o=acme,c=gb scope=1 attrs='' server='localhost' port='7393' tls=True bindpw='ssh' """ if not dn: dn = _config("dn", "basedn") # pylint: disable=C0103 if not scope: scope = _config("scope") if attrs == "": # Allow command line 'return all' attr override attrs = None elif attrs is None: attrs = _config("attrs") _ldap = _connect(**kwargs) start = time.time() log.debug( "Running LDAP search with filter:%s, dn:%s, scope:%s, attrs:%s", filter, dn, scope, attrs, ) results = _ldap.search_s(dn, int(scope), filter, attrs) elapsed = time.time() - start if elapsed < 0.200: elapsed_h = str(round(elapsed * 1000, 1)) + "ms" else: elapsed_h = str(round(elapsed, 2)) + "s" ret = { "results": results, "count": len(results), "time": {"human": elapsed_h, "raw": str(round(elapsed, 5))}, } return ret class _LDAPConnection: """ Setup an LDAP connection. """ 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 if self.uri == "": self.uri = f"ldap://{self.server}:{self.port}" try: if no_verify: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) self.ldap = ldap.initialize(f"{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: # pylint: disable=broad-except raise CommandExecutionError( "Failed to bind to LDAP server {} as {}: {}".format( self.uri, self.binddn, ldap_error ) )