diff options
author | 2024-07-26 14:54:49 +0100 | |
---|---|---|
committer | 2024-07-26 14:54:49 +0100 | |
commit | 496a75523de2873ff0c0d53eb7c610caa5760229 (patch) | |
tree | 2528170239727823fcc732a041bd259d6f3225c0 | |
parent | Add new directory APIs module (diff) |
Add FreeIPA module
-rw-r--r-- | arthur/apis/directory/freeipa.py | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/arthur/apis/directory/freeipa.py b/arthur/apis/directory/freeipa.py new file mode 100644 index 0000000..4d8daf2 --- /dev/null +++ b/arthur/apis/directory/freeipa.py @@ -0,0 +1,95 @@ +"""API utilities for modifying data via FreeIPA.""" + +from secrets import token_urlsafe + +from bonsai import LDAPDN +from python_freeipa import ClientMeta + +from arthur.config import CONFIG +from arthur.constants import LDAP_ROLE_MAPPING + +PW_LENGTH = 20 + + +def create_client() -> ClientMeta: + """Create a new client and login to FreeIPA.""" + username = LDAPDN(CONFIG.ldap_bind_user).rdns[0][0][1] + + client = ClientMeta( + CONFIG.ldap_host.host, verify_ssl=CONFIG.ldap_certificate_location.as_posix() + ) + + client.login(username, CONFIG.ldap_bind_password.get_secret_value()) + + return client + + +def get_user(username: str) -> dict: + """Fetch a user from FreeIPA.""" + client = create_client() + + return client.user_show(username) + + +def set_user_groups(username: str, groups: list[str]) -> None: + """ + Update a members groups to the provided list. + + Any managed groups not specified will be removed from the user. + """ + user = get_user(username) + + client = create_client() + + memberof_groups = user.get("result", {}).get("memberof_group", []) + + add_groups = [group for group in groups if group not in memberof_groups] + remove_groups = [ + group for group in memberof_groups if group not in groups and group in LDAP_ROLE_MAPPING + ] + + for group in add_groups: + client.group_add_member(group, o_user=[username]) + + for group in remove_groups: + client.group_remove_member(group, o_user=[username]) + + +def deactivate_user(username: str) -> None: + """Deactivate a user in FreeIPA.""" + client = create_client() + + client.user_mod(username, o_nsaccountlock=True) + + +def create_user(username: str, display_name: str, groups: list[str], discord_id: int) -> str: + """ + Create a new user in FreeIPA. If the user exists, the password is reset and returned. + + Returns the new user password on success. + """ + client = create_client() + + pw = token_urlsafe(PW_LENGTH) + + client.user_add( + username, + o_givenname=display_name, + o_cn=display_name, + o_sn=display_name, + o_displayname=display_name, + o_userpassword=pw, + o_employeenumber=discord_id, + ) + + for group in groups: + client.group_add_member(group, o_user=[username]) + + return pw + + +def delete_user(username: str) -> None: + """Delete a user from FreeIPA.""" + client = create_client() + + client.user_del(username) |