From 89257a7d37d8e7f9d17460032d88a796e766dbcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Gr=C3=B6ger?= Date: Sat, 14 Nov 2020 13:16:30 +0100 Subject: [PATCH] [auth_ldap] delete unused roles in ldap --- flaschengeist/plugins/auth_ldap/__init__.py | 91 +++++++++++++++------ 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/flaschengeist/plugins/auth_ldap/__init__.py b/flaschengeist/plugins/auth_ldap/__init__.py index f37bb17..3474f44 100644 --- a/flaschengeist/plugins/auth_ldap/__init__.py +++ b/flaschengeist/plugins/auth_ldap/__init__.py @@ -35,7 +35,7 @@ class AuthLDAP(AuthPlugin): app.config["LDAP_SECRET"] = (config["secret"],) self.ldap = LDAPConn(app) self.dn = config["base_dn"] - self.default_gid = config['default_gid'] + self.default_gid = config["default_gid"] # TODO: might not be set if modify is called if "admin_dn" in config: self.admin_dn = config["admin_dn"] @@ -74,22 +74,33 @@ class AuthLDAP(AuthPlugin): try: ldap_conn = self.ldap.connect(self.admin_dn, self.admin_secret) self.ldap.connection.search( - "ou=user,{}".format(self.dn), "(uidNumber=*)", SUBTREE, attributes=["uidNumber"] + "ou=user,{}".format(self.dn), + "(uidNumber=*)", + SUBTREE, + attributes=["uidNumber"], ) - uidNumbers = sorted(self.ldap.response(), key = lambda i: i['attributes']['uidNumber'], reverse=True) - uidNumber = uidNumbers[0]['attributes']['uidNumber'] + 1 - dn = f'cn={user.firstname} {user.lastname},ou=user,{self.dn}' - object_class = ['inetOrgPerson', 'posixAccount', 'person', 'organizationalPerson'] + uidNumbers = sorted( + self.ldap.response(), + key=lambda i: i["attributes"]["uidNumber"], + reverse=True, + ) + uidNumber = uidNumbers[0]["attributes"]["uidNumber"] + 1 + dn = f"cn={user.firstname} {user.lastname},ou=user,{self.dn}" + object_class = [ + "inetOrgPerson", + "posixAccount", + "person", + "organizationalPerson", + ] attributes = { - 'sn': user.firstname, - 'givenName': user.lastname, - 'gidNumber': self.default_gid, - 'homeDirectory': f'/home/{user.userid}', - 'loginShell': '/bin/bash', - 'uid': user.userid, - 'userPassword': hashed(HASHED_SALTED_MD5, password), - 'uidNumber': uidNumber - + "sn": user.firstname, + "givenName": user.lastname, + "gidNumber": self.default_gid, + "homeDirectory": f"/home/{user.userid}", + "loginShell": "/bin/bash", + "uid": user.userid, + "userPassword": hashed(HASHED_SALTED_MD5, password), + "uidNumber": uidNumber, } ldap_conn.add(dn, object_class, attributes) self._set_roles(user) @@ -99,37 +110,63 @@ class AuthLDAP(AuthPlugin): def _get_groups(self, uid): groups = [] self.ldap.connection.search( - "ou=group,{}".format(self.dn), "(memberUID={})".format(uid), SUBTREE, attributes=["cn"] + "ou=group,{}".format(self.dn), + "(memberUID={})".format(uid), + SUBTREE, + attributes=["cn"], ) groups_data = self.ldap.connection.response for data in groups_data: groups.append(data["attributes"]["cn"][0]) return groups + def _get_all_roles(self, ldap_conn): + self.ldap.connection.search( + f"ou=group,{self.dn}", + "(cn=*)", + SUBTREE, + attributes=["cn", "gidNumber", "memberUid"], + ) + return self.ldap.response() + + def _delete_unsed_roles(self): + ldap_conn = self.ldap.connect(self.admin_dn, self.admin_secret) + ldap_roles = self._get_all_roles(ldap_conn) + for role in ldap_roles: + if len(role["attributes"]["memberUid"]) == 0: + ldap_conn.delete(role["dn"]) + def _set_roles(self, user: User): try: ldap_conn = self.ldap.connect(self.admin_dn, self.admin_secret) - self.ldap.connection.search(f"ou=group,{self.dn}", "(cn=*)", SUBTREE, attributes=["cn", "gidNumber"]) - ldap_roles = self.ldap.response() - gid_numbers = sorted(ldap_roles, key=lambda i: i['attributes']['gidNumber'], reverse=True) - gid_number = gid_numbers[0]['attributes']['gidNumber'] + 1 + ldap_roles = self._get_all_roles(ldap_conn) + + gid_numbers = sorted( + ldap_roles, key=lambda i: i["attributes"]["gidNumber"], reverse=True + ) + gid_number = gid_numbers[0]["attributes"]["gidNumber"] + 1 for user_role in user.roles: - if user_role not in [role["attributes"]["cn"][0] for role in ldap_roles]: - ldap_conn.add(f"cn={user_role},ou=group,{self.dn}", ["posixGroup"], attributes={"gidNumber": gid_number}) + if user_role not in [ + role["attributes"]["cn"][0] for role in ldap_roles + ]: + ldap_conn.add( + f"cn={user_role},ou=group,{self.dn}", + ["posixGroup"], + attributes={"gidNumber": gid_number}, + ) - ldap_conn = self.ldap.connect(self.admin_dn, self.admin_secret) - self.ldap.connection.search(f"ou=group,{self.dn}", "(cn=*)", SUBTREE, attributes=["cn", "gidNumber"]) - ldap_roles = self.ldap.response() + ldap_roles = self._get_all_roles(ldap_conn) for ldap_role in ldap_roles: if ldap_role["attributes"]["cn"][0] in user.roles: - modify = {'memberUid': [(MODIFY_ADD, [user.userid])]} + modify = {"memberUid": [(MODIFY_ADD, [user.userid])]} else: - modify = {'memberUid': [(MODIFY_DELETE, [user.userid])]} + modify = {"memberUid": [(MODIFY_DELETE, [user.userid])]} ldap_conn.modify(ldap_role["dn"], modify) + self._delete_unsed_roles() except (LDAPPasswordIsMandatoryError, LDAPBindError): raise BadRequest