mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-06-28 11:10:21 -07:00
keycloak: add support for client_credentials authentication (#10231)
Some checks are pending
EOL CI / EOL Sanity (Ⓐ2.16) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py2.7) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.11) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.6) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/3/) (push) Waiting to run
nox / Run extra sanity tests (push) Waiting to run
Some checks are pending
EOL CI / EOL Sanity (Ⓐ2.16) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py2.7) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.11) (push) Waiting to run
EOL CI / EOL Units (Ⓐ2.16+py3.6) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+alpine3+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+fedora38+py:azp/posix/3/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/1/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/2/) (push) Waiting to run
EOL CI / EOL I (Ⓐ2.16+opensuse15+py:azp/posix/3/) (push) Waiting to run
nox / Run extra sanity tests (push) Waiting to run
* add client_credentials authentication for keycloak tasks incl. test case * support client credentials in all keycloak modules * Add changelog fragment * fix typos in required list * Update changelogs/fragments/10231-keycloak-add-client-credentials-authentication.yml Co-authored-by: Felix Fontein <felix@fontein.de> * revert keycloak url in test environment --------- Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
parent
74ed0fc438
commit
f44ca23d7a
27 changed files with 190 additions and 50 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- keycloak - add support for ``grant_type=client_credentials`` to all keycloak modules, so that specifying ``auth_client_id`` and ``auth_client_secret`` is sufficient for authentication (https://github.com/ansible-collections/community.general/pull/10231).
|
|
@ -248,6 +248,29 @@ def _request_token_using_refresh_token(module_params):
|
||||||
return _token_request(module_params, payload)
|
return _token_request(module_params, payload)
|
||||||
|
|
||||||
|
|
||||||
|
def _request_token_using_client_credentials(module_params):
|
||||||
|
""" Obtains connection header with token for the authentication,
|
||||||
|
using the provided auth_client_id and auth_client_secret by grant_type
|
||||||
|
client_credentials. Ensure that the used client uses client authorization
|
||||||
|
with service account roles enabled and required service roles assigned.
|
||||||
|
:param module_params: parameters of the module. Must include 'auth_client_id'
|
||||||
|
and 'auth_client_secret'..
|
||||||
|
:return: connection header
|
||||||
|
"""
|
||||||
|
client_id = module_params.get('auth_client_id')
|
||||||
|
client_secret = module_params.get('auth_client_secret')
|
||||||
|
|
||||||
|
temp_payload = {
|
||||||
|
'grant_type': 'client_credentials',
|
||||||
|
'client_id': client_id,
|
||||||
|
'client_secret': client_secret,
|
||||||
|
}
|
||||||
|
# Remove empty items, for instance missing client_secret
|
||||||
|
payload = {k: v for k, v in temp_payload.items() if v is not None}
|
||||||
|
|
||||||
|
return _token_request(module_params, payload)
|
||||||
|
|
||||||
|
|
||||||
def get_token(module_params):
|
def get_token(module_params):
|
||||||
""" Obtains connection header with token for the authentication,
|
""" Obtains connection header with token for the authentication,
|
||||||
token already given or obtained from credentials
|
token already given or obtained from credentials
|
||||||
|
@ -257,7 +280,13 @@ def get_token(module_params):
|
||||||
token = module_params.get('token')
|
token = module_params.get('token')
|
||||||
|
|
||||||
if token is None:
|
if token is None:
|
||||||
token = _request_token_using_credentials(module_params)
|
auth_client_id = module_params.get('auth_client_id')
|
||||||
|
auth_client_secret = module_params.get('auth_client_secret')
|
||||||
|
auth_username = module_params.get('auth_username')
|
||||||
|
if auth_client_id is not None and auth_client_secret is not None and auth_username is None:
|
||||||
|
token = _request_token_using_client_credentials(module_params)
|
||||||
|
else:
|
||||||
|
token = _request_token_using_credentials(module_params)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'Authorization': 'Bearer ' + token,
|
'Authorization': 'Bearer ' + token,
|
||||||
|
@ -387,6 +416,21 @@ class KeycloakAPI(object):
|
||||||
|
|
||||||
r = make_request_catching_401()
|
r = make_request_catching_401()
|
||||||
|
|
||||||
|
if isinstance(r, Exception):
|
||||||
|
# Try to re-auth with client_id and client_secret, if available
|
||||||
|
auth_client_id = self.module.params.get('auth_client_id')
|
||||||
|
auth_client_secret = self.module.params.get('auth_client_secret')
|
||||||
|
if auth_client_id is not None and auth_client_secret is not None:
|
||||||
|
try:
|
||||||
|
token = _request_token_using_client_credentials(self.module.params)
|
||||||
|
self.restheaders['Authorization'] = 'Bearer ' + token
|
||||||
|
|
||||||
|
r = make_request_catching_401()
|
||||||
|
except KeycloakError as e:
|
||||||
|
# Token refresh returns 400 if token is expired/invalid, so continue on if we get a 400
|
||||||
|
if e.authError is not None and e.authError.code != 400:
|
||||||
|
raise e
|
||||||
|
|
||||||
if isinstance(r, Exception):
|
if isinstance(r, Exception):
|
||||||
# Either no re-auth options were available, or they all failed
|
# Either no re-auth options were available, or they all failed
|
||||||
raise r
|
raise r
|
||||||
|
|
|
@ -367,8 +367,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -237,8 +237,8 @@ def main():
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -153,8 +153,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=(
|
required_one_of=(
|
||||||
[['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
[['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -139,8 +139,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=(
|
required_one_of=(
|
||||||
[['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
[['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -253,8 +253,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=(
|
required_one_of=(
|
||||||
[['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
[['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -134,8 +134,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=(
|
required_one_of=(
|
||||||
[['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
[['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -941,8 +941,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['client_id', 'id'],
|
required_one_of=([['client_id', 'id'],
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -268,8 +268,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -354,8 +354,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['id', 'name'],
|
required_one_of=([['id', 'name'],
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -145,10 +145,10 @@ def keycloak_clientscope_type_module():
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([
|
required_one_of=([
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password'],
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret'],
|
||||||
['default_clientscopes', 'optional_clientscopes']
|
['default_clientscopes', 'optional_clientscopes']
|
||||||
]),
|
]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
mutually_exclusive=[
|
mutually_exclusive=[
|
||||||
['token', 'auth_realm'],
|
['token', 'auth_realm'],
|
||||||
|
|
|
@ -311,8 +311,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['id', 'name'],
|
required_one_of=([['id', 'name'],
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -155,8 +155,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -334,8 +334,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['id', 'name'],
|
required_one_of=([['id', 'name'],
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -500,8 +500,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -705,8 +705,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['id', 'realm', 'enabled'],
|
required_one_of=([['id', 'realm', 'enabled'],
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -263,8 +263,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,8 @@ def main():
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
argument_spec=argument_spec,
|
argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([["token", "auth_realm", "auth_username", "auth_password"]]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -252,8 +252,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -266,8 +266,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -410,8 +410,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -841,8 +841,8 @@ def main():
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['id', 'name'],
|
required_one_of=([['id', 'name'],
|
||||||
['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -242,9 +242,9 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password'],
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret'],
|
||||||
['uid', 'target_username', 'service_account_user_client_id']]),
|
['uid', 'target_username', 'service_account_user_client_id']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -533,8 +533,8 @@ def main():
|
||||||
|
|
||||||
module = AnsibleModule(argument_spec=argument_spec,
|
module = AnsibleModule(argument_spec=argument_spec,
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password']]),
|
required_one_of=([['token', 'auth_realm', 'auth_username', 'auth_password', 'auth_client_id', 'auth_client_secret']]),
|
||||||
required_together=([['auth_realm', 'auth_username', 'auth_password']]),
|
required_together=([['auth_username', 'auth_password']]),
|
||||||
required_by={'refresh_token': 'auth_realm'},
|
required_by={'refresh_token': 'auth_realm'},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,19 @@
|
||||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
# 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
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
- name: Reset public login in master admin-cli (if potentially previous test failed)
|
||||||
|
community.general.keycloak_client:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
auth_client_id: "admin-cli"
|
||||||
|
auth_client_secret: "{{ client_secret }}"
|
||||||
|
client_id: "admin-cli"
|
||||||
|
secret: "{{ client_secret }}"
|
||||||
|
public_client: true
|
||||||
|
state: present
|
||||||
|
|
||||||
- name: Create realm
|
- name: Create realm
|
||||||
community.general.keycloak_realm:
|
community.general.keycloak_realm:
|
||||||
auth_keycloak_url: "{{ url }}"
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
@ -201,6 +214,89 @@
|
||||||
debug:
|
debug:
|
||||||
var: result
|
var: result
|
||||||
|
|
||||||
|
- name: PREPARE - Temporarily disable public login in master admin-cli
|
||||||
|
community.general.keycloak_client:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
auth_client_id: "admin-cli"
|
||||||
|
auth_client_secret: "{{ client_secret }}"
|
||||||
|
client_id: "admin-cli"
|
||||||
|
secret: "{{ client_secret }}"
|
||||||
|
public_client: false
|
||||||
|
service_accounts_enabled: true
|
||||||
|
client_authenticator_type: "client-secret"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: PREPARE - Get admin role id
|
||||||
|
community.general.keycloak_role:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
auth_client_id: "admin-cli"
|
||||||
|
auth_client_secret: "{{ client_secret }}"
|
||||||
|
name: "admin"
|
||||||
|
register: admin_role
|
||||||
|
|
||||||
|
- name: PREPARE - Assign admin role to admin-cli in master
|
||||||
|
community.general.keycloak_user_rolemapping:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
auth_client_id: "admin-cli"
|
||||||
|
auth_client_secret: "{{ client_secret }}"
|
||||||
|
realm: "master"
|
||||||
|
roles:
|
||||||
|
- name: "admin"
|
||||||
|
service_account_user_client_id: "admin-cli"
|
||||||
|
|
||||||
|
- name: Create new realm role with valid client_id and client_secret
|
||||||
|
community.general.keycloak_role:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_client_id: "admin-cli"
|
||||||
|
auth_client_secret: "{{ client_secret }}"
|
||||||
|
realm: "{{ realm }}"
|
||||||
|
name: "{{ role }}"
|
||||||
|
description: "{{ keycloak_role_description }}"
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Debug
|
||||||
|
debug:
|
||||||
|
var: result
|
||||||
|
|
||||||
|
- name: Reset temporarily disabled public login in master admin-cli
|
||||||
|
community.general.keycloak_client:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
auth_client_id: "admin-cli"
|
||||||
|
auth_client_secret: "{{ client_secret }}"
|
||||||
|
client_id: "admin-cli"
|
||||||
|
secret: "{{ client_secret }}"
|
||||||
|
public_client: true
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Remove created realm role
|
||||||
|
community.general.keycloak_role:
|
||||||
|
auth_keycloak_url: "{{ url }}"
|
||||||
|
auth_realm: "{{ admin_realm }}"
|
||||||
|
auth_username: "{{ admin_user }}"
|
||||||
|
auth_password: "{{ admin_password }}"
|
||||||
|
realm: "{{ realm }}"
|
||||||
|
name: "{{ role }}"
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Debug
|
||||||
|
debug:
|
||||||
|
var: result
|
||||||
|
|
||||||
### Unhappy path tests
|
### Unhappy path tests
|
||||||
|
|
||||||
- name: Fail to create new realm role with invalid username/password
|
- name: Fail to create new realm role with invalid username/password
|
||||||
|
@ -215,7 +311,6 @@
|
||||||
state: present
|
state: present
|
||||||
register: result
|
register: result
|
||||||
failed_when: >
|
failed_when: >
|
||||||
(result.exception is not defined) or
|
|
||||||
("HTTP Error 401: Unauthorized" not in result.msg)
|
("HTTP Error 401: Unauthorized" not in result.msg)
|
||||||
|
|
||||||
- name: Fail to create new realm role with invalid auth token
|
- name: Fail to create new realm role with invalid auth token
|
||||||
|
@ -228,7 +323,6 @@
|
||||||
state: present
|
state: present
|
||||||
register: result
|
register: result
|
||||||
failed_when: >
|
failed_when: >
|
||||||
(result.exception is not defined) or
|
|
||||||
("HTTP Error 401: Unauthorized" not in result.msg)
|
("HTTP Error 401: Unauthorized" not in result.msg)
|
||||||
|
|
||||||
- name: Fail to create new realm role with invalid auth and refresh tokens, and invalid username/password
|
- name: Fail to create new realm role with invalid auth and refresh tokens, and invalid username/password
|
||||||
|
@ -245,5 +339,4 @@
|
||||||
state: present
|
state: present
|
||||||
register: result
|
register: result
|
||||||
failed_when: >
|
failed_when: >
|
||||||
(result.exception is not defined) or
|
|
||||||
("HTTP Error 401: Unauthorized" not in result.msg)
|
("HTTP Error 401: Unauthorized" not in result.msg)
|
||||||
|
|
|
@ -9,6 +9,7 @@ admin_user: admin
|
||||||
admin_password: password
|
admin_password: password
|
||||||
realm: myrealm
|
realm: myrealm
|
||||||
client_id: myclient
|
client_id: myclient
|
||||||
|
client_secret: myclientsecret
|
||||||
role: myrole
|
role: myrole
|
||||||
|
|
||||||
keycloak_role_name: test
|
keycloak_role_name: test
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue