Browse Source

Merge branch 'master' into add_delete_mapper_from_scope_and_add_mapper_to_sp_client

pull/129/head
Marcos Pereira 4 years ago
committed by GitHub
parent
commit
7510cdbf5e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      README.md
  2. 2
      docs/source/index.rst
  3. 142
      keycloak/keycloak_admin.py
  4. 6
      keycloak/urls_patterns.py

11
README.md

@ -94,11 +94,11 @@ token_rpt_info = keycloak_openid.introspect(keycloak_openid.introspect(token['ac
token_type_hint="requesting_party_token"))
# Introspect Token
token_info = keycloak_openid.introspect(token['access_token']))
token_info = keycloak_openid.introspect(token['access_token'])
# Decode Token
KEYCLOAK_PUBLIC_KEY = keycloak_openid.public_key()
options = {"verify_signature": True, "verify_aud": True, "exp": True}
options = {"verify_signature": True, "verify_aud": True, "verify_exp": True}
token_info = keycloak_openid.decode_token(token['access_token'], key=KEYCLOAK_PUBLIC_KEY, options=options)
# Get permissions by token
@ -114,7 +114,8 @@ from keycloak import KeycloakAdmin
keycloak_admin = KeycloakAdmin(server_url="http://localhost:8080/auth/",
username='example-admin',
password='secret',
realm_name="example_realm",
realm_name="master",
user_realm_name="only_if_other_realm_than_master",
client_secret_key="client-secret",
verify=True)
@ -140,7 +141,7 @@ count_users = keycloak_admin.users_count()
users = keycloak_admin.get_users({})
# Get user ID from name
user-id-keycloak = keycloak_admin.get_user_id("example@example.com")
user_id_keycloak = keycloak_admin.get_user_id("example@example.com")
# Get User
user = keycloak_admin.get_user("user-id-keycloak")
@ -175,7 +176,7 @@ server_info = keycloak_admin.get_server_info()
clients = keycloak_admin.get_clients()
# Get client - id (not client-id) from client by name
client_id=keycloak_admin.get_client_id("my-client")
client_id = keycloak_admin.get_client_id("my-client")
# Get representation of the client - id of client (not client-id)
client = keycloak_admin.get_client(client_id="client_id")

2
docs/source/index.rst

@ -132,7 +132,7 @@ Main methods::
# Decode Token
KEYCLOAK_PUBLIC_KEY = "secret"
options = {"verify_signature": True, "verify_aud": True, "exp": True}
options = {"verify_signature": True, "verify_aud": True, "verify_exp": True}
token_info = keycloak_openid.decode_token(token['access_token'], key=KEYCLOAK_PUBLIC_KEY, options=options)
# Get permissions by token

142
keycloak/keycloak_admin.py

@ -29,7 +29,10 @@ 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, URL_ADMIN_REALM_ROLES_ROLE_BY_NAME, URL_ADMIN_GROUPS_CLIENT_ROLES
URL_ADMIN_GET_GROUPS_REALM_ROLES, URL_ADMIN_REALM_ROLES_ROLE_BY_NAME, URL_ADMIN_GROUPS_CLIENT_ROLES, \
URL_ADMIN_GET_GROUPS_REALM_ROLES, URL_ADMIN_REALM_ROLES_ROLE_BY_NAME, \
URL_ADMIN_REALM_ROLES_COMPOSITE_REALM_ROLE
from .connection import ConnectionManager
from .exceptions import raise_error_from_response, KeycloakGetError
from .keycloak_openid import KeycloakOpenID
@ -44,7 +47,9 @@ from .urls_patterns import URL_ADMIN_SERVER_INFO, URL_ADMIN_CLIENT_AUTHZ_RESOURC
URL_ADMIN_CLIENT_SCOPES_ADD_MAPPER, URL_ADMIN_CLIENT_SCOPE, URL_ADMIN_CLIENT_SECRETS, \
URL_ADMIN_USER_REALM_ROLES, URL_ADMIN_REALM, URL_ADMIN_COMPONENTS, URL_ADMIN_COMPONENT, URL_ADMIN_KEYS, \
URL_ADMIN_USER_FEDERATED_IDENTITY, URL_ADMIN_USER_FEDERATED_IDENTITIES, \
URL_ADMIN_CLIENT_PROTOCOL_MAPPER, URL_ADMIN_CLIENT_SCOPES_MAPPERS
URL_ADMIN_CLIENT_PROTOCOL_MAPPER, URL_ADMIN_CLIENT_SCOPES_MAPPERS, \
URL_ADMIN_FLOWS_EXECUTIONS_EXEUCUTION, URL_ADMIN_FLOWS_EXECUTIONS_FLOW, URL_ADMIN_FLOWS_COPY, \
URL_ADMIN_FLOWS_ALIAS
class KeycloakAdmin:
@ -975,6 +980,19 @@ class KeycloakAdmin:
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[201], skip_exists=skip_exists)
def get_realm_role(self, role_name):
"""
Get realm role by role name
:param role_name: role's name, not id!
RoleRepresentation
https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_rolerepresentation
:return: role_id
"""
params_path = {"realm-name": self.realm_name, "role-name": role_name}
data_raw = self.raw_get(URL_ADMIN_REALM_ROLES_ROLE_BY_NAME.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def update_realm_role(self, role_name, payload):
"""
Update a role for the realm by name
@ -1000,6 +1018,53 @@ class KeycloakAdmin:
URL_ADMIN_REALM_ROLES_ROLE_BY_NAME.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204])
def add_composite_realm_roles_to_role(self, role_name, roles):
"""
Add composite roles to the role
:param role_name: The name of the role
:param roles: roles list or role (use RoleRepresentation) to be updated
:return Keycloak server response
"""
payload = roles if isinstance(roles, list) else [roles]
params_path = {"realm-name": self.realm_name, "role-name": role_name}
data_raw = self.raw_post(
URL_ADMIN_REALM_ROLES_COMPOSITE_REALM_ROLE.format(**params_path),
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError,
expected_codes=[204])
def remove_composite_realm_roles_to_role(self, role_name, roles):
"""
Remove composite roles from the role
:param role_name: The name of the role
:param roles: roles list or role (use RoleRepresentation) to be removed
:return Keycloak server response
"""
payload = roles if isinstance(roles, list) else [roles]
params_path = {"realm-name": self.realm_name, "role-name": role_name}
data_raw = self.raw_delete(
URL_ADMIN_REALM_ROLES_COMPOSITE_REALM_ROLE.format(**params_path),
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError,
expected_codes=[204])
def get_composite_realm_roles_of_role(self, role_name):
"""
Get composite roles of the role
:param role_name: The name of the role
:return Keycloak server response (array RoleRepresentation)
"""
params_path = {"realm-name": self.realm_name, "role-name": role_name}
data_raw = self.raw_get(
URL_ADMIN_REALM_ROLES_COMPOSITE_REALM_ROLE.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def assign_realm_roles(self, user_id, client_id, roles):
"""
Assign realm roles to a user
@ -1073,24 +1138,22 @@ class KeycloakAdmin:
data=json.dumps(payload))
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204])
def delete_group_client_roles(self, group_id, client_id, roles):
def get_group_client_roles(self, group_id, client_id):
"""
Delete client roles of a group
Get client roles of a group
:param group_id: id of group
:param client_id: id of client (not client-id)
: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, "client-id": client_id}
data_raw = self.raw_get(URL_ADMIN_GROUPS_CLIENT_ROLES.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def get_group_client_roles(self, group_id, client_id, roles):
def delete_group_client_roles(self, group_id, client_id, roles):
"""
Get client roles of a group
Delete client roles of a group
:param group_id: id of group
:param client_id: id of client (not client-id)
@ -1166,6 +1229,20 @@ class KeycloakAdmin:
params_path = {"realm-name": self.realm_name}
data_raw = self.raw_get(URL_ADMIN_FLOWS.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def get_authentication_flow_for_id(self, flow_id):
"""
Get one authentication flow by it's id/alias. Returns all flow details
AuthenticationFlowRepresentation
https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_authenticationflowrepresentation
:param flow_id: the id of a flow NOT it's alias
:return: Keycloak server response (AuthenticationFlowRepresentation)
"""
params_path = {"realm-name": self.realm_name, "flow-id": flow_id}
data_raw = self.raw_get(URL_ADMIN_FLOWS_ALIAS.format(**params_path))
return raise_error_from_response(data_raw, KeycloakGetError)
def create_authentication_flow(self, payload, skip_exists=False):
"""
@ -1184,6 +1261,20 @@ class KeycloakAdmin:
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[201], skip_exists=skip_exists)
def copy_authentication_flow(self, payload, flow_alias):
"""
Copy existing authentication flow under a new name. The new name is given as 'newName' attribute of the passed payload.
:param payload: JSON containing 'newName' attribute
:param flow_alias: the flow alias
:return: Keycloak server response (RoleRepresentation)
"""
params_path = {"realm-name": self.realm_name, "flow-alias": flow_alias}
data_raw = self.raw_post(URL_ADMIN_FLOWS_COPY.format(**params_path),
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[201])
def get_authentication_flow_executions(self, flow_alias):
"""
Get authentication flow executions. Returns all execution steps
@ -1211,6 +1302,41 @@ class KeycloakAdmin:
data_raw = self.raw_put(URL_ADMIN_FLOWS_EXECUTIONS.format(**params_path),
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[204])
def create_authentication_flow_execution(self, payload, flow_alias):
"""
Create an authentication flow execution
AuthenticationExecutionInfoRepresentation
https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_authenticationexecutioninforepresentation
:param payload: AuthenticationExecutionInfoRepresentation
:param flow_alias: The flow alias
:return: Keycloak server response
"""
params_path = {"realm-name": self.realm_name, "flow-alias": flow_alias}
data_raw = self.raw_post(URL_ADMIN_FLOWS_EXECUTIONS_EXEUCUTION.format(**params_path),
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[201])
def create_authentication_flow_subflow(self, payload, flow_alias, skip_exists=False):
"""
Create a new sub authentication flow for a given authentication flow
AuthenticationFlowRepresentation
https://www.keycloak.org/docs-api/8.0/rest-api/index.html#_authenticationflowrepresentation
:param payload: AuthenticationFlowRepresentation
:param flow_alias: The flow alias
:param skip_exists: If true then do not raise an error if authentication flow already exists
:return: Keycloak server response (RoleRepresentation)
"""
params_path = {"realm-name": self.realm_name, "flow-alias": flow_alias}
data_raw = self.raw_post(URL_ADMIN_FLOWS_EXECUTIONS_FLOW.format(**params_path),
data=payload)
return raise_error_from_response(data_raw, KeycloakGetError, expected_codes=[201], skip_exists=skip_exists)
def sync_users(self, storage_id, action):
"""

6
keycloak/urls_patterns.py

@ -81,10 +81,14 @@ URL_ADMIN_REALMS = "admin/realms"
URL_ADMIN_REALM = "admin/realms/{realm-name}"
URL_ADMIN_IDPS = "admin/realms/{realm-name}/identity-provider/instances"
URL_ADMIN_REALM_ROLES_ROLE_BY_NAME = "admin/realms/{realm-name}/roles/{role-name}"
URL_ADMIN_REALM_ROLES_COMPOSITE_REALM_ROLE = "admin/realms/{realm-name}/roles/{role-name}/composites"
URL_ADMIN_FLOWS = "admin/realms/{realm-name}/authentication/flows"
URL_ADMIN_FLOWS_ALIAS = "admin/realms/{realm-name}/authentication/flows/{flow-id}"
URL_ADMIN_FLOWS_COPY = "admin/realms/{realm-name}/authentication/flows/{flow-alias}/copy"
URL_ADMIN_FLOWS_EXECUTIONS = "admin/realms/{realm-name}/authentication/flows/{flow-alias}/executions"
URL_ADMIN_FLOWS_EXECUTIONS_EXEUCUTION = "admin/realms/{realm-name}/authentication/flows/{flow-alias}/executions/execution"
URL_ADMIN_FLOWS_EXECUTIONS_FLOW = "admin/realms/{realm-name}/authentication/flows/{flow-alias}/executions/flow"
URL_ADMIN_COMPONENTS = "admin/realms/{realm-name}/components"
URL_ADMIN_COMPONENT = "admin/realms/{realm-name}/components/{component-id}"

Loading…
Cancel
Save