From c3fd33566d565131df059c24b670c0500fe8eb34 Mon Sep 17 00:00:00 2001 From: Michael Hollister Date: Fri, 9 Aug 2024 13:43:26 -0500 Subject: [PATCH 1/3] Automated MMR signing key generation process --- .../configuring-playbook-matrix-media-repo.md | 2 - group_vars/matrix_servers | 7 ++- .../matrix-media-repo/tasks/setup_install.yml | 52 +++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/docs/configuring-playbook-matrix-media-repo.md b/docs/configuring-playbook-matrix-media-repo.md index 20a0aae0e..27681bc79 100644 --- a/docs/configuring-playbook-matrix-media-repo.md +++ b/docs/configuring-playbook-matrix-media-repo.md @@ -27,8 +27,6 @@ The repo is pre-configured for integrating with the Postgres database, Traefik p By default, the media-repo will use the local filesystem for data storage. You can alternatively use a `s3` cloud backend as well. Access token caching is also enabled by default since the logout endpoints are proxied through the media repo. -**Note:** If you want to use authenticated media endpoints ([MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916)), you must configure a signing key for your MMR instance to authorize outbound federation requests. See https://docs.t2bot.io/matrix-media-repo/v1.3.5/installation/signing-key/ for more details on how to configure your server with a signing key. - ## Configuring the media-repo Additional common configuration options: diff --git a/group_vars/matrix_servers b/group_vars/matrix_servers index 2869596a6..ed10a1983 100755 --- a/group_vars/matrix_servers +++ b/group_vars/matrix_servers @@ -3642,6 +3642,11 @@ matrix_media_repo_systemd_required_services_list_auto: | ([devture_postgres_identifier ~ '.service'] if devture_postgres_enabled and matrix_media_repo_database_hostname == devture_postgres_connection_hostname else []) }} +matrix_media_repo_generate_signing_key: "{{ matrix_homeserver_implementation == 'synapse' or matrix_homeserver_implementation == 'dendrite'}}" +matrix_media_repo_homeserver_signing_key: "{{ matrix_media_repo_synapse_signing_key if matrix_homeserver_implementation == 'synapse' else (matrix_media_repo_dendrite_signing_key if matrix_homeserver_implementation == 'dendrite' else '') }}" +matrix_media_repo_synapse_signing_key: "{{ matrix_synapse_config_dir_path }}/{{ matrix_server_fqn_matrix }}.signing.key" +matrix_media_repo_dendrite_signing_key: "{{ matrix_dendrite_config_dir_path }}/{{ matrix_server_fqn_matrix }}.signing.pem" + # Auto configured server setup by the playbook matrix_media_repo_homeservers_auto: - # Keep the dash from this line. @@ -3666,7 +3671,7 @@ matrix_media_repo_homeservers_auto: # The signing key to use for authorizing outbound federation requests. If not specified, # requests will not be authorized. See https://docs.t2bot.io/matrix-media-repo/v1.3.5/installation/signing-key/ # for details. - signingKeyPath: "" + signingKeyPath: "{{ '/config/' + matrix_media_repo_identifier + '.signing.key' if matrix_media_repo_generate_signing_key else '' }}" matrix_media_repo_homeserver_federation_enabled: "{{ matrix_homeserver_federation_enabled }}" diff --git a/roles/custom/matrix-media-repo/tasks/setup_install.yml b/roles/custom/matrix-media-repo/tasks/setup_install.yml index a25b3f130..dfed94ee0 100755 --- a/roles/custom/matrix-media-repo/tasks/setup_install.yml +++ b/roles/custom/matrix-media-repo/tasks/setup_install.yml @@ -77,6 +77,58 @@ changed_when: true when: "matrix_media_repo_git_pull_results.changed | bool or matrix_media_repo_docker_image_check_result.stdout == ''" +- name: Check existence of media-repo signing key + ansible.builtin.stat: + path: "{{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key" + register: matrix_media_repo_signing_key_stat + +- when: "matrix_media_repo_generate_signing_key | bool and not (matrix_media_repo_signing_key_stat.stat.exists | bool)" + block: + - name: Generate media-repo signing key + ansible.builtin.command: + cmd: | + {{ devture_systemd_docker_base_host_command_docker }} run + --rm + --name={{ matrix_media_repo_identifier }} + --user={{ matrix_synapse_uid }}:{{ matrix_synapse_gid }} + --cap-drop=ALL + --mount type=bind,src={{ matrix_media_repo_config_path }},dst=/config + --workdir='/config' + --entrypoint='generate_signing_key' + {{ matrix_media_repo_docker_image }} + -output {{ matrix_media_repo_identifier }}.signing.key + creates: "{{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key" + + - name: Merge media-repo signing key with homeserver signing key + ansible.builtin.command: + cmd: | + {{ devture_systemd_docker_base_host_command_docker }} run + --rm + --name={{ matrix_media_repo_identifier }} + --user={{ matrix_synapse_uid }}:{{ matrix_synapse_gid }} + --cap-drop=ALL + --mount type=bind,src={{ matrix_media_repo_config_path }},dst=/config + --mount type=bind,src={{ matrix_base_data_path }},dst=/matrix + --workdir='/config' + --entrypoint='combine_signing_keys' + {{ matrix_media_repo_docker_image }} + -format {{ matrix_homeserver_implementation }} -output {{ matrix_media_repo_homeserver_signing_key }}.merged {{ matrix_media_repo_homeserver_signing_key }} {{ matrix_media_repo_identifier }}.signing.key + creates: "{{ matrix_media_repo_homeserver_signing_key }}." + + - name: Backup existing homeserver signing key before replacing it + ansible.builtin.copy: + remote_src: true + src: "{{ matrix_media_repo_homeserver_signing_key }}" + dest: "{{ matrix_media_repo_homeserver_signing_key }}.{{ matrix_homeserver_implementation }}.backup" + mode: 0644 + owner: "{{ matrix_user_username }}" + group: "{{ matrix_user_groupname }}" + + - name: Replace homeserver signing key with merged signing key + ansible.builtin.command: + cmd: "mv {{ matrix_media_repo_homeserver_signing_key }}.merged {{ matrix_media_repo_homeserver_signing_key }}" + removes: "{{ matrix_media_repo_homeserver_signing_key }}.merged" + - name: Ensure media-repo container network is created community.general.docker_network: enable_ipv6: "{{ devture_systemd_docker_base_ipv6_enabled }}" From 56b0a720000e490749a436c8717cdfe03ee3f4c7 Mon Sep 17 00:00:00 2001 From: Michael Hollister Date: Tue, 13 Aug 2024 14:22:14 -0500 Subject: [PATCH 2/3] Apply PR feedback --- .../configuring-playbook-matrix-media-repo.md | 20 +++++++++++++++++++ .../matrix-media-repo/defaults/main.yml | 7 +++++++ .../matrix-media-repo/tasks/setup_install.yml | 15 +++++++++----- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/configuring-playbook-matrix-media-repo.md b/docs/configuring-playbook-matrix-media-repo.md index 27681bc79..170bc714b 100644 --- a/docs/configuring-playbook-matrix-media-repo.md +++ b/docs/configuring-playbook-matrix-media-repo.md @@ -89,6 +89,26 @@ matrix_media_repo_datastore_s3_opts_bucket_name: "your-media-bucket" Full list of configuration options with documentation can be found in [`roles/custom/matrix-media-repo/defaults/main.yml`](https://github.com/spantaleev/matrix-docker-ansible-deploy/blob/master/roles/custom/matrix-media-repo/defaults/main.yml) +## Signing Keys + +Authenticated media endpoints ([MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916)) requires MMR to have a configured signing key to authorize outbound federation requests. Additionally, the signing key must be merged with your homeserver's signing key file. + +The playbook default is to generate a MMR signing key when invoking the setup role and merge it with your homeserver if you are using Synapse or Dendrite. This can be disabled if desired by setting the option in your inventory: + +```yaml +matrix_media_repo_generate_signing_key: false +``` + +If you wish to manually generate the signing key and merge it with your homeserver's signing key file, see https://docs.t2bot.io/matrix-media-repo/v1.3.5/installation/signing-key/ for more details. + +**Note that if you uninstall MMR from the playbook, it will not remove the old MMR signing key from your homeserver's signing key file. You will have to remove it manually.** + +### Key backup and revoking + +Since your homeserver signing key file is modified by the playbook, a backup will be created in `HOMESERVER_DIR/config/DOMAIN.signing.key.backup`. If you need to remove/revoke old keys, you can restore from this backup or remove the MMR key id from your `DOMAIN.signing.key` file. + +Additionally, its recommended after revoking a signing key to update your homeserver config file (`old_signing_keys` field for Synapse and `old_private_keys` for Dendrite). See your homeserver config file for further documentation on how to populate the field. + ## Importing data from an existing media store If you want to add this repo to an existing homeserver managed by the playbook, you will need to import existing media into MMR's database or you will lose access to older media while it is active. MMR versions up to `v1.3.3` only support importing from Synapse, but newer versions (at time of writing: only `latest`) also support importing from Dendrite. diff --git a/roles/custom/matrix-media-repo/defaults/main.yml b/roles/custom/matrix-media-repo/defaults/main.yml index 902b6fd67..5d2ffd716 100755 --- a/roles/custom/matrix-media-repo/defaults/main.yml +++ b/roles/custom/matrix-media-repo/defaults/main.yml @@ -319,6 +319,13 @@ matrix_media_repo_homeservers_auto: [] # Additional servers to be managed by MMR matrix_media_repo_homeservers_additional: [] +# If true, the playbook will generate a signing key when the setup role is invoked. +matrix_media_repo_generate_signing_key: "{{ matrix_homeserver_implementation == 'synapse' or matrix_homeserver_implementation == 'dendrite' }}" + +# Path where the homeserver signing key is located. Set automatically in +# `group_vars/matrix_servers` depending on which homeserver is being used. +matrix_media_repo_homeserver_signing_key: "" + # Options for controlling how access tokens work with the media repo. It is recommended that if # you are going to use these options that the `/logout` and `/logout/all` client-server endpoints # be proxied through this process. They will also be called on the homeserver, and the response diff --git a/roles/custom/matrix-media-repo/tasks/setup_install.yml b/roles/custom/matrix-media-repo/tasks/setup_install.yml index dfed94ee0..513456c1c 100755 --- a/roles/custom/matrix-media-repo/tasks/setup_install.yml +++ b/roles/custom/matrix-media-repo/tasks/setup_install.yml @@ -96,8 +96,8 @@ --workdir='/config' --entrypoint='generate_signing_key' {{ matrix_media_repo_docker_image }} - -output {{ matrix_media_repo_identifier }}.signing.key - creates: "{{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key" + -output {{ matrix_media_repo_identifier }}.signing.key.TEMP + creates: "{{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key.TEMP" - name: Merge media-repo signing key with homeserver signing key ansible.builtin.command: @@ -108,12 +108,12 @@ --user={{ matrix_synapse_uid }}:{{ matrix_synapse_gid }} --cap-drop=ALL --mount type=bind,src={{ matrix_media_repo_config_path }},dst=/config - --mount type=bind,src={{ matrix_base_data_path }},dst=/matrix + --mount type=bind,src={{ matrix_media_repo_homeserver_signing_key | dirname }},dst=/homeserver-signing-key-dir --workdir='/config' --entrypoint='combine_signing_keys' {{ matrix_media_repo_docker_image }} - -format {{ matrix_homeserver_implementation }} -output {{ matrix_media_repo_homeserver_signing_key }}.merged {{ matrix_media_repo_homeserver_signing_key }} {{ matrix_media_repo_identifier }}.signing.key - creates: "{{ matrix_media_repo_homeserver_signing_key }}." + -format {{ matrix_homeserver_implementation }} -output /homeserver-signing-key-dir/{{ matrix_media_repo_homeserver_signing_key | basename }}.merged /homeserver-signing-key-dir/{{ matrix_media_repo_homeserver_signing_key | basename }} {{ matrix_media_repo_identifier }}.signing.key.TEMP + creates: "{{ matrix_media_repo_homeserver_signing_key }}.merged" - name: Backup existing homeserver signing key before replacing it ansible.builtin.copy: @@ -129,6 +129,11 @@ cmd: "mv {{ matrix_media_repo_homeserver_signing_key }}.merged {{ matrix_media_repo_homeserver_signing_key }}" removes: "{{ matrix_media_repo_homeserver_signing_key }}.merged" + - name: Finalize media-repo signing key setup + ansible.builtin.command: + cmd: "mv {{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key.TEMP {{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key" + removes: "{{ matrix_media_repo_config_path }}/{{ matrix_media_repo_identifier }}.signing.key.TEMP" + - name: Ensure media-repo container network is created community.general.docker_network: enable_ipv6: "{{ devture_systemd_docker_base_ipv6_enabled }}" From 05e813a846fb690863f959f1269a379e5494042c Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Thu, 15 Aug 2024 09:25:08 +0300 Subject: [PATCH 3/3] Default matrix_media_repo_generate_signing_key to false in the matrix-media-repo role No need to duplicate the same logic as in `group_vars/matrix_servers`. Having it disabled by default in the role itself and overriding it at the playbook level (based on the selected homeserver implementation) makes more sense. --- roles/custom/matrix-media-repo/defaults/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/roles/custom/matrix-media-repo/defaults/main.yml b/roles/custom/matrix-media-repo/defaults/main.yml index 5d2ffd716..a8231beef 100755 --- a/roles/custom/matrix-media-repo/defaults/main.yml +++ b/roles/custom/matrix-media-repo/defaults/main.yml @@ -320,7 +320,8 @@ matrix_media_repo_homeservers_auto: [] matrix_media_repo_homeservers_additional: [] # If true, the playbook will generate a signing key when the setup role is invoked. -matrix_media_repo_generate_signing_key: "{{ matrix_homeserver_implementation == 'synapse' or matrix_homeserver_implementation == 'dendrite' }}" +# This is adjusted in `group_vars/matrix_servers` depending on the homeserver implementation. +matrix_media_repo_generate_signing_key: false # Path where the homeserver signing key is located. Set automatically in # `group_vars/matrix_servers` depending on which homeserver is being used.