Draupnir proxy (#3313)

* Allow redircting abuse-reports to draupnir

* Document redirecting abuse-reports to draupnir via traefik

* Apply suggestions from code review

Co-authored-by: Slavi Pantaleev <slavi@devture.com>

* Rename variable

---------

Co-authored-by: Slavi Pantaleev <slavi@devture.com>
This commit is contained in:
Chasethechicken 2024-08-08 05:41:45 +02:00 committed by GitHub
parent 62ed4b6c9c
commit 4d46b625ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 139 additions and 29 deletions

View File

@ -146,7 +146,10 @@ matrix_bot_draupnir_configuration_extension_yaml: |
Draupnir supports two methods to receive reports in the management room. Draupnir supports two methods to receive reports in the management room.
The first method intercepts the report API endpoint of the client-server API, which requires integration with the reverse proxy in front of the homeserver. The first method intercepts the report API endpoint of the client-server API, which requires integration with the reverse proxy in front of the homeserver.
While this playbook uses reverse proxies, it does not yet implement this. If you are using traefik, this playbook can set this up for you:
```yaml
matrix_bot_draupnir_abuse_reporting_enabled: true
```
The other method polls an synapse admin API endpoint and is hence only available when using synapse and when the Draupnir user is an admin user (see step 1). The other method polls an synapse admin API endpoint and is hence only available when using synapse and when the Draupnir user is an admin user (see step 1).
To enable it, set `pollReports: true` in Draupnir's config: To enable it, set `pollReports: true` in Draupnir's config:

View File

@ -2791,6 +2791,8 @@ matrix_bot_mjolnir_raw_homeserver_url: "{{ matrix_addons_homeserver_client_api_u
# We don't enable bots by default. # We don't enable bots by default.
matrix_bot_draupnir_enabled: false matrix_bot_draupnir_enabled: false
matrix_bot_draupnir_container_http_host_bind_port: "{{ (matrix_playbook_service_host_bind_interface_prefix ~ '8769') if matrix_playbook_service_host_bind_interface_prefix else '' }}"
matrix_bot_draupnir_systemd_required_services_list_auto: | matrix_bot_draupnir_systemd_required_services_list_auto: |
{{ {{
matrix_addons_homeserver_systemd_services_list matrix_addons_homeserver_systemd_services_list
@ -2805,7 +2807,11 @@ matrix_bot_draupnir_container_network: "{{ matrix_addons_container_network }}"
matrix_bot_draupnir_container_additional_networks_auto: |- matrix_bot_draupnir_container_additional_networks_auto: |-
{{ {{
( (
([] if matrix_addons_homeserver_container_network == '' else [matrix_addons_homeserver_container_network]) ([] if matrix_addons_homeserver_container_network == '' else
[matrix_addons_homeserver_container_network])
+
([matrix_playbook_reverse_proxyable_services_additional_network] if
(matrix_playbook_reverse_proxyable_services_additional_network and matrix_bot_draupnir_container_labels_traefik_enabled) else [])
+ +
([matrix_pantalaimon_container_network] if (matrix_bot_draupnir_pantalaimon_use and matrix_pantalaimon_container_network != matrix_bot_draupnir_container_network) else []) ([matrix_pantalaimon_container_network] if (matrix_bot_draupnir_pantalaimon_use and matrix_pantalaimon_container_network != matrix_bot_draupnir_container_network) else [])
) | unique ) | unique
@ -2814,6 +2820,11 @@ matrix_bot_draupnir_container_additional_networks_auto: |-
matrix_bot_draupnir_homeserver_url: "{{ 'http://matrix-pantalaimon:8009' if matrix_bot_draupnir_pantalaimon_use else matrix_addons_homeserver_client_api_url }}" matrix_bot_draupnir_homeserver_url: "{{ 'http://matrix-pantalaimon:8009' if matrix_bot_draupnir_pantalaimon_use else matrix_addons_homeserver_client_api_url }}"
matrix_bot_draupnir_raw_homeserver_url: "{{ matrix_addons_homeserver_client_api_url }}" matrix_bot_draupnir_raw_homeserver_url: "{{ matrix_addons_homeserver_client_api_url }}"
matrix_bot_draupnir_container_labels_traefik_enabled: "{{ matrix_bot_draupnir_web_enabled and matrix_playbook_reverse_proxy_type in ['playbook-managed-traefik', 'other-traefik-container'] }}"
matrix_bot_draupnir_container_labels_traefik_docker_network: "{{ matrix_playbook_reverse_proxyable_services_additional_network }}"
matrix_bot_draupnir_container_labels_traefik_entrypoints: "{{ devture_traefik_entrypoint_primary }}"
matrix_bot_draupnir_container_labels_traefik_tls_certResolver: "{{ devture_traefik_certResolver_primary }}"
###################################################################### ######################################################################
# #
# /matrix-bot-draupnir # /matrix-bot-draupnir

View File

@ -19,12 +19,21 @@ matrix_bot_draupnir_config_path: "{{ matrix_bot_draupnir_base_path }}/config"
matrix_bot_draupnir_data_path: "{{ matrix_bot_draupnir_base_path }}/data" matrix_bot_draupnir_data_path: "{{ matrix_bot_draupnir_base_path }}/data"
matrix_bot_draupnir_docker_src_files_path: "{{ matrix_bot_draupnir_base_path }}/docker-src" matrix_bot_draupnir_docker_src_files_path: "{{ matrix_bot_draupnir_base_path }}/docker-src"
matrix_bot_draupnir_abuse_reporting_enabled: false
matrix_bot_draupnir_web_enabled: "{{ matrix_bot_draupnir_abuse_reporting_enabled }}"
matrix_bot_draupnir_display_reports: "{{ matrix_bot_draupnir_abuse_reporting_enabled }}"
matrix_bot_draupnir_container_network: "" matrix_bot_draupnir_container_network: ""
matrix_bot_draupnir_container_additional_networks: "{{ matrix_bot_draupnir_container_additional_networks_auto + matrix_bot_draupnir_container_additional_networks_custom }}" matrix_bot_draupnir_container_additional_networks: "{{ matrix_bot_draupnir_container_additional_networks_auto + matrix_bot_draupnir_container_additional_networks_custom }}"
matrix_bot_draupnir_container_additional_networks_auto: [] matrix_bot_draupnir_container_additional_networks_auto: []
matrix_bot_draupnir_container_additional_networks_custom: [] matrix_bot_draupnir_container_additional_networks_custom: []
# Controls whether the matrix-bot-draupnir container exposes its HTTP port (tcp/80 in the container).
#
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:8766"), or empty string to not expose.
matrix_bot_draupnir_container_http_host_bind_port: ''
# A list of extra arguments to pass to the container # A list of extra arguments to pass to the container
matrix_bot_draupnir_container_extra_arguments: [] matrix_bot_draupnir_container_extra_arguments: []
@ -96,3 +105,25 @@ matrix_bot_draupnir_configuration_extension: "{{ matrix_bot_draupnir_configurati
# Holds the final configuration (a combination of the default and its extension). # Holds the final configuration (a combination of the default and its extension).
# You most likely don't need to touch this variable. Instead, see `matrix_bot_draupnir_configuration_yaml`. # You most likely don't need to touch this variable. Instead, see `matrix_bot_draupnir_configuration_yaml`.
matrix_bot_draupnir_configuration: "{{ matrix_bot_draupnir_configuration_yaml | from_yaml | combine(matrix_bot_draupnir_configuration_extension, recursive=True) }}" matrix_bot_draupnir_configuration: "{{ matrix_bot_draupnir_configuration_yaml | from_yaml | combine(matrix_bot_draupnir_configuration_extension, recursive=True) }}"
# Controls whether labels will be added that redirect the /_matrix/client/../rooms/../report paths to draupnir
# Following these recommendations (https://github.com/element-hq/synapse/blob/master/docs/reverse_proxy.md), by default, we don't.
# Regardless of whether this is enabled, it may or may not take effect due to the value of other variables.
# See `matrix_synapse_container_labels_traefik_enabled` or `matrix_synapse_container_labels_matrix_related_labels_enabled`
matrix_bot_draupnir_container_labels_traefik_enabled: false
matrix_bot_draupnir_container_labels_traefik_docker_network: "{{ matrix_draupnir_bot_container_network }}"
matrix_bot_draupnir_container_labels_traefik_hostname: "{{ matrix_synapse_container_labels_traefik_hostname }}"
matrix_bot_draupnir_container_labels_traefik_path_regexp: "^/_matrix/client/(r0|v3)/rooms/([^/]*)/report/"
matrix_bot_draupnir_container_labels_traefik_rule: "Host(`{{ matrix_bot_draupnir_container_labels_traefik_hostname }}`) && PathRegexp(`{{ matrix_bot_draupnir_container_labels_traefik_path_regexp }}`)"
matrix_bot_draupnir_container_labels_traefik_priority: 0
matrix_bot_draupnir_container_labels_traefik_entrypoints: "{{ matrix_synapse_container_labels_traefik_entrypoints }}"
matrix_bot_draupnir_container_labels_traefik_tls: "{{ matrix_bot_draupnir_container_labels_traefik_entrypoints != 'web' }}"
matrix_bot_draupnir_container_labels_traefik_tls_certResolver: "{{ matrix_synapse_container_labels_traefik_tls_certResolver }}" # noqa var-naming
# matrix_bot_draupnir_container_labels_traefik_labels_additional_labels contains a multiline string with additional labels to add to the container label file.
# See `../templates/labels.j2` for details.
#
# Example:
# matrix_bot_draupnir_container_labels_traefik_labels_additional_labels: |
# my.label=1
# another.label="here"
matrix_bot_draupnir_container_labels_traefik_labels_additional_labels: ''

View File

@ -17,6 +17,17 @@
- {path: "{{ matrix_bot_draupnir_docker_src_files_path }}", when: "{{ matrix_bot_draupnir_container_image_self_build }}"} - {path: "{{ matrix_bot_draupnir_docker_src_files_path }}", when: "{{ matrix_bot_draupnir_container_image_self_build }}"}
when: "item.when | bool" when: "item.when | bool"
- name: Ensure matrix-bot-draupnir support files installed
ansible.builtin.template:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_groupname }}"
mode: 0644
with_items:
- src: "{{ role_path }}/templates/labels.j2"
dest: "{{ matrix_bot_draupnir_base_path }}/labels"
- name: Ensure draupnir Docker image is pulled - name: Ensure draupnir Docker image is pulled
community.docker.docker_image: community.docker.docker_image:
name: "{{ matrix_bot_draupnir_docker_image }}" name: "{{ matrix_bot_draupnir_docker_image }}"

View File

@ -0,0 +1,53 @@
{% if matrix_bot_draupnir_container_labels_traefik_enabled %}
traefik.enable=true
{% if matrix_bot_draupnir_container_labels_traefik_docker_network %}
traefik.docker.network={{ matrix_bot_draupnir_container_labels_traefik_docker_network }}
{% endif %}
traefik.http.services.matrix-bot-draupnir.loadbalancer.server.port=8080
############################################################
# #
# Abuse Reports (/_matrix/client/../rooms/../report) #
# #
############################################################
{% set middlewares = [] %}
traefik.http.middlewares.matrix-bot-draupnir-redirect.replacepathregex.regex=^/_matrix/client/(r0|v3)/rooms/([^/]*)/report/(.*)$
traefik.http.middlewares.matrix-bot-draupnir-redirect.replacepathregex.replacement=/api/1/report/$2/$3
{% set middlewares = middlewares + ['matrix-bot-draupnir-redirect'] %}
traefik.http.middlewares.matrix-bot-draupnir-cors.headers.accesscontrolalloworiginlist=*
traefik.http.middlewares.matrix-bot-draupnir-cors.headers.accesscontrolallowheaders=Content-Type,Authorization
traefik.http.middlewares.matrix-bot-draupnir-cors.headers.accesscontrolallowmethods=POST,OPTIONS
{% set middlewares = middlewares + ['matrix-bot-draupnir-cors'] %}
traefik.http.routers.matrix-bot-draupnir.rule={{ matrix_bot_draupnir_container_labels_traefik_rule }}
{% if matrix_bot_draupnir_container_labels_traefik_priority | int > 0 %}
traefik.http.routers.matrix-bot-draupnir.priority={{ matrix_bot_draupnir_container_labels_traefik_priority }}
{% endif %}
{% if middlewares | length > 0 %}
traefik.http.routers.matrix-bot-draupnir.middlewares={{ middlewares | join(',') }}
{% endif %}
traefik.http.routers.matrix-bot-draupnir.service=matrix-bot-draupnir
traefik.http.routers.matrix-bot-draupnir.entrypoints={{ matrix_bot_draupnir_container_labels_traefik_entrypoints }}
traefik.http.routers.matrix-bot-draupnir.tls={{ matrix_bot_draupnir_container_labels_traefik_tls | to_json }}
{% if matrix_bot_draupnir_container_labels_traefik_tls %}
traefik.http.routers.matrix-bot-draupnir.tls.certResolver={{ matrix_bot_draupnir_container_labels_traefik_tls_certResolver }}
{% endif %}
############################################################
# #
# /Abuse Reports (/_matrix/client/../rooms/../report) #
# #
############################################################
{% endif %}
{{ matrix_bot_draupnir_container_labels_traefik_labels_additional_labels }}

View File

@ -227,32 +227,29 @@ health:
# Defaults to 418. # Defaults to 418.
unhealthyStatus: 418 unhealthyStatus: 418
{% if matrix_bot_draupnir_web_enabled %}
# Options for exposing web APIs. # Options for exposing web APIs.
#web: web:
# # Whether to enable web APIs. # Whether to enable web APIs.
# enabled: false enabled: true
#
# # The port to expose the webserver on. Defaults to 8080. # The port to expose the webserver on. Defaults to 8080.
# port: 8080 port: 8080
#
# # The address to listen for requests on. Defaults to only the current # The address to listen for requests on. Defaults to only the current
# # computer. # computer.
# address: localhost address: 0.0.0.0
#
# # Alternative setting to open to the entire web. Be careful, # A web API designed to intercept Matrix API
# # as this will increase your security perimeter: # POST /_matrix/client/r0/rooms/{roomId}/report/{eventId}
# # # and display readable abuse reports in the moderation room.
# # address: "0.0.0.0" #
# # If you wish to take advantage of this feature, you will need
# # A web API designed to intercept Matrix API # to configure a reverse proxy, see e.g. test/nginx.conf
# # POST /_matrix/client/r0/rooms/{roomId}/report/{eventId} abuseReporting:
# # and display readable abuse reports in the moderation room. # Whether to enable this feature.
# # enabled: {{ matrix_bot_draupnir_abuse_reporting_enabled | to_json }}
# # If you wish to take advantage of this feature, you will need {% endif %}
# # to configure a reverse proxy, see e.g. test/nginx.conf
# abuseReporting:
# # Whether to enable this feature.
# enabled: false
# Whether or not to actively poll synapse for abuse reports, to be used # Whether or not to actively poll synapse for abuse reports, to be used
# instead of intercepting client calls to synapse's abuse endpoint, when that # instead of intercepting client calls to synapse's abuse endpoint, when that
@ -261,4 +258,4 @@ pollReports: false
# Whether or not new reports, received either by webapi or polling, # Whether or not new reports, received either by webapi or polling,
# should be printed to our managementRoom. # should be printed to our managementRoom.
displayReports: false displayReports: {{ matrix_bot_draupnir_display_reports | to_json }}

View File

@ -24,13 +24,17 @@ ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
--cap-drop=ALL \ --cap-drop=ALL \
--read-only \ --read-only \
--network={{ matrix_bot_draupnir_container_network }} \ --network={{ matrix_bot_draupnir_container_network }} \
{% if matrix_bot_draupnir_container_http_host_bind_port %}
-p {{ matrix_bot_draupnir_container_http_host_bind_port }}:8080 \
{% endif %}
--label-file={{ matrix_bot_draupnir_base_path }}/labels \
--mount type=bind,src={{ matrix_bot_draupnir_config_path }},dst=/data/config,ro \ --mount type=bind,src={{ matrix_bot_draupnir_config_path }},dst=/data/config,ro \
--mount type=bind,src={{ matrix_bot_draupnir_data_path }},dst=/data \ --mount type=bind,src={{ matrix_bot_draupnir_data_path }},dst=/data \
{% for arg in matrix_bot_draupnir_container_extra_arguments %} {% for arg in matrix_bot_draupnir_container_extra_arguments %}
{{ arg }} \ {{ arg }} \
{% endfor %} {% endfor %}
{{ matrix_bot_draupnir_docker_image }} \ {{ matrix_bot_draupnir_docker_image }} \
bot --draupnir-config /data/config/production.yaml bot --draupnir-config /data/config/production.yaml
{% for network in matrix_bot_draupnir_container_additional_networks %} {% for network in matrix_bot_draupnir_container_additional_networks %}
ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-bot-draupnir ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} network connect {{ network }} matrix-bot-draupnir