Compare commits

..

9 Commits

Author SHA1 Message Date
uumas
0895fba761 lint 2025-03-22 02:07:23 +02:00
uumas
46242f30d5 synapse: Support configuring login via oidc provider 2025-03-22 02:05:43 +02:00
uumas
cefa207eed synapse: Use matrix authentication service 2025-03-22 02:05:28 +02:00
uumas
974621ee16 Add matrix authentication service role 2025-03-22 02:02:32 +02:00
uumas
ffe3279886 volume: Make uid/gid assert quiet 2025-03-22 01:46:17 +02:00
uumas
f1eb28b431 service: Support specifying additional vhost locations and container
networks
2025-03-22 01:44:40 +02:00
uumas
e3007ff405 service: Support specifying wants 2025-03-22 01:43:47 +02:00
uumas
2528e2605c service: Make secrets available in a variable 2025-03-22 01:42:03 +02:00
uumas
d5cd823e5a container: Move secrets to its own tasks file 2025-03-22 01:31:24 +02:00
18 changed files with 405 additions and 12 deletions

View File

@@ -22,13 +22,9 @@
loop_control:
loop_var: volume
- name: Create secrets for container {{ container_name }}
containers.podman.podman_secret:
name: "{{ item.name }}"
data: "{{ item.value | default(lookup('community.general.random_string', special=false, length=128)) }}"
skip_existing: "{{ item.value is not defined }}"
no_log: true
loop: "{{ container_secrets }}"
- name: Create secrets
ansible.builtin.include_tasks: secrets.yaml
when: container_secrets | length > 0
- name: Create container service {{ container_name }}
containers.podman.podman_container:

View File

@@ -0,0 +1,8 @@
---
- name: Create secrets for container {{ container_name }}
containers.podman.podman_secret:
name: "{{ item.name }}"
data: "{{ item.value | default(lookup('community.general.random_string', special=false, length=128)) }}"
skip_existing: "{{ item.value is not defined }}"
no_log: true
loop: "{{ container_secrets }}"

View File

@@ -0,0 +1 @@
Sets up a matrix authentication service podman container.

View File

@@ -0,0 +1,5 @@
---
matrix_authentication_service_postgres_tag: 16-alpine
matrix_authentication_service_email_smtp_server: ""
matrix_authentication_service_additional_networks: []

View File

@@ -0,0 +1,132 @@
---
argument_specs:
main:
description: "Sets up a matrix authentication service podman container."
options:
matrix_authentication_service_additional_networks:
description: A list of additional podman networks for the matrix authentication service container.
type: list
required: false
default: []
elements: str
matrix_authentication_service_domain:
description: Domain for matrix authentication service
type: str
required: true
matrix_authentication_service_homeserver_name:
description: Homserver server name
type: str
required: true
matrix_authentication_service_homeserver_address:
description: Address where homeserver is accessible to matrix authentication service
type: str
required: true
matrix_authentication_service_client_secret:
description: >
See [upstream docs](https://element-hq.github.io/matrix-authentication-service/setup/homeserver.html#provision-a-client-for-the-homeserver-to-use)
type: str
required: true
matrix_authentication_service_homeserver_secret:
description: See [upstream docs](https://element-hq.github.io/matrix-authentication-service/reference/configuration.html#matrix)
type: str
required: true
matrix_authentication_service_secrets:
description:
- Matrix authentication service secrets.
- See [upstream docs](https://element-hq.github.io/matrix-authentication-service/reference/configuration.html#secrets) for more info
type: dict
required: true
options:
encryption:
type: str
required: true
keys:
type: list
required: true
elements: dict
options:
kid:
type: str
required: true
key:
type: str
required: true
matrix_authentication_service_email_smtp_server:
description: email.smtp_host, set this to enable sending emails
type: str
required: false
default: ""
matrix_authentication_service_email_smtp_user:
description: Required if matrix_authentication_service_email_smtp_server is set
type: str
matrix_authentication_service_email_smtp_password:
description: Required if matrix_authentication_service_email_smtp_server is set
type: str
matrix_authentication_service_email_from:
description: Required if matrix_authentication_service_email_smtp_server is set
type: str
matrix_authentication_service_upstream_oauth2_client_id:
description: See https://element-hq.github.io/matrix-authentication-service/reference/configuration.html#upstream_oauth2providers
type: str
required: false
default: ""
matrix_authentication_service_upstream_oauth2_human_name:
description: Required if matrix_authentication_service_upstream_oauth2_client_id is set
type: str
matrix_authentication_service_upstream_oauth2_client_secret:
description: Required if matrix_authentication_service_upstream_oauth2_client_id is set
type: str
matrix_authentication_service_upstream_oauth2_issuer:
description: Required if matrix_authentication_service_upstream_oauth2_client_id is set
type: str
matrix_authentication_service_upstream_oauth2_scope:
description: Required if matrix_authentication_service_upstream_oauth2_client_id is set
type: str
matrix_authentication_service_upstream_oauth2_claims_imports:
description: Required if matrix_authentication_service_upstream_oauth2_client_id is set
type: dict
options:
subject:
type: dict
required: false
options:
template:
type: str
required: true
localpart:
type: dict
required: true
options:
action:
type: str
required: true
template:
description: Required if action is not ignore
type: str
displayname:
type: dict
required: true
options:
action:
type: str
required: true
template:
description: Required if action is not ignore
type: str
email:
type: dict
required: true
options:
action:
type: str
required: true
template:
description: Required if action is not ignore
type: str
matrix_authentication_service_postgres_tag:
description: Postgres tag to use for matrix authentication service postgres container
type: str
required: false
default: 16-alpine

View File

@@ -0,0 +1,16 @@
---
- name: Matrix authentication service container
ansible.builtin.import_role:
name: service
vars:
service_name: matrix-authentication-service
service_container_image: "ghcr.io/element-hq/matrix-authentication-service:latest"
service_container_additional_networks: "{{ matrix_authentication_service_additional_networks }}"
service_database_type: postgres
service_postgres_tag: "{{ matrix_authentication_service_postgres_tag }}"
service_container_mounts:
- type: template
source: config.yaml.j2
destination: /config.yaml
service_container_http_port: 8080
service_domains: "{{ [matrix_authentication_service_domain] }}"

View File

@@ -0,0 +1,86 @@
---
# vim:ft=yaml
# {{ ansible_managed }}
http:
listeners:
- name: web
resources:
- name: discovery
- name: human
- name: oauth
- name: compat
- name: graphql
- name: assets
binds:
- address: '[::]:8080'
proxy_protocol: false
- name: internal
resources:
- name: health
binds:
- host: localhost
port: 8081
proxy_protocol: false
trusted_proxies:
- 192.168.0.0/16
- 172.16.0.0/12
- 10.0.0.0/10
- 127.0.0.1/8
- fd00::/8
- ::1/128
public_base: https://{{ matrix_authentication_service_domain }}/
database:
host: matrix-authentication-service-postgres
username: matrix_authentication_service
password: "{{ _service_database_password }}"
database: matrix_authentication_service
secrets:
{{ matrix_authentication_service_secrets | to_nice_yaml(indent=2) | indent(2) }}
passwords:
enabled: {{ matrix_authentication_service_upstream_oauth2_client_id | length == 0 }}
schemes:
- version: 1
algorithm: argon2id
minimum_complexity: 3
clients:
- client_id: 0000000000000000000SYNAPSE
client_auth_method: client_secret_basic
client_secret: "{{ matrix_authentication_service_client_secret }}"
matrix:
homeserver: {{ matrix_authentication_service_homeserver_name }}
secret: "{{ matrix_authentication_service_homeserver_secret }}"
endpoint: {{ matrix_authentication_service_homeserver_address }}
account:
email_change_allowed: true
displayname_change_allowed: true
password_registration_enabled: false
{% if matrix_authentication_service_email_smtp_server | length > 0 %}
email:
from: '{{ matrix_authentication_service_email_from }}'
transport: smtp
mode: starttls
hostname: {{ matrix_authentication_service_email_smtp_server }}
port: 587
username: {{ matrix_authentication_service_email_smtp_user }}
password: {{ matrix_authentication_service_email_smtp_password }}
{% endif %}
{% if matrix_authentication_service_upstream_oauth2_client_id | length > 0 %}
upstream_oauth2:
providers:
- id: 01JD3SBR0NMQB0M1WE3HF26E48
human_name: "{{ matrix_authentication_service_upstream_oauth2_human_name }}"
issuer: "{{ matrix_authentication_service_upstream_oauth2_issuer }}"
client_id: "{{ matrix_authentication_service_upstream_oauth2_client_id }}"
client_secret: "{{ matrix_authentication_service_upstream_oauth2_client_secret }}"
scope: "{{ matrix_authentication_service_upstream_oauth2_scope }}"
claims_imports:
{{ matrix_authentication_service_upstream_oauth2_claims_imports | to_nice_yaml(indent=2) | indent(8) }}
token_endpoint_auth_method: client_secret_basic
{% endif %}

View File

@@ -1,6 +1,8 @@
---
service_domains: []
service_vhost_locations: []
service_container_additional_networks: []
service_container_user: ""
service_container_publish_ports: []
service_container_mounts: []
@@ -12,4 +14,5 @@ service_database_type: none
service_additional_containers: []
service_requires: []
service_wants: []
service_auto_update: true

View File

@@ -20,6 +20,10 @@ argument_specs:
- Required if service_domains is not empty.
type: int
required: false
service_vhost_locations:
description: Passed to vhost role as vhost_locations
required: false
default: []
service_container_image:
description: "The image to run in the service container(s), in FQIN format (registry/imagename:tag)."
@@ -30,6 +34,12 @@ argument_specs:
type: str
required: false
default: ""
service_container_additional_networks:
description: A list of additional podman networks for the service container (in addition to service name network).
type: list
required: false
default: []
elements: str
service_container_publish_ports:
description: "A list of published ports in docker format (<host listen address>:<host port>:<container port>)"
type: list
@@ -80,7 +90,11 @@ argument_specs:
required: false
default: ""
service_container_secrets:
description: A list of secrets available to the service container in /run/secrets/<service name>-<secret name>
description:
- A list of secrets available to the service container in /run/secrets/<service name>-<secret name>
- >
A dict of secrets and their values (including autogenerated values) is available as `_service_podman_secrets` for use
in tepmlates or environment variables. This should only be used if the container doesn't support reading the secret from file
type: list
required: false
default: []
@@ -195,6 +209,12 @@ argument_specs:
required: false
default: []
elements: str
service_wants:
description: List of systemd units this service container weakly depends on.
type: list
required: false
default: []
elements: str
service_auto_update:
description: Whether to let podman automatically update the service containers whenever the specified image gets updated
type: bool

View File

@@ -11,6 +11,10 @@
ansible.builtin.include_tasks: database.yaml
when: "service_database_type != 'none'"
- name: Secrets for {{ service_name }}
ansible.builtin.include_tasks: secrets.yaml
when: service_container_secrets | length > 0
- name: Mounts for {{ service_name }}
ansible.builtin.include_tasks: mounts.yaml
when: service_container_mounts | length > 0
@@ -24,12 +28,11 @@
container_user: "{{ service_container_user }}"
container_mounts: "{{ _service_container_mounts }}"
container_publish_ports: "{{ service_container_publish_ports }}"
container_networks:
- "{{ service_name }}"
container_networks: "{{ [service_name] + service_container_additional_networks }}"
container_secrets: "{{ _service_container_secrets }}"
container_env: "{{ service_container_env }}"
container_requires: "{{ _service_container_requires }}"
container_wants: "{{ [service_name + '-socat.socket'] if service_domains | length > 0 else [] }}"
container_wants: "{{ _service_container_wants }}"
container_auto_update: "{{ service_auto_update }}"
- name: Reverse proxy for {{ service_name }}

View File

@@ -33,3 +33,4 @@
vhost_domains: "{{ service_domains }}"
vhost_proxy_target_netproto: unix
vhost_proxy_target_socket: "/run/{{ service_name }}-socat.sock"
vhost_locations: "{{ service_vhost_locations }}"

View File

@@ -0,0 +1,25 @@
---
- name: Create secrets
ansible.builtin.include_role:
name: container
tasks_from: secrets.yaml
rolespec_validate: false # FIXME make proper validation possible
vars:
container_name: "{{ service_name }}"
container_secrets: "{{ _service_container_secrets }}"
- name: Gather secrets information
containers.podman.podman_secret_info:
showsecret: true
register: _service_podman_secret_info
no_log: true
- name: Store secrets in a variable for later
ansible.builtin.set_fact:
_service_podman_secrets: >
{{ _service_podman_secret_info.secrets
| map(attribute='Spec.Name')
| zip(_service_podman_secret_info.secrets | map(attribute='SecretData'))
| community.general.dict
}}
no_log: true

View File

@@ -12,3 +12,5 @@ _service_container_secrets: >
)
| map('combine')
}}
_service_container_wants: "{{ service_wants + ([service_name + '-socat.socket'] if service_domains | length > 0 else []) }}"

View File

@@ -1,6 +1,8 @@
---
synapse_postgres_tag: 16-alpine
synapse_mas_domain: "auth.{{ synapse_external_domain }}"
synapse_trusted_key_servers:
- matrix.org
@@ -16,3 +18,4 @@ synapse_auto_accept_invites:
synapse_auto_join_rooms: []
synapse_smtp_server: ""
synapse_oidc_provider_client_id: ""

View File

@@ -17,6 +17,14 @@ argument_specs:
- This is used to set the public_baseurl option for synapse (with https:// and trailing / added)
type: str
required: true
synapse_mas_secrets:
description: Passed to the matrix_authentication_service role
type: dict
required: true
synapse_mas_domain:
description: The public-facing domain that clients use to access matrix authentication service. Defaults to auth.`synapse_external_domain`
type: str
required: false
synapse_signing_key:
description: The homeserver signing key
type: str
@@ -80,6 +88,29 @@ argument_specs:
default: []
elements: str
synapse_oidc_provider_client_id:
type: str
required: false
default: ""
synapse_oidc_provider_name:
description: Required if synapse_oidc_provider_client_id is set
type: str
synapse_oidc_provider_client_secret:
description: Required if synapse_oidc_provider_client_id is set
type: str
synapse_oidc_provider_issuer:
description: Required if synapse_oidc_provider_client_id is set
type: str
synapse_oidc_provider_scope:
description: Required if synapse_oidc_provider_client_id is set
type: list
elements: str
synapse_oidc_provider_mas_claims_imports:
description:
- Passed to matrix authentication service.
- See https://element-hq.github.io/matrix-authentication-service/setup/sso.html#user-attributes-mapping
type: dict
synapse_postgres_tag:
description: Postgres tag to use for synapse postgres container
type: str

View File

@@ -33,6 +33,8 @@
service_container_secrets:
- name: signing-key
value: "{{ synapse_signing_key }}"
- name: mas-client-secret
- name: mas-homeserver-secret
service_container_env:
SYNAPSE_SERVER_NAME: "{{ synapse_server_name }}"
SYNAPSE_REPORT_STATS: "no"
@@ -40,3 +42,43 @@
GID: 991
service_container_http_port: 8008
service_domains: "{{ [synapse_external_domain] }}"
service_vhost_locations:
- path: /_matrix/client/*/login
proxy_target_socket: /run/matrix-authentication-service-socat.sock
- path: /_matrix/client/*/logout
proxy_target_socket: /run/matrix-authentication-service-socat.sock
- path: /_matrix/client/*/refresh
proxy_target_socket: /run/matrix-authentication-service-socat.sock
- path: /_matrix/client/*/login/*
proxy_target_socket: /run/matrix-authentication-service-socat.sock
- path: /_matrix/client/*/logout/*
proxy_target_socket: /run/matrix-authentication-service-socat.sock
- path: /_matrix/client/*/refresh/*
proxy_target_socket: /run/matrix-authentication-service-socat.sock
service_wants:
- matrix-authentication-service.service
- name: Matrix authentication service for synapse
ansible.builtin.include_role:
name: matrix_authentication_service
vars:
matrix_authentication_service_additional_networks:
- synapse
matrix_authentication_service_secrets: "{{ synapse_mas_secrets }}"
matrix_authentication_service_domain: "{{ synapse_mas_domain }}"
matrix_authentication_service_homeserver_name: "{{ synapse_server_name }}"
matrix_authentication_service_homeserver_address: http://synapse:8009
matrix_authentication_service_client_secret: "{{ _service_podman_secrets['synapse-mas-client-secret'] }}"
matrix_authentication_service_homeserver_secret: "{{ _service_podman_secrets['synapse-mas-homeserver-secret'] }}"
matrix_authentication_service_email_smtp_server: "{{ synapse_email_smtp_server }}"
matrix_authentication_service_email_smtp_user: "{{ synapse_email_smtp_user }}"
matrix_authentication_service_email_smtp_password: "{{ synapse_email_smtp_password }}"
matrix_authentication_service_email_from: "{{ synapse_email_from | replace('%(app)s', synapse_email_app_name) }}"
matrix_authentication_service_upstream_oauth2_client_id: "{{ synapse_oidc_provider_client_id }}"
matrix_authentication_service_upstream_oauth2_client_secret: "{{ synapse_oidc_provider_client_secret }}"
matrix_authentication_service_upstream_oauth2_issuer: "{{ synapse_oidc_provider_issuer }}"
matrix_authentication_service_upstream_oauth2_scope: "{{ synapse_oidc_provider_scopes | join(' ') }}"
matrix_authentication_service_upstream_oauth2_claims_imports: "{{ synapse_oidc_provider_mas_claims_imports }}"
matrix_authentication_service_upstream_oauth2_human_name: "{{ synapse_oidc_provider_name }}"

View File

@@ -17,6 +17,12 @@ listeners:
x_forwarded: true
resources:
- names: [client, federation]
- port: 8009
tls: false
type: http
x_forwarded: false
resources:
- names: [client]
database:
name: psycopg2
@@ -33,6 +39,8 @@ enable_registration: false
enable_3pid_changes: false
ui_auth:
session_timeout: 5m
password_config:
enabled: false
trusted_key_servers:
{% for server in synapse_trusted_key_servers %}
@@ -97,3 +105,13 @@ allow_public_rooms_over_federation: {{ synapse_allow_public_rooms_over_federatio
auto_accept_invites: {{ synapse_auto_accept_invites }}
auto_join_rooms: {{ synapse_auto_join_rooms }}
autocreate_auto_join_rooms: false
experimental_features:
msc3861:
enabled: true
issuer: http://matrix-authentication-service:8080/
client_id: 0000000000000000000SYNAPSE
client_auth_method: client_secret_basic
client_secret: "{{ _service_podman_secrets['synapse-mas-client-secret'] }}"
admin_token: "{{ _service_podman_secrets['synapse-mas-homeserver-secret'] }}"
account_management_url: "https://{{ synapse_mas_domain }}/account"

View File

@@ -5,3 +5,4 @@
- volume_uid is string
- volume_gid is string
fail_msg: "volume_uid and volume_gid must be strings, not int."
quiet: true