Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add service mail via. fortune address #461

Merged
merged 9 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ansible/roles/common/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@
name:
- tmux
- vim
- fortune-mod
- cowsay
state: present
tags:
- role::common
Expand Down
39 changes: 39 additions & 0 deletions ansible/roles/postfix/files/services/fortune-reply.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

# Read the entire email into a variable
EMAIL=$(cat)

# Extract the sender's email address
SENDER=$(echo "$EMAIL" | maddr -a -h from -)

# Extract the Message-ID of the original email
MESSAGE_ID=$(echo "$EMAIL" | mhdr -h message-id -)

# Extract the original Subject and prefix it with "Re: " if necessary
ORIGINAL_SUBJECT=$(echo "$EMAIL" | mhdr -h subject -)

# Construct the reply subject
REPLY_SUBJECT="Re: $ORIGINAL_SUBJECT"

# Extract the To address
TO_ADDRESS=$(echo "$EMAIL" | maddr -a -h to -)

# Generate the fortune output
if [[ "$TO_ADDRESS" =~ "fortune+cowsay" ]]; then
FORTUNE_OUTPUT=$(/usr/games/fortune | /usr/games/cowsay)
else
FORTUNE_OUTPUT=$(/usr/games/fortune)
fi

# Send a reply with the proper headers
(
echo "Subject: $REPLY_SUBJECT"
echo "From: Fortunes by Python Discord <[email protected]>"
echo "To: $SENDER"
echo "In-Reply-To: $MESSAGE_ID"
echo "References: $MESSAGE_ID"
echo
echo "Here's your fortune:"
echo
echo "$FORTUNE_OUTPUT"
) | /usr/sbin/sendmail -t
4 changes: 4 additions & 0 deletions ansible/roles/postfix/handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@
- name: Regenerate virtual table
command: postmap /etc/postfix/virtual
changed_when: true

- name: Regenerate transport table
command: postmap /etc/postfix/transport
changed_when: true
28 changes: 28 additions & 0 deletions ansible/roles/postfix/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- postsrsd
# Security and anti-spam tools
- postfix-policyd-spf-python
# Mail scripting utilities
- mblaze
state: present
tags:
- role::postfix
Expand Down Expand Up @@ -85,6 +87,28 @@
notify:
- Restart postfix

- name: Copy Postfix scripts directory
copy:
src: services/
dest: /etc/postfix/service-scripts/
directory_mode: "0755"
mode: "0744"
owner: servicemailer
group: servicemailer
tags:
- role::postfix

- name: Template Postfix mail transport map
template:
src: transport.j2
dest: /etc/postfix/transport
mode: "0644"
owner: root
group: root
tags:
- role::postfix
notify: Regenerate transport table

- name: Add custom services to master.cf
blockinfile:
path: /etc/postfix/master.cf
Expand All @@ -99,6 +123,10 @@
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

# Service Mail pipes
fortune-pipe unix - n n - - pipe
flags=Fq user=servicemailer argv=/etc/postfix/service-scripts/fortune-reply.sh
tags:
- role::postfix
notify:
Expand Down
6 changes: 5 additions & 1 deletion ansible/roles/postfix/templates/main.cf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ relay_recipient_maps =
ldap:/etc/postfix/ldap-service-mail.cf,
hash:/etc/postfix/virtual

local_recipient_maps = $relay_recipient_maps
local_recipient_maps =
$relay_recipient_maps,
hash:/etc/postfix/transport

transport_maps = hash:/etc/postfix/transport

mydestination = {{ postfix_mailserver_name }}, localhost, {{ postfix_destination_domains | join(', ') }}
relayhost =
Expand Down
5 changes: 5 additions & 0 deletions ansible/roles/postfix/templates/transport.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Managed by Ansible
#
# Postfix Mail Transport Map

[email protected] fortune-pipe:
64 changes: 64 additions & 0 deletions docs/docs/services/email/mail-services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
description: Automated services available over the Python Discord mailserver
---
# Automated Mail Services

We host a selection of services that are made accessible via email to
`@int.pydis.wtf` addresses.

Unlike service accounts, their mail is not delivered to typical UNIX mailboxes
(for example, like DMARC reports are), but is instead processed by a local
script which is spawned by the `master.cf` Postfix config file, and run as the
`servicemailer` user.

These scripts are flexible on what they can do, they can respond to an email,
forward something, trigger an action, and so on. The full message body is passed
to the script for processing.

Services are categorised into the following groups:

| Icon | Access |
|-----------------|----------------------------------------------|
| :green_circle: | Available to any mail user |
| :orange_circle: | Available to any PyDis LDAP user |
| :red_circle: | Only available to members of the DevOps team |

## Available Services

### :green_circle: Fortunes ([`[email protected]`](mailto:[email protected]))

The fortune service responds to an email with a fortune generated by the
[Fortune](https://en.wikipedia.org/wiki/Fortune_(Unix)) command. It is one of
the simplest examples of an automatic mail service.

Optionally, if users send to `[email protected]` then their fortune
response will be wrapped by a cow.

You can trigger this service by sending an email with any subject and any
content. It will reply to the email address you sent from.

## Security

Mail-available services are generally secure, we apply the same security
restrictions we do to all inbound mail:

- Validate SPF policy
- Validate DKIM policy
- Validate DMARC policy

You can read more about these [here](./components/validation.md).

Ultimately, there is no reason to believe that service mail opens any additional
vulnerabilities, though it should not be used for tasks requiring fine-grained
authorization or to trigger actions that are known to cause consequences, no
matter how small.

Ideal use-cases for service mail are:

- Services that run harmless commands and return the responses (i.e. `fortune`)
- Services which query information that is non-sensitive (i.e. currently
triggered Prometheus alerts)

Anything that is sensitive or otherwise not suited should instead be implemented
as a feature on King Arthur or any other system with fine-grained access
control.
Loading