New Module: Keycloak Realm Info (#3998)

* feat(plugins/keycloak): add get_realm_info_by_id as util function

* feat(plugins/keycloak): add keycloak_realm_info module

* chore: add maintainer

* feat(plugins/keycloak): remove supports_check_mode

* feat(plugins/keycloak): add supports_check_mode back

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* docs(plugins/keycloak): cleanup docs

* feat(plugins/keycloak): add unit test

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* Update plugins/modules/identity/keycloak/keycloak_realm_info.py

Co-authored-by: Felix Fontein <felix@fontein.de>

* feat(plugins/keycloak): remove end_state

* docs(plugins/keycloak): complete sentences

* docs(plugins/keycloak): use dict for return type

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Fynnnnn 2022-01-11 13:42:47 +08:00 committed by GitHub
commit 1214d42472
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 282 additions and 0 deletions

View file

@ -38,6 +38,7 @@ from ansible.module_utils.six.moves.urllib.parse import urlencode, quote
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible.module_utils.common.text.converters import to_native, to_text
URL_REALM_INFO = "{url}/realms/{realm}"
URL_REALMS = "{url}/admin/realms"
URL_REALM = "{url}/admin/realms/{realm}"
@ -230,6 +231,31 @@ class KeycloakAPI(object):
self.validate_certs = self.module.params.get('validate_certs')
self.restheaders = connection_header
def get_realm_info_by_id(self, realm='master'):
""" Obtain realm public info by id
:param realm: realm id
:return: dict of real, representation or None if none matching exist
"""
realm_info_url = URL_REALM_INFO.format(url=self.baseurl, realm=realm)
try:
return json.loads(to_native(open_url(realm_info_url, method='GET', headers=self.restheaders,
validate_certs=self.validate_certs).read()))
except HTTPError as e:
if e.code == 404:
return None
else:
self.module.fail_json(msg='Could not obtain realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
except ValueError as e:
self.module.fail_json(msg='API returned incorrect JSON when trying to obtain realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
except Exception as e:
self.module.fail_json(msg='Could not obtain realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
def get_realm_by_id(self, realm='master'):
""" Obtain realm representation by id

View file

@ -0,0 +1,132 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
DOCUMENTATION = '''
---
module: keycloak_realm_info
short_description: Allows obtaining Keycloak realm public information via Keycloak API
version_added: 4.3.0
description:
- This module allows you to get Keycloak realm public information via the Keycloak REST API.
- The names of module options are snake_cased versions of the camelCase ones found in the
Keycloak API and its documentation at U(https://www.keycloak.org/docs-api/8.0/rest-api/index.html).
- Attributes are multi-valued in the Keycloak API. All attributes are lists of individual values and will
be returned that way by this module. You may pass single values for attributes when calling the module,
and this will be translated into a list suitable for the API.
options:
auth_keycloak_url:
description:
- URL to the Keycloak instance.
type: str
required: true
aliases:
- url
validate_certs:
description:
- Verify TLS certificates (do not disable this in production).
type: bool
default: yes
realm:
type: str
description:
- They Keycloak realm ID.
default: 'master'
author:
- Fynn Chen (@fynncfchen)
'''
EXAMPLES = '''
- name: Get a Keycloak public key
community.general.keycloak_realm_info:
realm: MyCustomRealm
auth_keycloak_url: https://auth.example.com/auth
delegate_to: localhost
'''
RETURN = '''
msg:
description: Message as to what action was taken.
returned: always
type: str
realm_info:
description:
- Representation of the realm public infomation.
returned: always
type: dict
contains:
realm:
description: Realm ID.
type: str
returned: always
sample: MyRealm
public_key:
description: Public key of the realm.
type: str
returned: always
sample: MIIBIjANBgkqhkiG9w0BAQEFAAO...
token-service:
description: Token endpoint URL.
type: str
returned: always
sample: https://auth.example.com/auth/realms/MyRealm/protocol/openid-connect
account-service:
description: Account console URL.
type: str
returned: always
sample: https://auth.example.com/auth/realms/MyRealm/account
tokens-not-before:
description: The token not before.
type: int
returned: always
sample: 0
'''
from ansible_collections.community.general.plugins.module_utils.identity.keycloak.keycloak import KeycloakAPI
from ansible.module_utils.basic import AnsibleModule
def main():
"""
Module execution
:return:
"""
argument_spec = dict(
auth_keycloak_url=dict(type='str', aliases=['url'], required=True, no_log=False),
validate_certs=dict(type='bool', default=True),
realm=dict(default='master'),
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
result = dict(changed=False, msg='', realm_info='')
kc = KeycloakAPI(module, {})
realm = module.params.get('realm')
realm_info = kc.get_realm_info_by_id(realm=realm)
result['realm_info'] = realm_info
result['msg'] = 'Get realm public info successful for ID {realm}'.format(realm=realm)
module.exit_json(**result)
if __name__ == '__main__':
main()

View file

@ -0,0 +1 @@
./identity/keycloak/keycloak_realm_info.py