mirror of
				https://github.com/kevinveenbirkenbach/computer-playbook.git
				synced 2025-11-04 12:18:17 +00: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,7 +45,7 @@ plugins:
 | 
			
		||||
    enabled: true
 | 
			
		||||
    items:
 | 
			
		||||
      - id: "org.xwiki.contrib.oidc:oidc-authenticator"
 | 
			
		||||
        version: "2.19.2"
 | 
			
		||||
        version: ""
 | 
			
		||||
 | 
			
		||||
  ldap:
 | 
			
		||||
    enabled: false
 | 
			
		||||
 
 | 
			
		||||
@@ -74,9 +74,35 @@ def xwiki_job_id(response: Any, default: Optional[str] = None, strict: bool = Fa
 | 
			
		||||
    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):
 | 
			
		||||
    """Custom filters for XWiki helpers."""
 | 
			
		||||
    def filters(self):
 | 
			
		||||
        return {
 | 
			
		||||
            "xwiki_job_id": xwiki_job_id,
 | 
			
		||||
            "xwiki_extension_status": xwiki_extension_status,
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,21 @@
 | 
			
		||||
    xwiki_ldap_enabled_switch:        false
 | 
			
		||||
    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
 | 
			
		||||
  include_tasks: 03_administrator.yml
 | 
			
		||||
  when: not (XWIKI_SSO_ENABLED | bool)
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,39 @@
 | 
			
		||||
  delay: 15
 | 
			
		||||
  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"
 | 
			
		||||
  uri:
 | 
			
		||||
    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