fix(keycloak/ldap): make userObjectClasses JSON-safe and exclude posixAccount

- Render userObjectClasses via `tojson` (and trim) to avoid invalid control
  characters and ensure valid realm import parsing.
- Introduce KEYCLOAK_LDAP_USER_OBJECT_CLASSES in vars; exclude `posixAccount`
  for Keycloak’s LDAP config while keeping it for Ansible-managed UNIX users.
- Update UserStorageProvider template to use the new variable.

Rationale:
Keycloak must not require `posixAccount` on every LDAP user. We keep
`posixAccount` structural for Ansible provisioning, but filter it out for
Keycloak to prevent sync/import errors on entries without POSIX attributes.

Touched:
- roles/web-app-keycloak/templates/import/components/org.keycloak.storage.UserStorageProvider.json.j2
- roles/web-app-keycloak/vars/main.yml

Refs: conversation https://chatgpt.com/share/68aa1ef0-3658-800f-bdf4-5b57131d03b4
This commit is contained in:
Kevin Veen-Birkenbach 2025-08-23 22:05:26 +02:00
parent 6016da6f1f
commit eb781dbf8b
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
2 changed files with 10 additions and 1 deletions

View File

@ -245,7 +245,7 @@
{# Build objectClasses from structural + auxiliary definitions #} {# Build objectClasses from structural + auxiliary definitions #}
"userObjectClasses": [ "userObjectClasses": [
"{{ (ldap.user.objects.structural + (ldap.user.objects.auxiliary | dict2items | map(attribute='value') | list)) | join(', ') }}" {{ KEYCLOAK_LDAP_USER_OBJECT_CLASSES | trim | tojson }}
], ],
"rdnLDAPAttribute": [ "{{ ldap.user.attributes.id }}" ], "rdnLDAPAttribute": [ "{{ ldap.user.attributes.id }}" ],

View File

@ -60,6 +60,15 @@ KEYCLOAK_LDAP_BIND_DN: "{{ ldap.dn.administrator.data }}"
KEYCLOAK_LDAP_BIND_PW: "{{ ldap.bind_credential }}" KEYCLOAK_LDAP_BIND_PW: "{{ ldap.bind_credential }}"
KEYCLOAK_LDAP_URL: "{{ ldap.server.uri }}" KEYCLOAK_LDAP_URL: "{{ ldap.server.uri }}"
# It's important to filter the posixAccount class out, because it is just used by ansible
KEYCLOAK_LDAP_USER_OBJECT_CLASSES: >
{{
(
(ldap.user.objects.structural | reject('equalto','posixAccount') | list)
+ (ldap.user.objects.auxiliary | dict2items | map(attribute='value') | list)
) | join(', ')
}}
## API ## API
KEYCLOAK_MASTER_API_USER: "{{ applications | get_app_conf(application_id, 'users.administrator') }}" # Master Administrator KEYCLOAK_MASTER_API_USER: "{{ applications | get_app_conf(application_id, 'users.administrator') }}" # Master Administrator
KEYCLOAK_MASTER_API_USER_NAME: "{{ KEYCLOAK_MASTER_API_USER.username }}" # Master Administrator Username KEYCLOAK_MASTER_API_USER_NAME: "{{ KEYCLOAK_MASTER_API_USER.username }}" # Master Administrator Username