Skip to content

Add SQL backend files #5

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
27 changes: 27 additions & 0 deletions sql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Postfix TLS Policy Maps - SQL Proxy

If you don't want to use a plain file Postfix lookup table to manage TLS policy maps, but a SQL backend, you'll very likely find the files in this directory helpful. You can use them as follows:

1. Create a `tls_policy` table in the SQL database you want to use with Postfix. You can use the provided [`scheme.sql`](scheme.sql) if you want to.

2. Create a proxy configuration file (e.g. `/etc/postfix/tls_policy.cf`) to tell Postfix the SQL query to use. You can again use the provided [`postfix_proxy.cf`](postfix_proxy.cf) as a blueprint, but don't forget to change username and password.

3. Configure Postfix to actually use the proxy configuration file by setting the `smtp_tls_policy_maps` parameter in Postfix's `main.cf` accordingly. Don't forget to reload/restart Postfix afterwards.
```
smtp_tls_policy_maps = mysql:/etc/postfix/tls_policy.cf
```

4. Use the provided [`update_database.sh`](update_database.sh) to convert the plain file Postfix lookup table to SQL queries and execute them. You can e.g. simply pipe stdout of the script to the `mysql` command.
```
$ ./update_database.sh ../tls_policy | mysql --user=db_user --password "db_name"
```
You can change the built-in SQL query template by setting the environment variable `TEMPLATE`. You can use the placeholders `{domain}`, `{policy}` and `{params}` in the template. As a reference, this is the script's default template:
```
DELETE FROM tls_policy WHERE domain = '{domain}'; INSERT INTO tls_policy (domain, policy, params) VALUES ('{domain}', '{policy}', '{params}');
```

5. You may want to repeat Step 4 on a regular basis (e.g. weekly) to always use the newest upstream TLS policy maps on your server. The provided `update_database.sh` always validates the policy file before converting it into SQL queries, so you can safely automatize this task with a cronjob. The following crontab line is intended to provide inspiration for you to create your own cronjob (it will work with Debian only). Most importantly, you'll have to find a way to safely pass the password of the SQL user to the cronjob.
```
0 4 * * 7 root curl -sS "https://raw.githubusercontent.com/csware/postfix-tls-policy/master/tls_policy" | /path/to/update_database.sh - | mysql --defaults-file="/etc/mysql/debian.cnf" --silent "db_name"
```

10 changes: 10 additions & 0 deletions sql/postfix_proxy.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
user = db_user
password = db_password
hosts = 127.0.0.1
dbname = db_name

query =
SELECT policy,
params
FROM tls_policy
WHERE domain = '%s'
6 changes: 6 additions & 0 deletions sql/scheme.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE tls_policy (
domain varchar(255) NOT NULL,
policy enum('none', 'may', 'encrypt', 'dane', 'dane-only', 'fingerprint', 'verify', 'secure') NOT NULL,
params varchar(255),
PRIMARY KEY (domain)
);
42 changes: 42 additions & 0 deletions sql/update_database.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/sh
if [ -z "$1" ]; then
echo "Usage: $(basename "$0") POLICY_FILE" >&2
exit 1
fi
if [ -z "$TEMPLATE" ]; then
TEMPLATE="DELETE FROM tls_policy WHERE domain = '{domain}';"
TEMPLATE="$TEMPLATE INSERT INTO tls_policy (domain, policy, params) VALUES ('{domain}', '{policy}', '{params}');"
fi

DATABASE="$1"
[ "$DATABASE" = "-" ] && DATABASE="/dev/stdin"

EXIT_CODE=0
while read -r LINE || [ -n "$LINE" ]; do
[ -n "$LINE" ] || continue
[ "$(echo "$LINE" | cut -c 1)" = "#" ] && continue

DATA="$(echo "$LINE" | sed -e 's/\s\+/ /')"
DOMAIN="$(echo "$DATA" | cut -s -d ' ' -f 1)"
POLICY="$(echo "$DATA" | cut -s -d ' ' -f 2)"
PARAMS="$(echo "$DATA" | cut -s -d ' ' -f 3-)"

if [ -z "$(echo "$DOMAIN" | sed -ne '/^[a-zA-Z0-9._-]\{1,255\}$/p')" ] \
|| ( case "$POLICY" in none|may|encrypt|dane|dane-only|fingerprint|verify|secure) false ;; esac ) \
|| ( case "$POLICY" in fingerprint|verify|secure) false ;; esac && [ -n "$PARAMS" ] ) \
|| ( [ "$POLICY" = "fingerprint" ] && [ -z "$(echo "$PARAMS" | sed -ne '/^match=[a-fA-F0-9:|]\+$/p')" ] ) \
|| ( ! case "$POLICY" in verify|secure) false ;; esac && [ -z "$(echo "$PARAMS" | sed -ne '/^match=[a-zA-Z0-9:._-]\+$/p')" ] )
then
echo "Invalid row: $LINE" >&2
EXIT_CODE=1
continue
fi

echo "$TEMPLATE" | sed \
-e "s/{domain}/$(echo "$DOMAIN" | sed -e 's/[\/&]/\\&/g')/g" \
-e "s/{policy}/$(echo "$POLICY" | sed -e 's/[\/&]/\\&/g')/g" \
-e "s/{params}/$(echo "$PARAMS" | sed -e 's/[\/&]/\\&/g')/g"
done < "$DATABASE"

exit $EXIT_CODE