Files
computer-playbook/roles/web-app-openbao/tasks/04_auth_methods.yml
kevinveenbirkenbachandClaude Opus 5.5 c925150848 fix(web-app-openbao): ship the LDAP auth method as an external plugin
OpenBao 2.7 removed the builtin LDAP auth engine from the server binary
(openbao/openbao GH-3882). `bao auth enable ldap` answered
"plugin not found in the catalog: ldap" and the deploy stopped there.

The role now builds its own image. A multi-stage Dockerfile copies the
openbao-plugin-auth-ldap binary out of the image declared as the
`auth-ldap` service entry into /opt/openbao/plugins. A second server
config file, plugins.hcl, names that directory and registers the plugin
declaratively. It sets plugin_auto_register = true explicitly: the image
starts the server with a config directory, and on that path 2.7.1 does
not apply the documented default, so without the line the catalog stays
empty. The Dockerfile sets the file mode in a helper stage instead of
COPY --chmod, which only BuildKit accepts.

The mount is enabled with -plugin-version=latest, so it follows whichever
plugin version the image ships. A mount created by the former builtin
engine is tuned and reloaded onto the plugin, which needs `update` on
sys/plugins/reload/backend in the ansible-admin policy.

The LDAP tasks move into tasks/addons/auth-ldap.yml and the plugin is
declared under meta/addons as a required addon bridged to `ldap`. Its
Playwright spec logs in through the mount and asserts that sys/auth
reports an external running plugin version.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 13:25:17 +02:00

114 lines
4.9 KiB
YAML

---
- name: "📇 Configure the OIDC auth method against Keycloak"
when: OPENBAO_SSO_ENABLED | bool
block:
- name: "🧩 Enable the OIDC auth method"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ OPENBAO_LOCAL_CID | quote }}
sh -c 'bao auth list -format=json | grep -q "oidc/" ||
{ bao auth enable oidc && echo OPENBAO_CHANGED; }'
register: openbao_oidc_enable
changed_when: "'OPENBAO_CHANGED' in openbao_oidc_enable.stdout"
delegate_to: "{{ OPENBAO_HOST_NODE }}"
- name: "📇 Point the OIDC method at the Keycloak realm"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec -i {{ OPENBAO_LOCAL_CID | quote }}
bao write auth/oidc/config
oidc_discovery_url={{ OPENBAO_OIDC_ISSUER | quote }}
oidc_client_id={{ OPENBAO_OIDC_CLIENT_ID | quote }}
oidc_client_secret=-
default_role={{ OPENBAO_OIDC_DEFAULT_ROLE | quote }}
args:
stdin: "{{ OPENBAO_OIDC_CLIENT_SECRET }}"
stdin_add_newline: false
changed_when: false
delegate_to: "{{ OPENBAO_HOST_NODE }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
- name: "📇 Configure the default OIDC role, which grants only the 'default' policy"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ OPENBAO_LOCAL_CID | quote }}
sh -c 'set -e;
p=auth/oidc/role/{{ OPENBAO_OIDC_DEFAULT_ROLE }};
before=$(bao read -format=json $p 2>/dev/null | grep -v request_id || true);
bao write $p role_type=oidc
user_claim={{ OPENBAO_OIDC_USER_CLAIM | quote }}
groups_claim={{ OPENBAO_OIDC_GROUPS_CLAIM | quote }}
oidc_scopes=openid,profile,email
token_policies=default
allowed_redirect_uris={{ OPENBAO_OIDC_REDIRECT_URIS | quote }} >/dev/null;
after=$(bao read -format=json $p | grep -v request_id);
[ "$before" = "$after" ] || echo OPENBAO_CHANGED'
register: openbao_oidc_role
changed_when: "'OPENBAO_CHANGED' in openbao_oidc_role.stdout"
delegate_to: "{{ OPENBAO_HOST_NODE }}"
- name: "📇 Configure the LDAP auth method against svc-db-openldap"
ansible.builtin.include_tasks:
file: addons/auth-ldap.yml
apply:
delegate_to: "{{ OPENBAO_HOST_NODE }}"
when: OPENBAO_LDAP_ENABLED | bool
- name: "🔍 Read the auth mount accessors"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ OPENBAO_LOCAL_CID | quote }}
bao auth list -format=json
register: openbao_auth_list
changed_when: false
delegate_to: "{{ OPENBAO_HOST_NODE }}"
- name: "🔧 Keep the auth mount table, keyed by mount path such as 'oidc/'"
ansible.builtin.set_fact:
openbao_auth_mounts: "{{ openbao_auth_list.stdout | from_json }}"
- name: "👥 Upsert the external identity group per RBAC role"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ OPENBAO_LOCAL_CID | quote }}
sh -c 'set -e;
p=identity/group/name/{{ item }};
before=$(bao read -field=policies $p 2>/dev/null || true);
bao write $p type=external policies={{ item | quote }} >/dev/null;
after=$(bao read -field=policies $p);
[ "$before" = "$after" ] || echo OPENBAO_CHANGED'
loop: "{{ OPENBAO_RBAC_ROLES }}"
register: openbao_identity_group
changed_when: "'OPENBAO_CHANGED' in openbao_identity_group.stdout"
delegate_to: "{{ OPENBAO_HOST_NODE }}"
- name: "🔍 Read the identity group ids"
ansible.builtin.shell: > # nocheck: container-exec-resolver runtime-resolved CID, delegated to the hosting node
container exec {{ OPENBAO_LOCAL_CID | quote }}
bao read -field=id identity/group/name/{{ item | quote }}
loop: "{{ OPENBAO_RBAC_ROLES }}"
register: openbao_group_ids
changed_when: false
delegate_to: "{{ OPENBAO_HOST_NODE }}"
- name: "🔗 Bind each Keycloak group path to its OpenBao identity group"
ansible.builtin.include_tasks:
file: utils/group_alias.yml
apply:
delegate_to: "{{ OPENBAO_HOST_NODE }}"
loop: "{{ openbao_group_ids.results }}"
loop_control:
loop_var: openbao_group
vars:
alias_mount: "oidc/"
alias_name: "/{{ lookup('rbac_group_path', application_id=application_id, role=openbao_group.item) }}"
when: OPENBAO_SSO_ENABLED | bool
- name: "🔗 Bind each LDAP role group to its OpenBao identity group"
ansible.builtin.include_tasks:
file: utils/group_alias.yml
apply:
delegate_to: "{{ OPENBAO_HOST_NODE }}"
loop: "{{ openbao_group_ids.results }}"
loop_control:
loop_var: openbao_group
vars:
alias_mount: "ldap/"
alias_name: "{{ application_id }}-{{ openbao_group.item }}"
when: OPENBAO_LDAP_ENABLED | bool