Merge pull request #205 from kingoftheconnors/master

Add Slack bridging support
This commit is contained in:
Slavi Pantaleev 2019-08-21 07:43:07 +03:00 committed by GitHub
commit 811a46ad07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 450 additions and 0 deletions

View File

@ -0,0 +1,83 @@
# Setting up Appservice Slack (optional)
The playbook can install and configure [matrix-appservice-slack](https://github.com/matrix-org/matrix-appservice-slack) for you.
See the project's [documentation](https://github.com/matrix-org/matrix-appservice-slack/blob/master/README.md) to learn what it does and why it might be useful to you.
Setup Instructions:
loosely based on [this](https://github.com/matrix-org/matrix-appservice-slack#Setup)
1. Create a new Matrix room to act as the administration control room. Note its internal room ID. This can
be done in Riot by making a message, opening the options for that message and choosing "view source". The
room ID will be displayed near the top.
2. Enable the bridge with the following configuration in your `vars.yml` file:
```yaml
matrix_appservice_slack_enabled: true
matrix_appservice_slack_control_room_id: "Your matrix admin room id"
```
3. If you've already installed Matrix services using the playbook before, you'll need to re-run it (`--tags=setup-all,start`). If not, proceed with [configuring other playbook services](configuring-playbook.md) and then with [Installing](installing.md). Get back to this guide once ready.
4. Invite the bridge bot user into the admin room:
```
/invite @slackbot:MY.DOMAIN
```
Note that the bot's domain is your server's domain **without the `matrix.` prefix.**
5. Create a new Slack App [here](https://api.slack.com/apps).
Name the app & select the team/workspace this app will belong to.
Click on bot users and add a new bot user. We will use this account to bridge the the rooms.
6. Click on Event Subscriptions and enable them and use the request url `https://matrix.DOMAIN/appservice-slack`. Then add the following events and save:
Bot User Events:
- team_domain_change
- message.channels
- message.groups (if you want to bridge private channels)
- reaction_added
- reaction_removed
7. Click on OAuth & Permissions and add the following scopes:
- chat:write:bot
- users:read
- reactions:write
If you want to bridge files, also add the following:
- files:write:user
Note: In order to make Slack files visible to matrix users, this bridge will make Slack files visible to anyone with the url (including files in private channels). This is different than the current behavior in Slack, which only allows authenticated access to media posted in private channels. See MSC701 for details.
8. Click on Install App and Install App to Workspace. Note the access tokens shown. You will need the Bot User OAuth Access Token and if you want to bridge files, the OAuth Access Token whenever you link a room.
9. For each channel you would like to bridge, perform the following steps:
* Create a Matrix room in the usual manner for your client. Take a note of its Matrix room ID - it will look something like !aBcDeF:example.com.
* Invite the bot user to both the Slack and Matrix channels you would like to bridge using `/invite @slackbot` for slack and `/invite @slackbot:MY.DOMAIN` for matrix.
* Determine the "channel ID" that Slack uses to identify the channel, which can be found in the url https://XXX.slack.com/messages/<channel id>/.
* Issue a link command in the administration control room with these collected values as arguments:
with file bridging:
```
link --channel_id CHANNELID --room !the-matrix:room.id --slack_bot_token xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx --slack_user_token xoxp-xxxxxxxx-xxxxxxxxx-xxxxxxxx-xxxxxxxx
```
without file bridging:
```
link --channel_id CHANNELID --room !the-matrix:room.id --slack_bot_token xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx
```
These arguments can be shortened to single-letter forms:
```
link -I CHANNELID -R !the-matrix:room.id -t xoxb-xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxx
```
Other configuration options are available via the `matrix_appservice_slack_configuration_extension_yaml` variable.

View File

@ -85,4 +85,6 @@ When you're done with all the configuration you'd like to do, continue with [Ins
- [Setting up Appservice Discord bridging](configuring-playbook-bridge-appservice-discord.md) (optional)
- [Setting up Appservice Slack bridging](configuring-playbook-bridge-appservice-slack.md) (optional)
- [Setting up Email2Matrix](configuring-playbook-email2matrix.md) (optional)

View File

@ -60,6 +60,39 @@ matrix_appservice_discord_homeserver_token: "{{ matrix_synapse_macaroon_secret_k
######################################################################
######################################################################
#
# matrix-appservice-slack
#
######################################################################
# We don't enable bridges by default.
matrix_appservice_slack_enabled: false
# Normally, matrix-nginx-proxy is enabled and nginx can reach matrix-appservice-slack over the container network.
# If matrix-nginx-proxy is not enabled, or you otherwise have a need for it, you can expose
# matrix-appservice-slack's client-server port to the local host.
matrix_appservice_slack_container_http_host_bind_port: "{{ '' if matrix_nginx_proxy_enabled else '127.0.0.1:{{ matrix_appservice_slack_slack_port }}' }}"
matrix_appservice_slack_appservice_token: "{{ matrix_synapse_macaroon_secret_key | password_hash('sha512', 'slack-appservice-token') | to_uuid }}"
matrix_appservice_slack_homeserver_token: "{{ matrix_synapse_macaroon_secret_key | password_hash('sha512', 'slack-homeserver-token') | to_uuid }}"
matrix_appservice_slack_id_token: "{{ matrix_synapse_macaroon_secret_key | password_hash('sha512', 'slack-id-token') | to_uuid }}"
matrix_appservice_slack_systemd_required_services_list: |
{{
['docker.service']
+
(['matrix-synapse.service'] if matrix_synapse_enabled else [])
}}
######################################################################
#
# /matrix-bridge-appservice-slack
#
######################################################################
######################################################################
#
# matrix-bridge-appservice-irc

View File

@ -0,0 +1,106 @@
# matrix-appservice-slack is a Matrix <-> Slack bridge
# See: https://github.com/matrix-org/matrix-appservice-slack
matrix_appservice_slack_enabled: true
matrix_appservice_slack_docker_image: "cadair/matrix-appservice-slack:latest"
matrix_appservice_slack_base_path: "{{ matrix_base_data_path }}/appservice-slack"
matrix_appservice_slack_config_path: "{{ matrix_appservice_slack_base_path }}/config"
matrix_appservice_slack_data_path: "{{ matrix_appservice_slack_base_path }}/data"
matrix_appservice_slack_public_endpoint: /appservice-slack
matrix_appservice_slack_inbound_uri_prefix: "{{ matrix_homeserver_url }}{{ matrix_appservice_slack_public_endpoint }}"
# Once you make a control room in Matrix, you can get its ID by typing any message and checking its source
matrix_appservice_slack_control_room_id: ''
matrix_appservice_slack_bot_name: 'slackbot'
matrix_appservice_slack_user_prefix: 'slack_'
# Controls the SLACK_PORT and MATRIX_PORT of the installation
matrix_appservice_slack_matrix_port: 9004
matrix_appservice_slack_slack_port: 9003
# Controls whether the appservice-slack container exposes its HTTP port (tcp/9003 in the container).
#
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:9999"), or empty string to not expose.
matrix_appservice_slack_container_http_host_bind_port: ''
matrix_appservice_slack_homeserver_media_url: "matrix.{{ matrix_domain }}"
matrix_appservice_slack_homeserver_url: "http://matrix-synapse:8008"
matrix_appservice_slack_homeserver_domain: "{{ matrix_domain }}"
matrix_appservice_slack_appservice_url: 'http://matrix-appservice-slack'
# A list of extra arguments to pass to the container
matrix_appservice_slack_container_extra_arguments: []
# List of systemd services that matrix-appservice-slack.service depends on.
matrix_appservice_slack_systemd_required_services_list: ['docker.service']
# List of systemd services that matrix-appservice-slack.service wants
matrix_appservice_slack_systemd_wanted_services_list: []
matrix_appservice_slack_appservice_token: ''
matrix_appservice_slack_homeserver_token: ''
matrix_appservice_slack_id_token: ''
matrix_appservice_slack_configuration_yaml: |
slack_hook_port: {{ matrix_appservice_slack_slack_port }}
inbound_uri_prefix: "{{ matrix_appservice_slack_inbound_uri_prefix }}"
bot_username: "{{ matrix_appservice_slack_bot_name }}"
username_prefix: {{ matrix_appservice_slack_user_prefix }}
homeserver:
media_url: "{{ matrix_appservice_slack_homeserver_media_url }}"
url: "{{ matrix_appservice_slack_homeserver_url }}"
server_name: "{{ matrix_domain }}"
dbdir: "/data"
matrix_admin_room: "{{ matrix_appservice_slack_control_room_id }}"
matrix_appservice_slack_configuration_extension_yaml: |
#slack_hook_port: 9898
#inbound_uri_prefix: "https://my.server.here:9898/"
#bot_username: "slackbot"
#username_prefix: "slack_"
# Optional
#slack_master_token: "abc-123-def"
# Optional
#matrix_admin_room: "!aBcDeF:matrix.org"
#homeserver:
# url: http://localhost:8008
# server_name: my.server
# Optional
#tls:
# key_file: /path/to/tls.key
# crt_file: /path/to/tls.crt
#logging:
# console: "info"
# files:
# - "./debug.log": "info"
#- "./error.log": "error"
matrix_appservice_slack_configuration_extension: "{{ matrix_appservice_slack_configuration_extension_yaml|from_yaml if matrix_appservice_slack_configuration_extension_yaml|from_yaml else {} }}"
matrix_appservice_slack_configuration: "{{ matrix_appservice_slack_configuration_yaml|from_yaml|combine(matrix_appservice_slack_configuration_extension, recursive=True) }}"
matrix_appservice_slack_registration_yaml: |
id: "{{ matrix_appservice_slack_id_token }}"
as_token: "{{ matrix_appservice_slack_appservice_token }}"
hs_token: "{{ matrix_appservice_slack_homeserver_token }}"
namespaces:
users:
- exclusive: true
regex: '@{{ matrix_appservice_slack_user_prefix }}.*'
aliases:
- exclusive: false
regex: '#{{ matrix_appservice_slack_user_prefix }}.*'
rooms: []
url: "{{matrix_appservice_slack_appservice_url}}:{{ matrix_appservice_slack_matrix_port }}"
sender_localpart: slackbot
rate_limited: true
protocols: null
matrix_appservice_slack_registration: "{{ matrix_appservice_slack_registration_yaml|from_yaml }}"

View File

@ -0,0 +1,79 @@
# If the matrix-synapse role is not used, `matrix_synapse_role_executed` won't exist.
# We don't want to fail in such cases.
- name: Fail if matrix-synapse role already executed
fail:
msg: >-
The matrix-bridge-appservice-slack role needs to execute before the matrix-synapse role.
when: "matrix_synapse_role_executed|default(False)"
- set_fact:
matrix_systemd_services_list: "{{ matrix_systemd_services_list + ['matrix-appservice-slack'] }}"
when: matrix_appservice_slack_enabled|bool
# If the matrix-synapse role is not used, these variables may not exist.
- set_fact:
matrix_synapse_container_extra_arguments: >
{{ matrix_synapse_container_extra_arguments|default([]) }}
+
{{ ["--mount type=bind,src={{ matrix_appservice_slack_config_path }}/slack-registration.yaml,dst=/matrix-appservice-slack-registration.yaml,ro"] }}
matrix_synapse_app_service_config_files: >
{{ matrix_synapse_app_service_config_files|default([]) }}
+
{{ ["/matrix-appservice-slack-registration.yaml"] }}
when: matrix_appservice_slack_enabled|bool
# If the matrix-synapse role is not used, `matrix_synapse_role_executed` won't exist.
# We don't want to fail in such cases.
- name: Fail if matrix-synapse role already executed
fail:
msg: >-
The matrix-bridge-appservice-slack role needs to execute before the matrix-synapse role.
when: "matrix_synapse_role_executed|default(False)"
- block:
- name: Fail if matrix-nginx-proxy role already executed
fail:
msg: >-
Trying to append Slack Appservice's reverse-proxying configuration to matrix-nginx-proxy,
but it's pointless since the matrix-nginx-proxy role had already executed.
To fix this, please change the order of roles in your plabook,
so that the matrix-nginx-proxy role would run after the matrix-bridge-appservice-slack role.
when: matrix_nginx_proxy_role_executed|default(False)|bool
- name: Generate Matrix Appservice Slack proxying configuration for matrix-nginx-proxy
set_fact:
matrix_appservice_slack_matrix_nginx_proxy_configuration: |
location {{ matrix_appservice_slack_public_endpoint }} {
{% if matrix_nginx_proxy_enabled|default(False) %}
{# Use the embedded DNS resolver in Docker containers to discover the service #}
resolver 127.0.0.11 valid=5s;
set $backend "{{ matrix_appservice_slack_appservice_url }}:{{ matrix_appservice_slack_slack_port }}";
proxy_pass $backend;
{% else %}
{# Generic configuration for use outside of our container setup #}
proxy_pass http://127.0.0.1:{{ matrix_appservice_slack_slack_port }};
{% endif %}
}
- name: Register Slack Appservice proxying configuration with matrix-nginx-proxy
set_fact:
matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks: |
{{
matrix_nginx_proxy_proxy_matrix_additional_server_configuration_blocks|default([])
+
[matrix_appservice_slack_matrix_nginx_proxy_configuration]
}}
tags:
- always
when: matrix_appservice_slack_enabled|bool
- name: Warn about reverse-proxying if matrix-nginx-proxy not used
debug:
msg: >-
NOTE: You've enabled the Matrix Slack bridge but are not using the matrix-nginx-proxy
reverse proxy.
Please make sure that you're proxying the `{{ something }}`
URL endpoint to the matrix-appservice-slack container.
You can expose the container's port using the `matrix_appservice_slack_container_http_host_bind_port` variable.
when: "matrix_appservice_slack_enabled|bool and matrix_nginx_proxy_enabled is not defined"

View File

@ -0,0 +1,21 @@
- import_tasks: "{{ role_path }}/tasks/init.yml"
tags:
- always
- import_tasks: "{{ role_path }}/tasks/validate_config.yml"
when: "run_setup|bool and matrix_appservice_slack_enabled|bool"
tags:
- setup-all
- setup-appservice-slack
- import_tasks: "{{ role_path }}/tasks/setup_install.yml"
when: "run_setup|bool and matrix_appservice_slack_enabled|bool"
tags:
- setup-all
- setup-appservice-slack
- import_tasks: "{{ role_path }}/tasks/setup_uninstall.yml"
when: "run_setup|bool and not matrix_appservice_slack_enabled|bool"
tags:
- setup-all
- setup-appservice-slack

View File

@ -0,0 +1,46 @@
---
- name: Ensure Appservice Slack image is pulled
docker_image:
name: "{{ matrix_appservice_slack_docker_image }}"
source: "{{ 'pull' if ansible_version.major > 2 or ansible_version.minor > 7 else omit }}"
- name: Ensure AppService Slack paths exist
file:
path: "{{ item }}"
state: directory
mode: 0750
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
with_items:
- "{{ matrix_appservice_slack_base_path }}"
- "{{ matrix_appservice_slack_config_path }}"
- "{{ matrix_appservice_slack_data_path }}"
- name: Ensure Matrix Appservice Slack config installed
copy:
content: "{{ matrix_appservice_slack_configuration|to_nice_yaml }}"
dest: "{{ matrix_appservice_slack_config_path }}/config.yaml"
mode: 0644
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
- name: Ensure appservice-slack registration.yaml installed
copy:
content: "{{ matrix_appservice_slack_registration|to_nice_yaml }}"
dest: "{{ matrix_appservice_slack_config_path }}/slack-registration.yaml"
mode: 0644
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
- name: Ensure matrix-appservice-slack.service installed
template:
src: "{{ role_path }}/templates/systemd/matrix-appservice-slack.service.j2"
dest: "/etc/systemd/system/matrix-appservice-slack.service"
mode: 0644
register: matrix_appservice_slack_systemd_service_result
- name: Ensure systemd reloaded after matrix-appservice-slack.service installation
service:
daemon_reload: yes
when: "matrix_appservice_slack_systemd_service_result.changed"

View File

@ -0,0 +1,24 @@
---
- name: Check existence of matrix-appservice-slack service
stat:
path: "/etc/systemd/system/matrix-appservice-slack.service"
register: matrix_appservice_slack_service_stat
- name: Ensure matrix-appservice-slack is stopped
service:
name: matrix-appservice-slack
state: stopped
daemon_reload: yes
when: "matrix_appservice_slack_service_stat.stat.exists"
- name: Ensure matrix-appservice-slack.service doesn't exist
file:
path: "/etc/systemd/system/matrix-appservice-slack.service"
state: absent
when: "matrix_appservice_slack_service_stat.stat.exists"
- name: Ensure systemd reloaded after matrix-appservice-slack.service removal
service:
daemon_reload: yes
when: "matrix_appservice_slack_service_stat.stat.exists"

View File

@ -0,0 +1,12 @@
---
- name: Fail if required settings not defined
fail:
msg: >-
You need to define a required configuration setting (`{{ item }}`).
when: "vars[item] == ''"
with_items:
- "matrix_appservice_slack_control_room_id"
- "matrix_appservice_slack_appservice_token"
- "matrix_appservice_slack_homeserver_token"
- "matrix_appservice_slack_id_token"

View File

@ -0,0 +1,43 @@
#jinja2: lstrip_blocks: "True"
[Unit]
Description=Matrix Appservice Slack server
{% for service in matrix_appservice_slack_systemd_required_services_list %}
Requires={{ service }}
After={{ service }}
{% endfor %}
{% for service in matrix_appservice_slack_systemd_wanted_services_list %}
Wants={{ service }}
{% endfor %}
[Service]
Type=simple
ExecStartPre=-/usr/bin/docker kill matrix-appservice-slack
ExecStartPre=-/usr/bin/docker rm matrix-appservice-slack
# Intentional delay, so that the homeserver (we likely depend on) can manage to start.
ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/docker run --rm --name matrix-appservice-slack \
--log-driver=none \
--user={{ matrix_user_uid }}:{{ matrix_user_gid }} \
--cap-drop=ALL \
--network={{ matrix_docker_network }} \
{% if matrix_appservice_slack_container_http_host_bind_port %}
-p {{ matrix_appservice_slack_container_http_host_bind_port }}:{{matrix_appservice_slack_slack_port}} \
{% endif %}
-v {{ matrix_appservice_slack_config_path }}:/config:z \
-v {{ matrix_appservice_slack_data_path }}:/data:z \
{% for arg in matrix_appservice_slack_container_extra_arguments %}
{{ arg }} \
{% endfor %}
{{ matrix_appservice_slack_docker_image }} \
node app.js -p {{matrix_appservice_slack_matrix_port}} -c /config/config.yaml -f /config/slack-registration.yaml
ExecStop=-/usr/bin/docker kill matrix-appservice-slack
ExecStop=-/usr/bin/docker rm matrix-appservice-slack
Restart=always
RestartSec=30
SyslogIdentifier=matrix-appservice-slack
[Install]
WantedBy=multi-user.target

View File

@ -9,6 +9,7 @@
- matrix-postgres
- matrix-corporal
- matrix-bridge-appservice-discord
- matrix-bridge-appservice-slack
- matrix-bridge-appservice-irc
- matrix-bridge-mautrix-facebook
- matrix-bridge-mautrix-hangouts