mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-09-11 21:07:16 +02:00
XWiki: LDAP/OIDC admin mapping, config mounts, and REST installs
- LDAP: move settings to xwiki.cfg; enable trylocal (1/0), group_mapping to XWiki.XWikiAdminGroup, and mode_group_sync=always. - OIDC: add groups claim request (oidc.userinfoclaims), map provider group to XWiki.XWikiAdminGroup, and use space-separated scopes. - Compose: mount xwiki.cfg and xwiki.properties into /usr/local/xwiki. - Extensions: wait for REST readiness; pre-check OIDC/LDAP extensions (URL-encoded IDs); install via REST job only if missing. - Vars: strict mappings to LDAP.* and OIDC.* (no defaults), add XWIKI_ADMIN_GROUP and derived DNs. - Config: expose ldap.local_enabled; tidy meta tags; README grammar update. Conversation: https://chatgpt.com/share/68c2b8ad-4814-800f-b377-065f967998db
This commit is contained in:
@@ -6,7 +6,7 @@ Empower your organization with **XWiki**, an open-source enterprise wiki and kno
|
||||
|
||||
## Overview
|
||||
|
||||
This role deploys XWiki using Docker, automating the installation, configuration, and management of your XWiki server. It integrates with an external PostgreSQL database, Redis for caching and sessions, and an Nginx reverse proxy. The role supports advanced features such as global CSS injection, Matomo analytics, OIDC authentication, and centralized logout, making it a powerful and customizable solution within the Infinito.Nexus ecosystem.
|
||||
This role deploys XWiki using Docker, automating the installation, configuration, and management of your XWiki server. It integrates with an MariaDB database and an Nginx reverse proxy. The role supports advanced features such as global CSS injection, Matomo analytics, OIDC authentication, and centralized logout, making it a powerful and customizable solution within the Infinito.Nexus ecosystem.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -17,7 +17,6 @@ This role deploys XWiki using Docker, automating the installation, configuration
|
||||
- **Office Integration:** Import, export, and collaborate on Office documents (Word, Excel, PDF).
|
||||
- **Customization & Theming:** Adapt the look and feel of your wiki with skins, CSS, and scripting.
|
||||
- **Integration Ready:** Connect with external systems such as Keycloak (OIDC), LDAP, or analytics tools like Matomo.
|
||||
- **Scalability:** Backend support with PostgreSQL and Redis for performance and session handling.
|
||||
|
||||
## Further Resources
|
||||
|
||||
|
@@ -29,3 +29,5 @@ server:
|
||||
- "x.wiki.{{ PRIMARY_DOMAIN }}"
|
||||
rbac:
|
||||
roles: {}
|
||||
ldap:
|
||||
local_enabled: true # Allows local login if LDAP is down
|
||||
|
@@ -8,7 +8,10 @@ galaxy_info:
|
||||
Kevin Veen-Birkenbach
|
||||
Consulting & Coaching Solutions
|
||||
https://www.veen.world
|
||||
galaxy_tags: [wiki, collaboration, knowledge, documentation, cms]
|
||||
galaxy_tags:
|
||||
- wiki
|
||||
- documentation
|
||||
- xwiki
|
||||
repository: "https://s.infinito.nexus/code"
|
||||
issue_tracker_url: "https://s.infinito.nexus/issues"
|
||||
documentation: "https://s.infinito.nexus/code/"
|
||||
|
68
roles/web-app-xwiki/tasks/01_core.yml
Normal file
68
roles/web-app-xwiki/tasks/01_core.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
- name: "load docker, db and proxy for {{ application_id }}"
|
||||
include_role:
|
||||
name: sys-stk-full-stateful
|
||||
vars:
|
||||
docker_compose_flush_handlers: false
|
||||
|
||||
- name: "Render xwiki.cfg"
|
||||
template:
|
||||
src: "xwiki.cfg.j2"
|
||||
dest: "{{ XWIKI_HOST_CONF_PATH }}"
|
||||
notify: docker compose up
|
||||
|
||||
- name: "Render xwiki.properties"
|
||||
template:
|
||||
src: "xwiki.properties.j2"
|
||||
dest: "{{ XWIKI_HOST_PROPERTIES_PATH }}"
|
||||
notify: docker compose up
|
||||
|
||||
- name: "flush docker compose for '{{ application_id }}'"
|
||||
meta: flush_handlers
|
||||
|
||||
- name: "Wait until XWiki REST is ready"
|
||||
uri:
|
||||
url: "http://127.0.0.1:{{ XWIKI_HOST_PORT }}/xwiki/rest/"
|
||||
status_code: [200, 401]
|
||||
return_content: no
|
||||
register: xwiki_rest_up
|
||||
retries: 60
|
||||
delay: 5
|
||||
until: xwiki_rest_up is succeeded
|
||||
|
||||
- name: "Check if OIDC extension installed"
|
||||
uri:
|
||||
url: "http://127.0.0.1:{{ XWIKI_HOST_PORT }}/xwiki/rest/wikis/xwiki/extensions/{{ XWIKI_EXT_OIDC_ID | urlencode }}"
|
||||
method: GET
|
||||
user: "{{ XWIKI_ADMIN_USER }}"
|
||||
password: "{{ XWIKI_ADMIN_PASS }}"
|
||||
force_basic_auth: yes
|
||||
status_code: [200,404]
|
||||
register: xwiki_oidc_ext
|
||||
when: XWIKI_OIDC_ENABLED | bool
|
||||
|
||||
- name: "Check if LDAP extension installed"
|
||||
uri:
|
||||
url: "http://127.0.0.1:{{ XWIKI_HOST_PORT }}/xwiki/rest/wikis/xwiki/extensions/{{ XWIKI_EXT_LDAP_ID | urlencode }}"
|
||||
method: GET
|
||||
user: "{{ XWIKI_ADMIN_USER }}"
|
||||
password: "{{ XWIKI_ADMIN_PASS }}"
|
||||
force_basic_auth: yes
|
||||
status_code: [200,404]
|
||||
register: xwiki_ldap_ext
|
||||
when: XWIKI_LDAP_ENABLED | bool
|
||||
|
||||
- name: "Install LDAP and/or OIDC extensions"
|
||||
uri:
|
||||
url: "{{ XWIKI_REST_BASE }}"
|
||||
method: PUT
|
||||
user: "{{ XWIKI_ADMIN_USER }}"
|
||||
password: "{{ XWIKI_ADMIN_PASS }}"
|
||||
force_basic_auth: yes
|
||||
headers: { Content-Type: "text/xml" }
|
||||
body: "{{ lookup('template', 'installjobrequest.xml.j2') }}"
|
||||
status_code: 200
|
||||
when:
|
||||
- (XWIKI_OIDC_ENABLED | bool and xwiki_oidc_ext.status == 404) or
|
||||
(XWIKI_LDAP_ENABLED | bool and (xwiki_ldap_ext is not skipped) and xwiki_ldap_ext.status == 404)
|
||||
|
||||
- include_tasks: utils/run_once.yml
|
@@ -1,7 +1,4 @@
|
||||
---
|
||||
- block:
|
||||
- name: "load docker, db and proxy for {{ application_id }}"
|
||||
include_role:
|
||||
name: sys-stk-full-stateful
|
||||
- include_tasks: utils/run_once.yml
|
||||
- include_tasks: 01_core.yml
|
||||
when: run_once_web_app_xwiki is not defined
|
||||
|
@@ -7,8 +7,10 @@
|
||||
container_name: "{{ XWIKI_CONTAINER }}"
|
||||
hostname: '{{ XWIKI_HOSTNAME}}'
|
||||
ports:
|
||||
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:{{ container_port }}"
|
||||
- "127.0.0.1:{{ XWIKI_HOST_PORT }}:{{ container_port }}"
|
||||
volumes:
|
||||
- "{{ XWIKI_HOST_CONF_PATH }}:/usr/local/xwiki/xwiki.cfg"
|
||||
- "{{ XWIKI_HOST_PROPERTIES_PATH }}:/usr/local/xwiki/xwiki.properties"
|
||||
- 'data:/usr/local/xwiki'
|
||||
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
|
@@ -3,27 +3,3 @@ DB_PASSWORD="{{ database_password }}"
|
||||
DB_HOST="{{ database_host }}"
|
||||
DB_PORT="{{ database_port }}"
|
||||
DB_DATABASE="{{ database_name }}"
|
||||
|
||||
### Pretix core
|
||||
#XWIKI_XWIKI_INSTANCE_NAME="{{ PRIMARY_DOMAIN | upper }} Tickets"
|
||||
#XWIKI_XWIKI_ALLOWED_HOSTS="{{ XWIKI_HOSTNAME }},127.0.0.1,localhost"
|
||||
#XWIKI_XWIKI_URL="{{ XWIKI_URL }}"
|
||||
#XWIKI_XWIKI_AUTH_BACKENDS="xwiki.base.auth.NativeAuthBackend{% if XWIKI_OIDC_ENABLED %},xwiki_oidc.auth.OIDCAuthBackend{% endif %}"
|
||||
#
|
||||
### Locale
|
||||
#XWIKI_LOCALE_TIMEZONE="{{ HOST_TIMEZONE }}"
|
||||
#
|
||||
#{% if XWIKI_OIDC_ENABLED %}
|
||||
### OIDC (plugin)
|
||||
#XWIKI_OIDC_TITLE="{{ XWIKI_OIDC_LABEL | replace('\"','\\\"') }}"
|
||||
#XWIKI_OIDC_ISSUER="{{ XWIKI_OIDC_ISSUER }}"
|
||||
#XWIKI_OIDC_AUTHORIZATION_ENDPOINT="{{ XWIKI_OIDC_AUTH_URL }}"
|
||||
#XWIKI_OIDC_TOKEN_ENDPOINT="{{ XWIKI_OIDC_TOKEN_URL }}"
|
||||
#XWIKI_OIDC_USERINFO_ENDPOINT="{{ XWIKI_OIDC_USERINFO_URL }}"
|
||||
#XWIKI_OIDC_END_SESSION_ENDPOINT="{{ XWIKI_OIDC_LOGOUT_URL }}"
|
||||
#XWIKI_OIDC_JWKS_URI="{{ XWIKI_OIDC_JWKS_URL }}"
|
||||
#XWIKI_OIDC_CLIENT_ID="{{ XWIKI_OIDC_CLIENT_ID }}"
|
||||
#XWIKI_OIDC_CLIENT_SECRET="{{ XWIKI_OIDC_CLIENT_SECRET }}"
|
||||
#XWIKI_OIDC_SCOPES="{{ XWIKI_OIDC_SCOPES }}"
|
||||
#XWIKI_OIDC_UNIQUE_ATTRIBUTE="{{ XWIKI_OIDC_UNIQUE_ATTRIBUTE }}"
|
||||
#{% endif %}
|
||||
|
27
roles/web-app-xwiki/templates/installjobrequest.xml.j2
Normal file
27
roles/web-app-xwiki/templates/installjobrequest.xml.j2
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jobRequest xmlns="http://www.xwiki.org">
|
||||
<id>install-extensions</id>
|
||||
<jobType>install</jobType>
|
||||
<request>
|
||||
<namespace>wiki:xwiki</namespace>
|
||||
<interactive>false</interactive>
|
||||
<verbose>true</verbose>
|
||||
<installDependencies>true</installDependencies>
|
||||
<extensions>
|
||||
{% if XWIKI_LDAP_ENABLED | bool %}
|
||||
<extension>
|
||||
<id>{{ XWIKI_EXT_LDAP_ID }}</id>
|
||||
<version>{{ XWIKI_EXT_LDAP_VERSION }}</version>
|
||||
<namespace>wiki:xwiki</namespace>
|
||||
</extension>
|
||||
{% endif %}
|
||||
{% if XWIKI_OIDC_ENABLED | bool %}
|
||||
<extension>
|
||||
<id>{{ XWIKI_EXT_OIDC_ID }}</id>
|
||||
<version>{{ XWIKI_EXT_OIDC_VERSION }}</version>
|
||||
<namespace>wiki:xwiki</namespace>
|
||||
</extension>
|
||||
{% endif %}
|
||||
</extensions>
|
||||
</request>
|
||||
</jobRequest>
|
20
roles/web-app-xwiki/templates/xwiki.cfg.j2
Normal file
20
roles/web-app-xwiki/templates/xwiki.cfg.j2
Normal file
@@ -0,0 +1,20 @@
|
||||
# ---- Authentication selection
|
||||
{% if XWIKI_OIDC_ENABLED | bool %}
|
||||
xwiki.authentication.authclass=org.xwiki.contrib.oidc.auth.OIDCAuthServiceImpl
|
||||
{% elif XWIKI_LDAP_ENABLED | bool %}
|
||||
xwiki.authentication.authclass=org.xwiki.contrib.ldap.XWikiLDAPAuthServiceImpl
|
||||
xwiki.authentication.ldap=1
|
||||
xwiki.authentication.ldap.trylocal={{ (XWIKI_LDAP_TRYLOCAL | bool) | ternary(1, 0) }}
|
||||
xwiki.authentication.ldap.group_mapping=XWiki.XWikiAdminGroup={{ XWIKI_LDAP_ADMIN_GROUP_DN }}
|
||||
xwiki.authentication.ldap.mode_group_sync=always
|
||||
xwiki.authentication.ldap.server={{ XWIKI_LDAP_SERVER }}
|
||||
xwiki.authentication.ldap.port={{ XWIKI_LDAP_PORT }}
|
||||
xwiki.authentication.ldap.base_DN={{ XWIKI_LDAP_BASE_DN }}
|
||||
xwiki.authentication.ldap.bind_DN={{ XWIKI_LDAP_BIND_DN }}
|
||||
xwiki.authentication.ldap.bind_pass={{ XWIKI_LDAP_BIND_PASS }}
|
||||
xwiki.authentication.ldap.fields_mapping={{ XWIKI_LDAP_FIELDS_MAPPING }}
|
||||
xwiki.authentication.ldap.update_user=1
|
||||
{% else %}
|
||||
# Fallback: Native XWiki Auth
|
||||
# xwiki.authentication.authclass=com.xpn.xwiki.user.impl.xwiki.XWikiAuthServiceImpl
|
||||
{% endif %}
|
16
roles/web-app-xwiki/templates/xwiki.properties.j2
Normal file
16
roles/web-app-xwiki/templates/xwiki.properties.j2
Normal file
@@ -0,0 +1,16 @@
|
||||
############################################
|
||||
# OIDC
|
||||
{% if XWIKI_OIDC_ENABLED | bool %}
|
||||
oidc.provider={{ XWIKI_OIDC_PROVIDER }}
|
||||
oidc.endpoint.authorization={{ XWIKI_OIDC_AUTHORIZATION }}
|
||||
oidc.endpoint.token={{ XWIKI_OIDC_TOKEN }}
|
||||
oidc.endpoint.userinfo={{ XWIKI_OIDC_USERINFO }}
|
||||
oidc.endpoint.logout={{ XWIKI_OIDC_LOGOUT }}
|
||||
oidc.clientid={{ XWIKI_OIDC_CLIENT_ID }}
|
||||
oidc.secret={{ XWIKI_OIDC_CLIENT_SECRET }}
|
||||
oidc.scope={{ XWIKI_OIDC_SCOPES }}
|
||||
oidc.enableUser=true
|
||||
oidc.userinfoclaims={{ XWIKI_OIDC_GROUPS_CLAIM }}
|
||||
oidc.groups.claim={{ XWIKI_OIDC_GROUPS_CLAIM }}
|
||||
oidc.groups.mapping=XWiki.XWikiAdminGroup={{ XWIKI_OIDC_ADMIN_PROVIDER_GROUP }}
|
||||
{% endif %}
|
@@ -1,33 +1,63 @@
|
||||
# General
|
||||
application_id: "web-app-xwiki"
|
||||
database_type: "mariadb"
|
||||
container_port: 8080
|
||||
container_hostname: "{{ domains | get_domain(application_id) }}"
|
||||
application_id: "web-app-xwiki"
|
||||
database_type: "mariadb"
|
||||
container_port: 8080
|
||||
container_hostname: "{{ domains | get_domain(application_id) }}"
|
||||
|
||||
# Pretix
|
||||
# XWiki
|
||||
|
||||
XWIKI_HOST_PORT: "{{ ports.localhost.http[application_id] }}"
|
||||
|
||||
## URLs
|
||||
XWIKI_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}"
|
||||
XWIKI_HOSTNAME: "{{ container_hostname }}"
|
||||
XWIKI_HOSTNAME: "{{ container_hostname }}"
|
||||
|
||||
## OIDC (mirrors GitLab’s pattern)
|
||||
XWIKI_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}"
|
||||
XWIKI_OIDC_LABEL: "{{ OIDC.BUTTON_TEXT }}"
|
||||
XWIKI_OIDC_CLIENT_ID: "{{ OIDC.CLIENT.ID }}"
|
||||
XWIKI_OIDC_CLIENT_SECRET: "{{ OIDC.CLIENT.SECRET }}"
|
||||
XWIKI_OIDC_ISSUER: "{{ OIDC.CLIENT.ISSUER_URL }}"
|
||||
XWIKI_OIDC_AUTH_URL: "{{ OIDC.CLIENT.AUTHORIZE_URL }}"
|
||||
XWIKI_OIDC_TOKEN_URL: "{{ OIDC.CLIENT.TOKEN_URL }}"
|
||||
XWIKI_OIDC_USERINFO_URL: "{{ OIDC.CLIENT.USER_INFO_URL }}"
|
||||
XWIKI_OIDC_LOGOUT_URL: "{{ OIDC.CLIENT.LOGOUT_URL }}"
|
||||
XWIKI_OIDC_JWKS_URL: "{{ OIDC.CLIENT.CERTS }}"
|
||||
XWIKI_OIDC_SCOPES: "openid,email,profile"
|
||||
# Use Keycloak username claim by default (plugin default is 'sub')
|
||||
XWIKI_OIDC_UNIQUE_ATTRIBUTE: "{{ OIDC.ATTRIBUTES.USERNAME }}"
|
||||
## Paths
|
||||
XWIKI_HOST_CONF_PATH: "{{ [docker_compose.directories.config, 'xwiki.cfg'] | path_join }}"
|
||||
XWIKI_HOST_PROPERTIES_PATH: "{{ [docker_compose.directories.config, 'xwiki.properties'] | path_join }}"
|
||||
|
||||
## Docker
|
||||
XWIKI_IMAGE_CUSTOM: "xwiki_custom"
|
||||
XWIKI_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.xwiki.image') }}"
|
||||
XWIKI_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.xwiki.version') }}"
|
||||
XWIKI_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.xwiki.name') }}"
|
||||
XWIKI_DATA_VOLUME: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}"
|
||||
XWIKI_IMAGE_CUSTOM: "xwiki_custom"
|
||||
XWIKI_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.xwiki.image') }}"
|
||||
XWIKI_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.xwiki.version') }}"
|
||||
XWIKI_CONTAINER: "{{ applications | get_app_conf(application_id, 'docker.services.xwiki.name') }}"
|
||||
XWIKI_DATA_VOLUME: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}"
|
||||
|
||||
# Feature toggles (must be set in config/main.yml -> features)
|
||||
XWIKI_LDAP_ENABLED: "{{ applications | get_app_conf(application_id, 'features.ldap') }}"
|
||||
XWIKI_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}"
|
||||
|
||||
# Admin credentials (must be provided via inventory/vault)
|
||||
XWIKI_ADMIN_USER: "{{ users.administrator.username }}"
|
||||
XWIKI_ADMIN_PASS: "{{ users.administrator.password }}"
|
||||
XWIKI_ADMIN_GROUP: "{{ application_id }}-administrator"
|
||||
|
||||
# REST endpoint (local inside container)
|
||||
XWIKI_REST_BASE: "http://127.0.0.1:{{ XWIKI_HOST_PORT }}/xwiki/rest/jobs?jobType=install&async=false"
|
||||
|
||||
# Extension IDs + Versions (pin versions explicitly)
|
||||
XWIKI_EXT_LDAP_ID: "org.xwiki.contrib.ldap:ldap-authenticator"
|
||||
XWIKI_EXT_LDAP_VERSION: "9.15.7"
|
||||
XWIKI_EXT_OIDC_ID: "org.xwiki.contrib.oidc:oidc-authenticator"
|
||||
XWIKI_EXT_OIDC_VERSION: "2.19.2"
|
||||
|
||||
# LDAP configuration (mapped to LDAP.* context)
|
||||
XWIKI_LDAP_SERVER: "{{ LDAP.SERVER.DOMAIN }}"
|
||||
XWIKI_LDAP_PORT: "{{ LDAP.SERVER.PORT }}"
|
||||
XWIKI_LDAP_BASE_DN: "{{ LDAP.DN.ROOT }}"
|
||||
XWIKI_LDAP_BIND_DN: "{{ LDAP.DN.ADMINISTRATOR.DATA }}"
|
||||
XWIKI_LDAP_BIND_PASS: "{{ LDAP.BIND_CREDENTIAL }}"
|
||||
XWIKI_LDAP_TRYLOCAL: "{{ applications | get_app_conf(application_id, 'ldap.local_enabled') }}"
|
||||
XWIKI_LDAP_FIELDS_MAPPING: "last_name={{ LDAP.USER.ATTRIBUTES.SURNAME }},first_name={{ LDAP.USER.ATTRIBUTES.FIRSTNAME }},email={{ LDAP.USER.ATTRIBUTES.MAIL }}"
|
||||
XWIKI_LDAP_ADMIN_GROUP_DN: "cn={{ XWIKI_ADMIN_GROUP ~ ',' ~ LDAP.DN.OU.GROUPS }}"
|
||||
|
||||
# OIDC configuration (must exist in OIDC.* context)
|
||||
XWIKI_OIDC_PROVIDER: "{{ OIDC.CLIENT.ISSUER_URL }}"
|
||||
XWIKI_OIDC_AUTHORIZATION: "{{ OIDC.CLIENT.AUTHORIZE_URL }}"
|
||||
XWIKI_OIDC_TOKEN: "{{ OIDC.CLIENT.TOKEN_URL }}"
|
||||
XWIKI_OIDC_USERINFO: "{{ OIDC.CLIENT.USER_INFO_URL }}"
|
||||
XWIKI_OIDC_LOGOUT: "{{ OIDC.CLIENT.LOGOUT_URL }}"
|
||||
XWIKI_OIDC_CLIENT_ID: "{{ OIDC.CLIENT.ID }}"
|
||||
XWIKI_OIDC_CLIENT_SECRET: "{{ OIDC.CLIENT.SECRET }}"
|
||||
XWIKI_OIDC_SCOPES: "openid email profile {{ RBAC.GROUP.CLAIM }}"
|
||||
XWIKI_OIDC_GROUPS_CLAIM: "{{ RBAC.GROUP.CLAIM }}"
|
||||
XWIKI_OIDC_ADMIN_PROVIDER_GROUP: "{{ [RBAC.GROUP.NAME, XWIKI_ADMIN_GROUP] | path_join }}"
|
||||
|
Reference in New Issue
Block a user