Keycloak: add realm management (#2155)

* Keycloak: add realm management

* Minor fixes

* Review fixes

* Remove sort of list because condition on list cannot be true

* Add exception in fail_json and update test

* Change output for secret and version in comments

* Update copyright

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

* Add missing traceback

* Apply suggestions from code review

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

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
kris2kris 2021-04-21 12:42:28 +02:00 committed by GitHub
commit cecbc2be2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 1171 additions and 0 deletions

View file

@ -30,12 +30,16 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type
import json
import traceback
from ansible.module_utils.urls import open_url
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible.module_utils._text import to_native
URL_REALMS = "{url}/realms"
URL_REALM = "{url}/realms/{realm}"
URL_TOKEN = "{url}/realms/{realm}/protocol/openid-connect/token"
URL_CLIENT = "{url}/admin/realms/{realm}/clients/{id}"
URL_CLIENTS = "{url}/admin/realms/{realm}/clients"
@ -138,6 +142,75 @@ class KeycloakAPI(object):
self.validate_certs = self.module.params.get('validate_certs')
self.restheaders = connection_header
def get_realm_by_id(self, realm='master'):
""" Obtain realm representation by id
:param realm: realm id
:return: dict of real, representation or None if none matching exist
"""
realm_url = URL_REALM.format(url=self.baseurl, realm=realm)
try:
return json.loads(to_native(open_url(realm_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 update_realm(self, realmrep, realm="master"):
""" Update an existing realm
:param realmrep: corresponding (partial/full) realm representation with updates
:param realm: realm to be updated in Keycloak
:return: HTTPResponse object on success
"""
realm_url = URL_REALM.format(url=self.baseurl, realm=realm)
try:
return open_url(realm_url, method='PUT', headers=self.restheaders,
data=json.dumps(realmrep), validate_certs=self.validate_certs)
except Exception as e:
self.module.fail_json(msg='Could not update realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
def create_realm(self, realmrep):
""" Create a realm in keycloak
:param realmrep: Realm representation of realm to be created.
:return: HTTPResponse object on success
"""
realm_url = URL_REALMS.format(url=self.baseurl)
try:
return open_url(realm_url, method='POST', headers=self.restheaders,
data=json.dumps(realmrep), validate_certs=self.validate_certs)
except Exception as e:
self.module.fail_json(msg='Could not create realm %s: %s' % (realmrep['id'], str(e)),
exception=traceback.format_exc())
def delete_realm(self, realm="master"):
""" Delete a realm from Keycloak
:param realm: realm to be deleted
:return: HTTPResponse object on success
"""
realm_url = URL_REALM.format(url=self.baseurl, realm=realm)
try:
return open_url(realm_url, method='DELETE', headers=self.restheaders,
validate_certs=self.validate_certs)
except Exception as e:
self.module.fail_json(msg='Could not delete realm %s: %s' % (realm, str(e)),
exception=traceback.format_exc())
def get_clients(self, realm='master', filter=None):
""" Obtains client representations for clients in a realm