diff --git a/roles/authelia-for-mas/defaults/main.json b/roles/authelia-for-mas/defaults/main.json new file mode 100644 index 0000000..58848ef --- /dev/null +++ b/roles/authelia-for-mas/defaults/main.json @@ -0,0 +1,6 @@ +{ + "var_authelia_for_mas_mas_url_base": "https://mas.example.org", + "var_authelia_for_mas_id": "01JADRQ54Y0KCQS0AEJQ4YTY36", + "var_authelia_for_mas_client_id": "mas", + "var_authelia_for_mas_client_secret": "REPLACE_ME" +} diff --git a/roles/authelia-for-mas/info.md b/roles/authelia-for-mas/info.md new file mode 100644 index 0000000..281cfd0 --- /dev/null +++ b/roles/authelia-for-mas/info.md @@ -0,0 +1,8 @@ +## Beschreibung + +Um [MAS](../mas) gegen [Authelia](../authelia) authentifizieren zu lassen + + +## Verweise + +- [MAS-Dokumentation | Configure an upstream SSO provider](https://element-hq.github.io/matrix-authentication-service/setup/sso.html) diff --git a/roles/authelia-for-mas/tasks/main.json b/roles/authelia-for-mas/tasks/main.json new file mode 100644 index 0000000..f5b4616 --- /dev/null +++ b/roles/authelia-for-mas/tasks/main.json @@ -0,0 +1,25 @@ +[ + { + "name": "configuration | emplace", + "become": true, + "ansible.builtin.template": { + "src": "authelia-client-conf.json.j2", + "dest": "/etc/authelia/conf.d/clients/mas.json" + } + }, + { + "name": "configuration | apply", + "become": true, + "ansible.builtin.command": { + "cmd": "/usr/bin/authelia-conf-compose" + } + }, + { + "name": "restart service", + "become": true, + "ansible.builtin.systemd_service": { + "state": "restarted", + "name": "authelia" + } + } +] diff --git a/roles/authelia-for-mas/templates/authelia-client-conf.json.j2 b/roles/authelia-for-mas/templates/authelia-client-conf.json.j2 new file mode 100644 index 0000000..1310283 --- /dev/null +++ b/roles/authelia-for-mas/templates/authelia-client-conf.json.j2 @@ -0,0 +1,16 @@ +{ + "client_id": "{{var_authelia_for_mas_client_id}}", + "client_secret": "{{var_authelia_for_mas_client_secret}}", + "client_name": "MAS", + "public": false, + "authorization_policy": "one_factor", + "redirect_uris": [ + "{{var_authelia_for_mas_mas_url_base}}/upstream/callback/{{var_authelia_for_mas_id}}" + ], + "scopes": [ + "openid", + "email", + "profile" + ], + "token_endpoint_auth_method": "client_secret_basic" +} diff --git a/roles/authelia-for-mas/vardef.json b/roles/authelia-for-mas/vardef.json new file mode 100644 index 0000000..03568f8 --- /dev/null +++ b/roles/authelia-for-mas/vardef.json @@ -0,0 +1,19 @@ +{ + "mas_url_base": { + "type": "string", + "mandatory": false + }, + "id": { + "type": "string", + "mandatory": false, + "description": "needs to be a ULID" + }, + "client_id": { + "type": "string", + "mandatory": false + }, + "client_secret": { + "type": "string", + "mandatory": false + } +} diff --git a/roles/hedgedoc/defaults/main.json b/roles/hedgedoc/defaults/main.json index f59f7f1..5dc2820 100644 --- a/roles/hedgedoc/defaults/main.json +++ b/roles/hedgedoc/defaults/main.json @@ -11,7 +11,7 @@ "var_hedgedoc_database_data_postgresql_password": "REPLACE_ME", "var_hedgedoc_database_data_postgresql_schema": "hedgedoc", "var_hedgedoc_domain": "hedgedoc.example.org", - "var_hedgedoc_authentication_kind": "authelia", + "var_hedgedoc_authentication_kind": "internal", "var_hedgedoc_authentication_data_authelia_client_id": "hedgedoc", "var_hedgedoc_authentication_data_authelia_client_secret": "REPLACE_ME", "var_hedgedoc_authentication_data_authelia_url_base": "https://authelia.example.org", diff --git a/roles/mas-and-nginx/defaults/main.json b/roles/mas-and-nginx/defaults/main.json new file mode 100644 index 0000000..f3be49f --- /dev/null +++ b/roles/mas-and-nginx/defaults/main.json @@ -0,0 +1,5 @@ +{ + "var_mas_and_nginx_server_port": 2839, + "var_mas_and_nginx_domain": "REPLACE_ME", + "var_mas_and_nginx_tls_mode": "force" +} diff --git a/roles/mas-and-nginx/info.md b/roles/mas-and-nginx/info.md new file mode 100644 index 0000000..117fbee --- /dev/null +++ b/roles/mas-and-nginx/info.md @@ -0,0 +1,8 @@ +## Beschreibung + +- zur Einrichtung von [nginx](../nginx) als Reverse-Proxy für [MAS](../mas) + + +## Verweise + +- [MAS-Dokumentation | Configuring a reverse proxy](https://element-hq.github.io/matrix-authentication-service/setup/reverse-proxy.html) diff --git a/roles/mas-and-nginx/tasks/main.json b/roles/mas-and-nginx/tasks/main.json new file mode 100644 index 0000000..63a1213 --- /dev/null +++ b/roles/mas-and-nginx/tasks/main.json @@ -0,0 +1,35 @@ +[ + { + "name": "deactivate default site", + "become": true, + "ansible.builtin.file": { + "state": "absent", + "dest": "/etc/nginx/sites-enabled/default" + } + }, + { + "name": "emplace configuration | data", + "become": true, + "ansible.builtin.template": { + "src": "conf.j2", + "dest": "/etc/nginx/sites-available/{{var_mas_and_nginx_domain}}" + } + }, + { + "name": "emplace configuration | link", + "become": true, + "ansible.builtin.file": { + "state": "link", + "src": "/etc/nginx/sites-available/{{var_mas_and_nginx_domain}}", + "dest": "/etc/nginx/sites-enabled/{{var_mas_and_nginx_domain}}" + } + }, + { + "name": "restart nginx", + "become": true, + "ansible.builtin.systemd_service": { + "state": "restarted", + "name": "nginx" + } + } +] diff --git a/roles/mas-and-nginx/templates/conf.j2 b/roles/mas-and-nginx/templates/conf.j2 new file mode 100644 index 0000000..779f527 --- /dev/null +++ b/roles/mas-and-nginx/templates/conf.j2 @@ -0,0 +1,36 @@ +{% macro mas_common() %} + location / { + proxy_http_version 1.1; + proxy_pass http://localhost:{{var_mas_and_nginx_server_port | string}}; + + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +{% endmacro %} + +server { + server_name {{var_mas_and_nginx_domain}}; + + listen 80; + listen [::]:80; + +{% if (var_mas_and_nginx_tls_mode == 'force') %} + return 301 https://$http_host$request_uri; +{% else %} +{{ mas_common() }} +{% endif %} +} + +{% if (var_mas_and_nginx_tls_mode != 'disable') %} +server { + server_name {{var_mas_and_nginx_domain}}; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + + ssl_certificate_key /etc/ssl/private/{{var_mas_and_nginx_domain}}.pem; + ssl_certificate /etc/ssl/fullchains/{{var_mas_and_nginx_domain}}.pem; + include /etc/nginx/ssl-hardening.conf; + +{{ mas_common() }} +} +{% endif %} diff --git a/roles/mas-and-nginx/vardef.json b/roles/mas-and-nginx/vardef.json new file mode 100644 index 0000000..2ae6020 --- /dev/null +++ b/roles/mas-and-nginx/vardef.json @@ -0,0 +1,19 @@ +{ + "port": { + "type": "integer", + "mandatory": false + }, + "domain": { + "type": "string", + "mandatory": false + }, + "tls_mode": { + "type": "string", + "options": [ + "disable", + "enable", + "force" + ], + "mandatory": false + } +} diff --git a/roles/mas-for-synapse/defaults/main.json b/roles/mas-for-synapse/defaults/main.json new file mode 100644 index 0000000..5802580 --- /dev/null +++ b/roles/mas-for-synapse/defaults/main.json @@ -0,0 +1,5 @@ +{ + "var_mas_for_synapse_synapse_url_base": "https://synapse.example.org", + "var_mas_for_synapse_client_id": "01JAE3YFB91XFWEDQY0WFDW5VN", + "var_mas_for_synapse_client_secret": "REPLACE_ME" +} diff --git a/roles/mas-for-synapse/info.md b/roles/mas-for-synapse/info.md new file mode 100644 index 0000000..f22001b --- /dev/null +++ b/roles/mas-for-synapse/info.md @@ -0,0 +1,9 @@ +## Beschreibung + +Um [Synapse](../synapse) gegen [MAS](../mas) authentifizieren zu lassen + + +## Verweise + +- [Synapse-Dokumentation | OpenID Connect](https://matrix-org.github.io/synapse/latest/openid.html) +- [MAS-Dokumentation | Homeserver configuration](https://element-hq.github.io/matrix-authentication-service/setup/homeserver.html) diff --git a/roles/mas-for-synapse/tasks/main.json b/roles/mas-for-synapse/tasks/main.json new file mode 100644 index 0000000..29fc15e --- /dev/null +++ b/roles/mas-for-synapse/tasks/main.json @@ -0,0 +1,25 @@ +[ + { + "name": "configuration | emplace", + "become": true, + "ansible.builtin.template": { + "src": "mas-client-conf.json.j2", + "dest": "/opt/mas/conf.d/clients/synapse.json" + } + }, + { + "name": "configuration | apply", + "become": true, + "ansible.builtin.command": { + "cmd": "/usr/local/bin/mas-conf-compose" + } + }, + { + "name": "restart service", + "become": true, + "ansible.builtin.systemd_service": { + "state": "restarted", + "name": "mas" + } + } +] diff --git a/roles/mas-for-synapse/templates/mas-client-conf.json.j2 b/roles/mas-for-synapse/templates/mas-client-conf.json.j2 new file mode 100644 index 0000000..0fa50eb --- /dev/null +++ b/roles/mas-for-synapse/templates/mas-client-conf.json.j2 @@ -0,0 +1,5 @@ +{ + "client_id": "{{var_mas_for_synapse_client_id}}", + "client_secret": "{{var_mas_for_synapse_client_secret}}", + "client_auth_method": "client_secret_basic" +} diff --git a/roles/mas/defaults/main.json b/roles/mas/defaults/main.json new file mode 100644 index 0000000..e50f260 --- /dev/null +++ b/roles/mas/defaults/main.json @@ -0,0 +1,23 @@ +{ + "var_mas_user": "mas", + "var_mas_directory": "/opt/mas", + "var_mas_server_server_address": "[::]", + "var_mas_server_server_port": 2839, + "var_mas_server_server_domain": "mas.example.org", + "var_mas_database_host": "postgresql.example.org", + "var_mas_database_port": 5432, + "var_mas_database_username": "mas_user", + "var_mas_database_password": "REPLACE_ME", + "var_mas_database_schema": "mas", + "var_mas_matrix_server": "synapse.example.org", + "var_mas_matrix_secret": "REPLACE_ME", + "var_mas_matrix_endpoint": "https://synapse.example.org/", + "var_mas_encryption_key": "REPLACE_ME", + "var_mas_authentication_upstream_kind": "none", + "var_mas_authentication_upstream_data_authelia_url_base": "https://authelia.example.org", + "var_mas_authentication_upstream_data_authelia_auth_method": "client_secret_basic", + "var_mas_authentication_upstream_data_authelia_scope": "openid profile email", + "var_mas_authentication_upstream_data_authelia_id": "01JADRQ54Y0KCQS0AEJQ4YTY36", + "var_mas_authentication_upstream_data_authelia_client_id": "mas", + "var_mas_authentication_upstream_data_authelia_client_secret": "REPLACE_ME" +} diff --git a/roles/mas/files/conf-compose.py b/roles/mas/files/conf-compose.py new file mode 100644 index 0000000..fc8fc60 --- /dev/null +++ b/roles/mas/files/conf-compose.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python3 + +import sys as _sys +import os as _os +import yaml as _yaml +import json as _json +import argparse as _argparse + + +def file_read(path): + handle = open(path, "r") + content = handle.read() + handle.close() + return content + + +def file_write(path, content): + directory = _os.path.dirname(path) + if (not _os.path.exists(directory)): + _os.makedirs(directory, exist_ok = True) + else: + pass + handle = open(path, "w") + handle.write(content) + handle.close() + return content + + +def dict_merge(core, mantle, path = None): + if (path is None): + path = [] + result = {} + for source in [core, mantle]: + for (key, value_new, ) in source.items(): + path_ = (path + [key]) + type_new = type(value_new) + if (not (key in result)): + result[key] = value_new + else: + value_old = result[key] + type_old = type(value_old) + if (value_old is None): + result[key] = value_new + else: + if (not (type_old == type_new)): + raise ValueError( + "type mismatch at path %s: %s vs. %s" + % ( + ".".join(path), + str(type_old), + str(type_new), + ) + ) + else: + if (type_old == dict): + result[key] = dict_merge(value_old, value_new, path_) + elif (type_old == list): + result[key] = (value_old + value_new) + else: + result[key] = value_new + return result + + +def main(): + ## args + argument_parser = _argparse.ArgumentParser() + argument_parser.add_argument( + "-s", + "--source-directory", + type = str, + dest = "source_directory", + default = "/opt/mas/conf.d", + metavar = "", + ) + argument_parser.add_argument( + "-f", + "--output-format", + type = str, + choices = ["json", "yaml"], + dest = "output_format", + default = "yaml", + metavar = "", + ) + argument_parser.add_argument( + "-o", + "--output-path", + type = str, + dest = "output_path", + default = "/opt/mas/config.yaml", + metavar = "", + ) + args = argument_parser.parse_args() + + ## exec + data = {} + ### base + if True: + data_raw = _yaml.safe_load(file_read(_os.path.join(args.source_directory, "base.yaml"))) + data = dict_merge( + data, + { + "secrets": data_raw["secrets"], + "passwords": data_raw["passwords"], + } + ) + ### database + if True: + data = dict_merge( + data, + _json.loads(file_read(_os.path.join(args.source_directory, "database.json"))) + ) + ### http + if True: + data = dict_merge( + data, + _json.loads(file_read(_os.path.join(args.source_directory, "http.json"))) + ) + ### matrix + if True: + data = dict_merge( + data, + _json.loads(file_read(_os.path.join(args.source_directory, "matrix.json"))) + ) + ### upstream + if True: + data = dict_merge( + data, + _json.loads(file_read(_os.path.join(args.source_directory, "upstream.json"))) + ) + ### email + if True: + data = dict_merge( + data, + _json.loads(file_read(_os.path.join(args.source_directory, "email.json"))) + ) + ### clients + if True: + data = dict_merge( + data, + { + "clients": list( + map( + lambda name: _json.loads(file_read(_os.path.join(args.source_directory, "clients", name))), + _os.listdir(_os.path.join(args.source_directory, "clients")) + ) + ), + } + ) + ## output + if True: + if (args.output_format == "json"): + output_content = _json.dumps(data, indent = "\t") + elif (args.output_format == "yaml"): + output_content = _yaml.dump(data) + else: + raise ValueError("invalid output format") + file_write(args.output_path, output_content) + + +main() diff --git a/roles/mas/info.md b/roles/mas/info.md new file mode 100644 index 0000000..1eaeb83 --- /dev/null +++ b/roles/mas/info.md @@ -0,0 +1,8 @@ +## Beschreibung + +für [Matrix Authentication Service](https://github.com/element-hq/matrix-authentication-service), was eine OIDC-Portal für [Synapse](../synapse) ist + + +## Verweise + +- [Dokumentation](https://element-hq.github.io/matrix-authentication-service/index.html) diff --git a/roles/mas/tasks/main.json b/roles/mas/tasks/main.json new file mode 100644 index 0000000..019ebe2 --- /dev/null +++ b/roles/mas/tasks/main.json @@ -0,0 +1,123 @@ +[ + { + "name": "user", + "become": true, + "ansible.builtin.user": { + "name": "{{var_mas_user}}", + "create_home": true, + "home": "{{var_mas_directory}}" + } + }, + { + "name": "directories", + "become": true, + "loop": [ + "{{var_mas_directory}}/conf.d", + "{{var_mas_directory}}/conf.d/clients", + "{{var_mas_directory}}/scripts" + ], + "ansible.builtin.file": { + "state": "directory", + "owner": "{{var_mas_user}}", + "path": "{{item}}" + } + }, + { + "name": "download", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.get_url": { + "url": "https://github.com/element-hq/matrix-authentication-service/releases/latest/download/mas-cli-x86_64-linux.tar.gz", + "dest": "/tmp/mas.tar.gz" + } + }, + { + "name": "extract", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.unarchive": { + "remote_src": true, + "src": "/tmp/mas.tar.gz", + "dest": "{{var_mas_directory}}", + "owner": "{{var_mas_user}}" + } + }, + { + "name": "configuration | compose script", + "become": true, + "ansible.builtin.copy": { + "src": "conf-compose.py", + "dest": "/usr/local/bin/mas-conf-compose", + "mode": "0555" + } + }, + { + "name": "configuration | base", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.shell": { + "cmd": "./mas-cli config generate > {{var_mas_directory}}/conf.d/base.yaml", + "chdir": "{{var_mas_directory}}" + } + }, + { + "name": "configuration | database", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.template": { + "src": "config-database.json.j2", + "dest": "{{var_mas_directory}}/conf.d/database.json" + } + }, + { + "name": "configuration | http", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.template": { + "src": "config-http.json.j2", + "dest": "{{var_mas_directory}}/conf.d/http.json" + } + }, + { + "name": "configuration | matrix", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.template": { + "src": "config-matrix.json.j2", + "dest": "{{var_mas_directory}}/conf.d/matrix.json" + } + }, + { + "name": "configuration | upstream", + "become": true, + "become_user": "{{var_mas_user}}", + "ansible.builtin.template": { + "src": "config-upstream.json.j2", + "dest": "{{var_mas_directory}}/conf.d/upstream.json" + } + }, + { + "name": "configuration | apply", + "become": true, + "ansible.builtin.command": { + "cmd": "/usr/local/bin/mas-conf-compose" + } + }, + { + "name": "systemd unit", + "become": true, + "ansible.builtin.template": { + "src": "systemd_unit.j2", + "dest": "/etc/systemd/system/mas.service" + } + }, + { + "name": "run", + "become": true, + "ansible.builtin.systemd_service": { + "name": "mas", + "enabled": true, + "state": "restarted" + } + } +] diff --git a/roles/mas/templates/config-database.json.j2 b/roles/mas/templates/config-database.json.j2 new file mode 100644 index 0000000..c227ba6 --- /dev/null +++ b/roles/mas/templates/config-database.json.j2 @@ -0,0 +1,9 @@ +{ + "database": { + "host": "{{var_mas_database_host}}", + "port": {{var_mas_database_port | string}}, + "username": "{{var_mas_database_username}}", + "password": "{{var_mas_database_password}}", + "database": "{{var_mas_database_schema}}" + } +} diff --git a/roles/mas/templates/config-email.json.j2 b/roles/mas/templates/config-email.json.j2 new file mode 100644 index 0000000..39608c6 --- /dev/null +++ b/roles/mas/templates/config-email.json.j2 @@ -0,0 +1,7 @@ +{ + "email": { + "from": "Authentication Service ", + "reply_to": "Authentication Service ", + "transport": "blackhole" + } +} diff --git a/roles/mas/templates/config-http.json.j2 b/roles/mas/templates/config-http.json.j2 new file mode 100644 index 0000000..3ec21c0 --- /dev/null +++ b/roles/mas/templates/config-http.json.j2 @@ -0,0 +1,60 @@ +{ + "http": { + "listeners": [ + { + "name": "web", + "resources": [ + { + "name": "discovery" + }, + { + "name": "human" + }, + { + "name": "oauth" + }, + { + "name": "compat" + }, + { + "name": "graphql" + }, + { + "name": "assets" + } + ], + "binds": [ + { + "address": "{{var_mas_server_server_address}}:{{var_mas_server_server_port | string}}" + } + ], + "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://{{var_mas_server_server_domain}}/", + "issuer": "https://{{var_mas_server_server_domain}}/" + } +} diff --git a/roles/mas/templates/config-matrix.json.j2 b/roles/mas/templates/config-matrix.json.j2 new file mode 100644 index 0000000..5c6d5d1 --- /dev/null +++ b/roles/mas/templates/config-matrix.json.j2 @@ -0,0 +1,7 @@ +{ + "matrix": { + "homeserver": "{{var_mas_matrix_server}}", + "secret": "{{var_mas_matrix_secret}}", + "endpoint": "{{var_mas_matrix_endpoint}}" + } +} diff --git a/roles/mas/templates/config-upstream.json.j2 b/roles/mas/templates/config-upstream.json.j2 new file mode 100644 index 0000000..220db66 --- /dev/null +++ b/roles/mas/templates/config-upstream.json.j2 @@ -0,0 +1,35 @@ +{ +{% if var_mas_authentication_upstream_kind == 'none' %} +{% endif %} +{% if var_mas_authentication_upstream_kind == 'authelia' %} + "upstream_oauth2": { + "providers": [ + { + "id": "{{var_mas_authentication_upstream_data_authelia_id}}", + "issuer": "{{var_mas_authentication_upstream_data_authelia_url_base}}", + "authorization_endpoint": "{{var_mas_authentication_upstream_data_authelia_url_base}}/api/oidc/authorization", + "token_endpoint": "{{var_mas_authentication_upstream_data_authelia_url_base}}/api/oidc/token", + "token_endpoint_auth_method": "{{var_mas_authentication_upstream_data_authelia_auth_method}}", + "scope": "{{var_mas_authentication_upstream_data_authelia_scope}}", + "discovery_mode": "insecure", + "client_id": "{{var_mas_authentication_upstream_data_authelia_client_id}}", + "client_secret": "{{var_mas_authentication_upstream_data_authelia_client_secret}}", + "claims_imports": { + "localpart": { + "action": "require", + "template": "{{"{{"}} user.preferred_username {{"}}"}}" + }, + "displayname": { + "action": "suggest", + "template": "{{"{{"}} user.name {{"}}"}}" + }, + "email": { + "action": "suggest", + "template": "{{"{{"}} user.email {{"}}"}}", + "set_email_verification": "always" + } + } + ] + } +{% endif %} +} diff --git a/roles/mas/templates/systemd_unit.j2 b/roles/mas/templates/systemd_unit.j2 new file mode 100644 index 0000000..f68219f --- /dev/null +++ b/roles/mas/templates/systemd_unit.j2 @@ -0,0 +1,15 @@ +[Unit] +Description=MAS +After=network.target + +[Service] +WorkingDirectory={{var_mas_directory}} +ExecStart={{var_mas_directory}}/mas-cli server +Type=simple +Restart=always +User={{var_mas_user}} + +[Install] +WantedBy=default.target +RequiredBy=network.target + diff --git a/roles/mas/vardef.json b/roles/mas/vardef.json new file mode 100644 index 0000000..176dd0e --- /dev/null +++ b/roles/mas/vardef.json @@ -0,0 +1,91 @@ +{ + "user": { + "type": "string", + "mandatory": false + }, + "directory": { + "type": "string", + "mandatory": false + }, + "server_address": { + "type": "string", + "mandatory": false + }, + "server_port": { + "type": "string", + "mandatory": false + }, + "domain": { + "type": "string", + "mandatory": false + }, + "database_host": { + "type": "string", + "mandatory": false + }, + "database_port": { + "type": "integer", + "mandatory": false + }, + "database_username": { + "type": "string", + "mandatory": false + }, + "database_password": { + "type": "string", + "mandatory": true + }, + "database_schema": { + "type": "string", + "mandatory": false + }, + "matrix_server": { + "type": "string", + "mandatory": false + }, + "matrix_secret": { + "type": "string", + "mandatory": true + }, + "matrix_endpoint": { + "type": "string", + "mandatory": false + }, + "encryption_key": { + "type": "string", + "mandatory": true + }, + "authentication_upstream_kind": { + "nullable": false, + "type": "string", + "options": [ + "none", + "authelia" + ] + }, + "authentication_upstream_data_authelia_url_base": { + "type": "string", + "mandatory": false + }, + "authentication_upstream_data_authelia_auth_method": { + "type": "string", + "mandatory": false + }, + "authentication_upstream_data_authelia_scope": { + "type": "string", + "mandatory": false + }, + "authentication_upstream_data_authelia_id": { + "type": "string", + "mandatory": false, + "description": "needs to be a ULID" + }, + "authentication_upstream_data_authelia_client_id": { + "type": "string", + "mandatory": false + }, + "authentication_upstream_data_authelia_client_secret": { + "type": "string", + "mandatory": false + } +} diff --git a/roles/postgresql-for-mas/defaults/main.json b/roles/postgresql-for-mas/defaults/main.json new file mode 100644 index 0000000..42dcb1a --- /dev/null +++ b/roles/postgresql-for-mas/defaults/main.json @@ -0,0 +1,5 @@ +{ + "var_postgresql_for_mas_username": "mas_user", + "var_postgresql_for_mas_password": "REPLACE_ME", + "var_postgresql_for_mas_schema": "mas" +} diff --git a/roles/postgresql-for-mas/tasks/main.json b/roles/postgresql-for-mas/tasks/main.json new file mode 100644 index 0000000..ce83508 --- /dev/null +++ b/roles/postgresql-for-mas/tasks/main.json @@ -0,0 +1,49 @@ +[ + { + "name": "packages", + "become": true, + "ansible.builtin.apt": { + "update_cache": true, + "pkg": [ + "acl", + "python3-psycopg2" + ] + } + }, + { + "name": "user", + "become": true, + "become_user": "postgres", + "community.postgresql.postgresql_user": { + "state": "present", + "name": "{{var_postgresql_for_mas_username}}", + "password": "{{var_postgresql_for_mas_password}}" + }, + "environment": { + "PGOPTIONS": "-c password_encryption=scram-sha-256" + } + }, + { + "name": "schema", + "become": true, + "become_user": "postgres", + "community.postgresql.postgresql_db": { + "state": "present", + "name": "{{var_postgresql_for_mas_schema}}", + "owner": "{{var_postgresql_for_mas_username}}" + } + }, + { + "name": "rights", + "become": true, + "become_user": "postgres", + "community.postgresql.postgresql_privs": { + "state": "present", + "db": "{{var_postgresql_for_mas_schema}}", + "objs": "ALL_IN_SCHEMA", + "roles": "{{var_postgresql_for_mas_username}}", + "privs": "ALL", + "grant_option": true + } + } +] diff --git a/roles/synapse-and-nginx/info.md b/roles/synapse-and-nginx/info.md index 7d09e48..686d632 100644 --- a/roles/synapse-and-nginx/info.md +++ b/roles/synapse-and-nginx/info.md @@ -6,3 +6,9 @@ ## Verweise - [Synapse-Dokumentation über die Nutzung von Reverse-Proxies](https://matrix-org.github.io/synapse/latest/reverse_proxy.html) + + +## ToDo + +- MAS-Einbindung (siehe https://element-hq.github.io/matrix-authentication-service/setup/reverse-proxy.html) + diff --git a/roles/synapse-and-nginx/templates/conf.j2 b/roles/synapse-and-nginx/templates/conf.j2 index 952b9e4..1373f00 100644 --- a/roles/synapse-and-nginx/templates/conf.j2 +++ b/roles/synapse-and-nginx/templates/conf.j2 @@ -1,5 +1,5 @@ {% macro synapse_common() %} - location ~ ^(/_matrix|/_synapse/client) { + location ~ ^(/_matrix|/_synapse/client|/.well-known) { proxy_pass http://localhost:8008; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; diff --git a/roles/synapse/defaults/main.json b/roles/synapse/defaults/main.json index 87eff2a..ba81aba 100644 --- a/roles/synapse/defaults/main.json +++ b/roles/synapse/defaults/main.json @@ -20,6 +20,12 @@ "var_synapse_authentication_data_authelia_client_id": "synapse", "var_synapse_authentication_data_authelia_client_secret": "REPLACE_ME", "var_synapse_authentication_data_authelia_url_base": "https://authelia.example.org", + "var_synapse_authentication_data_mas_url_base": "http://localhost:2839", + "var_synapse_authentication_data_mas_client_id": "01JAE3YFB91XFWEDQY0WFDW5VN", + "var_synapse_authentication_data_mas_client_secret": "REPLACE_ME", + "var_synapse_authentication_data_mas_admin_token": "REPLACE_ME", + "var_synapse_authentication_data_mas_provider_id": "mas", + "var_synapse_authentication_data_mas_provider_name": "MAS", "var_synapse_smtp_host": "smtp.example.org", "var_synapse_smtp_port": 587, "var_synapse_smtp_username": "synapse@smtp.example.org", diff --git a/roles/synapse/info.md b/roles/synapse/info.md index 9f4407e..88503ae 100644 --- a/roles/synapse/info.md +++ b/roles/synapse/info.md @@ -9,3 +9,4 @@ Zur Einrichtung des [matrix.org](https://matrix.org/)-Servers Synapse - [GitHub-Repository](https://github.com/matrix-org/synapse) - [Configuration Manual](https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html) - [Dokumentation | PostgreSQL](https://matrix-org.github.io/synapse/latest/postgres.html#using-postgres) +- [MAS-Dokumentation | Homeserver configuration](https://element-hq.github.io/matrix-authentication-service/setup/homeserver.html) diff --git a/roles/synapse/tasks/main.json b/roles/synapse/tasks/main.json index 63e0e78..0450ca2 100644 --- a/roles/synapse/tasks/main.json +++ b/roles/synapse/tasks/main.json @@ -7,6 +7,13 @@ "dest": "/etc/apt/sources.list.d/bullseye-backports-for-synapse.list" } }, + { + "name": "update sources", + "become": true, + "ansible.builtin.apt": { + "update_cache": true + } + }, { "name": "prepare package installation | server-name", "become": true, diff --git a/roles/synapse/templates/homeserver.yaml.j2 b/roles/synapse/templates/homeserver.yaml.j2 index a8b43b4..278a4b4 100644 --- a/roles/synapse/templates/homeserver.yaml.j2 +++ b/roles/synapse/templates/homeserver.yaml.j2 @@ -126,6 +126,21 @@ oidc_providers: email_template: "{{"{{"}} user.email {{"}}"}}" {% endif %} +{% if var_synapse_authentication_kind == 'mas' %} +enable_registration: false +enable_registration_without_verification: false + +experimental_features: + msc3861: + enabled: true + issuer: "{{var_synapse_authentication_data_mas_url_base}}" + client_auth_method: client_secret_basic + client_id: "{{var_synapse_authentication_data_mas_client_id}}" + client_secret: "{{var_synapse_authentication_data_mas_client_secret}}" + admin_token: "{{var_synapse_authentication_data_mas_admin_token}}" + account_management_url: "{{var_synapse_authentication_data_mas_url_base}}/account" +{% endif %} + account_validity: bcrypt_rounds: 12 diff --git a/roles/synapse/vardef.json b/roles/synapse/vardef.json index 391dfdb..95e1549 100644 --- a/roles/synapse/vardef.json +++ b/roles/synapse/vardef.json @@ -71,7 +71,8 @@ "mandatory": false, "options": [ "internal", - "authelia" + "authelia", + "mas" ] }, "authentication_data_authelia_provider_id": { @@ -94,6 +95,30 @@ "type": "string", "mandatory": false }, + "authentication_data_mas_url_base": { + "type": "string", + "mandatory": false + }, + "authentication_data_mas_client_id": { + "type": "string", + "mandatory": false + }, + "authentication_data_mas_client_secret": { + "type": "string", + "mandatory": false + }, + "authentication_data_mas_admin_token": { + "type": "string", + "mandatory": false + }, + "authentication_data_mas_provider_id": { + "type": "string", + "mandatory": false + }, + "authentication_data_mas_provider_name": { + "type": "string", + "mandatory": false + }, "smtp_host": { "type": "string", "mandatory": false