diff --git a/roles/svc-opt-ssd-hdd/tasks/main.yml b/roles/svc-opt-ssd-hdd/tasks/main.yml index b2b2a9d5..2a652372 100644 --- a/roles/svc-opt-ssd-hdd/tasks/main.yml +++ b/roles/svc-opt-ssd-hdd/tasks/main.yml @@ -1,5 +1,5 @@ - include_role: name: sys-service vars: - system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_OPTIMIZE_DRIVE }} {{ SYS_SERVICE_BACKUP_RMT_2_LOC }} --timeout "{{ SYS_TIMEOUT_STORAGE_OPTIMIZER }}"' + system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_OPTIMIZE_DRIVE }} {{ SYS_SERVICE_BACKUP_RMT_2_LOC }} {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_STORAGE_OPTIMIZER }}"' system_service_tpl_exec_start: '{{ system_service_script_exec }} --mass-storage-path {{ OPT_DRIVE_MASS_STORAGE_PATH }} --rapid-storage-path {{ OPT_DRIVE_RAPID_STORAGE_PATH }}' \ No newline at end of file diff --git a/roles/sys-ctl-rpr-docker-hard/tasks/01_core.yml b/roles/sys-ctl-rpr-docker-hard/tasks/01_core.yml index 4e712f55..3a2030f6 100644 --- a/roles/sys-ctl-rpr-docker-hard/tasks/01_core.yml +++ b/roles/sys-ctl-rpr-docker-hard/tasks/01_core.yml @@ -8,7 +8,7 @@ vars: system_service_on_calendar: "{{ SYS_SCHEDULE_REPAIR_DOCKER_HARD }}" system_service_timer_enabled: true - system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_REPAIR_DOCKER_HARD }} --timeout "{{ SYS_TIMEOUT_RESTART_DOCKER }}"' + system_service_tpl_exec_start_pre: '/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }} --ignore {{ SYS_SERVICE_REPAIR_DOCKER_HARD }} {{ SYS_SERVICE_GROUP_CLEANUP | join(" ") }} --timeout "{{ SYS_TIMEOUT_RESTART_DOCKER }}"' system_service_tpl_exec_start: '{{ system_service_script_exec }} {{ PATH_DOCKER_COMPOSE_INSTANCES }}' system_service_tpl_exec_start_post: "/usr/bin/systemctl start {{ SYS_SERVICE_CLEANUP_ANONYMOUS_VOLUMES }}" system_service_tpl_on_failure: "{{ SYS_SERVICE_ON_FAILURE_COMPOSE }}" diff --git a/roles/sys-ctl-rpr-docker-soft/tasks/01_core.yml b/roles/sys-ctl-rpr-docker-soft/tasks/01_core.yml index 80241c87..06464842 100644 --- a/roles/sys-ctl-rpr-docker-soft/tasks/01_core.yml +++ b/roles/sys-ctl-rpr-docker-soft/tasks/01_core.yml @@ -12,4 +12,3 @@ system_service_tpl_exec_start_pre: "/usr/bin/python {{ PATH_SYSTEM_LOCK_SCRIPT }} {{ SYS_SERVICE_GROUP_MANIPULATION | join(' ') }} --ignore {{ SYS_SERVICE_GROUP_CLEANUP| join(' ') }} {{ SYS_SERVICE_REPAIR_DOCKER_SOFT }} --timeout '{{ SYS_TIMEOUT_HEAL_DOCKER }}'" system_service_tpl_exec_start: > /bin/sh -c '{{ system_service_script_exec }} --manipulation-string "{{ SYS_SERVICE_GROUP_MANIPULATION | join(" ") }}" {{ PATH_DOCKER_COMPOSE_INSTANCES }}' - diff --git a/roles/web-app-desktop/templates/javascript/oidc.js.j2 b/roles/web-app-desktop/templates/javascript/oidc.js.j2 index cedd6dd4..5b9a2950 100644 --- a/roles/web-app-desktop/templates/javascript/oidc.js.j2 +++ b/roles/web-app-desktop/templates/javascript/oidc.js.j2 @@ -16,7 +16,7 @@ const KC_CONFIG = { silentCheckSsoRedirectUri: window.location.origin + "{{ DESKTOP_LOCATION_SILENT_CHECK }}" }; -const DEBUG = {{ 'true' if MODE_DEBUG | default(false) else 'false' }}; +const DEBUG = {{ 'true' if MODE_DEBUG else 'false' }}; /* ============================================== 2) Helpers for menu manipulation diff --git a/roles/web-app-joomla/tasks/02_debug.yml b/roles/web-app-joomla/tasks/02_debug.yml index f6387ab9..55bea906 100644 --- a/roles/web-app-joomla/tasks/02_debug.yml +++ b/roles/web-app-joomla/tasks/02_debug.yml @@ -4,9 +4,9 @@ - docker - exec - -e - - "J_MODE_DEBUG={{ MODE_DEBUG | default(false) | bool | ternary('1','0') }}" + - "J_MODE_DEBUG={{ MODE_DEBUG | bool | ternary('1','0') }}" - -e - - "J_ERR_LEVEL={{ MODE_DEBUG | default(false) | bool | ternary('maximum','default') }}" + - "J_ERR_LEVEL={{ MODE_DEBUG | bool | ternary('maximum','default') }}" - "{{ JOOMLA_CONTAINER }}" - php - -r diff --git a/roles/web-app-mediawiki/config/main.yml b/roles/web-app-mediawiki/config/main.yml index 1d1b070b..20755c98 100644 --- a/roles/web-app-mediawiki/config/main.yml +++ b/roles/web-app-mediawiki/config/main.yml @@ -1,5 +1,4 @@ sitename: "Wiki on {{ PRIMARY_DOMAIN | upper }}" -meta_namespace: "Meta" server: domains: canonical: @@ -21,3 +20,4 @@ features: central_database: true css: true desktop: true + oidc: true diff --git a/roles/web-app-mediawiki/tasks/01_install.yml b/roles/web-app-mediawiki/tasks/01_install.yml new file mode 100644 index 00000000..6aeca6f9 --- /dev/null +++ b/roles/web-app-mediawiki/tasks/01_install.yml @@ -0,0 +1,44 @@ +- name: "Wait for DB to be reachable" + command: > + docker exec {{ MEDIAWIKI_CONTAINER }} + php /var/www/html/maintenance/sql.php --query "SELECT 1;" + register: mw_db_ready + retries: 15 + delay: 2 + until: mw_db_ready.rc == 0 + changed_when: false + failed_when: false + +- name: "Install MediaWiki if no schema exists" + command: > + docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} + php /var/www/html/maintenance/install.php + --dbname="{{ database_name }}" + --dbuser="{{ database_username }}" + --dbpass="{{ database_password }}" + --dbserver="{{ database_host }}:{{ database_port }}" + --installdbuser="{{ database_username }}" + --installdbpass="{{ database_password }}" + --server="{{ MEDIAWIKI_URL }}" + --scriptpath="" + --lang={{ HOST_LL }} + --pass="{{ MEDIAWIKI_ADMINISTRATOR_PASSWORD }}" + "{{ MEDIAWIKI_SITENAME }}" + "{{ MEDIAWIKI_ADMINISTRATOR_NAME }}" + no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" + register: mw_install + changed_when: mw_install.rc == 0 + failed_when: > + mw_install.rc != 0 and + ('LocalSettings.php file has been detected' not in (((mw_install.stdout | default('')) ~ (mw_install.stderr | default(''))))) and + ('run update.php instead' not in (((mw_install.stdout | default('')) ~ (mw_install.stderr | default(''))))) + +- name: "Initialize / migrate MediaWiki database schema" + command: > + docker exec + -u {{ MEDIAWIKI_USER }} + {{ MEDIAWIKI_CONTAINER }} + php /var/www/html/maintenance/update.php --quick + register: mw_update + changed_when: "'...done.' in (mw_update.stdout | default(''))" + failed_when: mw_update.rc != 0 \ No newline at end of file diff --git a/roles/web-app-mediawiki/tasks/02_debug.yml b/roles/web-app-mediawiki/tasks/02_debug.yml new file mode 100644 index 00000000..4ba96627 --- /dev/null +++ b/roles/web-app-mediawiki/tasks/02_debug.yml @@ -0,0 +1,37 @@ +--- +# Aktiviert Debug, wenn MODE_DEBUG=true; entfernt es sauber, wenn false. + +- name: "DEBUG | Enable block when MODE_DEBUG=true" + when: MODE_DEBUG | bool + include_tasks: _enable_debug.yml + +- name: "DEBUG | Disable block when MODE_DEBUG=false" + when: not (MODE_DEBUG | bool) + block: + - name: "Remove require_once line from LocalSettings.php (if present)" + shell: | + docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} bash -lc ' + LSP={{ MEDIAWIKI_HTML_DIR }}/LocalSettings.php + if [ -f "$LSP" ]; then + if grep -Fqx -- "require_once __DIR__ . '\''/debug.php'\'';" "$LSP"; then + sed -i "\#require_once __DIR__ . '/debug.php';#d" "$LSP" + echo REMOVED_REQUIRE + fi + fi + ' + args: { executable: /bin/bash } + register: _dbg_rm_req + changed_when: "'REMOVED_REQUIRE' in (_dbg_rm_req.stdout | default(''))" + + - name: "Remove debug.php from container (if present)" + shell: > + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc + "if [ -f {{ MEDIAWIKI_HTML_DIR }}/debug.php ]; then rm -f {{ MEDIAWIKI_HTML_DIR }}/debug.php; echo REMOVED_FILE; fi" + args: { executable: /bin/bash } + register: _dbg_rm_file + changed_when: "'REMOVED_FILE' in (_dbg_rm_file.stdout | default(''))" + + - name: "Remove local debug.php (if present)" + file: + path: "{{ MEDIAWIKI_CONFIG_DIR }}/debug.php" + state: absent diff --git a/roles/web-app-mediawiki/tasks/03_admin.yml b/roles/web-app-mediawiki/tasks/03_admin.yml new file mode 100644 index 00000000..0530088f --- /dev/null +++ b/roles/web-app-mediawiki/tasks/03_admin.yml @@ -0,0 +1,19 @@ +- name: "Create MediaWiki admin user" + command: > + docker exec + -u {{ MEDIAWIKI_USER }} + {{ MEDIAWIKI_CONTAINER }} + php /var/www/html/maintenance/createAndPromote.php + --bureaucrat --sysop + {{ MEDIAWIKI_ADMINISTRATOR_NAME }} + {{ MEDIAWIKI_ADMINISTRATOR_PASSWORD }} + {{ MEDIAWIKI_ADMINISTRATOR_EMAIL }} + register: create_admin + changed_when: > + ('created' in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) or + ('Created' in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) + failed_when: > + create_admin.rc != 0 and + ('already exists' not in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) and + ('Account exists' not in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) + no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" \ No newline at end of file diff --git a/roles/web-app-mediawiki/tasks/04_extensions.yml b/roles/web-app-mediawiki/tasks/04_extensions.yml new file mode 100644 index 00000000..cda7f1ef --- /dev/null +++ b/roles/web-app-mediawiki/tasks/04_extensions.yml @@ -0,0 +1,147 @@ +--- +# Install PluggableAuth + OpenIDConnect INTO the running container (idempotent) +# Downloads on host (config dir), copy+extract inside container. + +- name: "EXT | Ensure local download dir exists" + file: + path: "{{ MEDIAWIKI_EXT_CFG_BASE }}" + state: directory + mode: "0755" + +- name: "EXT | Download extension tarballs ({{ MEDIAWIKI_EXT_BRANCH }})" + get_url: + url: "{{ ext.url }}" + dest: "{{ MEDIAWIKI_EXT_CFG_BASE }}/{{ ext.name }}.tar.gz" + mode: "0644" + loop: "{{ MEDIAWIKI_EXT_LIST }}" + loop_control: + loop_var: ext + label: "{{ ext.name }}" + +- name: "EXT | Copy & extract into container if not installed" + shell: > + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc ' + set -e + dst="{{ MEDIAWIKI_HTML_DIR }}/extensions/{{ ext.name }}" + if [ ! -f "$dst/extension.json" ]; then + rm -rf "$dst" && mkdir -p "$dst" + fi + ' + && docker cp "{{ MEDIAWIKI_EXT_CFG_BASE }}/{{ ext.name }}.tar.gz" "{{ MEDIAWIKI_CONTAINER }}:/tmp/{{ ext.name }}.tar.gz" + && docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc ' + set -e + dst="{{ MEDIAWIKI_HTML_DIR }}/extensions/{{ ext.name }}" + if [ ! -f "$dst/extension.json" ]; then + tar -xzf /tmp/{{ ext.name }}.tar.gz -C "$dst" --strip-components=1 + chown -R {{ MEDIAWIKI_USER }}:{{ MEDIAWIKI_USER }} "$dst" + rm -f /tmp/{{ ext.name }}.tar.gz + echo INSTALLED:{{ ext.name }} + else + rm -f /tmp/{{ ext.name }}.tar.gz + echo PRESENT:{{ ext.name }} + fi + ' + args: + executable: /bin/bash + loop: "{{ MEDIAWIKI_EXT_LIST }}" + loop_control: + loop_var: ext + label: "{{ ext.name }}" + register: _install_results + changed_when: "'INSTALLED:' in (stdout | default(''))" + +- name: "EXT | Determine if any extension was installed" + set_fact: + _any_installed: >- + {{ _install_results.results + | map(attribute='stdout') + | select('search', 'INSTALLED:') + | list | length > 0 }} + +# Ensure unzip + git are available in the container (idempotent) +- name: "EXT | Ensure unzip+git available in container" + shell: | + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc ' + set -e + need=0 + command -v unzip >/dev/null 2>&1 || need=1 + command -v git >/dev/null 2>&1 || need=1 + if [ "$need" -eq 1 ]; then + export DEBIAN_FRONTEND=noninteractive + apt-get update -y + apt-get install -y --no-install-recommends unzip git ca-certificates + rm -rf /var/lib/apt/lists/* + echo INSTALLED_TOOLS + fi + ' + args: + executable: /bin/bash + register: _tools + changed_when: "'INSTALLED_TOOLS' in (_tools.stdout | default(''))" + +# Ensure Composer is available inside the container (idempotent) +- name: "EXT | Ensure Composer available in container" + shell: | + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc ' + if ! command -v composer >/dev/null 2>&1; then + php -r "copy(\"https://getcomposer.org/installer\", \"composer-setup.php\");" + php composer-setup.php --install-dir=/usr/local/bin --filename=composer + rm -f composer-setup.php + echo INSTALLED_COMPOSER + fi + ' + args: + executable: /bin/bash + register: _composer + changed_when: "'INSTALLED_COMPOSER' in (_composer.stdout | default(''))" + +# Install dependencies per extension (only if vendor is missing) +# Use /tmp/composer for HOME/CACHE to avoid /var/www permission issues. +- name: "EXT | composer install in each extension when needed" + shell: | + docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} bash -lc ' + set -e + d="{{ MEDIAWIKI_HTML_DIR }}/extensions/{{ ext.name }}" + if [ -f "$d/composer.json" ] && [ ! -f "$d/vendor/autoload.php" ]; then + install -d -m 0775 /tmp/composer/cache + export COMPOSER_HOME=/tmp/composer + export COMPOSER_CACHE_DIR=/tmp/composer/cache + cd "$d" + composer install --no-dev -n --prefer-dist + echo COMPOSER_INSTALLED:{{ ext.name }} + fi + ' + args: + executable: /bin/bash + loop: "{{ MEDIAWIKI_EXT_LIST }}" + loop_control: + loop_var: ext + label: "{{ ext.name }}" + register: _ext_composer + changed_when: "'COMPOSER_INSTALLED:' in (stdout | default(''))" + +# Sanity check: Jumbojett OIDC client must be loadable +- name: "EXT | Sanity check: Jumbojett OpenIDConnect client present" + shell: > + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc + 'php -r "(@require \"{{ MEDIAWIKI_HTML_DIR }}/vendor/autoload.php\"); @require \"{{ MEDIAWIKI_HTML_DIR }}/extensions/OpenIDConnect/vendor/autoload.php\"; exit(class_exists(\"Jumbojett\\\\OpenIDConnectClient\")?0:1);"' + args: + executable: /bin/bash + register: _oidc_class + changed_when: false + failed_when: _oidc_class.rc != 0 + +# Run MediaWiki updates (changed if something installed) +- name: "EXT | Run update.php (safe to run repeatedly)" + shell: > + docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} + php {{ MEDIAWIKI_HTML_DIR }}/maintenance/update.php --quick + args: + executable: /bin/bash + register: _mw_upd + changed_when: > + (_any_installed) or + (_ext_composer is defined and + (_ext_composer.results | map(attribute='stdout') + | select('search','COMPOSER_INSTALLED:') + | list | length > 0)) diff --git a/roles/web-app-mediawiki/tasks/05_oidc.yml b/roles/web-app-mediawiki/tasks/05_oidc.yml new file mode 100644 index 00000000..78098765 --- /dev/null +++ b/roles/web-app-mediawiki/tasks/05_oidc.yml @@ -0,0 +1,61 @@ +--- +# All operations remain INSIDE the running container. +# Template is rendered into docker_compose.directories.config on the host. +# Change detection is based on checksum comparison vs. container file. + +- name: "OIDC | Ensure local config directory exists" + file: + path: "{{ MEDIAWIKI_CONFIG_DIR }}" + state: directory + mode: "0755" + +- name: "OIDC | Render oidc.php locally (template into config dir)" + template: + src: "oidc.php.j2" + dest: "{{ MEDIAWIKI_OIDC_FILE }}" + mode: "0644" + no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" + +- name: "OIDC | Compute local checksum" + stat: + path: "{{ MEDIAWIKI_OIDC_FILE }}" + checksum_algorithm: sha256 + register: _local_oidc + +- name: "OIDC | Compute container checksum (if exists)" + shell: > + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc + "test -f {{ MEDIAWIKI_HTML_DIR }}/oidc.php && + sha256sum {{ MEDIAWIKI_HTML_DIR }}/oidc.php | awk '{print $1}' || echo MISSING" + args: + executable: /bin/bash + register: _remote_oidc + changed_when: false + +- name: "OIDC | Copy oidc.php into container docroot only if different" + shell: > + if [ "{{ (_remote_oidc.stdout | default('') | trim) }}" != "{{ _local_oidc.stat.checksum }}" ]; then + docker cp "{{ MEDIAWIKI_OIDC_FILE }}" "{{ MEDIAWIKI_CONTAINER }}:{{ MEDIAWIKI_HTML_DIR }}/oidc.php" && + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc "chown {{ MEDIAWIKI_USER }}:{{ MEDIAWIKI_USER }} {{ MEDIAWIKI_HTML_DIR }}/oidc.php && chmod 0644 {{ MEDIAWIKI_HTML_DIR }}/oidc.php" && + echo COPIED; + fi + args: + executable: /bin/bash + register: _cp_oidc + changed_when: "'COPIED' in (_cp_oidc.stdout | default(''))" + +- name: "OIDC | Require oidc.php once inside LocalSettings.php" + shell: | + docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} bash -lc ' + LSP={{ MEDIAWIKI_HTML_DIR }}/LocalSettings.php + LINE="require_once __DIR__ . '\''/oidc.php'\'';" + if ! grep -Fqx -- "$LINE" "$LSP"; then + printf "%s\n" "$LINE" >> "$LSP" + echo ADDED_REQUIRE + fi + ' + args: + executable: /bin/bash + register: _mw_oidc_req + changed_when: "'ADDED_REQUIRE' in (_mw_oidc_req.stdout | default(''))" + diff --git a/roles/web-app-mediawiki/tasks/_enable_debug.yml b/roles/web-app-mediawiki/tasks/_enable_debug.yml new file mode 100644 index 00000000..86f8e2b5 --- /dev/null +++ b/roles/web-app-mediawiki/tasks/_enable_debug.yml @@ -0,0 +1,45 @@ +- name: "Render debug.php locally" + template: + src: "debug.php.j2" + dest: "{{ MEDIAWIKI_CONFIG_DIR }}/debug.php" + mode: "0644" + +- name: "Compute local checksum" + stat: + path: "{{ MEDIAWIKI_CONFIG_DIR }}/debug.php" + checksum_algorithm: sha256 + register: _dbg_local + +- name: "Compute container checksum (if exists)" + shell: > + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc + "test -f {{ MEDIAWIKI_HTML_DIR }}/debug.php && + sha256sum {{ MEDIAWIKI_HTML_DIR }}/debug.php | awk '{print $1}' || echo MISSING" + args: { executable: /bin/bash } + register: _dbg_remote + changed_when: false + +- name: "Copy debug.php into container only if different" + shell: > + if [ "{{ (_dbg_remote.stdout | default('') | trim) }}" != "{{ _dbg_local.stat.checksum }}" ]; then + docker cp "{{ MEDIAWIKI_CONFIG_DIR }}/debug.php" "{{ MEDIAWIKI_CONTAINER }}:{{ MEDIAWIKI_HTML_DIR }}/debug.php" && + docker exec {{ MEDIAWIKI_CONTAINER }} bash -lc "chown {{ MEDIAWIKI_USER }}:{{ MEDIAWIKI_USER }} {{ MEDIAWIKI_HTML_DIR }}/debug.php && chmod 0644 {{ MEDIAWIKI_HTML_DIR }}/debug.php" && + echo COPIED; + fi + args: { executable: /bin/bash } + register: _dbg_cp + changed_when: "'COPIED' in (_dbg_cp.stdout | default(''))" + +- name: "require_once debug.php in LocalSettings.php" + shell: | + docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} bash -lc ' + LSP={{ MEDIAWIKI_HTML_DIR }}/LocalSettings.php + LINE="require_once __DIR__ . '\''/debug.php'\'';" + if ! grep -Fqx -- "$LINE" "$LSP"; then + printf "%s\n" "$LINE" >> "$LSP" + echo ADDED_DEBUG_REQUIRE + fi + ' + args: { executable: /bin/bash } + register: _dbg_req + changed_when: "'ADDED_DEBUG_REQUIRE' in (_dbg_req.stdout | default(''))" \ No newline at end of file diff --git a/roles/web-app-mediawiki/tasks/main.yml b/roles/web-app-mediawiki/tasks/main.yml index da6fb1e9..500817d6 100644 --- a/roles/web-app-mediawiki/tasks/main.yml +++ b/roles/web-app-mediawiki/tasks/main.yml @@ -1,73 +1,22 @@ --- -- name: "load docker, db and proxy for {{ application_id }}" +- name: "load docker, db and proxy for '{{ application_id }}'" include_role: name: sys-stk-full-stateful vars: docker_compose_flush_handlers: true -- name: "Wait for DB to be reachable" - command: > - docker exec {{ MEDIAWIKI_CONTAINER }} - php /var/www/html/maintenance/sql.php --query "SELECT 1;" - register: mw_db_ready - retries: 15 - delay: 2 - until: mw_db_ready.rc == 0 - changed_when: false - failed_when: false +- name: "Load install procedures for '{{ application_id }}''" + include_tasks: 01_install.yml -- name: "Install MediaWiki if no schema exists" - command: > - docker exec -u {{ MEDIAWIKI_USER }} {{ MEDIAWIKI_CONTAINER }} - php /var/www/html/maintenance/install.php - --dbname="{{ database_name }}" - --dbuser="{{ database_username }}" - --dbpass="{{ database_password }}" - --dbserver="{{ database_host }}:{{ database_port }}" - --installdbuser="{{ database_username }}" - --installdbpass="{{ database_password }}" - --server="{{ MEDIAWIKI_URL }}" - --scriptpath="" - --lang={{ HOST_LL }} - --pass="{{ MEDIAWIKI_ADMINISTRATOR_PASSWORD }}" - "{{ MEDIAWIKI_SITENAME }}" - "{{ MEDIAWIKI_ADMINISTRATOR_NAME }}" - no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" - register: mw_install - changed_when: mw_install.rc == 0 - failed_when: > - mw_install.rc != 0 and - ('LocalSettings.php file has been detected' not in (((mw_install.stdout | default('')) ~ (mw_install.stderr | default(''))))) and - ('run update.php instead' not in (((mw_install.stdout | default('')) ~ (mw_install.stderr | default(''))))) +- name: "Load debug procedures for '{{ application_id }}''" + include_tasks: 02_debug.yml -- name: "Initialize / migrate MediaWiki database schema" - command: > - docker exec - -u {{ MEDIAWIKI_USER }} - {{ MEDIAWIKI_CONTAINER }} - php /var/www/html/maintenance/update.php --quick - register: mw_update - changed_when: "'...done.' in (mw_update.stdout | default(''))" - failed_when: mw_update.rc != 0 +- name: "Load admin setup procedures for '{{ application_id }}''" + include_tasks: 03_admin.yml -- name: "Create MediaWiki admin user" - command: > - docker exec - -u {{ MEDIAWIKI_USER }} - {{ MEDIAWIKI_CONTAINER }} - php /var/www/html/maintenance/createAndPromote.php - --bureaucrat --sysop - {{ MEDIAWIKI_ADMINISTRATOR_NAME }} - {{ MEDIAWIKI_ADMINISTRATOR_PASSWORD }} - {{ MEDIAWIKI_ADMINISTRATOR_EMAIL }} - register: create_admin - changed_when: > - ('created' in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) or - ('Created' in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) - failed_when: > - create_admin.rc != 0 and - ('already exists' not in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) and - ('Account exists' not in ((create_admin.stdout | default('')) ~ (create_admin.stderr | default('')))) - async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" - poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" - no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}" +- name: "Load OIDC procedures for '{{ application_id }}''" + include_tasks: "{{ item }}" + loop: + - 04_extensions.yml + - 05_oidc.yml + when: MEDIAWIKI_OIDC_ENABLED | bool \ No newline at end of file diff --git a/roles/web-app-mediawiki/templates/debug.php.j2 b/roles/web-app-mediawiki/templates/debug.php.j2 new file mode 100644 index 00000000..711c7c7d --- /dev/null +++ b/roles/web-app-mediawiki/templates/debug.php.j2 @@ -0,0 +1,21 @@ + 'php://stderr', + 'error' => 'php://stderr', + 'authentication' => 'php://stderr', + 'session' => 'php://stderr', + 'resourceloader' => 'php://stderr', + 'PluggableAuth' => 'php://stderr', + 'OpenIDConnect' => 'php://stderr', +]); diff --git a/roles/web-app-mediawiki/templates/oidc.php.j2 b/roles/web-app-mediawiki/templates/oidc.php.j2 new file mode 100644 index 00000000..fa4e923c --- /dev/null +++ b/roles/web-app-mediawiki/templates/oidc.php.j2 @@ -0,0 +1,27 @@ + 'OpenIDConnect', + 'data' => [ + // For Keycloak, use the REALM URL, e.g. https://auth.example/realms/ + 'providerURL' => '{{ MEDIAWIKI_OIDC_ISSUER }}', + 'clientID' => '{{ MEDIAWIKI_OIDC_CLIENT_ID }}', + 'clientsecret' => '{{ MEDIAWIKI_OIDC_CLIENT_SECRET }}', + 'scope' => [ 'openid', 'profile', 'email' ], + ], + ], +]; + +// Helpful defaults +$wgOpenIDConnect_UseEmailNameAsUserName = true; +$wgOpenIDConnect_MigrateUsers = true; +// ### OIDC (PluggableAuth) – END diff --git a/roles/web-app-mediawiki/vars/main.yml b/roles/web-app-mediawiki/vars/main.yml index 6d703461..60cb52be 100644 --- a/roles/web-app-mediawiki/vars/main.yml +++ b/roles/web-app-mediawiki/vars/main.yml @@ -7,6 +7,11 @@ container_port: 80 MEDIAWIKI_SITENAME: "{{ applications | get_app_conf(application_id, 'sitename') }}" MEDIAWIKI_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}" +## Folders +MEDIAWIKI_HTML_DIR: "/var/www/html" +MEDIAWIKI_CONFIG_DIR: "{{ docker_compose.directories.config }}" +MEDIAWIKI_OIDC_FILE: "{{ docker_compose.directories.config }}/oidc.php" + ## Docker MEDIAWIKI_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.mediawiki.version') }}" MEDIAWIKI_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.mediawiki.image') }}" @@ -17,4 +22,20 @@ MEDIAWIKI_USER: "www-data" # User MEDIAWIKI_ADMINISTRATOR_NAME: "{{ users.administrator.username }}" MEDIAWIKI_ADMINISTRATOR_PASSWORD: "{{ users.administrator.password }}" -MEDIAWIKI_ADMINISTRATOR_EMAIL: "{{ users.administrator.email }}" \ No newline at end of file +MEDIAWIKI_ADMINISTRATOR_EMAIL: "{{ users.administrator.email }}" + +# OIDC +MEDIAWIKI_OIDC_ENABLED: "{{ applications | get_app_conf(application_id, 'features.oidc') }}" +MEDIAWIKI_OIDC_CLIENT_ID: "{{ OIDC.CLIENT.ID }}" +MEDIAWIKI_OIDC_CLIENT_SECRET: "{{ OIDC.CLIENT.SECRET }}" +MEDIAWIKI_OIDC_ISSUER: "{{ OIDC.CLIENT.ISSUER_URL }}" +MEDIAWIKI_OIDC_BUTTON_TEXT: "{{ OIDC.BUTTON_TEXT }}" + +# Extensions +MEDIAWIKI_EXT_BRANCH: "REL1_44" # passend zu MediaWiki 1.44 +MEDIAWIKI_EXT_CFG_BASE: "{{ MEDIAWIKI_CONFIG_DIR }}/mwext/{{ MEDIAWIKI_EXT_BRANCH }}" +MEDIAWIKI_EXT_LIST: + - name: "PluggableAuth" + url: "https://codeload.github.com/wikimedia/mediawiki-extensions-PluggableAuth/tar.gz/refs/heads/{{ MEDIAWIKI_EXT_BRANCH }}" + - name: "OpenIDConnect" + url: "https://codeload.github.com/wikimedia/mediawiki-extensions-OpenIDConnect/tar.gz/refs/heads/{{ MEDIAWIKI_EXT_BRANCH }}" \ No newline at end of file