Bugfix: keycloak_identity_provider does not handle mapper changes properly (#7418)

* fix keycloak_identity_provider ITs to actually pass

- wrong identityProviderAlias in mapper configuration

* kc_identity_provider: add mapper reconfiguration regression tests

* test for removing an existing mapper
* test for adding a new mapper when others already exist
* test for module idempotency when mappers not ordered by name in ascending order

* kc_identity_provider: add bugfixes for mapper reconfigurations

* removing an existing mapper
* adding a new mapper when others already exist
* module idempotency when mappers not ordered by name in ascending order

* add changelog fragment

* prevent unnecessary update_mapper calls when there is no change

* Update changelogs/fragments/7418-kc_identity_provider-mapper-reconfiguration-fixes.yml

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

* Update changelogs/fragments/7418-kc_identity_provider-mapper-reconfiguration-fixes.yml

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

* Update changelogs/fragments/7418-kc_identity_provider-mapper-reconfiguration-fixes.yml

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

* Update plugins/modules/keycloak_identity_provider.py

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

* kc_identity_provider: sort changeset mappers via name OR id to prevent potential failures in case name was not specified in playbook

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

---------

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Jakub Danek 2023-12-28 09:50:01 +01:00 committed by GitHub
commit fd0d05d6f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 10 deletions

View file

@ -542,10 +542,14 @@ def main():
old_mapper = dict()
new_mapper = old_mapper.copy()
new_mapper.update(change)
if new_mapper != old_mapper:
if changeset.get('mappers') is None:
changeset['mappers'] = list()
changeset['mappers'].append(new_mapper)
if changeset.get('mappers') is None:
changeset['mappers'] = list()
# eventually this holds all desired mappers, unchanged, modified and newly added
changeset['mappers'].append(new_mapper)
# ensure idempotency in case module.params.mappers is not sorted by name
changeset['mappers'] = sorted(changeset['mappers'], key=lambda x: x.get('id') if x.get('name') is None else x['name'])
# Prepare the desired values using the existing values (non-existence results in a dict that is save to use as a basis)
desired_idp = before_idp.copy()
@ -612,10 +616,17 @@ def main():
# do the update
desired_idp = desired_idp.copy()
updated_mappers = desired_idp.pop('mappers', [])
original_mappers = list(before_idp.get('mappers', []))
kc.update_identity_provider(desired_idp, realm)
for mapper in updated_mappers:
if mapper.get('id') is not None:
kc.update_identity_provider_mapper(mapper, alias, realm)
# only update existing if there is a change
for i, orig in enumerate(original_mappers):
if mapper['id'] == orig['id']:
del original_mappers[i]
if mapper != orig:
kc.update_identity_provider_mapper(mapper, alias, realm)
else:
if mapper.get('identityProviderAlias') is None:
mapper['identityProviderAlias'] = alias