mirror of
https://github.com/ansible-middleware/keycloak.git
synced 2026-06-13 12:05:54 +00:00
Merge pull request #349 from felix-grzelka/consistent-naming-of-client-scope
Consistent naming of client scope
This commit is contained in:
@@ -71,7 +71,7 @@ All Keycloak administration modules from `community.general` are provided in thi
|
||||
* `keycloak_client_rolemapping`: manage client role mappings for users and groups.
|
||||
* `keycloak_client_rolescope`: manage client role scope mappings.
|
||||
* `keycloak_client_scope`: manage client scopes and protocol mappers (replaces `community.general.keycloak_clientscope`).
|
||||
* `keycloak_clientscope_type`: manage default and optional client scope assignments.
|
||||
* `keycloak_client_scope_type`: manage default and optional client scope assignments.
|
||||
* `keycloak_clientsecret_info`: retrieve client secret information.
|
||||
* `keycloak_clientsecret_regenerate`: regenerate a client secret.
|
||||
* `keycloak_clienttemplate`: manage legacy client templates.
|
||||
|
||||
@@ -14,8 +14,8 @@ action_groups:
|
||||
- keycloak_client_rolemapping
|
||||
- keycloak_client_rolescope
|
||||
- keycloak_client_scope
|
||||
- keycloak_clientscope_type
|
||||
- keycloak_clientscope_rolemappings
|
||||
- keycloak_client_scope_type
|
||||
- keycloak_client_scope_rolemappings
|
||||
- keycloak_clientsecret_info
|
||||
- keycloak_clientsecret_regenerate
|
||||
- keycloak_clienttemplate
|
||||
@@ -44,3 +44,19 @@ plugin_routing:
|
||||
warning_text: >-
|
||||
The module has been renamed to keycloak_client_scope for Keycloak 17+ (Quarkus).
|
||||
Update playbooks to use middleware_automation.keycloak.keycloak_client_scope.
|
||||
|
||||
keycloak_clientscope_type:
|
||||
redirect: middleware_automation.keycloak.keycloak_client_scope_type
|
||||
deprecation:
|
||||
removal_version: 5.0.0
|
||||
warning_text: >-
|
||||
The module has been renamed to keycloak_client_scope_type for Keycloak 17+ (Quarkus).
|
||||
Update playbooks to use middleware_automation.keycloak.keycloak_client_scope_type.
|
||||
|
||||
keycloak_clientscope_rolemappings:
|
||||
redirect: middleware_automation.keycloak.keycloak_client_scope_rolemappings
|
||||
deprecation:
|
||||
removal_version: 5.0.0
|
||||
warning_text: >-
|
||||
The module has been renamed to keycloak_client_scope_rolemappings for Keycloak 17+ (Quarkus).
|
||||
Update playbooks to use middleware_automation.keycloak.keycloak_client_scope_rolemappings.
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
- keycloak_client_rolemapping
|
||||
- keycloak_client_rolescope
|
||||
- keycloak_client_scope
|
||||
- keycloak_clientscope_type
|
||||
- keycloak_clientscope_rolemappings
|
||||
- keycloak_client_scope_type
|
||||
- keycloak_client_scope_rolemappings
|
||||
- keycloak_clientsecret_info
|
||||
- keycloak_clientsecret_regenerate
|
||||
- keycloak_clienttemplate
|
||||
@@ -265,10 +265,10 @@
|
||||
- "'404' not in (clienttemplate_result.msg | default(''))"
|
||||
- "'Not Found' not in (clienttemplate_result.msg | default(''))"
|
||||
|
||||
- name: keycloak_clientscope_type — attach scope as optional on realm
|
||||
middleware_automation.keycloak.keycloak_clientscope_type:
|
||||
- name: keycloak_client_scope_type — attach scope as optional on realm
|
||||
middleware_automation.keycloak.keycloak_client_scope_type:
|
||||
realm: "{{ target_realm }}"
|
||||
optional_clientscopes:
|
||||
optional_client_scopes:
|
||||
- "{{ scope }}"
|
||||
|
||||
- name: keycloak_user_rolemapping — assign realm role to user
|
||||
@@ -299,54 +299,54 @@
|
||||
- name: keycloak_client_rolescope — restrict realm role on client
|
||||
middleware_automation.keycloak.keycloak_client_rolescope:
|
||||
realm: "{{ target_realm }}"
|
||||
client_id: "{{ client }}"
|
||||
target_client_id: "{{ client }}"
|
||||
role_names:
|
||||
- "{{ role }}"
|
||||
state: present
|
||||
|
||||
- name: keycloak_clientscope_rolemappings — map client roles to clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: keycloak_client_scope_rolemappings — map client roles to client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
realm: "{{ target_realm }}"
|
||||
client_id: "{{ client }}"
|
||||
clientscope_id: "{{ scope }}"
|
||||
client_scope_id: "{{ scope }}"
|
||||
role_names:
|
||||
- "{{ client_role }}"
|
||||
register: clientscope_rolemappings_result
|
||||
register: client_scope_rolemappings_result
|
||||
|
||||
- name: Assert clientscope role mappings were created
|
||||
- name: Assert client scope role mappings were created
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- clientscope_rolemappings_result is changed
|
||||
- clientscope_rolemappings_result.end_state | length == 1
|
||||
- client_scope_rolemappings_result is changed
|
||||
- client_scope_rolemappings_result.end_state | length == 1
|
||||
|
||||
- name: keycloak_clientscope_rolemappings — remap client role (idempotency)
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: keycloak_client_scope_rolemappings — remap client role (idempotency)
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
realm: "{{ target_realm }}"
|
||||
client_id: "{{ client }}"
|
||||
clientscope_id: "{{ scope }}"
|
||||
client_scope_id: "{{ scope }}"
|
||||
role_names:
|
||||
- "{{ client_role }}"
|
||||
register: clientscope_rolemappings_idempotent_result
|
||||
register: client_scope_rolemappings_idempotent_result
|
||||
|
||||
- name: Assert clientscope role mappings are idempotent
|
||||
- name: Assert client scope role mappings are idempotent
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- clientscope_rolemappings_idempotent_result is not changed
|
||||
- clientscope_rolemappings_idempotent_result.end_state | length == 1
|
||||
- client_scope_rolemappings_idempotent_result is not changed
|
||||
- client_scope_rolemappings_idempotent_result.end_state | length == 1
|
||||
|
||||
- name: keycloak_clientscope_rolemappings — map realm role to clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: keycloak_client_scope_rolemappings — map realm role to client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
realm: "{{ target_realm }}"
|
||||
clientscope_id: "{{ scope }}"
|
||||
client_scope_id: "{{ scope }}"
|
||||
role_names:
|
||||
- "{{ role }}"
|
||||
register: clientscope_realm_rolemappings_result
|
||||
register: client_scope_realm_rolemappings_result
|
||||
|
||||
- name: Assert realm role was mapped to clientscope
|
||||
- name: Assert realm role was mapped to client_scope
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- clientscope_realm_rolemappings_result is changed
|
||||
- clientscope_realm_rolemappings_result.end_state | length == 1
|
||||
- client_scope_realm_rolemappings_result is changed
|
||||
- client_scope_realm_rolemappings_result.end_state | length == 1
|
||||
|
||||
- name: keycloak_user — set email_verified explicitly
|
||||
middleware_automation.keycloak.keycloak_user:
|
||||
@@ -517,19 +517,19 @@
|
||||
name: "{{ authz_scope }}"
|
||||
state: absent
|
||||
|
||||
- name: keycloak_clientscope_rolemappings — remove realm role from clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: keycloak_client_scope_rolemappings — remove realm role from client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
realm: "{{ target_realm }}"
|
||||
clientscope_id: "{{ scope }}"
|
||||
client_scope_id: "{{ scope }}"
|
||||
role_names:
|
||||
- "{{ role }}"
|
||||
state: absent
|
||||
|
||||
- name: keycloak_clientscope_rolemappings — remove client role from clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: keycloak_client_scope_rolemappings — remove client role from client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
realm: "{{ target_realm }}"
|
||||
client_id: "{{ client }}"
|
||||
clientscope_id: "{{ scope }}"
|
||||
client_scope_id: "{{ scope }}"
|
||||
role_names:
|
||||
- "{{ client_role }}"
|
||||
state: absent
|
||||
@@ -537,7 +537,7 @@
|
||||
- name: keycloak_client_rolescope — remove role scope mapping
|
||||
middleware_automation.keycloak.keycloak_client_rolescope:
|
||||
realm: "{{ target_realm }}"
|
||||
client_id: "{{ client }}"
|
||||
target_client_id: "{{ client }}"
|
||||
role_names:
|
||||
- "{{ role }}"
|
||||
state: absent
|
||||
|
||||
@@ -57,23 +57,23 @@ URL_GROUPS = "{url}/admin/realms/{realm}/groups"
|
||||
URL_GROUP = "{url}/admin/realms/{realm}/groups/{groupid}"
|
||||
URL_GROUP_CHILDREN = "{url}/admin/realms/{realm}/groups/{groupid}/children"
|
||||
|
||||
URL_CLIENTSCOPES = "{url}/admin/realms/{realm}/client-scopes"
|
||||
URL_CLIENTSCOPE = "{url}/admin/realms/{realm}/client-scopes/{id}"
|
||||
URL_CLIENTSCOPE_SCOPE_MAPPINGS = "{url}/admin/realms/{realm}/client-scopes/{id}/scope-mappings"
|
||||
URL_CLIENTSCOPE_SCOPE_MAPPINGS_REALM = "{url}/admin/realms/{realm}/client-scopes/{id}/scope-mappings/realm"
|
||||
URL_CLIENTSCOPE_SCOPE_MAPPINGS_CLIENT = "{url}/admin/realms/{realm}/client-scopes/{id}/scope-mappings/clients/{client}"
|
||||
URL_CLIENTSCOPE_PROTOCOLMAPPERS = "{url}/admin/realms/{realm}/client-scopes/{id}/protocol-mappers/models"
|
||||
URL_CLIENTSCOPE_PROTOCOLMAPPER = "{url}/admin/realms/{realm}/client-scopes/{id}/protocol-mappers/models/{mapper_id}"
|
||||
URL_CLIENT_SCOPES = "{url}/admin/realms/{realm}/client-scopes"
|
||||
URL_CLIENT_SCOPE = "{url}/admin/realms/{realm}/client-scopes/{id}"
|
||||
URL_CLIENT_SCOPE_SCOPE_MAPPINGS = "{url}/admin/realms/{realm}/client-scopes/{id}/scope-mappings"
|
||||
URL_CLIENT_SCOPE_SCOPE_MAPPINGS_REALM = "{url}/admin/realms/{realm}/client-scopes/{id}/scope-mappings/realm"
|
||||
URL_CLIENT_SCOPE_SCOPE_MAPPINGS_CLIENT = "{url}/admin/realms/{realm}/client-scopes/{id}/scope-mappings/clients/{client}"
|
||||
URL_CLIENT_SCOPE_PROTOCOLMAPPERS = "{url}/admin/realms/{realm}/client-scopes/{id}/protocol-mappers/models"
|
||||
URL_CLIENT_SCOPE_PROTOCOLMAPPER = "{url}/admin/realms/{realm}/client-scopes/{id}/protocol-mappers/models/{mapper_id}"
|
||||
|
||||
URL_DEFAULT_CLIENTSCOPES = "{url}/admin/realms/{realm}/default-default-client-scopes"
|
||||
URL_DEFAULT_CLIENTSCOPE = "{url}/admin/realms/{realm}/default-default-client-scopes/{id}"
|
||||
URL_OPTIONAL_CLIENTSCOPES = "{url}/admin/realms/{realm}/default-optional-client-scopes"
|
||||
URL_OPTIONAL_CLIENTSCOPE = "{url}/admin/realms/{realm}/default-optional-client-scopes/{id}"
|
||||
URL_DEFAULT_CLIENT_SCOPES = "{url}/admin/realms/{realm}/default-default-client-scopes"
|
||||
URL_DEFAULT_CLIENT_SCOPE = "{url}/admin/realms/{realm}/default-default-client-scopes/{id}"
|
||||
URL_OPTIONAL_CLIENT_SCOPES = "{url}/admin/realms/{realm}/default-optional-client-scopes"
|
||||
URL_OPTIONAL_CLIENT_SCOPE = "{url}/admin/realms/{realm}/default-optional-client-scopes/{id}"
|
||||
|
||||
URL_CLIENT_DEFAULT_CLIENTSCOPES = "{url}/admin/realms/{realm}/clients/{cid}/default-client-scopes"
|
||||
URL_CLIENT_DEFAULT_CLIENTSCOPE = "{url}/admin/realms/{realm}/clients/{cid}/default-client-scopes/{id}"
|
||||
URL_CLIENT_OPTIONAL_CLIENTSCOPES = "{url}/admin/realms/{realm}/clients/{cid}/optional-client-scopes"
|
||||
URL_CLIENT_OPTIONAL_CLIENTSCOPE = "{url}/admin/realms/{realm}/clients/{cid}/optional-client-scopes/{id}"
|
||||
URL_CLIENT_DEFAULT_CLIENT_SCOPES = "{url}/admin/realms/{realm}/clients/{cid}/default-client-scopes"
|
||||
URL_CLIENT_DEFAULT_CLIENT_SCOPE = "{url}/admin/realms/{realm}/clients/{cid}/default-client-scopes/{id}"
|
||||
URL_CLIENT_OPTIONAL_CLIENT_SCOPES = "{url}/admin/realms/{realm}/clients/{cid}/optional-client-scopes"
|
||||
URL_CLIENT_OPTIONAL_CLIENT_SCOPE = "{url}/admin/realms/{realm}/clients/{cid}/optional-client-scopes/{id}"
|
||||
|
||||
URL_CLIENT_GROUP_ROLEMAPPINGS = "{url}/admin/realms/{realm}/groups/{id}/role-mappings/clients/{client}"
|
||||
URL_CLIENT_GROUP_ROLEMAPPINGS_AVAILABLE = (
|
||||
@@ -701,7 +701,7 @@ class KeycloakAPI:
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not obtain list of clients for realm {realm}: {e}")
|
||||
|
||||
def get_client_by_clientid(self, client_id, realm: str = "master"):
|
||||
def get_client_by_client_id(self, client_id, realm: str = "master"):
|
||||
"""Get client representation by clientId
|
||||
:param client_id: The clientId to be queried
|
||||
:param realm: realm from which to obtain the client representation
|
||||
@@ -744,7 +744,7 @@ class KeycloakAPI:
|
||||
:param realm: client template from this realm
|
||||
:return: id of client (usually a UUID)
|
||||
"""
|
||||
result = self.get_client_by_clientid(client_id, realm)
|
||||
result = self.get_client_by_client_id(client_id, realm)
|
||||
if isinstance(result, dict) and "id" in result:
|
||||
return result["id"]
|
||||
else:
|
||||
@@ -1289,99 +1289,99 @@ class KeycloakAPI:
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not delete client template {id} in realm {realm}: {e}")
|
||||
|
||||
def get_clientscopes(self, realm: str = "master"):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
def get_client_scopes(self, realm: str = "master"):
|
||||
"""Fetch the name and ID of all client scopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the group, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the group you wish to return.
|
||||
get_client_scope_by_client_scope_id, passing in the ID of the group you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides; default 'master'.
|
||||
:return The clientscopes of this realm (default "master")
|
||||
:param realm: Realm in which the client scope resides; default 'master'.
|
||||
:return The client scopes of this realm (default "master")
|
||||
"""
|
||||
clientscopes_url = URL_CLIENTSCOPES.format(url=self.baseurl, realm=realm)
|
||||
client_scopes_url = URL_CLIENT_SCOPES.format(url=self.baseurl, realm=realm)
|
||||
try:
|
||||
return self._request_and_deserialize(clientscopes_url, method="GET")
|
||||
return self._request_and_deserialize(client_scopes_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not fetch list of clientscopes in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not fetch list of client scopes in realm {realm}: {e}")
|
||||
|
||||
def get_clientscope_by_clientscopeid(self, cid, realm: str = "master"):
|
||||
"""Fetch a keycloak clientscope from the provided realm using the clientscope's unique ID.
|
||||
def get_client_scope_by_client_scope_id(self, cid, realm: str = "master"):
|
||||
"""Fetch a keycloak client scope from the provided realm using the client scope's unique ID.
|
||||
|
||||
If the clientscope does not exist, None is returned.
|
||||
If the client scope does not exist, None is returned.
|
||||
|
||||
gid is a UUID provided by the Keycloak API
|
||||
:param cid: UUID of the clientscope to be returned
|
||||
:param realm: Realm in which the clientscope resides; default 'master'.
|
||||
:param cid: UUID of the client scope to be returned
|
||||
:param realm: Realm in which the client scope resides; default 'master'.
|
||||
"""
|
||||
clientscope_url = URL_CLIENTSCOPE.format(url=self.baseurl, realm=realm, id=cid)
|
||||
client_scope_url = URL_CLIENT_SCOPE.format(url=self.baseurl, realm=realm, id=cid)
|
||||
try:
|
||||
return self._request_and_deserialize(clientscope_url, method="GET")
|
||||
return self._request_and_deserialize(client_scope_url, method="GET")
|
||||
|
||||
except HTTPError as e:
|
||||
if e.code == HTTPStatus.NOT_FOUND:
|
||||
return None
|
||||
else:
|
||||
self.fail_request(e, msg=f"Could not fetch clientscope {cid} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not fetch client scope {cid} in realm {realm}: {e}")
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg=f"Could not clientscope group {cid} in realm {realm}: {e}")
|
||||
self.module.fail_json(msg=f"Could not client scope group {cid} in realm {realm}: {e}")
|
||||
|
||||
def get_clientscope_by_name(self, name, realm: str = "master"):
|
||||
"""Fetch a keycloak clientscope within a realm based on its name.
|
||||
def get_client_scope_by_name(self, name, realm: str = "master"):
|
||||
"""Fetch a keycloak client scope within a realm based on its name.
|
||||
|
||||
The Keycloak API does not allow filtering of the clientscopes resource by name.
|
||||
As a result, this method first retrieves the entire list of clientscopes - name and ID -
|
||||
The Keycloak API does not allow filtering of the client scopes resource by name.
|
||||
As a result, this method first retrieves the entire list of client scopes - name and ID -
|
||||
then performs a second query to fetch the group.
|
||||
|
||||
If the clientscope does not exist, None is returned.
|
||||
:param name: Name of the clientscope to fetch.
|
||||
:param realm: Realm in which the clientscope resides; default 'master'
|
||||
If the client scope does not exist, None is returned.
|
||||
:param name: Name of the client scope to fetch.
|
||||
:param realm: Realm in which the client scope resides; default 'master'
|
||||
"""
|
||||
try:
|
||||
all_clientscopes = self.get_clientscopes(realm=realm)
|
||||
all_client_scopes = self.get_client_scopes(realm=realm)
|
||||
|
||||
for clientscope in all_clientscopes:
|
||||
if clientscope["name"] == name:
|
||||
return self.get_clientscope_by_clientscopeid(clientscope["id"], realm=realm)
|
||||
for client_scope in all_client_scopes:
|
||||
if client_scope["name"] == name:
|
||||
return self.get_client_scope_by_client_scope_id(client_scope["id"], realm=realm)
|
||||
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg=f"Could not fetch clientscope {name} in realm {realm}: {e}")
|
||||
self.module.fail_json(msg=f"Could not fetch client scope {name} in realm {realm}: {e}")
|
||||
|
||||
def create_clientscope(self, clientscoperep, realm: str = "master"):
|
||||
"""Create a Keycloak clientscope.
|
||||
def create_client_scope(self, client_scope_rep, realm: str = "master"):
|
||||
"""Create a Keycloak client scope.
|
||||
|
||||
:param clientscoperep: a ClientScopeRepresentation of the clientscope to be created. Must contain at minimum the field name.
|
||||
:param client_scope_rep: a ClientScopeRepresentation of the client scope to be created. Must contain at minimum the field name.
|
||||
:return: HTTPResponse object on success
|
||||
"""
|
||||
clientscopes_url = URL_CLIENTSCOPES.format(url=self.baseurl, realm=realm)
|
||||
client_scopes_url = URL_CLIENT_SCOPES.format(url=self.baseurl, realm=realm)
|
||||
try:
|
||||
return self._request(clientscopes_url, method="POST", data=json.dumps(clientscoperep))
|
||||
return self._request(client_scopes_url, method="POST", data=json.dumps(client_scope_rep))
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not create clientscope {clientscoperep['name']} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not create client scope {client_scope_rep['name']} in realm {realm}: {e}")
|
||||
|
||||
def update_clientscope(self, clientscoperep, realm: str = "master"):
|
||||
"""Update an existing clientscope.
|
||||
def update_client_scope(self, client_scope_rep, realm: str = "master"):
|
||||
"""Update an existing client scope.
|
||||
|
||||
:param grouprep: A GroupRepresentation of the updated group.
|
||||
:return HTTPResponse object on success
|
||||
"""
|
||||
clientscope_url = URL_CLIENTSCOPE.format(url=self.baseurl, realm=realm, id=clientscoperep["id"])
|
||||
client_scope_url = URL_CLIENT_SCOPE.format(url=self.baseurl, realm=realm, id=client_scope_rep["id"])
|
||||
|
||||
try:
|
||||
return self._request(clientscope_url, method="PUT", data=json.dumps(clientscoperep))
|
||||
return self._request(client_scope_url, method="PUT", data=json.dumps(client_scope_rep))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not update clientscope {clientscoperep['name']} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not update client scope {client_scope_rep['name']} in realm {realm}: {e}")
|
||||
|
||||
def delete_clientscope(self, name=None, cid=None, realm: str = "master"):
|
||||
"""Delete a clientscope. One of name or cid must be provided.
|
||||
def delete_client_scope(self, name=None, cid=None, realm: str = "master"):
|
||||
"""Delete a client scope. One of name or cid must be provided.
|
||||
|
||||
Providing the clientscope ID is preferred as it avoids a second lookup to
|
||||
convert a clientscope name to an ID.
|
||||
Providing the client scope ID is preferred as it avoids a second lookup to
|
||||
convert a client scope name to an ID.
|
||||
|
||||
:param name: The name of the clientscope. A lookup will be performed to retrieve the clientscope ID.
|
||||
:param cid: The ID of the clientscope (preferred to name).
|
||||
:param name: The name of the client scope. A lookup will be performed to retrieve the client scope ID.
|
||||
:param cid: The ID of the client scope (preferred to name).
|
||||
:param realm: The realm in which this group resides, default "master".
|
||||
"""
|
||||
|
||||
@@ -1393,9 +1393,9 @@ class KeycloakAPI:
|
||||
# in the case that both are provided, prefer the ID, since it is one
|
||||
# less lookup.
|
||||
if cid is None and name is not None:
|
||||
for clientscope in self.get_clientscopes(realm=realm):
|
||||
if clientscope["name"] == name:
|
||||
cid = clientscope["id"]
|
||||
for client_scope in self.get_client_scopes(realm=realm):
|
||||
if client_scope["name"] == name:
|
||||
cid = client_scope["id"]
|
||||
break
|
||||
|
||||
# if the group doesn't exist - no problem, nothing to delete.
|
||||
@@ -1403,41 +1403,41 @@ class KeycloakAPI:
|
||||
return None
|
||||
|
||||
# should have a good cid by here.
|
||||
clientscope_url = URL_CLIENTSCOPE.format(realm=realm, id=cid, url=self.baseurl)
|
||||
client_scope_url = URL_CLIENT_SCOPE.format(realm=realm, id=cid, url=self.baseurl)
|
||||
try:
|
||||
return self._request(clientscope_url, method="DELETE")
|
||||
return self._request(client_scope_url, method="DELETE")
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Unable to delete clientscope {cid}: {e}")
|
||||
self.fail_request(e, msg=f"Unable to delete client scope {cid}: {e}")
|
||||
|
||||
def get_clientscope_protocolmappers(self, cid, realm: str = "master"):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
def get_client_scope_protocolmappers(self, cid, realm: str = "master"):
|
||||
"""Fetch the name and ID of all client scopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the group, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the group you wish to return.
|
||||
get_client_scope_by_client_scope_id, passing in the ID of the group you wish to return.
|
||||
|
||||
:param cid: id of clientscope (not name).
|
||||
:param realm: Realm in which the clientscope resides; default 'master'.
|
||||
:param cid: id of client scope (not name).
|
||||
:param realm: Realm in which the client scope resides; default 'master'.
|
||||
:return The protocolmappers of this realm (default "master")
|
||||
"""
|
||||
protocolmappers_url = URL_CLIENTSCOPE_PROTOCOLMAPPERS.format(id=cid, url=self.baseurl, realm=realm)
|
||||
protocolmappers_url = URL_CLIENT_SCOPE_PROTOCOLMAPPERS.format(id=cid, url=self.baseurl, realm=realm)
|
||||
try:
|
||||
return self._request_and_deserialize(protocolmappers_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not fetch list of protocolmappers in realm {realm}: {e}")
|
||||
|
||||
def get_clientscope_protocolmapper_by_protocolmapperid(self, pid, cid, realm: str = "master"):
|
||||
"""Fetch a keycloak clientscope from the provided realm using the clientscope's unique ID.
|
||||
def get_client_scope_protocolmapper_by_protocolmapperid(self, pid, cid, realm: str = "master"):
|
||||
"""Fetch a keycloak client scope from the provided realm using the client scope's unique ID.
|
||||
|
||||
If the clientscope does not exist, None is returned.
|
||||
If the client scope does not exist, None is returned.
|
||||
|
||||
gid is a UUID provided by the Keycloak API
|
||||
|
||||
:param cid: UUID of the protocolmapper to be returned
|
||||
:param cid: UUID of the clientscope to be returned
|
||||
:param realm: Realm in which the clientscope resides; default 'master'.
|
||||
:param cid: UUID of the client scope to be returned
|
||||
:param realm: Realm in which the client scope resides; default 'master'.
|
||||
"""
|
||||
protocolmapper_url = URL_CLIENTSCOPE_PROTOCOLMAPPER.format(url=self.baseurl, realm=realm, id=cid, mapper_id=pid)
|
||||
protocolmapper_url = URL_CLIENT_SCOPE_PROTOCOLMAPPER.format(url=self.baseurl, realm=realm, id=cid, mapper_id=pid)
|
||||
try:
|
||||
return self._request_and_deserialize(protocolmapper_url, method="GET")
|
||||
|
||||
@@ -1449,24 +1449,24 @@ class KeycloakAPI:
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg=f"Could not fetch protocolmapper {cid} in realm {realm}: {e}")
|
||||
|
||||
def get_clientscope_protocolmapper_by_name(self, cid, name, realm: str = "master"):
|
||||
"""Fetch a keycloak clientscope within a realm based on its name.
|
||||
def get_client_scope_protocolmapper_by_name(self, cid, name, realm: str = "master"):
|
||||
"""Fetch a keycloak client scope within a realm based on its name.
|
||||
|
||||
The Keycloak API does not allow filtering of the clientscopes resource by name.
|
||||
As a result, this method first retrieves the entire list of clientscopes - name and ID -
|
||||
The Keycloak API does not allow filtering of the client scopes resource by name.
|
||||
As a result, this method first retrieves the entire list of client scopes - name and ID -
|
||||
then performs a second query to fetch the group.
|
||||
|
||||
If the clientscope does not exist, None is returned.
|
||||
:param cid: Id of the clientscope (not name).
|
||||
If the client scope does not exist, None is returned.
|
||||
:param cid: Id of the client scope (not name).
|
||||
:param name: Name of the protocolmapper to fetch.
|
||||
:param realm: Realm in which the clientscope resides; default 'master'
|
||||
:param realm: Realm in which the client scope resides; default 'master'
|
||||
"""
|
||||
try:
|
||||
all_protocolmappers = self.get_clientscope_protocolmappers(cid, realm=realm)
|
||||
all_protocolmappers = self.get_client_scope_protocolmappers(cid, realm=realm)
|
||||
|
||||
for protocolmapper in all_protocolmappers:
|
||||
if protocolmapper["name"] == name:
|
||||
return self.get_clientscope_protocolmapper_by_protocolmapperid(
|
||||
return self.get_client_scope_protocolmapper_by_protocolmapperid(
|
||||
protocolmapper["id"], cid, realm=realm
|
||||
)
|
||||
|
||||
@@ -1475,27 +1475,27 @@ class KeycloakAPI:
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg=f"Could not fetch protocolmapper {name} in realm {realm}: {e}")
|
||||
|
||||
def create_clientscope_protocolmapper(self, cid, mapper_rep, realm: str = "master"):
|
||||
"""Create a Keycloak clientscope protocolmapper.
|
||||
def create_client_scope_protocolmapper(self, cid, mapper_rep, realm: str = "master"):
|
||||
"""Create a Keycloak client scope protocolmapper.
|
||||
|
||||
:param cid: Id of the clientscope.
|
||||
:param cid: Id of the client scope.
|
||||
:param mapper_rep: a ProtocolMapperRepresentation of the protocolmapper to be created. Must contain at minimum the field name.
|
||||
:return: HTTPResponse object on success
|
||||
"""
|
||||
protocolmappers_url = URL_CLIENTSCOPE_PROTOCOLMAPPERS.format(url=self.baseurl, id=cid, realm=realm)
|
||||
protocolmappers_url = URL_CLIENT_SCOPE_PROTOCOLMAPPERS.format(url=self.baseurl, id=cid, realm=realm)
|
||||
try:
|
||||
return self._request(protocolmappers_url, method="POST", data=json.dumps(mapper_rep))
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not create protocolmapper {mapper_rep['name']} in realm {realm}: {e}")
|
||||
|
||||
def update_clientscope_protocolmappers(self, cid, mapper_rep, realm: str = "master"):
|
||||
"""Update an existing clientscope.
|
||||
def update_client_scope_protocolmappers(self, cid, mapper_rep, realm: str = "master"):
|
||||
"""Update an existing client scope.
|
||||
|
||||
:param cid: Id of the clientscope.
|
||||
:param cid: Id of the client scope.
|
||||
:param mapper_rep: A ProtocolMapperRepresentation of the updated protocolmapper.
|
||||
:return HTTPResponse object on success
|
||||
"""
|
||||
protocolmapper_url = URL_CLIENTSCOPE_PROTOCOLMAPPER.format(
|
||||
protocolmapper_url = URL_CLIENT_SCOPE_PROTOCOLMAPPER.format(
|
||||
url=self.baseurl, realm=realm, id=cid, mapper_id=mapper_rep["id"]
|
||||
)
|
||||
|
||||
@@ -1504,137 +1504,137 @@ class KeycloakAPI:
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e, msg=f"Could not update protocolmappers for clientscope {mapper_rep} in realm {realm}: {e}"
|
||||
e, msg=f"Could not update protocolmappers for client scope {mapper_rep} in realm {realm}: {e}"
|
||||
)
|
||||
|
||||
def get_default_clientscopes(self, realm, client_id=None):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
def get_default_client_scopes(self, realm, client_id=None):
|
||||
"""Fetch the name and ID of all client scopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the client scope, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the client scope you wish to return.
|
||||
get_client_scope_by_client_scope_id, passing in the ID of the client scope you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:return The default clientscopes of this realm or client
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
:return The default client scopes of this realm or client
|
||||
"""
|
||||
url = URL_DEFAULT_CLIENTSCOPES if client_id is None else URL_CLIENT_DEFAULT_CLIENTSCOPES
|
||||
return self._get_clientscopes_of_type(realm, url, "default", client_id)
|
||||
url = URL_DEFAULT_CLIENT_SCOPES if client_id is None else URL_CLIENT_DEFAULT_CLIENT_SCOPES
|
||||
return self._get_client_scopes_of_type(realm, url, "default", client_id)
|
||||
|
||||
def get_optional_clientscopes(self, realm, client_id=None):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
def get_optional_client_scopes(self, realm, client_id=None):
|
||||
"""Fetch the name and ID of all client scopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the client scope, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the client scope you wish to return.
|
||||
get_client_scope_by_client_scope_id, passing in the ID of the client scope you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:return The optional clientscopes of this realm or client
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
:return The optional client scopes of this realm or client
|
||||
"""
|
||||
url = URL_OPTIONAL_CLIENTSCOPES if client_id is None else URL_CLIENT_OPTIONAL_CLIENTSCOPES
|
||||
return self._get_clientscopes_of_type(realm, url, "optional", client_id)
|
||||
url = URL_OPTIONAL_CLIENT_SCOPES if client_id is None else URL_CLIENT_OPTIONAL_CLIENT_SCOPES
|
||||
return self._get_client_scopes_of_type(realm, url, "optional", client_id)
|
||||
|
||||
def _get_clientscopes_of_type(self, realm, url_template, scope_type, client_id=None):
|
||||
"""Fetch the name and ID of all clientscopes on the Keycloak server.
|
||||
def _get_client_scopes_of_type(self, realm, url_template, scope_type, client_id=None):
|
||||
"""Fetch the name and ID of all client scopes on the Keycloak server.
|
||||
|
||||
To fetch the full data of the client scope, make a subsequent call to
|
||||
get_clientscope_by_clientscopeid, passing in the ID of the client scope you wish to return.
|
||||
get_client_scope_by_client_scope_id, passing in the ID of the client scope you wish to return.
|
||||
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param url_template the template for the right type
|
||||
:param scope_type this can be either optional or default
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:return The clientscopes of the specified type of this realm
|
||||
:param client_id: The client in which the client scope resides.
|
||||
:return The client scopes of the specified type of this realm
|
||||
"""
|
||||
if client_id is None:
|
||||
clientscopes_url = url_template.format(url=self.baseurl, realm=realm)
|
||||
client_scopes_url = url_template.format(url=self.baseurl, realm=realm)
|
||||
try:
|
||||
return self._request_and_deserialize(clientscopes_url, method="GET")
|
||||
return self._request_and_deserialize(client_scopes_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not fetch list of {scope_type} clientscopes in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not fetch list of {scope_type} client scopes in realm {realm}: {e}")
|
||||
else:
|
||||
cid = self.get_client_id(client_id=client_id, realm=realm)
|
||||
clientscopes_url = url_template.format(url=self.baseurl, realm=realm, cid=cid)
|
||||
client_scopes_url = url_template.format(url=self.baseurl, realm=realm, cid=cid)
|
||||
try:
|
||||
return self._request_and_deserialize(clientscopes_url, method="GET")
|
||||
return self._request_and_deserialize(client_scopes_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e,
|
||||
msg=f"Could not fetch list of {scope_type} clientscopes in client {client_id}: {clientscopes_url}",
|
||||
msg=f"Could not fetch list of {scope_type} client scopes in client {client_id}: {client_scopes_url}",
|
||||
)
|
||||
|
||||
def _decide_url_type_clientscope(self, client_id=None, scope_type="default"):
|
||||
def _decide_url_type_client_scope(self, client_id=None, scope_type="default"):
|
||||
"""Decides which url to use.
|
||||
:param scope_type this can be either optional or default
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
"""
|
||||
if client_id is None:
|
||||
if scope_type == "default":
|
||||
return URL_DEFAULT_CLIENTSCOPE
|
||||
return URL_DEFAULT_CLIENT_SCOPE
|
||||
if scope_type == "optional":
|
||||
return URL_OPTIONAL_CLIENTSCOPE
|
||||
return URL_OPTIONAL_CLIENT_SCOPE
|
||||
else:
|
||||
if scope_type == "default":
|
||||
return URL_CLIENT_DEFAULT_CLIENTSCOPE
|
||||
return URL_CLIENT_DEFAULT_CLIENT_SCOPE
|
||||
if scope_type == "optional":
|
||||
return URL_CLIENT_OPTIONAL_CLIENTSCOPE
|
||||
return URL_CLIENT_OPTIONAL_CLIENT_SCOPE
|
||||
|
||||
def add_default_clientscope(self, id, realm: str = "master", client_id=None):
|
||||
def add_default_client_scope(self, id, realm: str = "master", client_id=None):
|
||||
"""Add a client scope as default either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "default", realm, "add")
|
||||
self._action_type_client_scope(id, client_id, "default", realm, "add")
|
||||
|
||||
def add_optional_clientscope(self, id, realm: str = "master", client_id=None):
|
||||
def add_optional_client_scope(self, id, realm: str = "master", client_id=None):
|
||||
"""Add a client scope as optional either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "optional", realm, "add")
|
||||
self._action_type_client_scope(id, client_id, "optional", realm, "add")
|
||||
|
||||
def delete_default_clientscope(self, id, realm: str = "master", client_id=None):
|
||||
def delete_default_client_scope(self, id, realm: str = "master", client_id=None):
|
||||
"""Remove a client scope as default either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "default", realm, "delete")
|
||||
self._action_type_client_scope(id, client_id, "default", realm, "delete")
|
||||
|
||||
def delete_optional_clientscope(self, id, realm: str = "master", client_id=None):
|
||||
def delete_optional_client_scope(self, id, realm: str = "master", client_id=None):
|
||||
"""Remove a client scope as optional either on realm or client level.
|
||||
|
||||
:param id: Client scope Id.
|
||||
:param realm: Realm in which the clientscope resides.
|
||||
:param client_id: The client in which the clientscope resides.
|
||||
:param realm: Realm in which the client scope resides.
|
||||
:param client_id: The client in which the client scope resides.
|
||||
"""
|
||||
self._action_type_clientscope(id, client_id, "optional", realm, "delete")
|
||||
self._action_type_client_scope(id, client_id, "optional", realm, "delete")
|
||||
|
||||
def _action_type_clientscope(
|
||||
def _action_type_client_scope(
|
||||
self, id=None, client_id=None, scope_type="default", realm: str = "master", action="add"
|
||||
):
|
||||
"""Delete or add a clientscope of type.
|
||||
:param name: The name of the clientscope. A lookup will be performed to retrieve the clientscope ID.
|
||||
:param client_id: The ID of the clientscope (preferred to name).
|
||||
"""Delete or add a client scope of type.
|
||||
:param name: The name of the client scope. A lookup will be performed to retrieve the client scope ID.
|
||||
:param client_id: The ID of the client scope (preferred to name).
|
||||
:param scope_type 'default' or 'optional'
|
||||
:param realm: The realm in which this group resides, default "master".
|
||||
"""
|
||||
cid = None if client_id is None else self.get_client_id(client_id=client_id, realm=realm)
|
||||
# should have a good cid by here.
|
||||
clientscope_type_url = self._decide_url_type_clientscope(client_id, scope_type).format(
|
||||
client_scope_type_url = self._decide_url_type_client_scope(client_id, scope_type).format(
|
||||
realm=realm, id=id, cid=cid, url=self.baseurl
|
||||
)
|
||||
try:
|
||||
method = "PUT" if action == "add" else "DELETE"
|
||||
return self._request(clientscope_type_url, method=method)
|
||||
return self._request(client_scope_type_url, method=method)
|
||||
|
||||
except Exception as e:
|
||||
place = "realm" if client_id is None else f"client {client_id}"
|
||||
self.fail_request(e, msg=f"Unable to {action} {scope_type} clientscope {id} @ {place} : {e}")
|
||||
self.fail_request(e, msg=f"Unable to {action} {scope_type} client scope {id} @ {place} : {e}")
|
||||
|
||||
def create_clientsecret(self, id, realm: str = "master"):
|
||||
"""Generate a new client secret by id
|
||||
@@ -2020,7 +2020,7 @@ class KeycloakAPI:
|
||||
composite_url = ""
|
||||
try:
|
||||
if clientid is not None:
|
||||
client = self.get_client_by_clientid(client_id=clientid, realm=realm)
|
||||
client = self.get_client_by_client_id(client_id=clientid, realm=realm)
|
||||
cid = client["id"]
|
||||
composite_url = URL_CLIENT_ROLE_COMPOSITES.format(
|
||||
url=self.baseurl, realm=realm, id=cid, name=quote(rolerep["name"], safe="")
|
||||
@@ -2038,7 +2038,7 @@ class KeycloakAPI:
|
||||
composite_url = ""
|
||||
try:
|
||||
if clientid is not None:
|
||||
client = self.get_client_by_clientid(client_id=clientid, realm=realm)
|
||||
client = self.get_client_by_client_id(client_id=clientid, realm=realm)
|
||||
cid = client["id"]
|
||||
composite_url = URL_CLIENT_ROLE_COMPOSITES.format(
|
||||
url=self.baseurl, realm=realm, id=cid, name=quote(rolerep["name"], safe="")
|
||||
@@ -2057,7 +2057,7 @@ class KeycloakAPI:
|
||||
composite_url = ""
|
||||
try:
|
||||
if clientid is not None:
|
||||
client = self.get_client_by_clientid(client_id=clientid, realm=realm)
|
||||
client = self.get_client_by_client_id(client_id=clientid, realm=realm)
|
||||
cid = client["id"]
|
||||
composite_url = URL_CLIENT_ROLE_COMPOSITES.format(
|
||||
url=self.baseurl, realm=realm, id=cid, name=quote(rolerep["name"], safe="")
|
||||
@@ -3259,192 +3259,192 @@ class KeycloakAPI:
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def get_all_clientscope_scope_mappings(self, clientscope_id, realm: str = "master"):
|
||||
"""Fetch all (realm and client) roles (scope-mappings) associated with the clientscope for a specific clientscope on the Keycloak server.
|
||||
:param clientscope_id: ID of the clientscope from which to obtain the associated roles.
|
||||
def get_all_client_scope_scope_mappings(self, client_scope_id, realm: str = "master"):
|
||||
"""Fetch all (realm and client) roles (scope-mappings) associated with the client scope for a specific client scope on the Keycloak server.
|
||||
:param client_scope_id: ID of the client scope from which to obtain the associated roles.
|
||||
:param realm: Realm from which to obtain the scope.
|
||||
:return: The clientscope scope-mappings.
|
||||
:return: The client scope scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS.format(url=self.baseurl, realm=realm, id=clientscope_id)
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS.format(url=self.baseurl, realm=realm, id=client_scope_id)
|
||||
try:
|
||||
return self._request_and_deserialize(client_role_scope_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not fetch roles for client-scope {clientscope_id} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not fetch roles for client scope {client_scope_id} in realm {realm}: {e}")
|
||||
|
||||
def get_clientscope_scope_mappings_realm(self, clientscope_id, realm: str = "master"):
|
||||
"""Fetch the realm roles (scope-mappings) associated with the clientscope for a specific clientscope on the Keycloak server.
|
||||
:param clientscope_id: ID of the clientscope from which to obtain the associated roles.
|
||||
def get_client_scope_scope_mappings_realm(self, client_scope_id, realm: str = "master"):
|
||||
"""Fetch the realm roles (scope-mappings) associated with the client scope for a specific client scope on the Keycloak server.
|
||||
:param client_scope_id: ID of the client scope from which to obtain the associated roles.
|
||||
:param realm: Realm from which to obtain the scope.
|
||||
:return: The clientscope realm scope-mappings.
|
||||
:return: The client scope realm scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS_REALM.format(
|
||||
url=self.baseurl, realm=realm, id=clientscope_id
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS_REALM.format(
|
||||
url=self.baseurl, realm=realm, id=client_scope_id
|
||||
)
|
||||
try:
|
||||
return self._request_and_deserialize(client_role_scope_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e, msg=f"Could not fetch realm roles for client-scope {clientscope_id} in realm {realm}: {e}"
|
||||
e, msg=f"Could not fetch realm roles for client scope {client_scope_id} in realm {realm}: {e}"
|
||||
)
|
||||
|
||||
def get_clientscope_scope_mappings_client(self, clientscope_id, client_id, realm: str = "master"):
|
||||
"""Fetch the client roles (scope-mappings) associated with the clientscope for a specific clientscope and client on the Keycloak server.
|
||||
:param clientscope_id: ID of the clientscope from which to obtain the associated roles.
|
||||
def get_client_scope_scope_mappings_client(self, client_scope_id, client_id, realm: str = "master"):
|
||||
"""Fetch the client roles (scope-mappings) associated with the client scope for a specific client scope and client on the Keycloak server.
|
||||
:param client_scope_id: ID of the client scope from which to obtain the associated roles.
|
||||
:param clientid: ID of the client from which to obtain the associated roles.
|
||||
:param realm: Realm from which to obtain the scope.
|
||||
:return: The clientscope client scope-mappings.
|
||||
:return: The client scope client scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS_CLIENT.format(
|
||||
url=self.baseurl, realm=realm, id=clientscope_id, client=client_id
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS_CLIENT.format(
|
||||
url=self.baseurl, realm=realm, id=client_scope_id, client=client_id
|
||||
)
|
||||
try:
|
||||
return self._request_and_deserialize(client_role_scope_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e,
|
||||
msg=f"Could not fetch client roles from client {client_id} for client-scope {clientscope_id} in realm {realm}: {e}",
|
||||
msg=f"Could not fetch client roles from client {client_id} for client scope {client_scope_id} in realm {realm}: {e}",
|
||||
)
|
||||
|
||||
def get_client_role_scope_from_client(self, clientid, clientscopeid, realm: str = "master"):
|
||||
def get_client_role_scope_from_client(self, target_client_id, role_owner_client_id, realm: str = "master"):
|
||||
"""Fetch the roles associated with the client's scope for a specific client on the Keycloak server.
|
||||
:param clientid: ID of the client from which to obtain the associated roles.
|
||||
:param clientscopeid: ID of the client who owns the roles.
|
||||
:param target_client_id: ID of the client from which to obtain the associated roles.
|
||||
:param role_owner_client_id: ID of the client who owns the roles.
|
||||
:param realm: Realm from which to obtain the scope.
|
||||
:return: The client scope of roles from specified client.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENT_ROLE_SCOPE_CLIENTS.format(
|
||||
url=self.baseurl, realm=realm, id=clientid, scopeid=clientscopeid
|
||||
url=self.baseurl, realm=realm, id=target_client_id, scopeid=role_owner_client_id
|
||||
)
|
||||
try:
|
||||
return self._request_and_deserialize(client_role_scope_url, method="GET")
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not fetch roles scope for client {clientid} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not fetch roles scope for client {target_client_id} in realm {realm}: {e}")
|
||||
|
||||
def update_client_role_scope_from_client(self, payload, clientid, clientscopeid, realm: str = "master"):
|
||||
def update_client_role_scope_from_client(self, roles, target_client_id, role_owner_client_id, realm: str = "master"):
|
||||
"""Update and fetch the roles associated with the client's scope on the Keycloak server.
|
||||
:param payload: List of roles to be added to the scope.
|
||||
:param clientid: ID of the client to update scope.
|
||||
:param clientscopeid: ID of the client who owns the roles.
|
||||
:param roles: List of roles to be added to the scope.
|
||||
:param target_client_id: ID of the client to update scope.
|
||||
:param role_owner_client_id: ID of the client who owns the roles.
|
||||
:param realm: Realm from which to obtain the clients.
|
||||
:return: The client scope of roles from specified client.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENT_ROLE_SCOPE_CLIENTS.format(
|
||||
url=self.baseurl, realm=realm, id=clientid, scopeid=clientscopeid
|
||||
url=self.baseurl, realm=realm, id=target_client_id, scopeid=role_owner_client_id
|
||||
)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not update roles scope for client {clientid} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not update roles scope for client {target_client_id} in realm {realm}: {e}")
|
||||
|
||||
return self.get_client_role_scope_from_client(clientid, clientscopeid, realm)
|
||||
return self.get_client_role_scope_from_client(target_client_id, role_owner_client_id, realm)
|
||||
|
||||
def delete_client_role_scope_from_client(self, payload, clientid, clientscopeid, realm: str = "master"):
|
||||
"""Delete the roles contains in the payload from the client's scope on the Keycloak server.
|
||||
:param payload: List of roles to be deleted.
|
||||
:param clientid: ID of the client to delete roles from scope.
|
||||
:param clientscopeid: ID of the client who owns the roles.
|
||||
def delete_client_role_scope_from_client(self, roles, target_client_id, role_owner_client_id, realm: str = "master"):
|
||||
"""Delete the roles from the client's scope on the Keycloak server.
|
||||
:param roles: List of roles to be deleted.
|
||||
:param target_client_id: ID of the client to delete roles from scope.
|
||||
:param role_owner_client_id: ID of the client who owns the roles.
|
||||
:param realm: Realm from which to obtain the clients.
|
||||
:return: The client scope of roles from specified client.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENT_ROLE_SCOPE_CLIENTS.format(
|
||||
url=self.baseurl, realm=realm, id=clientid, scopeid=clientscopeid
|
||||
url=self.baseurl, realm=realm, id=target_client_id, scopeid=role_owner_client_id
|
||||
)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not delete roles scope for client {clientid} in realm {realm}: {e}")
|
||||
self.fail_request(e, msg=f"Could not delete roles from scope for client {target_client_id} in realm {realm}: {e}")
|
||||
|
||||
return self.get_client_role_scope_from_client(clientid, clientscopeid, realm)
|
||||
return self.get_client_role_scope_from_client(target_client_id, role_owner_client_id, realm)
|
||||
|
||||
def update_clientscope_scope_mappings_client(
|
||||
self, payload: list[dict], clientscope_id: str, client_id: str, realm: str = "master"
|
||||
def update_client_scope_scope_mappings_client(
|
||||
self, roles: list[dict], client_scope_id: str, role_owner_client_id: str, realm: str = "master"
|
||||
):
|
||||
"""Update and fetch the client roles (scope-mappings) associated with the clientscope on the Keycloak server.
|
||||
:param payload: List of client roles to be added to the scope.
|
||||
:param clientscope_id: ID of the clientscope to update scope-mappings.
|
||||
:param clientid: ID of the client from which to obtain the associated roles.
|
||||
"""Update and fetch the client roles (scope-mappings) associated with the client scope on the Keycloak server.
|
||||
:param roles: List of client roles to be added to the scope.
|
||||
:param client_scope_id: ID of the client scope to update scope-mappings.
|
||||
:param role_owner_client_id: ID of the client from which to obtain the associated roles.
|
||||
:param realm: Realm from which to obtain the client.
|
||||
:return: The clientscope client scope-mappings.
|
||||
:return: The client scope client scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS_CLIENT.format(
|
||||
url=self.baseurl, realm=realm, id=clientscope_id, client=client_id
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS_CLIENT.format(
|
||||
url=self.baseurl, realm=realm, id=client_scope_id, client=role_owner_client_id
|
||||
)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e,
|
||||
msg=f"Could not update scope mappings for client-scope {client_id}.{clientscope_id} in realm {realm}: {e}",
|
||||
msg=f"Could not update scope mappings for client scope {role_owner_client_id}.{client_scope_id} in realm {realm}: {e}",
|
||||
)
|
||||
|
||||
return self.get_clientscope_scope_mappings_client(clientscope_id, client_id, realm)
|
||||
return self.get_client_scope_scope_mappings_client(client_scope_id, role_owner_client_id, realm)
|
||||
|
||||
def update_clientscope_scope_mappings_realm(self, payload: list[dict], clientscope_id: str, realm: str = "master"):
|
||||
"""Update and fetch the realm roles (scope-mappings) associated with the clientscope on the Keycloak server.
|
||||
:param payload: List of realm roles to be added to the scope.
|
||||
:param clientscope_id: ID of the clientscope to update scope-mappings.
|
||||
def update_client_scope_scope_mappings_realm(self, roles: list[dict], client_scope_id: str, realm: str = "master"):
|
||||
"""Update and fetch the realm roles (scope-mappings) associated with the client scope on the Keycloak server.
|
||||
:param roles: List of realm roles to be added to the scope.
|
||||
:param client_scope_id: ID of the client scope to update scope-mappings.
|
||||
:param realm: Realm from which to obtain the roles.
|
||||
:return: The clientscope realm scope-mappings.
|
||||
:return: The client scope realm scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS_REALM.format(
|
||||
url=self.baseurl, realm=realm, id=clientscope_id
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS_REALM.format(
|
||||
url=self.baseurl, realm=realm, id=client_scope_id
|
||||
)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e, msg=f"Could not update scope mappings for client-scope {clientscope_id} in realm {realm}: {e}"
|
||||
e, msg=f"Could not update scope mappings for client scope {client_scope_id} in realm {realm}: {e}"
|
||||
)
|
||||
|
||||
return self.get_clientscope_scope_mappings_realm(clientscope_id, realm)
|
||||
return self.get_client_scope_scope_mappings_realm(client_scope_id, realm)
|
||||
|
||||
def delete_clientscope_scope_mappings_client(
|
||||
self, payload: list[dict], clientscope_id: str, client_id: str, realm: str = "master"
|
||||
def delete_client_scope_scope_mappings_client(
|
||||
self, roles: list[dict], client_scope_id: str, role_owner_client_id: str, realm: str = "master"
|
||||
):
|
||||
"""Delete the client roles (scope_mappings) contained in the payload from the clientscope on the Keycloak server.
|
||||
:param payload: List of roles to be deleted.
|
||||
:param clientscope_id: ID of the clientscope to delete roles from scope-mappings.
|
||||
:param clientid: ID of the client who owns the roles.
|
||||
"""Delete the client roles (scope_mappings) from the client scope on the Keycloak server.
|
||||
:param roles: List of roles to be deleted.
|
||||
:param client_scope_id: ID of the client scope to delete roles from scope-mappings.
|
||||
:param role_owner_client_id: ID of the client who owns the roles.
|
||||
:param realm: Realm from which to obtain the client.
|
||||
:return: The clientscope client scope-mappings.
|
||||
:return: The client scope client scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS_CLIENT.format(
|
||||
url=self.baseurl, realm=realm, id=clientscope_id, client=client_id
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS_CLIENT.format(
|
||||
url=self.baseurl, realm=realm, id=client_scope_id, client=role_owner_client_id
|
||||
)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e,
|
||||
msg=f"Could not delete scope mappings for client-scope {client_id}.{clientscope_id} in realm {realm}: {e}",
|
||||
msg=f"Could not delete scope mappings for client scope {role_owner_client_id}.{client_scope_id} in realm {realm}: {e}",
|
||||
)
|
||||
|
||||
return self.get_clientscope_scope_mappings_client(clientscope_id, client_id, realm)
|
||||
return self.get_client_scope_scope_mappings_client(client_scope_id, role_owner_client_id, realm)
|
||||
|
||||
def delete_clientscope_scope_mappings_realm(self, payload: list[dict], clientscope_id: str, realm: str = "master"):
|
||||
"""Delete the realm roles (scope_mappings) contained in the payload from the clientscope on the Keycloak server.
|
||||
:param payload: List of roles to be deleted.
|
||||
:param clientscope_id: ID of the clientscope to delete roles from scope-mappings.
|
||||
def delete_client_scope_scope_mappings_realm(self, roles: list[dict], client_scope_id: str, realm: str = "master"):
|
||||
"""Delete the realm roles (scope_mappings) contained in the roles from the client scope on the Keycloak server.
|
||||
:param roles: List of roles to be deleted.
|
||||
:param client_scope_id: ID of the client scope to delete roles from scope-mappings.
|
||||
:param realm: Realm from which to obtain the roles.
|
||||
:return: The clientscope realm scope-mappings.
|
||||
:return: The client scope realm scope-mappings.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENTSCOPE_SCOPE_MAPPINGS_REALM.format(
|
||||
url=self.baseurl, realm=realm, id=clientscope_id
|
||||
client_role_scope_url = URL_CLIENT_SCOPE_SCOPE_MAPPINGS_REALM.format(
|
||||
url=self.baseurl, realm=realm, id=client_scope_id
|
||||
)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(
|
||||
e, msg=f"Could not delete scope mappings for client-scope {clientscope_id} in realm {realm}: {e}"
|
||||
e, msg=f"Could not delete scope mappings for client scope {client_scope_id} in realm {realm}: {e}"
|
||||
)
|
||||
|
||||
return self.get_clientscope_scope_mappings_realm(clientscope_id, realm)
|
||||
return self.get_client_scope_scope_mappings_realm(client_scope_id, realm)
|
||||
|
||||
def get_client_role_scope_from_realm(self, clientid, realm: str = "master"):
|
||||
"""Fetch the realm roles from the client's scope on the Keycloak server.
|
||||
@@ -3458,32 +3458,32 @@ class KeycloakAPI:
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not fetch roles scope for client {clientid} in realm {realm}: {e}")
|
||||
|
||||
def update_client_role_scope_from_realm(self, payload, clientid, realm: str = "master"):
|
||||
def update_client_role_scope_from_realm(self, roles, clientid, realm: str = "master"):
|
||||
"""Update and fetch the realm roles from the client's scope on the Keycloak server.
|
||||
:param payload: List of realm roles to add.
|
||||
:param roles: List of realm roles to add.
|
||||
:param clientid: ID of the client to update scope.
|
||||
:param realm: Realm from which to obtain the clients.
|
||||
:return: The client realm roles scope.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENT_ROLE_SCOPE_REALM.format(url=self.baseurl, realm=realm, id=clientid)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="POST", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not update roles scope for client {clientid} in realm {realm}: {e}")
|
||||
|
||||
return self.get_client_role_scope_from_realm(clientid, realm)
|
||||
|
||||
def delete_client_role_scope_from_realm(self, payload, clientid, realm: str = "master"):
|
||||
"""Delete the realm roles contains in the payload from the client's scope on the Keycloak server.
|
||||
:param payload: List of realm roles to delete.
|
||||
def delete_client_role_scope_from_realm(self, roles, clientid, realm: str = "master"):
|
||||
"""Delete the realm roles from the client's scope on the Keycloak server.
|
||||
:param roles: List of realm roles to delete.
|
||||
:param clientid: ID of the client to delete roles from scope.
|
||||
:param realm: Realm from which to obtain the clients.
|
||||
:return: The client realm roles scope.
|
||||
"""
|
||||
client_role_scope_url = URL_CLIENT_ROLE_SCOPE_REALM.format(url=self.baseurl, realm=realm, id=clientid)
|
||||
try:
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(payload))
|
||||
self._request(client_role_scope_url, method="DELETE", data=json.dumps(roles))
|
||||
|
||||
except Exception as e:
|
||||
self.fail_request(e, msg=f"Could not delete roles scope for client {clientid} in realm {realm}: {e}")
|
||||
|
||||
@@ -66,7 +66,7 @@ def keycloak_clientsecret_module_resolve_params(module: AnsibleModule, kc: Keycl
|
||||
# less lookup.
|
||||
if id is None:
|
||||
# Due to the required_one_of spec, client_id is guaranteed to not be None
|
||||
client = kc.get_client_by_clientid(client_id, realm=realm)
|
||||
client = kc.get_client_by_client_id(client_id, realm=realm)
|
||||
|
||||
if client is None:
|
||||
module.fail_json(msg=f"Client does not exist {client_id}")
|
||||
|
||||
@@ -1100,11 +1100,11 @@ def add_default_client_scopes(desired_client, before_client, realm, kc):
|
||||
missing_scopes = [item for item in desired_default_scope if item not in before_client["defaultClientScopes"]]
|
||||
if not missing_scopes:
|
||||
return
|
||||
client_scopes = kc.get_clientscopes(realm)
|
||||
client_scopes = kc.get_client_scopes(realm)
|
||||
for name in missing_scopes:
|
||||
scope = find_match(client_scopes, "name", name)
|
||||
if scope:
|
||||
kc.add_default_clientscope(scope["id"], realm, desired_client["clientId"])
|
||||
kc.add_default_client_scope(scope["id"], realm, desired_client["clientId"])
|
||||
|
||||
|
||||
def add_optional_client_scopes(desired_client, before_client, realm, kc):
|
||||
@@ -1139,11 +1139,11 @@ def add_optional_client_scopes(desired_client, before_client, realm, kc):
|
||||
missing_scopes = [item for item in desired_optional_scope if item not in before_client["optionalClientScopes"]]
|
||||
if not missing_scopes:
|
||||
return
|
||||
client_scopes = kc.get_clientscopes(realm)
|
||||
client_scopes = kc.get_client_scopes(realm)
|
||||
for name in missing_scopes:
|
||||
scope = find_match(client_scopes, "name", name)
|
||||
if scope:
|
||||
kc.add_optional_clientscope(scope["id"], realm, desired_client["clientId"])
|
||||
kc.add_optional_client_scope(scope["id"], realm, desired_client["clientId"])
|
||||
|
||||
|
||||
def remove_default_client_scopes(desired_client, before_client, realm, kc):
|
||||
@@ -1178,11 +1178,11 @@ def remove_default_client_scopes(desired_client, before_client, realm, kc):
|
||||
missing_scopes = [item for item in before_default_scope if item not in desired_client["defaultClientScopes"]]
|
||||
if not missing_scopes:
|
||||
return
|
||||
client_scopes = kc.get_default_clientscopes(realm, desired_client["clientId"])
|
||||
client_scopes = kc.get_default_client_scopes(realm, desired_client["clientId"])
|
||||
for name in missing_scopes:
|
||||
scope = find_match(client_scopes, "name", name)
|
||||
if scope:
|
||||
kc.delete_default_clientscope(scope["id"], realm, desired_client["clientId"])
|
||||
kc.delete_default_client_scope(scope["id"], realm, desired_client["clientId"])
|
||||
|
||||
|
||||
def remove_optional_client_scopes(desired_client, before_client, realm, kc):
|
||||
@@ -1217,11 +1217,11 @@ def remove_optional_client_scopes(desired_client, before_client, realm, kc):
|
||||
missing_scopes = [item for item in before_optional_scope if item not in desired_client["optionalClientScopes"]]
|
||||
if not missing_scopes:
|
||||
return
|
||||
client_scopes = kc.get_optional_clientscopes(realm, desired_client["clientId"])
|
||||
client_scopes = kc.get_optional_client_scopes(realm, desired_client["clientId"])
|
||||
for name in missing_scopes:
|
||||
scope = find_match(client_scopes, "name", name)
|
||||
if scope:
|
||||
kc.delete_optional_clientscope(scope["id"], realm, desired_client["clientId"])
|
||||
kc.delete_optional_client_scope(scope["id"], realm, desired_client["clientId"])
|
||||
|
||||
|
||||
def main():
|
||||
@@ -1346,7 +1346,7 @@ def main():
|
||||
|
||||
# See if it already exists in Keycloak
|
||||
if cid is None:
|
||||
before_client = kc.get_client_by_clientid(module.params.get("client_id"), realm=realm)
|
||||
before_client = kc.get_client_by_client_id(module.params.get("client_id"), realm=realm)
|
||||
if before_client is not None:
|
||||
cid = before_client["id"]
|
||||
else:
|
||||
@@ -1440,7 +1440,7 @@ def main():
|
||||
|
||||
# create it
|
||||
kc.create_client(desired_client, realm=realm)
|
||||
after_client = kc.get_client_by_clientid(desired_client["clientId"], realm=realm)
|
||||
after_client = kc.get_client_by_client_id(desired_client["clientId"], realm=realm)
|
||||
|
||||
result["end_state"] = sanitize_cr(after_client)
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ description:
|
||||
to the REST API using OpenID Connect; the user connecting and the client being used must have the requisite access rights.
|
||||
In a default Keycloak installation, admin-cli and an admin user would work, as would a separate client definition with
|
||||
the scope tailored to your needs and a user having the expected roles.
|
||||
- Client O(client_id) must have O(middleware_automation.keycloak.keycloak_client#module:full_scope_allowed) set to V(false).
|
||||
- Client O(target_client_id) must have O(middleware_automation.keycloak.keycloak_client#module:full_scope_allowed) set to V(false).
|
||||
- Attributes are multi-valued in the Keycloak API. All attributes are lists of individual values and are returned that way
|
||||
by this module. You may pass single values for attributes when calling the module, and this is translated into a list
|
||||
suitable for the API.
|
||||
@@ -50,12 +50,12 @@ options:
|
||||
- The Keycloak realm under which clients resides.
|
||||
default: 'master'
|
||||
|
||||
client_id:
|
||||
target_client_id:
|
||||
type: str
|
||||
required: true
|
||||
description:
|
||||
- Roles provided in O(role_names) while be added to this client scope.
|
||||
client_scope_id:
|
||||
role_owner_client_id:
|
||||
type: str
|
||||
description:
|
||||
- If the O(role_names) are client role, the client ID under which it resides.
|
||||
@@ -66,8 +66,8 @@ options:
|
||||
elements: str
|
||||
description:
|
||||
- Names of roles to manipulate.
|
||||
- If O(client_scope_id) is present, all roles must be under this client.
|
||||
- If O(client_scope_id) is absent, all roles must be under the realm.
|
||||
- If O(role_owner_client_id) is present, all roles must be under this client.
|
||||
- If O(role_owner_client_id) is absent, all roles must be under the realm.
|
||||
extends_documentation_fragment:
|
||||
- middleware_automation.keycloak.keycloak
|
||||
- middleware_automation.keycloak.actiongroup_keycloak
|
||||
@@ -85,8 +85,8 @@ EXAMPLES = r"""
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: MyCustomRealm
|
||||
client_id: frontend-client-public
|
||||
client_scope_id: backend-client-private
|
||||
target_client_id: frontend-client-public
|
||||
role_owner_client_id: backend-client-private
|
||||
role_names:
|
||||
- backend-role-admin
|
||||
- backend-role-user
|
||||
@@ -98,8 +98,8 @@ EXAMPLES = r"""
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: MyCustomRealm
|
||||
client_id: frontend-client-public
|
||||
client_scope_id: backend-client-private
|
||||
target_client_id: frontend-client-public
|
||||
role_owner_client_id: backend-client-private
|
||||
role_names:
|
||||
- backend-role-admin
|
||||
state: absent
|
||||
@@ -111,7 +111,7 @@ EXAMPLES = r"""
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: MyCustomRealm
|
||||
client_id: frontend-client-public
|
||||
target_client_id: frontend-client-public
|
||||
role_names:
|
||||
- realm-role-admin
|
||||
- realm-role-user
|
||||
@@ -167,8 +167,8 @@ def main():
|
||||
argument_spec = keycloak_argument_spec()
|
||||
|
||||
meta_args = dict(
|
||||
client_id=dict(type="str", required=True),
|
||||
client_scope_id=dict(type="str"),
|
||||
target_client_id=dict(type="str", required=True),
|
||||
role_owner_client_id=dict(type="str"),
|
||||
realm=dict(type="str", default="master"),
|
||||
role_names=dict(type="list", elements="str", required=True),
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
@@ -189,8 +189,8 @@ def main():
|
||||
kc = KeycloakAPI(module, connection_header)
|
||||
|
||||
realm = module.params.get("realm")
|
||||
clientid = module.params.get("client_id")
|
||||
client_scope_id = module.params.get("client_scope_id")
|
||||
target_client_id = module.params.get("target_client_id")
|
||||
role_owner_client_id = module.params.get("role_owner_client_id")
|
||||
role_names = module.params.get("role_names")
|
||||
state = module.params.get("state")
|
||||
|
||||
@@ -198,23 +198,23 @@ def main():
|
||||
if not objRealm:
|
||||
module.fail_json(msg=f"Failed to retrive realm '{realm}'")
|
||||
|
||||
objClient = kc.get_client_by_clientid(clientid, realm)
|
||||
objClient = kc.get_client_by_client_id(target_client_id, realm)
|
||||
if not objClient:
|
||||
module.fail_json(msg=f"Failed to retrive client '{realm}.{clientid}'")
|
||||
module.fail_json(msg=f"Failed to retrive client '{realm}.{target_client_id}'")
|
||||
if objClient["fullScopeAllowed"] and state == "present":
|
||||
module.fail_json(msg=f"FullScopeAllowed is active for Client '{realm}.{clientid}'")
|
||||
module.fail_json(msg=f"FullScopeAllowed is active for Client '{realm}.{target_client_id}'")
|
||||
|
||||
if client_scope_id:
|
||||
objClientScope = kc.get_client_by_clientid(client_scope_id, realm)
|
||||
if not objClientScope:
|
||||
module.fail_json(msg=f"Failed to retrive client '{realm}.{client_scope_id}'")
|
||||
before_role_mapping = kc.get_client_role_scope_from_client(objClient["id"], objClientScope["id"], realm)
|
||||
if role_owner_client_id:
|
||||
role_owner_client = kc.get_client_by_client_id(role_owner_client_id, realm)
|
||||
if not role_owner_client:
|
||||
module.fail_json(msg=f"Failed to retrive client '{realm}.{role_owner_client_id}'")
|
||||
before_role_mapping = kc.get_client_role_scope_from_client(objClient["id"], role_owner_client["id"], realm)
|
||||
else:
|
||||
before_role_mapping = kc.get_client_role_scope_from_realm(objClient["id"], realm)
|
||||
|
||||
if client_scope_id:
|
||||
if role_owner_client_id:
|
||||
# retrive all role from client_scope
|
||||
client_scope_roles_by_name = kc.get_client_roles_by_id(objClientScope["id"], realm)
|
||||
client_scope_roles_by_name = kc.get_client_roles_by_id(role_owner_client["id"], realm)
|
||||
else:
|
||||
# retrive all role from realm
|
||||
client_scope_roles_by_name = kc.get_realm_roles(realm)
|
||||
@@ -228,8 +228,8 @@ def main():
|
||||
# update desired
|
||||
for role_name in role_names:
|
||||
if role_name not in client_scope_roles_by_name:
|
||||
if client_scope_id:
|
||||
module.fail_json(msg=f"Failed to retrive role '{realm}.{client_scope_id}.{role_name}'")
|
||||
if role_owner_client_id:
|
||||
module.fail_json(msg=f"Failed to retrive role '{realm}.{role_owner_client_id}.{role_name}'")
|
||||
else:
|
||||
module.fail_json(msg=f"Failed to retrive role '{realm}.{role_name}'")
|
||||
if role_name not in role_mapping_by_name:
|
||||
@@ -253,33 +253,33 @@ def main():
|
||||
if not result["changed"]:
|
||||
# no changes
|
||||
result["end_state"] = before_role_mapping
|
||||
result["msg"] = f"No changes required for client role scope {clientid}."
|
||||
result["msg"] = f"No changes required for client role scope {target_client_id}."
|
||||
elif state == "present":
|
||||
# doing update
|
||||
if module.check_mode:
|
||||
result["end_state"] = desired_role_mapping
|
||||
elif client_scope_id:
|
||||
elif role_owner_client_id:
|
||||
result["end_state"] = kc.update_client_role_scope_from_client(
|
||||
role_mapping_to_manipulate, objClient["id"], objClientScope["id"], realm
|
||||
role_mapping_to_manipulate, objClient["id"], role_owner_client["id"], realm
|
||||
)
|
||||
else:
|
||||
result["end_state"] = kc.update_client_role_scope_from_realm(
|
||||
role_mapping_to_manipulate, objClient["id"], realm
|
||||
)
|
||||
result["msg"] = f"Client role scope for {clientid} has been updated"
|
||||
result["msg"] = f"Client role scope for {target_client_id} has been updated"
|
||||
else:
|
||||
# doing delete
|
||||
if module.check_mode:
|
||||
result["end_state"] = desired_role_mapping
|
||||
elif client_scope_id:
|
||||
elif role_owner_client_id:
|
||||
result["end_state"] = kc.delete_client_role_scope_from_client(
|
||||
role_mapping_to_manipulate, objClient["id"], objClientScope["id"], realm
|
||||
role_mapping_to_manipulate, objClient["id"], role_owner_client["id"], realm
|
||||
)
|
||||
else:
|
||||
result["end_state"] = kc.delete_client_role_scope_from_realm(
|
||||
role_mapping_to_manipulate, objClient["id"], realm
|
||||
)
|
||||
result["msg"] = f"Client role scope for {clientid} has been deleted"
|
||||
result["msg"] = f"Client role scope for {target_client_id} has been deleted"
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ def main():
|
||||
attributes = module.params.get('attributes')
|
||||
protocol_mappers = module.params.get('protocol_mappers')
|
||||
|
||||
before_scope = kc.get_clientscope_by_name(name, realm=realm)
|
||||
before_scope = kc.get_client_scope_by_name(name, realm=realm)
|
||||
|
||||
if state == 'absent':
|
||||
if before_scope:
|
||||
@@ -239,7 +239,7 @@ def main():
|
||||
result['diff'] = dict(before=before_scope, after='')
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
kc.delete_clientscope(cid=before_scope['id'], realm=realm)
|
||||
kc.delete_client_scope(cid=before_scope['id'], realm=realm)
|
||||
result['msg'] = "Client scope {name} has been deleted".format(name=name)
|
||||
else:
|
||||
result['msg'] = "Client scope {name} does not exist, doing nothing".format(name=name)
|
||||
@@ -261,8 +261,8 @@ def main():
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
|
||||
kc.create_clientscope(scope_rep, realm=realm)
|
||||
after_scope = kc.get_clientscope_by_name(name, realm=realm)
|
||||
kc.create_client_scope(scope_rep, realm=realm)
|
||||
after_scope = kc.get_client_scope_by_name(name, realm=realm)
|
||||
|
||||
if protocol_mappers:
|
||||
for mapper in protocol_mappers:
|
||||
@@ -272,8 +272,8 @@ def main():
|
||||
'protocolMapper': mapper['protocolMapper'],
|
||||
'config': mapper['config'],
|
||||
}
|
||||
kc.create_clientscope_protocolmapper(after_scope['id'], mapper_rep, realm=realm)
|
||||
after_scope = kc.get_clientscope_by_name(name, realm=realm)
|
||||
kc.create_client_scope_protocolmapper(after_scope['id'], mapper_rep, realm=realm)
|
||||
after_scope = kc.get_client_scope_by_name(name, realm=realm)
|
||||
|
||||
result['end_state'] = after_scope
|
||||
result['msg'] = "Client scope {name} has been created".format(name=name)
|
||||
@@ -296,10 +296,10 @@ def main():
|
||||
result['diff'] = dict(before=before_scope, after=scope_rep)
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
kc.update_clientscope(scope_rep, realm=realm)
|
||||
kc.update_client_scope(scope_rep, realm=realm)
|
||||
|
||||
if protocol_mappers:
|
||||
existing_mappers = kc.get_clientscope_protocolmappers(before_scope['id'], realm=realm)
|
||||
existing_mappers = kc.get_client_scope_protocolmappers(before_scope['id'], realm=realm)
|
||||
existing_mapper_names = {m['name'] for m in existing_mappers}
|
||||
|
||||
for mapper in protocol_mappers:
|
||||
@@ -312,9 +312,9 @@ def main():
|
||||
'protocolMapper': mapper['protocolMapper'],
|
||||
'config': mapper['config'],
|
||||
}
|
||||
kc.create_clientscope_protocolmapper(before_scope['id'], mapper_rep, realm=realm)
|
||||
kc.create_client_scope_protocolmapper(before_scope['id'], mapper_rep, realm=realm)
|
||||
|
||||
after_scope = kc.get_clientscope_by_name(name, realm=realm)
|
||||
after_scope = kc.get_client_scope_by_name(name, realm=realm)
|
||||
result['end_state'] = after_scope
|
||||
|
||||
if result['changed']:
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
module: keycloak_clientscope_rolemappings
|
||||
module: keycloak_client_scope_rolemappings
|
||||
|
||||
short_description: Allows administration of Keycloak clientscope scope mappings to restrict the usage of certain roles to
|
||||
specific clientscopes
|
||||
short_description: Allows administration of Keycloak client scope scope mappings to restrict the usage of certain roles to
|
||||
specific client scopes
|
||||
|
||||
# Originally added in community.general 13.1.0
|
||||
version_added: "3.0.0"
|
||||
|
||||
description:
|
||||
- This module allows you to add or remove Keycloak roles from clientscopes using the Keycloak REST API. It requires access
|
||||
- This module allows you to add or remove Keycloak roles from client scopes using the Keycloak REST API. It requires access
|
||||
to the REST API using OpenID Connect; the user connecting and the client being used must have the requisite access rights.
|
||||
In a default Keycloak installation, C(admin-cli) and an admin user would work, as would a separate client definition with
|
||||
the scope tailored to your needs and a user having the expected roles.
|
||||
@@ -49,11 +49,11 @@ options:
|
||||
- The Keycloak realm under which clients resides.
|
||||
default: 'master'
|
||||
|
||||
clientscope_id:
|
||||
client_scope_id:
|
||||
required: true
|
||||
type: str
|
||||
description:
|
||||
- Roles provided in O(role_names) will be added to this clientscope.
|
||||
- Roles provided in O(role_names) will be added to this client scope.
|
||||
|
||||
client_id:
|
||||
type: str
|
||||
@@ -81,40 +81,40 @@ author:
|
||||
"""
|
||||
|
||||
EXAMPLES = r"""
|
||||
- name: Add roles to clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: Add roles to client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
auth_keycloak_url: https://auth.example.com
|
||||
auth_realm: master
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: MyCustomRealm
|
||||
client_id: frontend-client-public
|
||||
clientscope_id: frontend-clientscope
|
||||
client_scope_id: frontend-client-scope
|
||||
role_names:
|
||||
- backend-role-admin
|
||||
- backend-role-user
|
||||
|
||||
- name: Remove roles from clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: Remove roles from client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
auth_keycloak_url: https://auth.example.com
|
||||
auth_realm: master
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: MyCustomRealm
|
||||
client_id: frontend-client-public
|
||||
clientscope_id: frontend-clientscope
|
||||
client_scope_id: frontend-client-scope
|
||||
role_names:
|
||||
- backend-role-admin
|
||||
state: absent
|
||||
|
||||
- name: Add realm roles to clientscope
|
||||
middleware_automation.keycloak.keycloak_clientscope_rolemappings:
|
||||
- name: Add realm roles to client scope
|
||||
middleware_automation.keycloak.keycloak_client_scope_rolemappings:
|
||||
auth_keycloak_url: https://auth.example.com
|
||||
auth_realm: master
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: MyCustomRealm
|
||||
clientscope_id: frontend-clientscope
|
||||
client_scope_id: frontend-client-scope
|
||||
role_names:
|
||||
- realm-role-admin
|
||||
- realm-role-user
|
||||
@@ -122,7 +122,7 @@ EXAMPLES = r"""
|
||||
|
||||
RETURN = r"""
|
||||
end_state:
|
||||
description: Representation of clientscope scope mappings after module execution.
|
||||
description: Representation of client scope scope mappings after module execution.
|
||||
returned: on success
|
||||
type: list
|
||||
elements: dict
|
||||
@@ -164,7 +164,7 @@ def main():
|
||||
|
||||
meta_args = dict(
|
||||
client_id=dict(type="str"),
|
||||
clientscope_id=dict(type="str", required=True),
|
||||
client_scope_id=dict(type="str", required=True),
|
||||
realm=dict(type="str", default="master"),
|
||||
role_names=dict(type="list", elements="str", required=True),
|
||||
state=dict(type="str", default="present", choices=["present", "absent"]),
|
||||
@@ -186,7 +186,7 @@ def main():
|
||||
|
||||
realm = module.params["realm"]
|
||||
client_id = module.params["client_id"]
|
||||
clientscope_id = module.params["clientscope_id"]
|
||||
client_scope_id = module.params["client_scope_id"]
|
||||
role_names = module.params["role_names"]
|
||||
state = module.params["state"]
|
||||
|
||||
@@ -194,23 +194,23 @@ def main():
|
||||
if not realm_object:
|
||||
module.fail_json(msg=f"Failed to retrieve realm '{realm}'")
|
||||
|
||||
clientscope_object = kc.get_clientscope_by_name(clientscope_id, realm)
|
||||
if not clientscope_object:
|
||||
module.fail_json(msg=f"Failed to retrieve client-scope '{clientscope_id}'")
|
||||
client_scope_object = kc.get_client_scope_by_name(client_scope_id, realm)
|
||||
if not client_scope_object:
|
||||
module.fail_json(msg=f"Failed to retrieve client scope '{client_scope_id}'")
|
||||
|
||||
if client_id:
|
||||
# add client role
|
||||
client_object = kc.get_client_by_clientid(client_id, realm)
|
||||
client_object = kc.get_client_by_client_id(client_id, realm)
|
||||
if not client_object:
|
||||
module.fail_json(msg=f"Failed to retrieve client '{realm}.{client_id}'")
|
||||
if client_object["fullScopeAllowed"] and state == "present":
|
||||
module.fail_json(msg=f"FullScopeAllowed is active for Client '{realm}.{client_id}'")
|
||||
|
||||
before_roles = kc.get_clientscope_scope_mappings_client(clientscope_object["id"], client_object["id"], realm)
|
||||
before_roles = kc.get_client_scope_scope_mappings_client(client_scope_object["id"], client_object["id"], realm)
|
||||
available_roles_by_name = kc.get_client_roles_by_id(client_object["id"], realm)
|
||||
else:
|
||||
# add realm role
|
||||
before_roles = kc.get_clientscope_scope_mappings_realm(clientscope_object["id"], realm)
|
||||
before_roles = kc.get_client_scope_scope_mappings_realm(client_scope_object["id"], realm)
|
||||
available_roles_by_name = kc.get_realm_roles(realm)
|
||||
|
||||
# convert to indexed Dict by name
|
||||
@@ -248,33 +248,33 @@ def main():
|
||||
if not result["changed"]:
|
||||
# no changes
|
||||
result["end_state"] = before_roles
|
||||
result["msg"] = f"No changes required for clientscope {clientscope_id}."
|
||||
result["msg"] = f"No changes required for client scope {client_scope_id}."
|
||||
elif state == "present":
|
||||
# doing update
|
||||
if module.check_mode:
|
||||
result["end_state"] = desired_role_mapping
|
||||
elif client_id:
|
||||
result["end_state"] = kc.update_clientscope_scope_mappings_client(
|
||||
changed_roles, clientscope_object["id"], client_object["id"], realm
|
||||
result["end_state"] = kc.update_client_scope_scope_mappings_client(
|
||||
changed_roles, client_scope_object["id"], client_object["id"], realm
|
||||
)
|
||||
else:
|
||||
result["end_state"] = kc.update_clientscope_scope_mappings_realm(
|
||||
changed_roles, clientscope_object["id"], realm
|
||||
result["end_state"] = kc.update_client_scope_scope_mappings_realm(
|
||||
changed_roles, client_scope_object["id"], realm
|
||||
)
|
||||
result["msg"] = f"Clientscope scope mappings for {clientscope_id} have been updated"
|
||||
result["msg"] = f"Clientscope scope mappings for {client_scope_id} have been updated"
|
||||
else:
|
||||
# doing delete
|
||||
if module.check_mode:
|
||||
result["end_state"] = desired_role_mapping
|
||||
elif client_id:
|
||||
result["end_state"] = kc.delete_clientscope_scope_mappings_client(
|
||||
changed_roles, clientscope_object["id"], client_object["id"], realm
|
||||
result["end_state"] = kc.delete_client_scope_scope_mappings_client(
|
||||
changed_roles, client_scope_object["id"], client_object["id"], realm
|
||||
)
|
||||
else:
|
||||
result["end_state"] = kc.delete_clientscope_scope_mappings_realm(
|
||||
changed_roles, clientscope_object["id"], realm
|
||||
result["end_state"] = kc.delete_client_scope_scope_mappings_realm(
|
||||
changed_roles, client_scope_object["id"], realm
|
||||
)
|
||||
result["msg"] = f"Clientscope scope mappings for {clientscope_id} have been deleted"
|
||||
result["msg"] = f"Clientscope scope mappings for {client_scope_id} have been deleted"
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
@@ -6,15 +6,15 @@
|
||||
from __future__ import annotations
|
||||
|
||||
DOCUMENTATION = r"""
|
||||
module: keycloak_clientscope_type
|
||||
module: keycloak_client_scope_type
|
||||
|
||||
short_description: Set the type of aclientscope in realm or client using Keycloak API
|
||||
short_description: Set the type of a client scope in a realm or client using the Keycloak API
|
||||
|
||||
# Originally added in community.general 6.6.0
|
||||
version_added: "3.0.0"
|
||||
|
||||
description:
|
||||
- This module allows you to set the type (optional, default) of clientscopes using the Keycloak REST API. It requires access
|
||||
- This module allows you to set the type (optional, default) of client scopes using the Keycloak REST API. It requires access
|
||||
to the REST API using OpenID Connect; the user connecting and the client being used must have the requisite access rights.
|
||||
In a default Keycloak installation, admin-cli and an admin user would work, as would a separate client definition with
|
||||
the scope tailored to your needs and a user having the expected roles.
|
||||
@@ -36,18 +36,18 @@ options:
|
||||
|
||||
client_id:
|
||||
description:
|
||||
- The O(client_id) of the client. If not set the clientscope types are set as a default for the realm.
|
||||
- The O(client_id) of the client. If not set the client scope types are set as a default for the realm.
|
||||
aliases:
|
||||
- clientId
|
||||
type: str
|
||||
|
||||
default_clientscopes:
|
||||
default_client_scopes:
|
||||
description:
|
||||
- Client scopes that should be of type default.
|
||||
type: list
|
||||
elements: str
|
||||
|
||||
optional_clientscopes:
|
||||
optional_client_scopes:
|
||||
description:
|
||||
- Client scopes that should be of type optional.
|
||||
type: list
|
||||
@@ -64,26 +64,26 @@ author:
|
||||
|
||||
EXAMPLES = r"""
|
||||
- name: Set default client scopes on realm level
|
||||
middleware_automation.keycloak.keycloak_clientscope_type:
|
||||
middleware_automation.keycloak.keycloak_client_scope_type:
|
||||
auth_client_id: admin-cli
|
||||
auth_keycloak_url: https://auth.example.com
|
||||
auth_realm: master
|
||||
auth_username: USERNAME
|
||||
auth_password: PASSWORD
|
||||
realm: "MyCustomRealm"
|
||||
default_clientscopes: ['profile', 'roles']
|
||||
default_client_scopes: ['profile', 'roles']
|
||||
delegate_to: localhost
|
||||
|
||||
|
||||
- name: Set default and optional client scopes on client level with token auth
|
||||
middleware_automation.keycloak.keycloak_clientscope_type:
|
||||
middleware_automation.keycloak.keycloak_client_scope_type:
|
||||
auth_client_id: admin-cli
|
||||
auth_keycloak_url: https://auth.example.com
|
||||
token: TOKEN
|
||||
realm: "MyCustomRealm"
|
||||
client_id: "MyCustomClient"
|
||||
default_clientscopes: ['profile', 'roles']
|
||||
optional_clientscopes: ['phone']
|
||||
default_client_scopes: ['profile', 'roles']
|
||||
optional_client_scopes: ['phone']
|
||||
delegate_to: localhost
|
||||
"""
|
||||
|
||||
@@ -94,16 +94,16 @@ msg:
|
||||
type: str
|
||||
sample: ""
|
||||
proposed:
|
||||
description: Representation of proposed client-scope types mapping.
|
||||
description: Representation of proposed client scope types mapping.
|
||||
returned: always
|
||||
type: dict
|
||||
sample:
|
||||
{
|
||||
"default_clientscopes": [
|
||||
"default_client_scopes": [
|
||||
"profile",
|
||||
"role"
|
||||
],
|
||||
"optional_clientscopes": []
|
||||
"optional_client_scopes": []
|
||||
}
|
||||
existing:
|
||||
description:
|
||||
@@ -112,11 +112,11 @@ existing:
|
||||
type: dict
|
||||
sample:
|
||||
{
|
||||
"default_clientscopes": [
|
||||
"default_client_scopes": [
|
||||
"profile",
|
||||
"role"
|
||||
],
|
||||
"optional_clientscopes": [
|
||||
"optional_client_scopes": [
|
||||
"phone"
|
||||
]
|
||||
}
|
||||
@@ -128,11 +128,11 @@ end_state:
|
||||
type: dict
|
||||
sample:
|
||||
{
|
||||
"default_clientscopes": [
|
||||
"default_client_scopes": [
|
||||
"profile",
|
||||
"role"
|
||||
],
|
||||
"optional_clientscopes": []
|
||||
"optional_client_scopes": []
|
||||
}
|
||||
"""
|
||||
|
||||
@@ -146,7 +146,7 @@ from ansible_collections.middleware_automation.keycloak.plugins.module_utils.ide
|
||||
)
|
||||
|
||||
|
||||
def keycloak_clientscope_type_module():
|
||||
def keycloak_client_scope_type_module():
|
||||
"""
|
||||
Returns an AnsibleModule definition.
|
||||
|
||||
@@ -157,8 +157,8 @@ def keycloak_clientscope_type_module():
|
||||
meta_args = dict(
|
||||
realm=dict(default="master"),
|
||||
client_id=dict(type="str", aliases=["clientId"]),
|
||||
default_clientscopes=dict(type="list", elements="str"),
|
||||
optional_clientscopes=dict(type="list", elements="str"),
|
||||
default_client_scopes=dict(type="list", elements="str"),
|
||||
optional_client_scopes=dict(type="list", elements="str"),
|
||||
)
|
||||
|
||||
argument_spec.update(meta_args)
|
||||
@@ -169,7 +169,7 @@ def keycloak_clientscope_type_module():
|
||||
required_one_of=(
|
||||
[
|
||||
["token", "auth_realm", "auth_username", "auth_password", "auth_client_id", "auth_client_secret"],
|
||||
["default_clientscopes", "optional_clientscopes"],
|
||||
["default_client_scopes", "optional_client_scopes"],
|
||||
]
|
||||
),
|
||||
required_together=([["auth_username", "auth_password"]]),
|
||||
@@ -180,21 +180,21 @@ def keycloak_clientscope_type_module():
|
||||
return module
|
||||
|
||||
|
||||
def clientscopes_to_add(existing, proposed):
|
||||
def client_scopes_to_add(existing, proposed):
|
||||
to_add = []
|
||||
existing_clientscope_ids = extract_field(existing, "id")
|
||||
for clientscope in proposed:
|
||||
if clientscope["id"] not in existing_clientscope_ids:
|
||||
to_add.append(clientscope)
|
||||
existing_client_scope_ids = extract_field(existing, "id")
|
||||
for client_scope in proposed:
|
||||
if client_scope["id"] not in existing_client_scope_ids:
|
||||
to_add.append(client_scope)
|
||||
return to_add
|
||||
|
||||
|
||||
def clientscopes_to_delete(existing, proposed):
|
||||
def client_scopes_to_delete(existing, proposed):
|
||||
to_delete = []
|
||||
proposed_clientscope_ids = extract_field(proposed, "id")
|
||||
for clientscope in existing:
|
||||
if clientscope["id"] not in proposed_clientscope_ids:
|
||||
to_delete.append(clientscope)
|
||||
proposed_client_scope_ids = extract_field(proposed, "id")
|
||||
for client_scope in existing:
|
||||
if client_scope["id"] not in proposed_client_scope_ids:
|
||||
to_delete.append(client_scope)
|
||||
return to_delete
|
||||
|
||||
|
||||
@@ -204,21 +204,21 @@ def extract_field(dictionary, field="name"):
|
||||
|
||||
def normalize_scopes(scopes):
|
||||
scopes_copy = scopes.copy()
|
||||
if isinstance(scopes_copy.get("default_clientscopes"), list):
|
||||
scopes_copy["default_clientscopes"] = sorted(scopes_copy["default_clientscopes"])
|
||||
if isinstance(scopes_copy.get("optional_clientscopes"), list):
|
||||
scopes_copy["optional_clientscopes"] = sorted(scopes_copy["optional_clientscopes"])
|
||||
if isinstance(scopes_copy.get("default_client_scopes"), list):
|
||||
scopes_copy["default_client_scopes"] = sorted(scopes_copy["default_client_scopes"])
|
||||
if isinstance(scopes_copy.get("optional_client_scopes"), list):
|
||||
scopes_copy["optional_client_scopes"] = sorted(scopes_copy["optional_client_scopes"])
|
||||
return scopes_copy
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
Module keycloak_clientscope_type
|
||||
Module keycloak_client_scope_type
|
||||
|
||||
:return:
|
||||
"""
|
||||
|
||||
module = keycloak_clientscope_type_module()
|
||||
module = keycloak_client_scope_type_module()
|
||||
|
||||
# Obtain access token, initialize API
|
||||
try:
|
||||
@@ -230,81 +230,81 @@ def main():
|
||||
|
||||
realm = module.params.get("realm")
|
||||
client_id = module.params.get("client_id")
|
||||
default_clientscopes = module.params.get("default_clientscopes")
|
||||
optional_clientscopes = module.params.get("optional_clientscopes")
|
||||
default_client_scopes = module.params.get("default_client_scopes")
|
||||
optional_client_scopes = module.params.get("optional_client_scopes")
|
||||
|
||||
result = dict(changed=False, msg="", proposed={}, existing={}, end_state={})
|
||||
|
||||
all_clientscopes = kc.get_clientscopes(realm)
|
||||
default_clientscopes_real = []
|
||||
optional_clientscopes_real = []
|
||||
all_client_scopes = kc.get_client_scopes(realm)
|
||||
default_client_scopes_real = []
|
||||
optional_client_scopes_real = []
|
||||
|
||||
for client_scope in all_clientscopes:
|
||||
if default_clientscopes is not None and client_scope["name"] in default_clientscopes:
|
||||
default_clientscopes_real.append(client_scope)
|
||||
if optional_clientscopes is not None and client_scope["name"] in optional_clientscopes:
|
||||
optional_clientscopes_real.append(client_scope)
|
||||
for client_scope in all_client_scopes:
|
||||
if default_client_scopes is not None and client_scope["name"] in default_client_scopes:
|
||||
default_client_scopes_real.append(client_scope)
|
||||
if optional_client_scopes is not None and client_scope["name"] in optional_client_scopes:
|
||||
optional_client_scopes_real.append(client_scope)
|
||||
|
||||
if default_clientscopes is not None and len(default_clientscopes_real) != len(default_clientscopes):
|
||||
module.fail_json(msg="At least one of the default_clientscopes does not exist!")
|
||||
if default_client_scopes is not None and len(default_client_scopes_real) != len(default_client_scopes):
|
||||
module.fail_json(msg="At least one of the default_client_scopes does not exist!")
|
||||
|
||||
if optional_clientscopes is not None and len(optional_clientscopes_real) != len(optional_clientscopes):
|
||||
module.fail_json(msg="At least one of the optional_clientscopes does not exist!")
|
||||
if optional_client_scopes is not None and len(optional_client_scopes_real) != len(optional_client_scopes):
|
||||
module.fail_json(msg="At least one of the optional_client_scopes does not exist!")
|
||||
|
||||
result["proposed"].update(
|
||||
{
|
||||
"default_clientscopes": "no-change" if default_clientscopes is None else default_clientscopes,
|
||||
"optional_clientscopes": "no-change" if optional_clientscopes is None else optional_clientscopes,
|
||||
"default_client_scopes": "no-change" if default_client_scopes is None else default_client_scopes,
|
||||
"optional_client_scopes": "no-change" if optional_client_scopes is None else optional_client_scopes,
|
||||
}
|
||||
)
|
||||
|
||||
default_clientscopes_existing = kc.get_default_clientscopes(realm, client_id)
|
||||
optional_clientscopes_existing = kc.get_optional_clientscopes(realm, client_id)
|
||||
default_client_scopes_existing = kc.get_default_client_scopes(realm, client_id)
|
||||
optional_client_scopes_existing = kc.get_optional_client_scopes(realm, client_id)
|
||||
|
||||
result["existing"].update(
|
||||
{
|
||||
"default_clientscopes": extract_field(default_clientscopes_existing),
|
||||
"optional_clientscopes": extract_field(optional_clientscopes_existing),
|
||||
"default_client_scopes": extract_field(default_client_scopes_existing),
|
||||
"optional_client_scopes": extract_field(optional_client_scopes_existing),
|
||||
}
|
||||
)
|
||||
|
||||
if module._diff:
|
||||
result["diff"] = dict(before=normalize_scopes(result["existing"]), after=normalize_scopes(result["proposed"]))
|
||||
|
||||
default_clientscopes_add = clientscopes_to_add(default_clientscopes_existing, default_clientscopes_real)
|
||||
optional_clientscopes_add = clientscopes_to_add(optional_clientscopes_existing, optional_clientscopes_real)
|
||||
default_client_scopes_add = client_scopes_to_add(default_client_scopes_existing, default_client_scopes_real)
|
||||
optional_client_scopes_add = client_scopes_to_add(optional_client_scopes_existing, optional_client_scopes_real)
|
||||
|
||||
default_clientscopes_delete = clientscopes_to_delete(default_clientscopes_existing, default_clientscopes_real)
|
||||
optional_clientscopes_delete = clientscopes_to_delete(optional_clientscopes_existing, optional_clientscopes_real)
|
||||
default_client_scopes_delete = client_scopes_to_delete(default_client_scopes_existing, default_client_scopes_real)
|
||||
optional_client_scopes_delete = client_scopes_to_delete(optional_client_scopes_existing, optional_client_scopes_real)
|
||||
|
||||
result["changed"] = any(
|
||||
len(x) > 0
|
||||
for x in [
|
||||
default_clientscopes_add,
|
||||
optional_clientscopes_add,
|
||||
default_clientscopes_delete,
|
||||
optional_clientscopes_delete,
|
||||
default_client_scopes_add,
|
||||
optional_client_scopes_add,
|
||||
default_client_scopes_delete,
|
||||
optional_client_scopes_delete,
|
||||
]
|
||||
)
|
||||
|
||||
if module.check_mode:
|
||||
module.exit_json(**result)
|
||||
|
||||
# first delete so clientscopes can change type
|
||||
for clientscope in default_clientscopes_delete:
|
||||
kc.delete_default_clientscope(clientscope["id"], realm, client_id)
|
||||
for clientscope in optional_clientscopes_delete:
|
||||
kc.delete_optional_clientscope(clientscope["id"], realm, client_id)
|
||||
# first delete so client_scopes can change type
|
||||
for client_scope in default_client_scopes_delete:
|
||||
kc.delete_default_client_scope(client_scope["id"], realm, client_id)
|
||||
for client_scope in optional_client_scopes_delete:
|
||||
kc.delete_optional_client_scope(client_scope["id"], realm, client_id)
|
||||
|
||||
for clientscope in default_clientscopes_add:
|
||||
kc.add_default_clientscope(clientscope["id"], realm, client_id)
|
||||
for clientscope in optional_clientscopes_add:
|
||||
kc.add_optional_clientscope(clientscope["id"], realm, client_id)
|
||||
for client_scope in default_client_scopes_add:
|
||||
kc.add_default_client_scope(client_scope["id"], realm, client_id)
|
||||
for client_scope in optional_client_scopes_add:
|
||||
kc.add_optional_client_scope(client_scope["id"], realm, client_id)
|
||||
|
||||
result["end_state"].update(
|
||||
{
|
||||
"default_clientscopes": extract_field(kc.get_default_clientscopes(realm, client_id)),
|
||||
"optional_clientscopes": extract_field(kc.get_optional_clientscopes(realm, client_id)),
|
||||
"default_client_scopes": extract_field(kc.get_default_client_scopes(realm, client_id)),
|
||||
"optional_client_scopes": extract_field(kc.get_optional_client_scopes(realm, client_id)),
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user