1# -*- coding: utf-8 -*- 2 3# Copyright: (c) 2016, Peter Sagerson <psagers@ignorare.net> 4# Copyright: (c) 2016, Jiri Tyr <jiri.tyr@gmail.com> 5# Copyright: (c) 2017-2018 Keller Fuchs (@KellerFuchs) <kellerfuchs@hashbang.sh> 6# 7# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 8 9from __future__ import absolute_import, division, print_function 10__metaclass__ = type 11 12import traceback 13from ansible.module_utils.common.text.converters import to_native 14 15try: 16 import ldap 17 import ldap.sasl 18 19 HAS_LDAP = True 20 21 SASCL_CLASS = { 22 'gssapi': ldap.sasl.gssapi, 23 'external': ldap.sasl.external, 24 } 25except ImportError: 26 HAS_LDAP = False 27 28 29def gen_specs(**specs): 30 specs.update({ 31 'bind_dn': dict(), 32 'bind_pw': dict(default='', no_log=True), 33 'dn': dict(required=True), 34 'referrals_chasing': dict(type='str', default='anonymous', choices=['disabled', 'anonymous']), 35 'server_uri': dict(default='ldapi:///'), 36 'start_tls': dict(default=False, type='bool'), 37 'validate_certs': dict(default=True, type='bool'), 38 'sasl_class': dict(choices=['external', 'gssapi'], default='external', type='str'), 39 }) 40 41 return specs 42 43 44class LdapGeneric(object): 45 def __init__(self, module): 46 # Shortcuts 47 self.module = module 48 self.bind_dn = self.module.params['bind_dn'] 49 self.bind_pw = self.module.params['bind_pw'] 50 self.dn = self.module.params['dn'] 51 self.referrals_chasing = self.module.params['referrals_chasing'] 52 self.server_uri = self.module.params['server_uri'] 53 self.start_tls = self.module.params['start_tls'] 54 self.verify_cert = self.module.params['validate_certs'] 55 self.sasl_class = self.module.params['sasl_class'] 56 57 # Establish connection 58 self.connection = self._connect_to_ldap() 59 60 def fail(self, msg, exn): 61 self.module.fail_json( 62 msg=msg, 63 details=to_native(exn), 64 exception=traceback.format_exc() 65 ) 66 67 def _connect_to_ldap(self): 68 if not self.verify_cert: 69 ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) 70 71 connection = ldap.initialize(self.server_uri) 72 73 if self.referrals_chasing == 'disabled': 74 # Switch off chasing of referrals (https://github.com/ansible-collections/community.general/issues/1067) 75 connection.set_option(ldap.OPT_REFERRALS, 0) 76 77 if self.start_tls: 78 try: 79 connection.start_tls_s() 80 except ldap.LDAPError as e: 81 self.fail("Cannot start TLS.", e) 82 83 try: 84 if self.bind_dn is not None: 85 connection.simple_bind_s(self.bind_dn, self.bind_pw) 86 else: 87 klass = SASCL_CLASS.get(self.sasl_class, ldap.sasl.external) 88 connection.sasl_interactive_bind_s('', klass()) 89 except ldap.LDAPError as e: 90 self.fail("Cannot bind to the server.", e) 91 92 return connection 93