def get_listMembers(self, listname, search_base): memberlist = [] with Connection( self.__ldap_server, self.__ldap_user, self.__ldap_password, auto_bind=True, ) as conn: bswlist = ObjectDef(["groupOfURLs"], conn) bswlist += "uniqueMember" bswmember = ObjectDef(["inetOrgPerson"], conn) r = Reader(conn, bswlist, search_base, "cn:=" + listname) r.search() for entry in r: # print(entry.entry_attributes_as_dict) # print(entry['uniqueMember']) for item in entry["uniqueMember"]: # print(item.split(',')[0].split('=')[1]) r2 = Reader( conn, bswmember, self.ldap_basedn, "cn:=" + item.split(",")[0].split("=")[1], ) r2.search() for member in r2: memberlist.append(( member["sn"][0] + "," + member["givenName"][0], member["mail"][0], )) return memberlist
def get_groupMembers(self, groupname, search_base): memberlist = [] with Connection( self.__ldap_server, self.__ldap_user, self.__ldap_password, auto_bind=True, ) as conn: bswmember = ObjectDef(["inetOrgPerson"], conn) bswgroup = ObjectDef(["groupOfUniqueNames"], conn) r = Reader(conn, bswgroup, search_base, "cn:=" + groupname) r.search() for entry in r: # print(entry.entry_attributes_as_dict) # print(entry['uniqueMember']) for item in entry["uniqueMember"]: r2 = Reader( conn, bswmember, self.ldap_basedn, "cn:=" + item.split(",")[0].split("=")[1], ) r2.search() if len(r2) == 0: add_members = self.get_groupMembers( item.split(",")[0].split("=")[1], search_base) memberlist.extend(add_members) else: for member in r2: memberlist.append(( member["sn"][0] + "," + member["givenName"][0], member["mail"][0], )) return memberlist
def __init__(self, obj): self.obj = obj self.query = [] self.base_dn = obj.base_dn self.sub_tree = obj.sub_tree self.object_def = ObjectDef(obj.object_classes) self.operational_attributes = obj.operational_attributes self.components_in_and = True
def test_search_with_dereference(self): reverse = lambda a, e: e[::-1] def raise_parentheses_rank(_, l): up = {'(': '[', ')': ']', '[': '{', ']': '}', '{': '<', '}': '>'} r = [] for e in l: s = '' for c in e: s += up[c] if c in up else c r.append(s) return r self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'abstract-member-4')) self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'abstract-member-5')) self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'abstract-member-6')) self.delete_at_teardown.append( add_group(self.connection, testcase_id, 'abstract-group', self.delete_at_teardown)) ou = ObjectDef('inetOrgPerson') ou += AttrDef('cn', 'Common Name', post_query=reverse) ou += AttrDef('sn', 'Surname') ou += AttrDef('givenName', 'Given Name', post_query=raise_parentheses_rank) ou += AttrDef('ACL') qu = 'Common Name: ' + testcase_id + 'abstract-member-*' ru = Reader(self.connection, ou, test_base, qu) lu = ru.search() self.assertEqual(len(lu), 3) og = ObjectDef('groupOfNames') og += AttrDef('member', dereference_dn=ou) og += 'cn' qg = 'cn := ' + testcase_id + 'abstract-group' rg = Reader(self.connection, og, test_base, qg) lg = rg.search() self.assertEqual(len(lg), 1) eg = lg[0] mg = eg.member self.assertEqual(len(mg), 3) ug = eg.member[0] self.assertTrue( str(ug.surname) in ['abstract-member-4', 'abstract-member-5', 'abstract-member-6'])
def get_definition(self, object_class: Union[str, List[str]], attributes: Iterable[str] = None) -> ObjectDef: """ Get a new object class definition automatically from LDAP Schema. object definitions are save as cache for later use in connection. :param object_class: The LDAP objectClass type to define :param attributes: Extra LDAP attributes to include :return: ldap3 ObjectDef instance """ # create definition if missing if object_class not in self.definitions: with LogExecutionTime( f"Loading LDAP Schema definition for objectClass {object_class}" ): self.definitions[object_class] = ObjectDef( object_class, self.connection) # add missing attributes if attributes: for attr in attributes: if attr not in self.definitions[object_class]: self.definitions[object_class] += AttrDef(attr) return self.definitions[object_class]
def list_ldap_users(): users = dict() server = Server(Config.LDAP, use_ssl=True, get_info=ALL) person = ObjectDef('inetOrgPerson') try: with Connection( server=server, user=Config.LDAP_ADMIN, password=Config.LDAP_ADMIN_PASSWORD, auto_bind=True, receive_timeout=30, ) as conn: conn.search( search_base="dc=edirepository,dc=org", search_filter="(objectclass=person)", attributes=["cn", "sn", "uid", "givenName", "mail"] ) for e in sorted(conn.entries): dn = e.entry_dn user = { "dn": e.entry_dn, "cn": e.cn[0], "sn": e.sn[0], "givenName": e.givenName[0], "mail": e.mail[0], } users[e.uid[0]] = user except Exception as e: logger.error(e) return users
def test_find_entry_with_text_index_match(self): self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'mat-1')) self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'mat-2')) self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'mat-3')) o = ObjectDef('inetOrgPerson') o += AttrDef('cn', 'Common Name') o += AttrDef('sn', 'Surname') o += AttrDef(test_multivalued_attribute, 'Given Name') query_text = 'Common Name:=' + testcase_id + 'mat-*' r = Reader(self.connection, o, test_base, query_text) results = r.search() self.assertEqual(len(results), 3) try: # multiple matches e = r['match'] except KeyError: pass e = r['-2'] # exact match self.assertTrue('mat-2' in e.entry_dn) try: e = r['no-match'] # no match except KeyError: pass
def profile(): with Connection(server, current_user.dn, current_user.get_password(), auto_bind=True) as conn: person = ObjectDef(["inetOrgPerson"], conn) r = Reader(conn, person, current_user.dn) r.search() # print(r[0].entry_attributes_as_dict) form = ProfileForm(request.form, obj=current_user) if request.method == "POST" and form.validate(): w = Writer.from_cursor(r) # print(w[0].entry_attributes_as_dict) current_user.email = form.email.data current_user.vorname = form.vorname.data current_user.nachname = form.nachname.data w[0].givenName = current_user.vorname w[0].sn = current_user.nachname w[0].mail = current_user.email result = w[0].entry_commit_changes(refresh=True, controls=None) if result: flash(u"Profiländerung erfolgreich", "success") return redirect(url_for("index")) else: flash(u"Profiländerung nicht erfolgreich", "danger") return render_template( "/admin/changeprofile.html", form=form, user=current_user, title=u"Profiländerung", )
def test_match_dn_in_cursor(self): self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'mat-1')) self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'mat-2')) self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'mat-3')) o = ObjectDef('inetOrgPerson') o += AttrDef('cn', 'Common Name') o += AttrDef('sn', 'Surname') o += AttrDef(test_multivalued_attribute, 'Given Name') query_text = 'Common Name:=' + testcase_id + 'mat-*' r = Reader(self.connection, o, test_base, query_text) results = r.search() self.assertEqual(len(results), 3) e = r.match_dn('mat') # multiple matches self.assertEqual(len(e), 3) e = r.match_dn( '-3' ) # single match. there's domains with -20xx in their names, so use -3 to match self.assertEqual(len(e), 1) e = r.match_dn('no-match') # no match self.assertEqual(len(e), 0)
def __init__(self, server, user): self.server = server self.user = user self.person = ObjectDef(['top', 'organizationalPerson', 'user']) self.person += AttrDef('distinguishedName', key='dn') self.person += AttrDef('objectClass', key='object_class') self.person += AttrDef('cn', key='cn') self.person += AttrDef('sAMAccountName', key='username') self.person += AttrDef('givenName', key='first_name') self.person += AttrDef('sn', key='last_name') self.person += AttrDef('displayName', key='full_name') self.person += AttrDef('userPrincipalName', key='logon') self.person += AttrDef('mail', key='email') self.person += AttrDef('extensionName', key='email_canonical') self.person += AttrDef('userAccountControl', key='control') self.person += AttrDef('memberOf', key='groups') self.person += AttrDef(server.email_domain, key='email_domain') self.person += AttrDef(server.email_buzon_size, key='email_buzon_size') self.person += AttrDef(server.email_message_size, key='email_message_size') self.person += AttrDef(server.internet_domain, key='internet_domain') self.person += AttrDef(server.internet_quota_type, key='internet_quota_type') self.person += AttrDef(server.internet_quota_size, key='internet_quota_size') self.person += AttrDef(server.internet_extra_quota_size, key='internet_extra_quota_size') self.person += AttrDef(server.ftp_home, key='ftp_folder') self.person += AttrDef(server.ftp_size, key='ftp_size') self.query = 'username: {}'.format(self.user.username, )
def user_factory(self, username: str, password: str, db) -> Optional[User]: connection = self._get_connection(username, password) # Attempting auth if not connection.bind(): return None search_filter = config.LDAP_SEARCH_FILTER connection.search(self.base_dn, (search_filter % username)) user_dn = connection.response[0]['dn'] user_obj = ObjectDef('user', connection) reader = Reader(connection, user_obj, user_dn) reader.search() result = reader.entries[0] # Saving user to db user = User(username=username, name=str(result.name)) user.save(db) UserLDAP( id=user.id, title=str(result.title), department=str(result.department), company=str(result.company), ).save(db) return user
class Host(): __def = ObjectDef(schema=_ldap, object_class=_cfg.hosts.objectclass) # attributes to request from LDAP __attr_name = _cfg.hosts.attr.name __attr_vars = _cfg.hosts.attr.var __attr = [__attr_name, __attr_vars] base = _cfg.hosts.base @classmethod def get_one(cls, name): """Fetch a single host (inventory host mode).""" reader = Reader(connection=_ldap, query=cls.__attr_name + ":" + name, base=cls.base, object_def=cls.__def, sub_tree=sub(_cfg.hosts)) entries = reader.search(attributes=cls.__attr) return cls(entries[0]) @classmethod def load_all(cls): by_name = {} by_dn = {} reader = Reader(connection=_ldap, base=cls.base, object_def=cls.__def, sub_tree=sub(_cfg.hosts)) entries = reader.search_paged(paged_size=_page_size, attributes=cls.__attr) for entry in entries: host = cls(entry) by_name[host.name] = host by_dn[host.dn] = host _log.info("Loaded %i hosts" % len(by_dn)) return (by_name, by_dn) def __init__(self, entry): self.dn = entry.entry_dn # select a consistent name value, if there are several self.name = entry_name(entry, __class__.__attr_name) # parse vars values self.vars = {} for json_vars in entry[__class__.__attr_vars].values: self.vars.update(find_vars_in_attr(json_vars)) def get_data(self): return self.vars def __str__(self): return "Host %s" % self.name
def check_oauthbase_exists(fix=True): """ Check the oauth2 base DN exists, and if not, create it """ conn = current_app.ldap3_login_manager.connection ou = ObjectDef('organizationalunit', conn) oauth2base = "%s,%s"%(current_app.config['LDAP_OAUTH2_CLIENT_DN'], current_app.config['LDAP_BASE_DN']) _check_dn_exists(oauth2base, ou, fix)
def test_search_object(self): self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'abstract-1')) o = ObjectDef(['inetorgPerson', 'person'], self.connection) r = Reader(self.connection, o, test_base, '(cn=' + testcase_id + 'abstract-1)') r.search() self.assertEqual(len(r), 1) self.assertEqual(r.entries[0].cn, testcase_id + 'abstract-1')
def check_userbase_exists(fix=True): """ Check the User base DN exists, and if not, create it. """ conn = current_app.ldap3_login_manager.connection ou = ObjectDef('organizationalunit', conn) userbase = "%s,%s"%(current_app.config['LDAP_USER_DN'], current_app.config['LDAP_BASE_DN']) _check_dn_exists(userbase, ou, fix)
def _objectdef(cls): """ Helper function to construct the objectdef at runtime. Subclasses MUST specify the objectClasses used in the `objectClasses` class attribute. """ from ldap3 import ObjectDef conn = current_app.ldap3_login_manager.connection return ObjectDef(cls.objectClasses, conn)
def __init__(cls, name, bases, ns): cls._attributes = dict() cls._object_def = ObjectDef(cls.object_classes) # loop through the namespace looking for LDAPAttribute instances for key, value in ns.items(): if isinstance(value, LDAPAttribute): cls._attributes[key] = value attr_def = value.get_abstract_attr_def(key) cls._object_def.add(attr_def)
def test_search_with_None_default(self): self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-12')) ou = ObjectDef('inetOrgPerson') ou += AttrDef('cn', 'CommonName') ou += AttrDef('employeeType', key='Employee', default=None) qu = 'CommonName := ' + testcase_id + 'abs-12' ru = Reader(self.connection, ou, test_base, qu) lu = ru.search() self.assertEqual(lu[0].employee.value, None)
def test_search_object(self): self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'abstract-1')) o = ObjectDef(['inetorgPerson', 'person'], self.connection) r = Reader(self.connection, o, test_base, '(cn=' + testcase_id + 'abstract-1)') r.search(attributes='cn' ) # AD returns operationError for reading some atributes self.assertEqual(len(r), 1) self.assertEqual(r.entries[0].cn, testcase_id + 'abstract-1')
def test_create_query_filter_single_attribute_multiple_value(self): o = ObjectDef() o += AttrDef('cn', 'Common Name') query_text = '|Common Name:=john;=Bob' r = Reader(self.connection, o, test_base, query_text) r._create_query_filter() self.assertEqual('(|(cn=Bob)(cn=john))', r.query_filter)
def test_create_query_filter_single_attribute_single_value(self): o = ObjectDef() o += AttrDef('cn', 'Common Name') query_text = 'Common Name:John' r = Reader(self.connection, o, test_base, query_text) r._create_query_filter() self.assertEqual('(cn=John)', r.query_filter)
def check_group_base_exists(fix=True): """ Check the Group base DN exists, and if not, create it. """ conn = current_app.ldap3_login_manager.connection ou = ObjectDef("organizationalunit", conn) groupbase = "%s,%s" % ( current_app.config["LDAP_GROUP_DN"], current_app.config["LDAP_BASE_DN"], ) _check_dn_exists(groupbase, ou, fix)
def process_outbound_entry(queue_entry, ldap_connection): """ Processes queue_entry and apply changes to the LDAP user/group. Args: queue_entry: (dict) A outbound_queue table entry. The mandatory keys in the dict are: { "data": (dict containing current state of LDAP object) "data_type": (str) } ldap_connection: (ldap Connection object) A bound ldap connection object. Returns: write_confirmation: (bool) Returns True if a change to LDAP occurred, returns False if no LDAP changes occurred """ distinguished_name = get_distinguished_name(queue_entry) data_type = queue_entry["data_type"] if data_type == "group": sawtooth_entry_filtered = outbound_group_filter(queue_entry["data"], "ldap") elif data_type == "user": # Outbound AD user changes is currently not supported return False object_def = ObjectDef(data_type, ldap_connection) reader_cursor = Reader(ldap_connection, object_def, distinguished_name) reader_cursor.search() writer_cursor = Writer.from_cursor(reader_cursor) if reader_cursor.entries: LOGGER.debug("Updating AD %s: %s", data_type, distinguished_name) validated_entry = validate_update_entry(sawtooth_entry_filtered, data_type) # Grab current state of user/group in LDAP ldap_resource = writer_cursor[0] # Update AD user/group for ad_attribute in validated_entry: ldap_current_value = ldap_resource[ad_attribute].value if ad_attribute != "distinguishedName" and validated_entry[ad_attribute]: # Convert member list to list if value is a string if ad_attribute == "member" and isinstance(ldap_current_value, str): ldap_current_value = [ldap_current_value] # Sort lists for comparison if isinstance(ldap_current_value, list): ldap_current_value.sort() validated_entry[ad_attribute].sort() if ldap_current_value != validated_entry[ad_attribute]: ldap_resource[ad_attribute] = validated_entry[ad_attribute] return ldap_resource.entry_commit_changes() LOGGER.debug("AD %s %s was not found.", data_type, distinguished_name) return False
def test_search_with_default(self): self.delete_at_teardown.append( add_user(self.connection, testcase_id, 'abstract-member-10')) ou = ObjectDef('inetOrgPerson') ou += AttrDef('cn', 'CommonName') ou += AttrDef('employeeType', key='Employee', default='not employed') qu = 'CommonName := ' + testcase_id + 'abstract-member-10' ru = Reader(self.connection, ou, test_base, qu) lu = ru.search() self.assertEqual(str(lu[0].employee), 'not employed')
def get_def_(names): """ Lit les définitions de classes LDAP afin de lister tous les attributs devant être extraits. :param names: la liste des noms de classes LDAP :return: une définition contenant tous les attributs \ correspondant aux classes listées :raises FatalError: une classe LDAP listée n'a pas pu être \ trouvée """ (first, rest) = (names[0], names[1:]) try: from ldap3 import ObjectDef dfn = ObjectDef(first, ldap_conn) for other in rest: for attr in ObjectDef(other, ldap_conn): dfn += attr except KeyError as e: raise FatalError('Classe LDAP {} inconnue'.format(str(e))) return dfn
def test_create_query_filter(self): o = ObjectDef() o += AttrDef('cn', 'Common Name') o += AttrDef('sn', 'Surname') o += AttrDef('givenName', 'Given Name') query_text = '|Common Name:=john;Bob, Surname:=smith' r = Reader(self.connection, o, test_base, query_text) r._create_query_filter() self.assertEqual('(&(sn=smith)(|(cn=Bob)(cn=john)))', r.query_filter)
def search_for_users(basedn): server = Server(IDIR_URL, get_info=ALL) #objectClass conn = Connection(server, user=current_app.config["LDAP_IDIR_USERNAME"], password=current_app.config["LDAP_IDIR_PASSWORD"], authentication=NTLM, auto_bind=True) obj_user = ObjectDef('user', conn) r = Reader(conn, obj_user, basedn) r.search() return [x.entry_attributes_as_dict for x in r]
def test_validate_query_filter(self): o = ObjectDef() o += AttrDef('cn', 'Common Name') o += AttrDef('sn', 'Surname') o += AttrDef('givenName', 'Given Name') query_text = '|Common Name:=john;=Bob, Surname:=smith' r = Reader(self.connection, o, test_base, query_text) r._validate_query() self.assertEqual('Surname: =smith, |CommonName: =Bob;=john', r.validated_query)
def get_lists(self, search_base): ldap_lists = [] with Connection( self.__ldap_server, self.__ldap_user, self.__ldap_password, auto_bind=True, ) as conn: r = Reader(conn, ObjectDef(["groupOfURLs"], conn), search_base) r.search() for entry in r.entries: ldap_lists.append(entry.entry_dn) return ldap_lists
def main(): server = Server('ipa.demo1.freeipa.org', get_info=ALL) conn = Connection( server, 'uid=admin,cn=users,cn=accounts,dc=demo1,dc=freeipa,dc=org', 'Secret123', auto_bind=True) person = ObjectDef('person', conn) r = Reader(conn, person, 'ou=ldap3-tutorial,dc=demo1,dc=freeipa,dc=org') print(r) print('************') person += 'uid' print(r)