From 5bc5d4f32152f947e369bcd267b1194815734a51 Mon Sep 17 00:00:00 2001 From: Luca Paganin Date: Sun, 17 Jul 2022 21:10:41 +0200 Subject: [PATCH] feat: add functions covering some missing REST API calls --- poetry.lock | 8 ++++++ src/keycloak/keycloak_admin.py | 51 ++++++++++++++++++++++++++++++++++ src/keycloak/urls_patterns.py | 8 ++++++ 3 files changed, 67 insertions(+) diff --git a/poetry.lock b/poetry.lock index 24b870b..ae1c1f0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -688,6 +688,14 @@ category = "main" optional = false python-versions = ">=3.6,<4" +[[package]] +name = "requests-toolbelt" +version = "0.9.1" +description = "A utility belt for advanced users of python-requests" +category = "main" +optional = false +python-versions = ">=3.6,<4" + [package.dependencies] pyasn1 = ">=0.1.3" diff --git a/src/keycloak/keycloak_admin.py b/src/keycloak/keycloak_admin.py index 00501ef..4d2c368 100644 --- a/src/keycloak/keycloak_admin.py +++ b/src/keycloak/keycloak_admin.py @@ -29,6 +29,8 @@ import json from builtins import isinstance from typing import Iterable +import copy +from requests_toolbelt import MultipartEncoder from . import urls_patterns from .connection import ConnectionManager @@ -2810,3 +2812,52 @@ class KeycloakAdmin: data=json.dumps(payload), ) return raise_error_from_response(data_raw, KeycloakPostError, expected_codes=[201]) + + def get_composite_client_roles_of_group(self, client_id, group_id): + params_path = {"realm-name": self.realm_name, "id": group_id, "client-id": client_id} + data_raw = self.raw_get(urls_patterns.URL_ADMIN_GROUPS_CLIENT_ROLES_COMPOSITE.format(**params_path)) + return raise_error_from_response(data_raw, KeycloakGetError) + + def get_role_client_level_children(self, client_id, role_id): + params_path = {"realm-name": self.realm_name, "role-id": role_id, "client-id": client_id} + data_raw = self.raw_get(urls_patterns.URL_ADMIN_CLIENT_ROLE_CHILDREN.format(**params_path)) + return raise_error_from_response(data_raw, KeycloakGetError) + + def get_user_credentials(self, user_id): + params_path = {"realm-name": self.realm_name, "id": user_id} + data_raw = self.raw_get(urls_patterns.URL_ADMIN_USER_CREDENTIALS.format(**params_path)) + return raise_error_from_response(data_raw, KeycloakGetError) + + def upload_certificate(self, client_id, certcont): + params_path = {"realm-name": self.realm_name, "id": client_id, "attr": "jwt.credential"} + m = MultipartEncoder( + fields={ + "keystoreFormat": "Certificate PEM", + "file": certcont + } + ) + new_headers = copy.deepcopy(self.connection.headers) + new_headers["Content-Type"] = m.content_type + self.connection.headers = new_headers + data_raw = self.raw_post(urls_patterns.URL_ADMIN_CLIENT_CERT_UPLOAD.format(**params_path), + data=m, headers=new_headers) + return raise_error_from_response(data_raw, KeycloakPostError) + + def get_required_action_by_alias(self, action_alias): + actions = self.get_required_actions() + for a in actions: + if a['alias'] == action_alias: + break + return a + + def get_required_actions(self): + params_path = {"realm-name": self.realm_name} + data_raw = self.raw_get(urls_patterns.URL_ADMIN_REQUIRED_ACTIONS.format(**params_path)) + return raise_error_from_response(data_raw, KeycloakGetError) + + def update_required_action(self, action_alias, payload): + if not isinstance(payload, str): + payload = json.dumps(payload) + params_path = {"realm-name": self.realm_name, "action-alias": action_alias} + data_raw = self.raw_put(urls_patterns.URL_ADMIN_REQUIRED_ACTIONS_ALIAS.format(**params_path), data=payload) + return raise_error_from_response(data_raw, KeycloakPutError) diff --git a/src/keycloak/urls_patterns.py b/src/keycloak/urls_patterns.py index 2990362..325d693 100644 --- a/src/keycloak/urls_patterns.py +++ b/src/keycloak/urls_patterns.py @@ -183,3 +183,11 @@ URL_ADMIN_USER_FEDERATED_IDENTITY = ( URL_ADMIN_EVENTS = "admin/realms/{realm-name}/events" URL_ADMIN_EVENTS_CONFIG = URL_ADMIN_EVENTS + "/config" URL_ADMIN_CLIENT_SESSION_STATS = "admin/realms/{realm-name}/client-session-stats" + +URL_ADMIN_REALM = "admin/realms/{realm-name}" +URL_ADMIN_GROUPS_CLIENT_ROLES_COMPOSITE = URL_ADMIN_GROUPS_CLIENT_ROLES+"/composite" +URL_ADMIN_CLIENT_ROLE_CHILDREN = "admin/realms/{realm-name}/roles-by-id/{role-id}/composites/clients/{client-id}" +URL_ADMIN_USER_CREDENTIALS = URL_ADMIN_USERS+"/{id}/credentials" +URL_ADMIN_CLIENT_CERT_UPLOAD = URL_ADMIN_CLIENT_CERTS + '/upload-certificate' +URL_ADMIN_REQUIRED_ACTIONS = URL_ADMIN_REALM + "/authentication/required-actions" +URL_ADMIN_REQUIRED_ACTIONS_ALIAS = URL_ADMIN_REQUIRED_ACTIONS + "/{action-alias}"