From f8a71bc4999fc0fca1ec697c18206351ac067f40 Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 29 Mar 2024 10:43:14 +0100 Subject: [PATCH 01/12] Implement keycloak authorization resources --- .../identity/keycloak/keycloak.py | 31 ++ plugins/modules/keycloak_authz_resource.py | 309 ++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 plugins/modules/keycloak_authz_resource.py diff --git a/plugins/module_utils/identity/keycloak/keycloak.py b/plugins/module_utils/identity/keycloak/keycloak.py index 9e1c3f4d93c..69bcc42b4b6 100644 --- a/plugins/module_utils/identity/keycloak/keycloak.py +++ b/plugins/module_utils/identity/keycloak/keycloak.py @@ -116,6 +116,7 @@ URL_AUTHZ_PERMISSION = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/permission/{permission_type}/{id}" URL_AUTHZ_PERMISSIONS = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/permission/{permission_type}" +URL_AUTHZ_RESOURCE = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/resource/{id}" URL_AUTHZ_RESOURCES = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/resource" URL_AUTHZ_CUSTOM_POLICY = "{url}/admin/realms/{realm}/clients/{client_id}/authz/resource-server/policy/{policy_type}" @@ -3025,6 +3026,16 @@ def update_authz_permission(self, payload, permission_type, id, client_id, realm except Exception as e: self.fail_open_url(e, msg='Could not create update permission %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e))) + def create_authz_resource(self, payload, client_id, realm): + """Create an authorization resource for a Keycloak client""" + url = URL_AUTHZ_RESOURCES.format(url=self.baseurl, client_id=client_id, realm=realm) + + try: + return open_url(url, method='POST', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout, + data=json.dumps(payload), validate_certs=self.validate_certs) + except Exception as e: + self.fail_open_url(e, msg='Could not create resource %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e))) + def get_authz_resource_by_name(self, name, client_id, realm): """Get authorization resource by name""" url = URL_AUTHZ_RESOURCES.format(url=self.baseurl, client_id=client_id, realm=realm) @@ -3037,6 +3048,26 @@ def get_authz_resource_by_name(self, name, client_id, realm): except Exception: return False + def remove_authz_permission(self, id, client_id, realm): + """Remove an authorization resource for a Keycloak client""" + url = URL_AUTHZ_RESOURCE.format(url=self.baseurl, id=id, client_id=client_id, realm=realm) + + try: + return open_url(url, method='DELETE', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout, + validate_certs=self.validate_certs) + except Exception as e: + self.fail_open_url(e, msg='Could not delete permission %s for client %s in realm %s: %s' % (id, client_id, realm, str(e))) + + def update_authz_resource(self, payload, id, client_id, realm): + """Update a resource for a Keycloak client""" + url = URL_AUTHZ_RESOURCE.format(url=self.baseurl, id=id, client_id=client_id, realm=realm) + + try: + return open_url(url, method='PUT', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout, + data=json.dumps(payload), validate_certs=self.validate_certs) + except Exception as e: + self.fail_open_url(e, msg='Could not create update permission %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e))) + def get_authz_policy_by_name(self, name, client_id, realm): """Get authorization policy by name""" url = URL_AUTHZ_POLICIES.format(url=self.baseurl, client_id=client_id, realm=realm) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py new file mode 100644 index 00000000000..268e964dba5 --- /dev/null +++ b/plugins/modules/keycloak_authz_resource.py @@ -0,0 +1,309 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2017, Eike Frost +# Copyright (c) 2021, Christophe Gilles +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or +# https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: keycloak_authz_resource + +version_added: 8.6.0 + +short_description: Allows administration of Keycloak client authorization resources via Keycloak API + +description: + - This module allows the administration of Keycloak client authorization resources via the Keycloak REST + API. Authorization resources are only available if a client has Authorization enabled. + + - This module requires access to the REST API via OpenID Connect; the user connecting and the realm + 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 realm definition with the scope tailored + to your needs and a user having the expected roles. + + - The names of module options are snake_cased versions of the camelCase options used by Keycloak. + The Authorization Services paths and payloads have not officially been documented by the Keycloak project. + U(https://www.puppeteers.net/blog/keycloak-authorization-services-rest-api-paths-and-payload/) + +attributes: + check_mode: + support: full + diff_mode: + support: full + +options: + state: + description: + - State of the authorization resource. + - On V(present), the authorization resource will be created (or updated if it exists already). + - On V(absent), the authorization resource will be removed if it exists. + choices: ['present', 'absent'] + default: 'present' + type: str + name: + description: + - Name of the authorization resource to create. + type: str + required: true + displayName: + description: + - The displayName of the authorization resource. + type: str + required: false + client_id: + description: + - The clientId of the keycloak client that should have the authorization scope. + - This is usually a human-readable name of the Keycloak client. + type: str + required: true + realm: + description: + - The name of the Keycloak realm the Keycloak client is in. + type: str + required: true + icon_uri: + description: + - A URI pointing to an icon. + type: str + required: false + uris: + description: + - Set of URIs which are protected by resource. + type: list + elements: str + required: false + default: [] + type: + description: + - OpenID Connect allows Clients to verify the identity of the End-User based on the + authentication performed by an Authorization Server. + - SAML enables web-based authentication and authorization scenarios including cross-domain + single sign-on (SSO) and uses security tokens containing assertions to pass information. + type: str + required: false + attributes: + description: + - The attributes associated wth the resource. + type: dict + required: false + default: {} + ownerManagedAccess: + description: + - If enabled, the access to this resource can be managed by the resource owner. + type: bool + required: false + default: false + +extends_documentation_fragment: + - community.general.keycloak + - community.general.attributes + +author: + - Maximilian Pohle (@mattock) +''' + +EXAMPLES = ''' +- name: Manage scope-based Keycloak authorization resource + community.general.keycloak_authz_resource: + name: test-resource + state: present + displayName: test-resource + client_id: myclient + realm: myrealm + auth_keycloak_url: http://localhost:8080/auth + auth_username: keycloak + auth_password: keycloak + auth_realm: master +''' + +RETURN = ''' +msg: + description: Message as to what action was taken. + returned: always + type: str + +end_state: + description: Representation of the authorization resource after module execution. + returned: on success + type: complex + contains: + _id: + description: ID of the authorization resource. + type: str + returned: when O(state=present) + sample: 9da05cd2-b273-4354-bbd8-0c133918a454 + attributes: + description: The attributes associated wth the resource. + type: dict + returned: when O(state=present) + sample: {"foo": "bar"} + displayName: + description: Name of the authorization resource to create. + type: dict + returned: when O(state=present) + sample: test-resource + owner: + description: Owner of the authorization resource. + type: str + returned: when O(state=present) + sample: {"id": "003-nc.003", "name": "nc.003"} + ownerManagedAccess: + description: If enabled, the access to this resource can be managed by the resource owner. + type: str + returned: when O(state=present) + sample: false + uris: + description: Set of URIs which are protected by resource. + type: str + returned: when O(state=present) + sample: ["http://localhost:8080"] + +''' + +from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI, \ + keycloak_argument_spec, get_token, KeycloakError +from ansible.module_utils.basic import AnsibleModule + + +def main(): + """ + Module execution + + :return: + """ + argument_spec = keycloak_argument_spec() + + meta_args = dict( + state=dict(type='str', default='present', + choices=['present', 'absent']), + name=dict(type='str', required=True), + attributes=dict(type='dict', required=False, default={}), + client_id=dict(type='str', required=True), + displayName=dict(type='str', required=False), + icon_uri=dict(type='str', required=False), + ownerManagedAccess=dict(type='bool', required=False, default=False), + realm=dict(type='str', required=True), + type=dict(type='str', required=False), + uris=dict(type='list', elements='str', default=[], required=False), + ) + + argument_spec.update(meta_args) + + module = AnsibleModule(argument_spec=argument_spec, + supports_check_mode=True, + required_one_of=( + [['token', 'auth_realm', 'auth_username', 'auth_password']]), + required_together=([['auth_realm', 'auth_username', 'auth_password']])) + + attributes = module.params.get('attributes') + client_id = module.params.get('client_id') + displayName = module.params.get('displayName') + icon_uri = module.params.get('icon_uri') + name = module.params.get('name') + ownerManagedAccess = module.params.get('ownerManagedAccess') + realm = module.params.get('realm') + state = module.params.get('state') + type = module.params.get('type') + uris = module.params.get('uris') + + result = dict(changed=False, msg='', end_state={}) + + # Obtain access token, initialize API + try: + connection_header = get_token(module.params) + except KeycloakError as e: + module.fail_json(msg=str(e)) + + kc = KeycloakAPI(module, connection_header) + + # Get id of the client based on client_id + cid = kc.get_client_id(client_id, realm=realm) + if not cid: + module.fail_json(msg='Invalid client %s for realm %s' % + (client_id, realm)) + + # Get current state of the permission using its name as the search + # filter. This returns False if it is not found. + resource = kc.get_authz_resource_by_name( + name=name, client_id=cid, realm=realm) + + # Generate a JSON payload for Keycloak Admin API. This is needed for + # "create" and "update" operations. + payload = {} + payload['attributes'] = attributes + + payload['name'] = name + if type: + payload['type'] = type + if displayName: + payload['displayName'] = displayName + if icon_uri: + payload['icon_uri'] = icon_uri + payload['ownerManagedAccess'] = ownerManagedAccess + payload['uris'] = uris + + payload['owner'] = { + 'id': cid, + 'name': client_id + } + + # Add "id" to payload for update operations + if resource: + payload['_id'] = resource['_id'] + + if resource and state == 'present': + result['msg'] = 'Update present' + result['diff'] = { + 'after': payload, + 'before': resource + } + + if result['diff']['before'] != result['diff']['after']: + if not module.check_mode: + kc.update_authz_resource(payload=payload, id=resource['_id'], client_id=cid, realm=realm) + result['msg'] = 'Would update resource' + result['changed'] = True + result['end_state'] = payload + + elif not resource and state == 'present': + result['diff'] = { + 'after': payload, + 'before': {} + } + + if not module.check_mode: + kc.create_authz_resource(payload=payload, client_id=cid, realm=realm) + result['msg'] = 'Resource created' + + result['changed'] = True + result['end_state'] = payload + elif resource and state == 'absent': + result['diff'] = { + 'after': {}, + 'before': resource + } + + if module.check_mode: + result['msg'] = 'Would remove permission' + else: + kc.remove_authz_permission(id=resource['_id'], client_id=cid, realm=realm) + result['msg'] = 'Resource removed' + + result['changed'] = True + + elif not resource and state == 'absent': + result['changed'] = False + else: + module.fail_json(msg='Unable to determine what to do with resource %s of client %s in realm %s' % ( + name, client_id, realm)) + + module.exit_json(**result) + + +if __name__ == '__main__': + main() From 6c1f74ad4c3776f92423b78f728bd2756c3f14ad Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Thu, 30 May 2024 13:22:50 +0200 Subject: [PATCH 02/12] add maintainer info --- .github/BOTMETA.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index 64cbc7021bc..7e95f323b27 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -752,6 +752,8 @@ files: maintainers: mattock $modules/keycloak_authz_permission_info.py: maintainers: mattock + $modules/keycloak_authz_resource.py: + maintainers: maximilianpohle $modules/keycloak_client_rolemapping.py: maintainers: Gaetan2907 $modules/keycloak_clientscope.py: From 3f092f697f2380712472e56947d692ea4bd4f718 Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Sat, 1 Jun 2024 13:10:26 +0200 Subject: [PATCH 03/12] add integration tests --- plugins/modules/keycloak_authz_resource.py | 2 + .../keycloak_authz_resource/readme.adoc | 27 +++ .../keycloak_authz_resource/tasks/main.yml | 209 ++++++++++++++++++ .../keycloak_authz_resource/vars/main.yml | 17 ++ 4 files changed, 255 insertions(+) create mode 100644 tests/integration/targets/keycloak_authz_resource/readme.adoc create mode 100644 tests/integration/targets/keycloak_authz_resource/tasks/main.yml create mode 100644 tests/integration/targets/keycloak_authz_resource/vars/main.yml diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index 268e964dba5..028fa536a6b 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -231,6 +231,8 @@ def main(): # filter. This returns False if it is not found. resource = kc.get_authz_resource_by_name( name=name, client_id=cid, realm=realm) + if resource and resource != {}: + resource['uris'].sort() # Generate a JSON payload for Keycloak Admin API. This is needed for # "create" and "update" operations. diff --git a/tests/integration/targets/keycloak_authz_resource/readme.adoc b/tests/integration/targets/keycloak_authz_resource/readme.adoc new file mode 100644 index 00000000000..8e052920c11 --- /dev/null +++ b/tests/integration/targets/keycloak_authz_resource/readme.adoc @@ -0,0 +1,27 @@ +// Copyright (c) Ansible Project +// GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +// SPDX-License-Identifier: GPL-3.0-or-later + +To be able to run these integration tests a keycloak server must be +reachable under a specific url with a specific admin user and password. +The exact values expected for these parameters can be found in +'vars/main.yml' file. A simple way to do this is to use the official +keycloak docker images like this: + +---- +docker run --name mykeycloak -p 8080:8080 -e KC_HTTP_RELATIVE_PATH= -e KEYCLOAK_ADMIN= -e KEYCLOAK_ADMIN_PASSWORD= quay.io/keycloak/keycloak:20.0.2 start-dev +---- + +Example with concrete values inserted: + +---- +docker run --name mykeycloak -p 8080:8080 -e KC_HTTP_RELATIVE_PATH=/auth -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=password quay.io/keycloak/keycloak:20.0.2 start-dev +---- + +This test suite can run against a fresh unconfigured server instance +(no preconfiguration required) and cleans up after itself (undoes all +its config changes) as long as it runs through completely. While its active +it changes the server configuration in the following ways: + + * creating, modifying and deleting some keycloak groups + diff --git a/tests/integration/targets/keycloak_authz_resource/tasks/main.yml b/tests/integration/targets/keycloak_authz_resource/tasks/main.yml new file mode 100644 index 00000000000..e30f3a0bf2a --- /dev/null +++ b/tests/integration/targets/keycloak_authz_resource/tasks/main.yml @@ -0,0 +1,209 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later +- name: Remove keycloak client to avoid failures from previous failed runs + community.general.keycloak_client: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + state: absent + +- name: Create keycloak client with authorization services enabled + community.general.keycloak_client: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + state: present + enabled: true + public_client: false + service_accounts_enabled: true + authorization_services_enabled: true + +- name: Create keycloak resource + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + displayName: "{{ displayName }}" + icon_uri: "{{ icon_uri }}" + uris: "{{ uris }}" + state: present + register: result + +- name: Assert that resource was created + assert: + that: + - result is changed + - result.end_state != {} + +- name: Create keycloak resource (test for idempotency) + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + displayName: "{{ displayName }}" + icon_uri: "{{ icon_uri }}" + uris: "{{ uris }}" + state: present + check_mode: true + diff: true + register: result + +- name: Assert that nothing has changed + assert: + that: + - result is not changed + - result.end_state != {} + +- name: Update keycloak resource + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + displayName: "{{ displayName }} changed" + icon_uri: "{{ icon_uri }}" + uris: "{{ uris }}" + state: present + diff: true + register: result + +- name: Assert that nothing has changed + assert: + that: + - result is changed + - result.end_state != {} + +- name: Update keycloak resource (test for idempotency) + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + displayName: "{{ displayName }} changed" + icon_uri: "{{ icon_uri }}" + uris: "{{ uris }}" + state: present + check_mode: true + diff: true + register: result + +- name: Assert that nothing has changed + assert: + that: + - result is not changed + - result.end_state != {} + +- name: Remove keycloak resource + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + displayName: "{{ displayName }} changed" + icon_uri: "{{ icon_uri }}" + uris: "{{ uris }}" + state: absent + diff: true + register: result + +- name: Assert that nothing has changed + assert: + that: + - result is changed + - result.end_state == {} + +- name: Remove keycloak resource (test for idempotency) + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + displayName: "{{ displayName }} changed" + icon_uri: "{{ icon_uri }}" + uris: "{{ uris }}" + state: absent + check_mode: true + diff: true + register: result + +- name: Assert that nothing has changed + assert: + that: + - result is not changed + - result.end_state == {} + +- name: Create keycloak resource (minimal) + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + state: present + register: result + +- name: Assert that resource was created + assert: + that: + - result is changed + - result.end_state != {} + +- name: Create keycloak resource (minimal) (test for idempotency) + community.general.keycloak_authz_resource: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + name: "{{ resource_name }}" + state: present + check_mode: true + diff: true + register: result + +- name: Assert that nothing has changed + assert: + that: + - result is not changed + - result.end_state != {} + +- name: Remove keycloak client to avoid failures from previous failed runs + community.general.keycloak_client: + auth_keycloak_url: "{{ url }}" + auth_realm: "{{ admin_realm }}" + auth_username: "{{ admin_user }}" + auth_password: "{{ admin_password }}" + realm: "{{ realm }}" + client_id: "{{ client_id }}" + state: absent diff --git a/tests/integration/targets/keycloak_authz_resource/vars/main.yml b/tests/integration/targets/keycloak_authz_resource/vars/main.yml new file mode 100644 index 00000000000..752029bbf6f --- /dev/null +++ b/tests/integration/targets/keycloak_authz_resource/vars/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright (c) Ansible Project +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +url: http://localhost:8080/auth +admin_realm: master +admin_user: admin +admin_password: password +realm: master +client_id: authz +resource_name: resource +displayName: Resource +icon_uri: icon.png +uris: + - https://url1.com + - https://url2.com From f3bb1da370a3fc501aec0b30e44639671e6137ad Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Sun, 2 Jun 2024 19:11:53 +0200 Subject: [PATCH 04/12] Update plugins/modules/keycloak_authz_resource.py Co-authored-by: Felix Fontein --- plugins/modules/keycloak_authz_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index 028fa536a6b..dd7324c0532 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -13,7 +13,7 @@ --- module: keycloak_authz_resource -version_added: 8.6.0 +version_added: 9.1.0 short_description: Allows administration of Keycloak client authorization resources via Keycloak API From 123714c7c184d61ac642110856db4c144263dd9e Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Sun, 2 Jun 2024 19:12:17 +0200 Subject: [PATCH 05/12] Update plugins/modules/keycloak_authz_resource.py Co-authored-by: Felix Fontein --- plugins/modules/keycloak_authz_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index dd7324c0532..72c264c97c4 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -104,7 +104,7 @@ - community.general.attributes author: - - Maximilian Pohle (@mattock) + - Maximilian Pohle (@maximilianpohle) ''' EXAMPLES = ''' From aa9dde295f6bdabfd338616048ed536109c6d003 Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:43:47 +0200 Subject: [PATCH 06/12] Update plugins/module_utils/identity/keycloak/keycloak.py Co-authored-by: Mark Armstrong --- plugins/module_utils/identity/keycloak/keycloak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/identity/keycloak/keycloak.py b/plugins/module_utils/identity/keycloak/keycloak.py index 69bcc42b4b6..a472d8e798c 100644 --- a/plugins/module_utils/identity/keycloak/keycloak.py +++ b/plugins/module_utils/identity/keycloak/keycloak.py @@ -3056,7 +3056,7 @@ def remove_authz_permission(self, id, client_id, realm): return open_url(url, method='DELETE', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout, validate_certs=self.validate_certs) except Exception as e: - self.fail_open_url(e, msg='Could not delete permission %s for client %s in realm %s: %s' % (id, client_id, realm, str(e))) + self.fail_open_url(e, msg='Could not delete resource %s for client %s in realm %s: %s' % (id, client_id, realm, str(e))) def update_authz_resource(self, payload, id, client_id, realm): """Update a resource for a Keycloak client""" From 8943796f84ac55b7645cffebb3ed84d45cf28b9b Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:44:02 +0200 Subject: [PATCH 07/12] Update plugins/modules/keycloak_authz_resource.py Co-authored-by: Mark Armstrong --- plugins/modules/keycloak_authz_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index 72c264c97c4..498007d0971 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -291,7 +291,7 @@ def main(): } if module.check_mode: - result['msg'] = 'Would remove permission' + result['msg'] = 'Would remove resource' else: kc.remove_authz_permission(id=resource['_id'], client_id=cid, realm=realm) result['msg'] = 'Resource removed' From 25f485a3420b511f2add4dfc2b2a539de913b49a Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:44:48 +0200 Subject: [PATCH 08/12] Update tests/integration/targets/keycloak_authz_resource/readme.adoc Co-authored-by: Mark Armstrong --- tests/integration/targets/keycloak_authz_resource/readme.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integration/targets/keycloak_authz_resource/readme.adoc b/tests/integration/targets/keycloak_authz_resource/readme.adoc index 8e052920c11..1ac1bd53c0a 100644 --- a/tests/integration/targets/keycloak_authz_resource/readme.adoc +++ b/tests/integration/targets/keycloak_authz_resource/readme.adoc @@ -23,5 +23,6 @@ This test suite can run against a fresh unconfigured server instance its config changes) as long as it runs through completely. While its active it changes the server configuration in the following ways: - * creating, modifying and deleting some keycloak groups + * Creating and deleting a Keycloak client with (human-readable) ID `authz` (configurable in `./vars/main.yml`). + * Creating, modifying and deleting resources on that client. From 3b6d35e28e15f2d1fcbf1a93b1c7397089e6e80b Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:44:58 +0200 Subject: [PATCH 09/12] Update plugins/modules/keycloak_authz_resource.py Co-authored-by: Mark Armstrong --- plugins/modules/keycloak_authz_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index 498007d0971..364bb5933fe 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -227,7 +227,7 @@ def main(): module.fail_json(msg='Invalid client %s for realm %s' % (client_id, realm)) - # Get current state of the permission using its name as the search + # Get current state of the resource using its name as the search # filter. This returns False if it is not found. resource = kc.get_authz_resource_by_name( name=name, client_id=cid, realm=realm) From d026a6ccb102431955ce773692c55403d09d9962 Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:45:04 +0200 Subject: [PATCH 10/12] Update plugins/modules/keycloak_authz_resource.py Co-authored-by: Mark Armstrong --- plugins/modules/keycloak_authz_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index 364bb5933fe..3c5b1269d64 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -57,7 +57,7 @@ required: false client_id: description: - - The clientId of the keycloak client that should have the authorization scope. + - The clientId of the keycloak client that should have the authorization resource. - This is usually a human-readable name of the Keycloak client. type: str required: true From 45154faab72c81dcf67e0f4adfdf6a28be6a3318 Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:45:14 +0200 Subject: [PATCH 11/12] Update plugins/modules/keycloak_authz_resource.py Co-authored-by: Mark Armstrong --- plugins/modules/keycloak_authz_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/keycloak_authz_resource.py b/plugins/modules/keycloak_authz_resource.py index 3c5b1269d64..d8b90003e04 100644 --- a/plugins/modules/keycloak_authz_resource.py +++ b/plugins/modules/keycloak_authz_resource.py @@ -108,7 +108,7 @@ ''' EXAMPLES = ''' -- name: Manage scope-based Keycloak authorization resource +- name: Manage Keycloak authorization resource community.general.keycloak_authz_resource: name: test-resource state: present From 836dc7989e9cbe4555a52b9c87dfa02279b079d3 Mon Sep 17 00:00:00 2001 From: Maximilian Pohle Date: Fri, 13 Sep 2024 13:45:24 +0200 Subject: [PATCH 12/12] Update plugins/module_utils/identity/keycloak/keycloak.py Co-authored-by: Mark Armstrong --- plugins/module_utils/identity/keycloak/keycloak.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/identity/keycloak/keycloak.py b/plugins/module_utils/identity/keycloak/keycloak.py index a472d8e798c..f576821e28c 100644 --- a/plugins/module_utils/identity/keycloak/keycloak.py +++ b/plugins/module_utils/identity/keycloak/keycloak.py @@ -3066,7 +3066,7 @@ def update_authz_resource(self, payload, id, client_id, realm): return open_url(url, method='PUT', http_agent=self.http_agent, headers=self.restheaders, timeout=self.connection_timeout, data=json.dumps(payload), validate_certs=self.validate_certs) except Exception as e: - self.fail_open_url(e, msg='Could not create update permission %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e))) + self.fail_open_url(e, msg='Could not create update resource %s for client %s in realm %s: %s' % (payload['name'], client_id, realm, str(e))) def get_authz_policy_by_name(self, name, client_id, realm): """Get authorization policy by name"""