From 7dff2e2b759e6a7009b41db4011bacc9d40fa2b2 Mon Sep 17 00:00:00 2001 From: Paolo Romolini Date: Mon, 24 Feb 2020 09:30:56 +0100 Subject: [PATCH 1/6] Add group realm roles delete, get and add Signed-off-by: Paolo Romolini Signed-off-by: Tamara Noncentini --- keycloak/keycloak_admin.py | 43 ++++++++++++++++++++++++++++++++++++++ keycloak/urls_patterns.py | 2 ++ 2 files changed, 45 insertions(+) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index 6d7bd20..089416a 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -28,6 +28,8 @@ import json from builtins import isinstance from typing import List, Iterable +from keycloak.urls_patterns import URL_ADMIN_GROUPS_REALM_ROLES, \ + URL_ADMIN_GET_GROUPS_REALM_ROLES from .connection import ConnectionManager from .exceptions import raise_error_from_response, KeycloakGetError from .keycloak_openid import KeycloakOpenID @@ -936,6 +938,47 @@ class KeycloakAdmin: data=json.dumps(payload)) return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204) + def assign_group_realm_roles(self, group_id, roles): + """ + Assign realm roles to a group + + :param group_id: id of groupp + :param roles: roles list or role (use GroupRoleRepresentation) + :return Keycloak server response + """ + + payload = roles if isinstance(roles, list) else [roles] + params_path = {"realm-name": self.realm_name, "id": group_id} + data_raw = self.raw_post(URL_ADMIN_GROUPS_REALM_ROLES.format(**params_path), + data=json.dumps(payload)) + return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204) + + def delete_group_realm_roles(self, group_id, roles): + """ + Delete realm roles of a group + + :param group_id: id of group + :param roles: roles list or role (use GroupRoleRepresentation) + :return Keycloak server response + """ + + payload = roles if isinstance(roles, list) else [roles] + params_path = {"realm-name": self.realm_name, "id": group_id} + data_raw = self.raw_delete(URL_ADMIN_GROUPS_REALM_ROLES.format(**params_path), + data=json.dumps(payload)) + return raise_error_from_response(data_raw, KeycloakGetError, expected_code=204) + + def get_group_realm_roles(self, group_id): + """ + Get all realm roles for a group. + + :param user_id: id of the group + :return: Keycloak server response (array RoleRepresentation) + """ + params_path = {"realm-name": self.realm_name, "id": group_id} + data_raw = self.raw_get(URL_ADMIN_GET_GROUPS_REALM_ROLES.format(**params_path)) + return raise_error_from_response(data_raw, KeycloakGetError) + def get_client_roles_of_user(self, user_id, client_id): """ Get all client roles for a user. diff --git a/keycloak/urls_patterns.py b/keycloak/urls_patterns.py index e3f4d95..19ca28f 100644 --- a/keycloak/urls_patterns.py +++ b/keycloak/urls_patterns.py @@ -43,6 +43,8 @@ URL_ADMIN_RESET_PASSWORD = "admin/realms/{realm-name}/users/{id}/reset-password" URL_ADMIN_GET_SESSIONS = "admin/realms/{realm-name}/users/{id}/sessions" URL_ADMIN_USER_CLIENT_ROLES = "admin/realms/{realm-name}/users/{id}/role-mappings/clients/{client-id}" URL_ADMIN_USER_REALM_ROLES = "admin/realms/{realm-name}/users/{id}/role-mappings/realm" +URL_ADMIN_GROUPS_REALM_ROLES = "admin/realms/{realm-name}/groups/{id}/role-mappings/realm" +URL_ADMIN_GET_GROUPS_REALM_ROLES = "admin/realms/{realm-name}/groups/{id}/role-mappings" URL_ADMIN_USER_CLIENT_ROLES_AVAILABLE = "admin/realms/{realm-name}/users/{id}/role-mappings/clients/{client-id}/available" URL_ADMIN_USER_CLIENT_ROLES_COMPOSITE = "admin/realms/{realm-name}/users/{id}/role-mappings/clients/{client-id}/composite" URL_ADMIN_USER_GROUP = "admin/realms/{realm-name}/users/{id}/groups/{group-id}" From d47131d5ab9172f7a9d6830b4a10c116481ddbdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=BCller?= Date: Thu, 5 Mar 2020 12:27:41 +0100 Subject: [PATCH 2/6] make data-parameter optional Fixing issue https://github.com/marcospereirampj/python-keycloak/issues/65 --- keycloak/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keycloak/connection.py b/keycloak/connection.py index 4841792..12903a0 100644 --- a/keycloak/connection.py +++ b/keycloak/connection.py @@ -199,7 +199,7 @@ class ConnectionManager(object): raise KeycloakConnectionError( "Can't connect to server (%s)" % e) - def raw_delete(self, path, data, **kwargs): + def raw_delete(self, path, data={}, **kwargs): """ Submit delete request to the path. :arg From 429761b520e0af0871073d5365bdf2e672ec4d8a Mon Sep 17 00:00:00 2001 From: Joshua Adelman Date: Thu, 5 Mar 2020 11:28:33 -0500 Subject: [PATCH 3/6] add MANIFEST.in to package license file --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..1aba38f --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include LICENSE From 505d0e5772ee690de0b0947389073f36180c59f8 Mon Sep 17 00:00:00 2001 From: Romain Philibert Date: Fri, 13 Mar 2020 16:53:57 +0100 Subject: [PATCH 4/6] Add generate_client_secrets --- keycloak/keycloak_admin.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index 6d7bd20..634019c 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -1103,6 +1103,20 @@ class KeycloakAdmin: return raise_error_from_response(data_raw, KeycloakGetError, expected_code=201) + def generate_client_secrets(self, client_id): + """ + + Generate a new secret for the client + https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_regeneratesecret + + :param client_id: id of client (not client-id) + :return: Keycloak server response (ClientRepresentation) + """ + + params_path = {"realm-name": self.realm_name, "id": client_id} + data_raw = self.raw_post(URL_ADMIN_CLIENT_SECRETS.format(**params_path), data=None) + return raise_error_from_response(data_raw, KeycloakGetError) + def get_client_secrets(self, client_id): """ From 43a7a3943b3256a9dacf6dd93c0bc077e4e4fa52 Mon Sep 17 00:00:00 2001 From: Romain Philibert Date: Fri, 13 Mar 2020 17:05:03 +0100 Subject: [PATCH 5/6] Add support for Client Credentials Grant in KeycloakAdmin --- docs/source/index.rst | 8 ++++++++ keycloak/keycloak_admin.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index af697da..597cfb2 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -158,6 +158,14 @@ Main methods:: # realm_name="example_realm", # verify=True, # custom_headers={'CustomHeader': 'value'}) + # + # You can also authenticate with client_id and client_secret + #keycloak_admin = KeycloakAdmin(server_url="http://localhost:8080/auth/", + # client_id="example_client", + # client_secret_key="secret", + # realm_name="example_realm", + # verify=True, + # custom_headers={'CustomHeader': 'value'}) # Add user new_user = keycloak_admin.create_user({"email": "example@example.com", diff --git a/keycloak/keycloak_admin.py b/keycloak/keycloak_admin.py index 6d7bd20..c96d397 100644 --- a/keycloak/keycloak_admin.py +++ b/keycloak/keycloak_admin.py @@ -60,7 +60,7 @@ class KeycloakAdmin: _custom_headers = None _user_realm_name = None - def __init__(self, server_url, username, password, realm_name='master', client_id='admin-cli', verify=True, + def __init__(self, server_url, username=None, password=None, realm_name='master', client_id='admin-cli', verify=True, client_secret_key=None, custom_headers=None, user_realm_name=None, auto_refresh_token=None): """ From 4315d90d0be73139dc4f839cc9ce7e940cc3d4d3 Mon Sep 17 00:00:00 2001 From: Marcos Pereira Date: Sat, 11 Apr 2020 03:11:12 -0300 Subject: [PATCH 6/6] Release 0.20.0 --- docs/source/conf.py | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 8614386..ba92885 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -60,9 +60,9 @@ author = 'Marcos Pereira' # built documents. # # The short X.Y version. -version = '0.19.0' +version = '0.20.0' # The full version, including alpha/beta/rc tags. -release = '0.19.0' +release = '0.20.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.py b/setup.py index b89cd31..a0a550b 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ with open("README.md", "r") as fh: setup( name='python-keycloak', - version='0.19.0', + version='0.20.0', url='https://github.com/marcospereirampj/python-keycloak', license='The MIT License', author='Marcos Pereira',