mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-09-17 15:56:04 +02:00
web-app-xwiki: verify extensions via Groovy page + new filter
- Added new filter 'xwiki_extension_status' (strips HTML, handles ) -> returns 200/404 - Introduced checker tasks (_check_extension_via_groovy.yml) instead of REST probe - Added early assert: superadmin login before extension installation - Collect and assert probe results in 04_extensions.yml - Set OIDC extension version to 'latest' (empty string) https://chatgpt.com/share/68ca36cb-ac38-800f-8281-8dea480b6676
This commit is contained in:
@@ -45,8 +45,8 @@ plugins:
|
|||||||
enabled: true
|
enabled: true
|
||||||
items:
|
items:
|
||||||
- id: "org.xwiki.contrib.oidc:oidc-authenticator"
|
- id: "org.xwiki.contrib.oidc:oidc-authenticator"
|
||||||
version: "2.19.2"
|
version: ""
|
||||||
|
|
||||||
ldap:
|
ldap:
|
||||||
enabled: false
|
enabled: false
|
||||||
items:
|
items:
|
||||||
|
@@ -74,9 +74,35 @@ def xwiki_job_id(response: Any, default: Optional[str] = None, strict: bool = Fa
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
def xwiki_extension_status(raw: str) -> int:
|
||||||
|
"""
|
||||||
|
Parse the output of the Groovy CheckExtension page.
|
||||||
|
|
||||||
|
- Strips HTML tags and entities ( )
|
||||||
|
- Returns 200 if extension is INSTALLED, otherwise 404
|
||||||
|
|
||||||
|
Args:
|
||||||
|
raw: Raw HTTP body from the checker page.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
200 if installed, 404 if missing/unknown.
|
||||||
|
"""
|
||||||
|
if raw is None:
|
||||||
|
return 404
|
||||||
|
|
||||||
|
text = re.sub(r"<[^>]+>", "", str(raw))
|
||||||
|
text = text.replace(" ", " ").replace("\u00A0", " ")
|
||||||
|
text = text.strip()
|
||||||
|
|
||||||
|
if text.startswith("INSTALLED::"):
|
||||||
|
return 200
|
||||||
|
return 404
|
||||||
|
|
||||||
|
|
||||||
class FilterModule(object):
|
class FilterModule(object):
|
||||||
"""Custom filters for XWiki helpers."""
|
"""Custom filters for XWiki helpers."""
|
||||||
def filters(self):
|
def filters(self):
|
||||||
return {
|
return {
|
||||||
"xwiki_job_id": xwiki_job_id,
|
"xwiki_job_id": xwiki_job_id,
|
||||||
|
"xwiki_extension_status": xwiki_extension_status,
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,21 @@
|
|||||||
xwiki_ldap_enabled_switch: false
|
xwiki_ldap_enabled_switch: false
|
||||||
xwiki_superadmin_enabled_switch: true
|
xwiki_superadmin_enabled_switch: true
|
||||||
|
|
||||||
|
- name: "ASSERT | superadmin can authenticate (needed for installer)"
|
||||||
|
uri:
|
||||||
|
url: "{{ [XWIKI_REST_XWIKI, 'spaces'] | url_join }}"
|
||||||
|
method: GET
|
||||||
|
user: "{{ XWIKI_SUPERADMIN_USERNAME }}"
|
||||||
|
password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
|
||||||
|
force_basic_auth: true
|
||||||
|
status_code: [200]
|
||||||
|
register: _super_check_ext
|
||||||
|
|
||||||
|
- name: "FAIL | superadmin authentication failed (extensions phase)"
|
||||||
|
fail:
|
||||||
|
msg: "superadmin authentication failed (check xwiki.cfg in image / password / Dockerfile build)"
|
||||||
|
when: _super_check_ext.status != 200
|
||||||
|
|
||||||
- name: Load setup procedures for admin
|
- name: Load setup procedures for admin
|
||||||
include_tasks: 03_administrator.yml
|
include_tasks: 03_administrator.yml
|
||||||
when: not (XWIKI_SSO_ENABLED | bool)
|
when: not (XWIKI_SSO_ENABLED | bool)
|
||||||
|
@@ -57,6 +57,39 @@
|
|||||||
delay: 15
|
delay: 15
|
||||||
until: _exec_page is succeeded
|
until: _exec_page is succeeded
|
||||||
|
|
||||||
|
- name: "XWIKI | Verify requested extensions via Groovy checker"
|
||||||
|
include_tasks: _check_extension_via_groovy.yml
|
||||||
|
loop: "{{ XWIKI_PLUGINS }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: plugin
|
||||||
|
label: "{{ plugin.id }}"
|
||||||
|
vars:
|
||||||
|
ext_id: "{{ plugin.id }}"
|
||||||
|
result_var: "probe_{{ plugin.id | regex_replace('[^A-Za-z0-9_]', '_') }}"
|
||||||
|
|
||||||
|
- name: "XWIKI | Collect probe results"
|
||||||
|
set_fact:
|
||||||
|
_xwiki_probe_results: "{{ _xwiki_probe_results | default([]) + [ {
|
||||||
|
'id': plugin.id,
|
||||||
|
'status': (
|
||||||
|
(hostvars[inventory_hostname]['probe_' ~ (plugin.id | regex_replace('[^A-Za-z0-9_]', '_'))]
|
||||||
|
| default({})).status
|
||||||
|
| default(404) | int
|
||||||
|
)
|
||||||
|
} ] }}"
|
||||||
|
loop: "{{ XWIKI_PLUGINS }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: plugin
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# Fail if any extension is missing
|
||||||
|
- name: "XWIKI | Assert all requested extensions are installed"
|
||||||
|
vars:
|
||||||
|
missing: "{{ _xwiki_probe_results | selectattr('status','equalto',404) | map(attribute='id') | list }}"
|
||||||
|
fail:
|
||||||
|
msg: "Missing extensions: {{ missing | join(', ') }}"
|
||||||
|
when: missing | length > 0
|
||||||
|
|
||||||
- name: "XWIKI | Delete installer page"
|
- name: "XWIKI | Delete installer page"
|
||||||
uri:
|
uri:
|
||||||
url: "{{ [XWIKI_REST_XWIKI_PAGES, 'InstallExtensions'] | url_join }}"
|
url: "{{ [XWIKI_REST_XWIKI_PAGES, 'InstallExtensions'] | url_join }}"
|
||||||
|
63
roles/web-app-xwiki/tasks/_check_extension_via_groovy.yml
Normal file
63
roles/web-app-xwiki/tasks/_check_extension_via_groovy.yml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# PUT a temporary Groovy page that checks installed extensions
|
||||||
|
- name: "XWIKI | PUT checker page XWiki.CheckExtension"
|
||||||
|
uri:
|
||||||
|
url: "{{ [XWIKI_REST_XWIKI_PAGES, 'CheckExtension'] | url_join }}"
|
||||||
|
method: PUT
|
||||||
|
user: "{{ XWIKI_SUPERADMIN_USERNAME }}"
|
||||||
|
password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
|
||||||
|
force_basic_auth: true
|
||||||
|
status_code: [200, 201, 202, 204]
|
||||||
|
headers:
|
||||||
|
Content-Type: "application/xml"
|
||||||
|
Accept: "application/xml"
|
||||||
|
body: |
|
||||||
|
<page xmlns="http://www.xwiki.org">
|
||||||
|
<title>CheckExtension</title>
|
||||||
|
<content><![CDATA[
|
||||||
|
{% raw %}{{groovy}}{% endraw %}
|
||||||
|
def ns = "wiki:xwiki"
|
||||||
|
def id = (request.getParameter("id") ?: "").toString()
|
||||||
|
if (!id) { print "ERROR::missing-id"; return }
|
||||||
|
def ext = services.extension.getInstalledExtension(id, ns)
|
||||||
|
if (ext) {
|
||||||
|
print "INSTALLED::${ext.id?.id}::${ext.id?.version}"
|
||||||
|
} else {
|
||||||
|
print "MISSING::${id}"
|
||||||
|
}
|
||||||
|
{% raw %}{{/groovy}}{% endraw %}
|
||||||
|
]]></content>
|
||||||
|
<syntax>xwiki/2.1</syntax>
|
||||||
|
</page>
|
||||||
|
register: _put_checker
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
# Call the page to check a single extension
|
||||||
|
- name: "XWIKI | Check installed via Groovy for {{ ext_id }}"
|
||||||
|
uri:
|
||||||
|
url: "http://127.0.0.1:{{ XWIKI_HOST_PORT }}/bin/view/XWiki/CheckExtension?xpage=plain&id={{ ext_id | urlencode }}"
|
||||||
|
method: GET
|
||||||
|
user: "{{ XWIKI_SUPERADMIN_USERNAME }}"
|
||||||
|
password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
|
||||||
|
force_basic_auth: true
|
||||||
|
status_code: [200]
|
||||||
|
return_content: yes
|
||||||
|
register: _check_output
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: "XWIKI | Save Groovy check result for {{ ext_id }}"
|
||||||
|
set_fact:
|
||||||
|
"{{ result_var }}":
|
||||||
|
status: "{{ _check_output.content | xwiki_extension_status }}"
|
||||||
|
raw: "{{ _check_output.content }}"
|
||||||
|
|
||||||
|
# Cleanup (optional; you can leave the page, but we remove it to keep things tidy)
|
||||||
|
- name: "XWIKI | Delete checker page"
|
||||||
|
uri:
|
||||||
|
url: "{{ [XWIKI_REST_XWIKI_PAGES, 'CheckExtension'] | url_join }}"
|
||||||
|
method: DELETE
|
||||||
|
user: "{{ XWIKI_SUPERADMIN_USERNAME }}"
|
||||||
|
password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
|
||||||
|
force_basic_auth: true
|
||||||
|
status_code: [204, 200, 202, 404]
|
||||||
|
register: _delete_checker
|
||||||
|
changed_when: _delete_checker.status != 404
|
@@ -1,44 +0,0 @@
|
|||||||
# roles/web-app-xwiki/tasks/_probe_extension.yml
|
|
||||||
# Probes the 'installed' extension repository to check if a given extension is present.
|
|
||||||
# Uses the wiki-namespaced REST base (/rest/wikis/xwiki) and falls back to /{id}/{version} if needed.
|
|
||||||
|
|
||||||
- name: "XWIKI | Probe extension {{ ext_id }} (installed repo)"
|
|
||||||
when: ext_enabled | bool
|
|
||||||
uri:
|
|
||||||
url: "{{ [XWIKI_REST_XWIKI, 'repositories/installed/extensions', ext_id | urlencode] | url_join }}?namespace={{ 'wiki:xwiki' | urlencode }}"
|
|
||||||
method: GET
|
|
||||||
user: "{{ XWIKI_SUPERADMIN_USERNAME }}"
|
|
||||||
password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
|
|
||||||
force_basic_auth: true
|
|
||||||
follow_redirects: none
|
|
||||||
return_content: no
|
|
||||||
headers:
|
|
||||||
Accept: "application/xml"
|
|
||||||
status_code: [200, 401, 404]
|
|
||||||
register: _probe
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
# Some XWiki builds/versions answer on /{id}/{version}. Try that if plain /{id} returned 404.
|
|
||||||
- name: "XWIKI | Probe extension {{ ext_id }} with version (fallback)"
|
|
||||||
when:
|
|
||||||
- ext_enabled | bool
|
|
||||||
- (_probe.status | default(404)) | int == 404
|
|
||||||
- ext_version is defined
|
|
||||||
uri:
|
|
||||||
url: "{{ [XWIKI_REST_XWIKI, 'repositories/installed/extensions', ext_id | urlencode, ext_version] | url_join }}?namespace={{ 'wiki:xwiki' | urlencode }}"
|
|
||||||
method: GET
|
|
||||||
user: "{{ XWIKI_SUPERADMIN_USERNAME }}"
|
|
||||||
password: "{{ XWIKI_SUPERADMIN_PASSWORD }}"
|
|
||||||
force_basic_auth: true
|
|
||||||
follow_redirects: none
|
|
||||||
return_content: no
|
|
||||||
headers:
|
|
||||||
Accept: "application/xml"
|
|
||||||
status_code: [200, 401, 404]
|
|
||||||
register: _probe_v
|
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: "XWIKI | Save probe result for {{ ext_id }}"
|
|
||||||
when: ext_enabled | bool
|
|
||||||
set_fact:
|
|
||||||
"{{ result_var }}": "{{ (_probe_v if (_probe_v is defined) else _probe) }}"
|
|
Reference in New Issue
Block a user