computer-playbook/roles/web-app-keycloak/tasks/03_update-ldap-bind.yml
Kevin Veen-Birkenbach 4fa1c6cfbd
ansible: quote file modes; keycloak: robust LDAP bind update + config cleanup
Highlights
- Quote all file modes as strings ("0755"/"0770") across multiple roles to avoid YAML octal quirks and improve portability.
- Keycloak: introduce actions.{import_realm,update_ldap_bind} feature flags and wire them via vars/config.
- Implement idempotent LDAP bind updater (tasks/03_update-ldap-bind.yml):
  * kcadm login with no_log protection,
  * fetch LDAP UserStorage component by name,
  * compare current bindDn/bindCredential and update only when changed.
- Keycloak realm import template: keep providerId="ldap" and set name from keycloak_ldap_component_name.
- Centralize Keycloak readiness check in tasks/main.yml; remove duplicate waits from 02_update_client_redirects.yml and 04_ssh_public_key.yml.
- 01_import.yml: fix typo (keycloak), quote modes, tidy spacing, and replace Jinja-in-Jinja fileglob with concatenation.
- 02_update_client_redirects.yml: correct assert fail_msg filename; keep login-first flow.
- Minor template/vars tidy-ups (spacing, comments, consistent variable usage).

Files touched (excerpt)
- roles/*/*: replace 0755/0770 → "0755"/"0770"
- roles/web-app-keycloak/config/main.yml: add actions map
- roles/web-app-keycloak/vars/main.yml: unify Keycloak vars and feature flags
- roles/web-app-keycloak/tasks/{01_import,02_update_client_redirects,03_update-ldap-bind,04_ssh_public_key,main}.yml
- roles/web-app-keycloak/templates/{docker-compose.yml.j2,import/realm.json.j2}

https://chatgpt.com/share/689bda16-b138-800f-8258-e13f6d7d8239
2025-08-13 02:20:38 +02:00

81 lines
3.0 KiB
YAML

---
# Updates the LDAP provider's bind DN / password using kcadm.sh, idempotently.
# Sources DN/password from group_vars/all/13_ldap.yml:
# - DN: ldap.dn.administrator.data
# - Password: ldap.bind_credential
- name: "Assert required vars exist"
assert:
that:
- keycloak_realm is defined
- keycloak_server_host_url is defined
- keycloak_server_internal_url is defined
- keycloak_kcadm_path is defined
- keycloak_master_api_user_name is defined
- keycloak_master_api_user_password is defined
- keycloak_ldap_component_name is defined
- ldap is defined
- ldap.dn.administrator.data is defined
- ldap.bind_credential is defined
fail_msg: "Missing Keycloak/LDAP vars. Ensure 13_ldap.yml is loaded and credentials are set."
- name: "kcadm login (master)"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
shell: >
{{ keycloak_kcadm_path }} config credentials
--server {{ keycloak_server_internal_url }}
--realm master
--user {{ keycloak_master_api_user_name }}
--password {{ keycloak_master_api_user_password }}
changed_when: false
# Resolve the LDAP component *by name* to avoid picking the wrong one.
- name: "Resolve LDAP component id by name '{{ keycloak_ldap_component_name }}'"
shell: >
{{ keycloak_kcadm_path }} get components
-r {{ keycloak_realm }}
--query 'name={{ keycloak_ldap_component_name }}'
--fields id,name,providerId,config --format json
register: kc_ldap_list
changed_when: false
- name: "Validate that exactly one LDAP component matched"
vars:
parsed: "{{ kc_ldap_list.stdout | from_json }}"
assert:
that:
- (parsed | length) == 1
fail_msg: >-
Expected exactly one LDAP component named '{{ keycloak_ldap_component_name }}',
found {{ (kc_ldap_list.stdout | from_json) | length }}.
- name: "Extract LDAP component facts"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
set_fact:
kc_ldap_component_id: "{{ (kc_ldap_list.stdout | from_json)[0].id }}"
kc_ldap_current_bind_dn: "{{ ((kc_ldap_list.stdout | from_json)[0].config['bindDn'] | default(['']))[0] }}"
kc_ldap_current_bind_pw: "{{ ((kc_ldap_list.stdout | from_json)[0].config['bindCredential'] | default(['']))[0] }}"
- name: "Determine if update is required"
set_fact:
kc_needs_update: >-
{{ (kc_ldap_current_bind_dn != ldap.dn.administrator.data)
or (kc_ldap_current_bind_pw != ldap.bind_credential) }}
- name: "Update LDAP bind DN / bind password"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
shell: >
{{ keycloak_kcadm_path }} update components/{{ kc_ldap_component_id }}
-r {{ keycloak_realm }}
-s 'config.bindDn=["{{ ldap.dn.administrator.data | replace("'", "\\'") }}"]'
-s 'config.bindCredential=["{{ ldap.bind_credential | replace("'", "\\'") }}"]'
when: kc_needs_update | bool
register: kc_bind_update
- name: "LDAP bind credentials updated"
debug:
msg: "LDAP bind DN/password updated on component {{ keycloak_ldap_component_name }}."
when:
- kc_bind_update is defined
- kc_bind_update.rc == 0