mirror of
https://github.com/spantaleev/matrix-docker-ansible-deploy.git
synced 2026-09-14 03:43:13 +00:00
Test matrix-authentication-service with Molecule
This commit is contained in:
@@ -122,6 +122,7 @@
|
|||||||
"description": "Automerge patch bumps of components whose role has a Molecule scenario (via branch push - no PR). A bump touches that role's defaults/main.yml, which makes the Molecule workflow run that role's scenario, so the update only merges once the component has been started on the configuration the role renders. Patch only: a minor carries behaviour changes no static rule can judge, and reading the release notes to decide is a job for a human or an agent. Keep this list in step with the roles that have a scenario - bin/check-molecule-automerge-list.py enforces that.",
|
"description": "Automerge patch bumps of components whose role has a Molecule scenario (via branch push - no PR). A bump touches that role's defaults/main.yml, which makes the Molecule workflow run that role's scenario, so the update only merges once the component has been started on the configuration the role renders. Patch only: a minor carries behaviour changes no static rule can judge, and reading the release notes to decide is a job for a human or an agent. Keep this list in step with the roles that have a scenario - bin/check-molecule-automerge-list.py enforces that.",
|
||||||
"matchFileNames": [
|
"matchFileNames": [
|
||||||
"roles/custom/matrix-alertmanager-receiver/defaults/main.yml",
|
"roles/custom/matrix-alertmanager-receiver/defaults/main.yml",
|
||||||
|
"roles/custom/matrix-authentication-service/defaults/main.yml",
|
||||||
"roles/custom/matrix-bot-baibot/defaults/main.yml",
|
"roles/custom/matrix-bot-baibot/defaults/main.yml",
|
||||||
"roles/custom/matrix-bot-draupnir/defaults/main.yml",
|
"roles/custom/matrix-bot-draupnir/defaults/main.yml",
|
||||||
"roles/custom/matrix-bot-maubot/defaults/main.yml",
|
"roles/custom/matrix-bot-maubot/defaults/main.yml",
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
---
|
||||||
|
- name: Include roles for Matrix Authentication Service Molecule tests
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
vars_files:
|
||||||
|
- "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
|
||||||
|
gather_facts: true
|
||||||
|
tasks:
|
||||||
|
- name: Include base roles for Matrix Authentication Service Molecule tests
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "{{ role_name }}"
|
||||||
|
public: true
|
||||||
|
loop:
|
||||||
|
- com.devture.ansible.role.playbook_help
|
||||||
|
- com.devture.ansible.role.systemd_docker_base
|
||||||
|
loop_control:
|
||||||
|
loop_var: role_name
|
||||||
|
|
||||||
|
# The role's main task file also carries separately invoked CLI actions. Include the
|
||||||
|
# validation and installation selected by the normal setup tags, without invoking them.
|
||||||
|
- name: Include Matrix Authentication Service setup task files
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: "custom/{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
|
||||||
|
public: true
|
||||||
|
tasks_from: "{{ role_task_file }}"
|
||||||
|
loop:
|
||||||
|
- validate_config.yml
|
||||||
|
- install.yml
|
||||||
|
loop_control:
|
||||||
|
loop_var: role_task_file
|
||||||
|
|
||||||
|
# Component roles install their unit; the complete playbook's service manager starts it.
|
||||||
|
- name: Ensure Matrix Authentication Service is started
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: Ensure systemd daemon is reloaded
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
daemon_reload: true
|
||||||
|
|
||||||
|
- name: Ensure Matrix Authentication Service systemd service is started
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: matrix-authentication-service.service
|
||||||
|
state: started
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
---
|
||||||
|
dependency:
|
||||||
|
name: galaxy
|
||||||
|
options:
|
||||||
|
requirements-file: requirements.yml
|
||||||
|
force: true
|
||||||
|
driver:
|
||||||
|
name: docker
|
||||||
|
platforms:
|
||||||
|
- name: matrix-authentication-service-${MOLECULE_DISTRO:-ubuntu2604}-default
|
||||||
|
image: "geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2604}-ansible:latest"
|
||||||
|
command: ${MOLECULE_DOCKER_COMMAND:-""}
|
||||||
|
volumes:
|
||||||
|
- /sys/fs/cgroup:/sys/fs/cgroup:rw
|
||||||
|
cgroupns_mode: host
|
||||||
|
privileged: true
|
||||||
|
pre_build_image: true
|
||||||
|
provisioner:
|
||||||
|
name: ansible
|
||||||
|
config_options:
|
||||||
|
defaults:
|
||||||
|
callback_result_format: yaml
|
||||||
|
inventory:
|
||||||
|
group_vars:
|
||||||
|
all:
|
||||||
|
matrix_authentication_service_hostname: mas.molecule.local
|
||||||
|
matrix_authentication_service_path_prefix: /molecule-auth
|
||||||
|
matrix_authentication_service_container_network: matrix-authentication-service-molecule
|
||||||
|
|
||||||
|
# verify.yml is a separate play where role defaults are out of scope. These are
|
||||||
|
# pinned to the paths the role derives from matrix_base_data_path.
|
||||||
|
matrix_authentication_service_base_path: /matrix/matrix-authentication-service
|
||||||
|
matrix_authentication_service_config_path: /matrix/matrix-authentication-service/config
|
||||||
|
matrix_authentication_service_data_path: /matrix/matrix-authentication-service/data
|
||||||
|
matrix_authentication_service_data_keys_path: /matrix/matrix-authentication-service/data/keys
|
||||||
|
|
||||||
|
# Real Postgres, with a database and role which differ from the component defaults.
|
||||||
|
# A migrated schema therefore proves hostname resolution and authentication too.
|
||||||
|
matrix_authentication_service_config_database_host: matrix-postgres-molecule
|
||||||
|
matrix_authentication_service_config_database_port: 5432
|
||||||
|
matrix_authentication_service_config_database_username: molecule_mas_user
|
||||||
|
matrix_authentication_service_config_database_password: molecule_pg_password_97af31
|
||||||
|
matrix_authentication_service_config_database_database: molecule_mas_database
|
||||||
|
matrix_authentication_service_config_database_max_connections: 7
|
||||||
|
matrix_authentication_service_config_database_min_connections: 2
|
||||||
|
matrix_authentication_service_config_database_connect_timeout: 17
|
||||||
|
|
||||||
|
matrix_authentication_service_config_secrets_encryption: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
||||||
|
matrix_authentication_service_config_matrix_homeserver: molecule.local
|
||||||
|
matrix_authentication_service_config_matrix_secret: molecule_homeserver_secret_d3a58f
|
||||||
|
matrix_authentication_service_config_matrix_endpoint: http://matrix.molecule.local:8008
|
||||||
|
|
||||||
|
# Values unlike both the role and MAS defaults, so parsed configuration assertions
|
||||||
|
# can tell whether this scenario reached the rendered file.
|
||||||
|
matrix_authentication_service_config_http_trusted_proxies:
|
||||||
|
- 198.51.100.0/24
|
||||||
|
- 2001:db8:1234::/48
|
||||||
|
matrix_authentication_service_config_email_from_name: Molecule MAS
|
||||||
|
matrix_authentication_service_config_email_from_address: auth@molecule.local
|
||||||
|
matrix_authentication_service_config_account_displayname_change_allowed: false
|
||||||
|
matrix_authentication_service_config_account_password_registration_enabled: true
|
||||||
|
matrix_authentication_service_config_account_password_registration_email_required: false
|
||||||
|
matrix_authentication_service_config_account_password_recovery_enabled: true
|
||||||
|
matrix_authentication_service_config_account_login_with_email_allowed: true
|
||||||
|
matrix_authentication_service_config_passwords_minimum_complexity: 2
|
||||||
|
|
||||||
|
# Traefik itself is intentionally absent. The rendered label file and Docker's live
|
||||||
|
# labels prove the role composed the non-default routing contract correctly.
|
||||||
|
matrix_authentication_service_container_labels_traefik_entrypoints: web
|
||||||
|
matrix_authentication_service_container_labels_traefik_tls_certResolver: molecule-resolver
|
||||||
|
matrix_authentication_service_container_labels_public_main_priority: 742
|
||||||
|
matrix_authentication_service_container_labels_public_compatibility_layer_enabled: true
|
||||||
|
matrix_authentication_service_container_labels_public_compatibility_layer_hostname: matrix.molecule.local
|
||||||
|
matrix_authentication_service_container_labels_public_compatibility_layer_priority: 743
|
||||||
|
matrix_authentication_service_container_labels_traefik_additional_response_headers_custom:
|
||||||
|
X-Molecule-MAS: covered
|
||||||
|
matrix_authentication_service_container_labels_additional_labels: |
|
||||||
|
molecule.mas.coverage=enabled
|
||||||
|
env:
|
||||||
|
# Workaround for https://github.com/ansible/molecule/issues/4391
|
||||||
|
ANSIBLE_ROLES_PATH: ${MOLECULE_PROJECT_DIRECTORY}/../..:/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:${ANSIBLE_HOME:-~/.ansible}/roles
|
||||||
|
scenario:
|
||||||
|
test_sequence:
|
||||||
|
- dependency
|
||||||
|
- cleanup
|
||||||
|
- destroy
|
||||||
|
- syntax
|
||||||
|
- create
|
||||||
|
- prepare
|
||||||
|
- converge
|
||||||
|
- idempotence
|
||||||
|
- verify
|
||||||
|
- cleanup
|
||||||
|
- destroy
|
||||||
|
verifier:
|
||||||
|
name: ansible
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
---
|
||||||
|
- name: Prepare Matrix Authentication Service Molecule tests
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
vars_files:
|
||||||
|
- "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/vars.yml"
|
||||||
|
- "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
|
||||||
|
gather_facts: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure apt cache is updated
|
||||||
|
ansible.builtin.apt:
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 600
|
||||||
|
when: ansible_facts['os_family'] == 'Debian'
|
||||||
|
|
||||||
|
- name: Ensure required packages are installed
|
||||||
|
ansible.builtin.package:
|
||||||
|
name:
|
||||||
|
- python3-requests
|
||||||
|
- fuse-overlayfs
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure Docker is installed
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: ansible-role-docker
|
||||||
|
vars:
|
||||||
|
docker_daemon_options:
|
||||||
|
storage-driver: fuse-overlayfs
|
||||||
|
|
||||||
|
- name: Ensure the matrix group exists
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "{{ matrix_group_name }}"
|
||||||
|
gid: "{{ matrix_user_gid }}"
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure the matrix user exists
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ matrix_user_name }}"
|
||||||
|
uid: "{{ matrix_user_uid }}"
|
||||||
|
group: "{{ matrix_group_name }}"
|
||||||
|
create_home: false
|
||||||
|
system: true
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure the base data path exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ matrix_base_data_path }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ matrix_user_name }}"
|
||||||
|
group: "{{ matrix_group_name }}"
|
||||||
|
mode: "0750"
|
||||||
|
|
||||||
|
- name: Ensure the private container network exists
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- network
|
||||||
|
- create
|
||||||
|
- "{{ matrix_authentication_service_container_network }}"
|
||||||
|
register: matrix_authentication_service_molecule_network
|
||||||
|
changed_when: matrix_authentication_service_molecule_network.rc == 0
|
||||||
|
failed_when:
|
||||||
|
- matrix_authentication_service_molecule_network.rc != 0
|
||||||
|
- "'already exists' not in matrix_authentication_service_molecule_network.stderr"
|
||||||
|
|
||||||
|
- name: Ensure Postgres is running
|
||||||
|
ansible.builtin.include_tasks:
|
||||||
|
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/tasks/postgres.yml"
|
||||||
|
vars:
|
||||||
|
molecule_shared_postgres_network: "{{ matrix_authentication_service_container_network }}"
|
||||||
|
molecule_shared_postgres_database: "{{ matrix_authentication_service_config_database_database }}"
|
||||||
|
molecule_shared_postgres_username: "{{ matrix_authentication_service_config_database_username }}"
|
||||||
|
molecule_shared_postgres_password: "{{ matrix_authentication_service_config_database_password }}"
|
||||||
|
|
||||||
|
# MAS does not need a successful homeserver request to expose discovery, but providing
|
||||||
|
# its configured endpoint makes the scenario independent of future startup checks.
|
||||||
|
- name: Ensure the homeserver stub is running
|
||||||
|
ansible.builtin.include_tasks:
|
||||||
|
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/tasks/homeserver-stub.yml"
|
||||||
|
vars:
|
||||||
|
molecule_shared_stub_network: "{{ matrix_authentication_service_container_network }}"
|
||||||
|
molecule_shared_stub_server_name: molecule.local
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../../../molecule-shared/requirements.yml
|
||||||
@@ -0,0 +1,538 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
---
|
||||||
|
# MAS exits on a bad startup configuration rather than retrying in-process. The restart
|
||||||
|
# counter guards that failure mode; live health, OIDC, JWKS, and schema checks carry the
|
||||||
|
# stronger proof that the stable process is actually using what this role rendered.
|
||||||
|
- name: Verify Matrix Authentication Service
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
vars_files:
|
||||||
|
- "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/vars.yml"
|
||||||
|
- "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/../../../molecule-shared/playbook-context.yml"
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
matrix_authentication_service_config: >-
|
||||||
|
{{ matrix_authentication_service_config_file.content | b64decode | from_yaml }}
|
||||||
|
matrix_authentication_service_web_listener: >-
|
||||||
|
{{ matrix_authentication_service_config.http.listeners
|
||||||
|
| selectattr('name', 'equalto', 'web') | first | default({}) }}
|
||||||
|
matrix_authentication_service_internal_listener: >-
|
||||||
|
{{ matrix_authentication_service_config.http.listeners
|
||||||
|
| selectattr('name', 'equalto', 'internal') | first | default({}) }}
|
||||||
|
matrix_authentication_service_discovery_body: >-
|
||||||
|
{{ matrix_authentication_service_discovery_http.stdout_lines[:-1] | join('\n') }}
|
||||||
|
matrix_authentication_service_discovery: >-
|
||||||
|
{{ matrix_authentication_service_discovery_body | from_json }}
|
||||||
|
matrix_authentication_service_jwks_body: >-
|
||||||
|
{{ matrix_authentication_service_jwks_http.stdout_lines[:-1] | join('\n') }}
|
||||||
|
matrix_authentication_service_jwks: >-
|
||||||
|
{{ matrix_authentication_service_jwks_body | from_json }}
|
||||||
|
matrix_authentication_service_jwks_kids: >-
|
||||||
|
{{ matrix_authentication_service_jwks['keys'] | map(attribute='kid') | list }}
|
||||||
|
matrix_authentication_service_labels_lines: >-
|
||||||
|
{{ (matrix_authentication_service_labels_file.content | b64decode).splitlines() }}
|
||||||
|
matrix_authentication_service_runtime: >-
|
||||||
|
{{ (matrix_authentication_service_container_inspect.stdout | from_json) | first }}
|
||||||
|
matrix_authentication_service_config_mounts: >-
|
||||||
|
{{ matrix_authentication_service_runtime.Mounts
|
||||||
|
| selectattr('Destination', 'equalto', '/config.yaml') | list }}
|
||||||
|
matrix_authentication_service_keys_mounts: >-
|
||||||
|
{{ matrix_authentication_service_runtime.Mounts
|
||||||
|
| selectattr('Destination', 'equalto', '/keys') | list }}
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# Read the pin from the role itself so Renovate changes what this assertion expects.
|
||||||
|
- name: Load the role's defaults under a separate name
|
||||||
|
ansible.builtin.include_vars:
|
||||||
|
file: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/main.yml"
|
||||||
|
name: matrix_authentication_service_role_defaults
|
||||||
|
|
||||||
|
- name: Wait for the Matrix Authentication Service unit to become active
|
||||||
|
ansible.builtin.systemd_service:
|
||||||
|
name: matrix-authentication-service.service
|
||||||
|
register: matrix_authentication_service_service
|
||||||
|
until: matrix_authentication_service_service.status.ActiveState == 'active'
|
||||||
|
retries: 30
|
||||||
|
delay: 5
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Assert the Matrix Authentication Service process is stable
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_service.status.ActiveState == 'active'
|
||||||
|
- matrix_authentication_service_service.status.NRestarts is defined
|
||||||
|
- matrix_authentication_service_service.status.NRestarts | int == 0
|
||||||
|
fail_msg: >-
|
||||||
|
matrix-authentication-service.service is
|
||||||
|
{{ matrix_authentication_service_service.status.ActiveState | default('unknown') }}
|
||||||
|
after {{ matrix_authentication_service_service.status.NRestarts | default('?') }} restart(s)
|
||||||
|
success_msg: "Matrix Authentication Service is active and has not restarted"
|
||||||
|
|
||||||
|
# The internal listener binds loopback inside the MAS container. Sharing its network
|
||||||
|
# namespace is the only way to probe it without changing the deployment contract.
|
||||||
|
- name: Request the prefixed internal health endpoint
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- run
|
||||||
|
- --rm
|
||||||
|
- --network=container:matrix-authentication-service
|
||||||
|
- "{{ molecule_shared_image_curl }}"
|
||||||
|
- --silent
|
||||||
|
- --show-error
|
||||||
|
- --write-out
|
||||||
|
- "\nHTTP_STATUS=%{http_code}"
|
||||||
|
- http://[::1]:8081/molecule-auth/health
|
||||||
|
register: matrix_authentication_service_health_http
|
||||||
|
changed_when: false
|
||||||
|
until: "'HTTP_STATUS=200' in matrix_authentication_service_health_http.stdout"
|
||||||
|
retries: 24
|
||||||
|
delay: 5
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Assert the internal listener reports healthy
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_health_http.rc == 0
|
||||||
|
- matrix_authentication_service_health_http.stdout_lines[-1] == 'HTTP_STATUS=200'
|
||||||
|
- matrix_authentication_service_health_http.stdout_lines[0] == 'ok'
|
||||||
|
fail_msg: >-
|
||||||
|
MAS did not report healthy on its prefixed, loopback-only internal listener
|
||||||
|
({{ matrix_authentication_service_health_http.stdout | default('no output') }})
|
||||||
|
success_msg: "MAS reports healthy on the prefixed internal listener"
|
||||||
|
|
||||||
|
- name: Request the unprefixed internal health path
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- run
|
||||||
|
- --rm
|
||||||
|
- --network=container:matrix-authentication-service
|
||||||
|
- "{{ molecule_shared_image_curl }}"
|
||||||
|
- --silent
|
||||||
|
- --output
|
||||||
|
- /dev/null
|
||||||
|
- --write-out
|
||||||
|
- "HTTP_STATUS=%{http_code}"
|
||||||
|
- http://[::1]:8081/health
|
||||||
|
register: matrix_authentication_service_unprefixed_health_http
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Assert the internal health resource exists only below the configured prefix
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_unprefixed_health_http.rc == 0
|
||||||
|
- matrix_authentication_service_unprefixed_health_http.stdout == 'HTTP_STATUS=404'
|
||||||
|
fail_msg: "The unprefixed health path answered, so the configured prefix is not proven"
|
||||||
|
success_msg: "The internal listener rejects the unprefixed health path"
|
||||||
|
|
||||||
|
# Probed through the private network because the role deliberately publishes no host port.
|
||||||
|
- name: Request the prefixed OpenID Provider discovery document
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- run
|
||||||
|
- --rm
|
||||||
|
- --network={{ matrix_authentication_service_container_network }}
|
||||||
|
- "{{ molecule_shared_image_curl }}"
|
||||||
|
- --silent
|
||||||
|
- --show-error
|
||||||
|
- --write-out
|
||||||
|
- "\nHTTP_STATUS=%{http_code}"
|
||||||
|
- http://matrix-authentication-service:8080/molecule-auth/.well-known/openid-configuration
|
||||||
|
register: matrix_authentication_service_discovery_http
|
||||||
|
changed_when: false
|
||||||
|
until: "'HTTP_STATUS=200' in matrix_authentication_service_discovery_http.stdout"
|
||||||
|
retries: 24
|
||||||
|
delay: 5
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Assert MAS serves a real OpenID Provider discovery document
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_discovery_http.rc == 0
|
||||||
|
- matrix_authentication_service_discovery_http.stdout_lines[-1] == 'HTTP_STATUS=200'
|
||||||
|
- matrix_authentication_service_discovery is mapping
|
||||||
|
- matrix_authentication_service_discovery.issuer == 'https://mas.molecule.local/molecule-auth/'
|
||||||
|
- matrix_authentication_service_discovery.authorization_endpoint == 'https://mas.molecule.local/molecule-auth/authorize'
|
||||||
|
- matrix_authentication_service_discovery.token_endpoint == 'https://mas.molecule.local/molecule-auth/oauth2/token'
|
||||||
|
- matrix_authentication_service_discovery.jwks_uri == 'https://mas.molecule.local/molecule-auth/oauth2/keys.json'
|
||||||
|
- matrix_authentication_service_discovery.userinfo_endpoint == 'https://mas.molecule.local/molecule-auth/oauth2/userinfo'
|
||||||
|
- "'openid' in matrix_authentication_service_discovery.scopes_supported"
|
||||||
|
- "'authorization_code' in matrix_authentication_service_discovery.grant_types_supported"
|
||||||
|
- "'S256' in matrix_authentication_service_discovery.code_challenge_methods_supported"
|
||||||
|
fail_msg: >-
|
||||||
|
MAS did not return the configured, prefixed OIDC discovery contract
|
||||||
|
({{ matrix_authentication_service_discovery_http.stdout | default('no output') }})
|
||||||
|
success_msg: "MAS advertises its configured prefixed OpenID Provider contract"
|
||||||
|
|
||||||
|
- name: Request the unprefixed discovery path
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- run
|
||||||
|
- --rm
|
||||||
|
- --network={{ matrix_authentication_service_container_network }}
|
||||||
|
- "{{ molecule_shared_image_curl }}"
|
||||||
|
- --silent
|
||||||
|
- --output
|
||||||
|
- /dev/null
|
||||||
|
- --write-out
|
||||||
|
- "HTTP_STATUS=%{http_code}"
|
||||||
|
- http://matrix-authentication-service:8080/.well-known/openid-configuration
|
||||||
|
register: matrix_authentication_service_unprefixed_discovery_http
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Assert discovery exists only below the configured prefix
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_unprefixed_discovery_http.rc == 0
|
||||||
|
- matrix_authentication_service_unprefixed_discovery_http.stdout == 'HTTP_STATUS=404'
|
||||||
|
fail_msg: "The unprefixed discovery path answered, so the configured prefix is not proven"
|
||||||
|
success_msg: "The public listener rejects the unprefixed discovery path"
|
||||||
|
|
||||||
|
- name: Request the JWKS advertised by discovery
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- run
|
||||||
|
- --rm
|
||||||
|
- --network={{ matrix_authentication_service_container_network }}
|
||||||
|
- "{{ molecule_shared_image_curl }}"
|
||||||
|
- --silent
|
||||||
|
- --show-error
|
||||||
|
- --write-out
|
||||||
|
- "\nHTTP_STATUS=%{http_code}"
|
||||||
|
- http://matrix-authentication-service:8080/molecule-auth/oauth2/keys.json
|
||||||
|
register: matrix_authentication_service_jwks_http
|
||||||
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Assert JWKS exposes all role-managed signing keys
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_jwks_http.rc == 0
|
||||||
|
- matrix_authentication_service_jwks_http.stdout_lines[-1] == 'HTTP_STATUS=200'
|
||||||
|
- matrix_authentication_service_jwks is mapping
|
||||||
|
- matrix_authentication_service_jwks['keys'] is sequence
|
||||||
|
- matrix_authentication_service_jwks['keys'] | length == 4
|
||||||
|
- "'default-rsa' in matrix_authentication_service_jwks_kids"
|
||||||
|
- "'default-ecdsa-p256' in matrix_authentication_service_jwks_kids"
|
||||||
|
- "'default-ecdsa-p384' in matrix_authentication_service_jwks_kids"
|
||||||
|
- "'default-ecdsa-k256' in matrix_authentication_service_jwks_kids"
|
||||||
|
- (matrix_authentication_service_jwks['keys'] | selectattr('kid', 'equalto', 'default-rsa') | first).kty == 'RSA'
|
||||||
|
- (matrix_authentication_service_jwks['keys'] | selectattr('kid', 'equalto', 'default-rsa') | first).n | length > 100
|
||||||
|
- (matrix_authentication_service_jwks['keys'] | selectattr('kid', 'equalto', 'default-ecdsa-p256') | first).crv == 'P-256'
|
||||||
|
- (matrix_authentication_service_jwks['keys'] | selectattr('kid', 'equalto', 'default-ecdsa-p384') | first).crv == 'P-384'
|
||||||
|
- (matrix_authentication_service_jwks['keys'] | selectattr('kid', 'equalto', 'default-ecdsa-k256') | first).crv == 'secp256k1'
|
||||||
|
fail_msg: "MAS did not derive the expected public JWKS from all four managed keys"
|
||||||
|
success_msg: "MAS exposes all four role-managed signing keys in its public JWKS"
|
||||||
|
|
||||||
|
- name: Read the rendered MAS configuration
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ matrix_authentication_service_config_path }}/config.yaml"
|
||||||
|
register: matrix_authentication_service_config_file
|
||||||
|
|
||||||
|
- name: Read the rendered MAS configuration identity
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ matrix_authentication_service_config_path }}/config.yaml"
|
||||||
|
register: matrix_authentication_service_config_stat
|
||||||
|
|
||||||
|
- name: Assert the parsed listener and public URL configuration
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_config.http.listeners | length == 2
|
||||||
|
- matrix_authentication_service_web_listener.resources | map(attribute='name') | list == ['discovery', 'human', 'oauth', 'compat', 'graphql', 'assets']
|
||||||
|
- "matrix_authentication_service_web_listener.binds == [{'address': '[::]:8080'}]"
|
||||||
|
- matrix_authentication_service_web_listener.prefix == '/molecule-auth'
|
||||||
|
- not matrix_authentication_service_web_listener.proxy_protocol
|
||||||
|
- "matrix_authentication_service_internal_listener.resources == [{'name': 'health'}]"
|
||||||
|
- "matrix_authentication_service_internal_listener.binds == [{'host': 'localhost', 'port': 8081}]"
|
||||||
|
- matrix_authentication_service_internal_listener.prefix == '/molecule-auth'
|
||||||
|
- matrix_authentication_service_config.http.public_base == 'https://mas.molecule.local/molecule-auth/'
|
||||||
|
- matrix_authentication_service_config.http.issuer == 'https://mas.molecule.local/molecule-auth/'
|
||||||
|
- matrix_authentication_service_config.http.trusted_proxies == ['198.51.100.0/24', '2001:db8:1234::/48']
|
||||||
|
fail_msg: "The parsed MAS listener or public URL configuration is incorrect"
|
||||||
|
success_msg: "The parsed MAS configuration carries the non-default listener contract"
|
||||||
|
|
||||||
|
- name: Assert the parsed Postgres pool configuration
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_config.database.host == matrix_authentication_service_config_database_host
|
||||||
|
- matrix_authentication_service_config.database.port == matrix_authentication_service_config_database_port
|
||||||
|
- matrix_authentication_service_config.database.username == matrix_authentication_service_config_database_username
|
||||||
|
- matrix_authentication_service_config.database.password == matrix_authentication_service_config_database_password
|
||||||
|
- matrix_authentication_service_config.database.database == matrix_authentication_service_config_database_database
|
||||||
|
- matrix_authentication_service_config.database.ssl_mode == 'disable'
|
||||||
|
- matrix_authentication_service_config.database.max_connections == 7
|
||||||
|
- matrix_authentication_service_config.database.min_connections == 2
|
||||||
|
- matrix_authentication_service_config.database.connect_timeout == 17
|
||||||
|
fail_msg: "The parsed MAS configuration does not point at scenario Postgres"
|
||||||
|
success_msg: "The parsed MAS configuration points at scenario Postgres"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Assert the parsed Matrix and cryptographic configuration
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_config.matrix.homeserver == 'molecule.local'
|
||||||
|
- matrix_authentication_service_config.matrix.endpoint == 'http://matrix.molecule.local:8008'
|
||||||
|
- matrix_authentication_service_config.matrix.secret == matrix_authentication_service_config_matrix_secret
|
||||||
|
- matrix_authentication_service_config.secrets.encryption == matrix_authentication_service_config_secrets_encryption
|
||||||
|
- matrix_authentication_service_config.secrets['keys'] | map(attribute='kid') | list == ['default-rsa', 'default-ecdsa-p256', 'default-ecdsa-p384', 'default-ecdsa-k256']
|
||||||
|
- matrix_authentication_service_config.secrets['keys'] | map(attribute='key_file') | list == ['/keys/rsa-2048.priv.pem', '/keys/ecdsa-p256.priv.pem', '/keys/ecdsa-p384.priv.pem', '/keys/ecdsa-k256.priv.pem']
|
||||||
|
fail_msg: "The parsed MAS Matrix or signing-key configuration is incorrect"
|
||||||
|
success_msg: "The parsed MAS configuration carries its Matrix secrets and managed keys"
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Assert the parsed non-default account behavior
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- not matrix_authentication_service_config.account.displayname_change_allowed
|
||||||
|
- matrix_authentication_service_config.account.password_registration_enabled
|
||||||
|
- not matrix_authentication_service_config.account.password_registration_email_required
|
||||||
|
- matrix_authentication_service_config.account.password_recovery_enabled
|
||||||
|
- matrix_authentication_service_config.account.login_with_email_allowed
|
||||||
|
- matrix_authentication_service_config.passwords.minimum_complexity == 2
|
||||||
|
- matrix_authentication_service_config.email.from == '"Molecule MAS" <auth@molecule.local>'
|
||||||
|
- matrix_authentication_service_config.email.transport == 'blackhole'
|
||||||
|
- matrix_authentication_service_config.clients == []
|
||||||
|
- "'upstream_oauth2' not in matrix_authentication_service_config"
|
||||||
|
- "'captcha' not in matrix_authentication_service_config"
|
||||||
|
fail_msg: "The parsed MAS configuration does not carry the scenario account behavior"
|
||||||
|
success_msg: "The parsed MAS configuration carries the non-default account behavior"
|
||||||
|
|
||||||
|
- name: Assert the rendered configuration file identity
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_config_stat.stat.uid | int == matrix_user_uid | int
|
||||||
|
- matrix_authentication_service_config_stat.stat.gid | int == matrix_user_gid | int
|
||||||
|
- matrix_authentication_service_config_stat.stat.mode == '0644'
|
||||||
|
fail_msg: "config.yaml has the wrong ownership or mode"
|
||||||
|
success_msg: "config.yaml has the playbook identity and expected mode"
|
||||||
|
|
||||||
|
- name: Read the managed signing-key identities
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ matrix_authentication_service_data_keys_path }}/{{ key_file }}"
|
||||||
|
loop:
|
||||||
|
- rsa-2048.priv.pem
|
||||||
|
- ecdsa-p256.priv.pem
|
||||||
|
- ecdsa-p384.priv.pem
|
||||||
|
- ecdsa-k256.priv.pem
|
||||||
|
loop_control:
|
||||||
|
loop_var: key_file
|
||||||
|
register: matrix_authentication_service_key_stats
|
||||||
|
|
||||||
|
- name: Assert every managed signing key is non-empty and private
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- key_stat.stat.exists
|
||||||
|
- key_stat.stat.isreg
|
||||||
|
- key_stat.stat.size | int > 200
|
||||||
|
- key_stat.stat.uid | int == matrix_user_uid | int
|
||||||
|
- key_stat.stat.gid | int == matrix_user_gid | int
|
||||||
|
- key_stat.stat.mode == '0600'
|
||||||
|
fail_msg: "A managed MAS signing key is missing, empty, exposed, or misowned"
|
||||||
|
success_msg: "The managed MAS signing key is present and private"
|
||||||
|
loop: "{{ matrix_authentication_service_key_stats.results }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: key_stat
|
||||||
|
label: "{{ key_stat.key_file }}"
|
||||||
|
|
||||||
|
- name: Validate every managed signing key with OpenSSL
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- openssl
|
||||||
|
- pkey
|
||||||
|
- -in
|
||||||
|
- "{{ matrix_authentication_service_data_keys_path }}/{{ key_file }}"
|
||||||
|
- -check
|
||||||
|
- -noout
|
||||||
|
loop:
|
||||||
|
- rsa-2048.priv.pem
|
||||||
|
- ecdsa-p256.priv.pem
|
||||||
|
- ecdsa-p384.priv.pem
|
||||||
|
- ecdsa-k256.priv.pem
|
||||||
|
loop_control:
|
||||||
|
loop_var: key_file
|
||||||
|
register: matrix_authentication_service_key_validation
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Assert OpenSSL accepts every managed signing key
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- key_validation.rc == 0
|
||||||
|
fail_msg: "OpenSSL rejected a role-managed MAS signing key"
|
||||||
|
success_msg: "OpenSSL accepts the role-managed MAS signing key"
|
||||||
|
loop: "{{ matrix_authentication_service_key_validation.results }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: key_validation
|
||||||
|
label: "{{ key_validation.key_file }}"
|
||||||
|
|
||||||
|
# These tables can only exist after MAS has reached the named host, authenticated as
|
||||||
|
# the non-default role, selected the non-default database, and run genuine migrations.
|
||||||
|
- name: List the tables MAS created in Postgres
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- exec
|
||||||
|
- matrix-postgres-molecule
|
||||||
|
- psql
|
||||||
|
- --username={{ matrix_authentication_service_config_database_username }}
|
||||||
|
- --dbname={{ matrix_authentication_service_config_database_database }}
|
||||||
|
- --tuples-only
|
||||||
|
- --no-align
|
||||||
|
- --command=SELECT tablename FROM pg_tables WHERE schemaname = 'public'
|
||||||
|
register: matrix_authentication_service_tables
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Count successful MAS migrations in Postgres
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- exec
|
||||||
|
- matrix-postgres-molecule
|
||||||
|
- psql
|
||||||
|
- --username={{ matrix_authentication_service_config_database_username }}
|
||||||
|
- --dbname={{ matrix_authentication_service_config_database_database }}
|
||||||
|
- --tuples-only
|
||||||
|
- --no-align
|
||||||
|
- --command=SELECT count(*) FROM _sqlx_migrations WHERE success
|
||||||
|
register: matrix_authentication_service_migrations
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Assert MAS genuinely migrated the configured Postgres database
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_tables.rc == 0
|
||||||
|
- "'_sqlx_migrations' in matrix_authentication_service_table_names"
|
||||||
|
- "'users' in matrix_authentication_service_table_names"
|
||||||
|
- "'user_sessions' in matrix_authentication_service_table_names"
|
||||||
|
- "'oauth2_clients' in matrix_authentication_service_table_names"
|
||||||
|
- "'oauth2_access_tokens' in matrix_authentication_service_table_names"
|
||||||
|
- "'upstream_oauth_providers' in matrix_authentication_service_table_names"
|
||||||
|
- matrix_authentication_service_table_names | length > 30
|
||||||
|
- matrix_authentication_service_migrations.rc == 0
|
||||||
|
- matrix_authentication_service_migrations.stdout | trim | int > 100
|
||||||
|
fail_msg: >-
|
||||||
|
MAS did not genuinely migrate {{ matrix_authentication_service_config_database_database }}
|
||||||
|
({{ matrix_authentication_service_table_names | length }} tables,
|
||||||
|
{{ matrix_authentication_service_migrations.stdout | trim | default('?') }} migrations)
|
||||||
|
success_msg: "MAS genuinely migrated the configured Postgres database"
|
||||||
|
vars:
|
||||||
|
matrix_authentication_service_table_names: >-
|
||||||
|
{{ matrix_authentication_service_tables.stdout_lines | select | list }}
|
||||||
|
|
||||||
|
- name: Read the Traefik labels the role rendered
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ matrix_authentication_service_config_path }}/labels"
|
||||||
|
register: matrix_authentication_service_labels_file
|
||||||
|
|
||||||
|
- name: Assert the rendered labels carry the non-default public routing contract
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- "'traefik.enable=true' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.docker.network=matrix-authentication-service-molecule' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.services.matrix-authentication-service.loadbalancer.server.port=8080' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers.matrix-authentication-service.rule=Host(`mas.molecule.local`) && PathPrefix(`/molecule-auth`)' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers.matrix-authentication-service.priority=742' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.middlewares.matrix-authentication-service-slashless-redirect.redirectregex.regex=(/molecule-auth)$' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.middlewares.matrix-authentication-service-add-headers.headers.customresponseheaders.X-Molecule-MAS=covered' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers.matrix-authentication-service.middlewares=matrix-authentication-service-slashless-redirect,matrix-authentication-service-add-headers' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers.matrix-authentication-service.entrypoints=web' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers.matrix-authentication-service.tls=false' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'molecule.mas.coverage=enabled' in matrix_authentication_service_labels_lines"
|
||||||
|
fail_msg: "The rendered labels do not carry the configured public MAS route"
|
||||||
|
success_msg: "The rendered labels carry the configured public MAS route"
|
||||||
|
|
||||||
|
- name: Assert the rendered labels carry the compatibility-layer route
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- "'traefik.http.middlewares.matrix-authentication-service-add-prefix.addprefix.prefix=/molecule-auth' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers._internalmatrix-authentication-service-public-compatibility-layer.rule=Host(`matrix.molecule.local`) && PathRegexp(`^/_matrix/client/(?P<version>([^/]+))/(?P<endpoint>(login|logout|refresh))`)' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers._internalmatrix-authentication-service-public-compatibility-layer.priority=743' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers._internalmatrix-authentication-service-public-compatibility-layer.middlewares=matrix-authentication-service-add-prefix' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers._internalmatrix-authentication-service-public-compatibility-layer.entrypoints=web' in matrix_authentication_service_labels_lines"
|
||||||
|
- "'traefik.http.routers._internalmatrix-authentication-service-public-compatibility-layer.tls=false' in matrix_authentication_service_labels_lines"
|
||||||
|
fail_msg: "The rendered labels do not carry the configured compatibility route"
|
||||||
|
success_msg: "The rendered labels carry the configured compatibility-layer route"
|
||||||
|
|
||||||
|
- name: Inspect the running MAS container
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- docker
|
||||||
|
- container
|
||||||
|
- inspect
|
||||||
|
- matrix-authentication-service
|
||||||
|
register: matrix_authentication_service_container_inspect
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Assert the running container uses the exact image pinned by the role
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.Config.Image == 'ghcr.io/element-hq/matrix-authentication-service:' + matrix_authentication_service_role_defaults.matrix_authentication_service_version
|
||||||
|
fail_msg: "The running MAS container does not use the exact role-pinned image"
|
||||||
|
success_msg: "The running MAS container uses the exact role-pinned image"
|
||||||
|
|
||||||
|
- name: Assert the running container uses the playbook identity
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.Config.User == (matrix_user_uid | string) + ':' + (matrix_user_gid | string)
|
||||||
|
fail_msg: "The running MAS container does not use the playbook UID and GID"
|
||||||
|
success_msg: "The running MAS container uses the playbook UID and GID"
|
||||||
|
|
||||||
|
- name: Assert the running container security isolation
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.HostConfig.ReadonlyRootfs is sameas true
|
||||||
|
- matrix_authentication_service_runtime.HostConfig.CapDrop == ['ALL']
|
||||||
|
- not matrix_authentication_service_runtime.HostConfig.Privileged
|
||||||
|
fail_msg: "The running MAS container lacks read-only, capability-dropped isolation"
|
||||||
|
success_msg: "The running MAS container has read-only, capability-dropped isolation"
|
||||||
|
|
||||||
|
- name: Assert the running container mounts only configuration and keys read-only
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.Mounts | length == 2
|
||||||
|
- matrix_authentication_service_config_mounts | length == 1
|
||||||
|
- matrix_authentication_service_config_mounts[0].RW is sameas false
|
||||||
|
- matrix_authentication_service_keys_mounts | length == 1
|
||||||
|
- matrix_authentication_service_keys_mounts[0].RW is sameas false
|
||||||
|
fail_msg: "The running MAS container's config or key mount contract is incorrect"
|
||||||
|
success_msg: "The running MAS container mounts only configuration and keys read-only"
|
||||||
|
|
||||||
|
- name: Assert the running container has only its dedicated network
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.NetworkSettings.Networks is mapping
|
||||||
|
- matrix_authentication_service_runtime.NetworkSettings.Networks | length == 1
|
||||||
|
- matrix_authentication_service_container_network in matrix_authentication_service_runtime.NetworkSettings.Networks
|
||||||
|
fail_msg: "The running MAS container has unexpected network attachments"
|
||||||
|
success_msg: "The running MAS container has only its dedicated network"
|
||||||
|
|
||||||
|
- name: Assert the running container publishes no host ports
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.HostConfig.PortBindings | default({}, true) | length == 0
|
||||||
|
- matrix_authentication_service_runtime.NetworkSettings.Ports | default({}, true) | length == 0
|
||||||
|
- not matrix_authentication_service_runtime.HostConfig.PublishAllPorts
|
||||||
|
fail_msg: "The running MAS container unexpectedly publishes a host port"
|
||||||
|
success_msg: "The running MAS container publishes no host ports"
|
||||||
|
|
||||||
|
- name: Assert Docker accepted the role's exact routing labels
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels is mapping
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['molecule.mas.coverage'] == 'enabled'
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['traefik.docker.network'] == 'matrix-authentication-service-molecule'
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['traefik.http.services.matrix-authentication-service.loadbalancer.server.port'] == '8080'
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['traefik.http.routers.matrix-authentication-service.rule'] == 'Host(`mas.molecule.local`) && PathPrefix(`/molecule-auth`)'
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['traefik.http.routers.matrix-authentication-service.priority'] == '742'
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['traefik.http.routers._internalmatrix-authentication-service-public-compatibility-layer.priority'] == '743'
|
||||||
|
- matrix_authentication_service_runtime.Config.Labels['traefik.http.middlewares.matrix-authentication-service-add-headers.headers.customresponseheaders.X-Molecule-MAS'] == 'covered'
|
||||||
|
fail_msg: "Docker did not attach the exact labels rendered by the role"
|
||||||
|
success_msg: "Docker attached the exact routing labels rendered by the role"
|
||||||
Reference in New Issue
Block a user