easywks/README.md
2021-09-27 23:40:10 +02:00

222 lines
No EOL
7.4 KiB
Markdown

# EasyWKS
### OpenPGP WKS for Human Beings
---
This is a work-in-progress project. See ROADMAP.md for details
## What is WKD/WKS?
Due to all the issues involved with the PGP key servers we're using today, GnuPG introduced a feature named [**Web Key
Discovery**][wkd] (WKD): Instead of searching for keys on the usual key servers, WKD is taking a **fully**
decentralized and federated approach, where each mail domain is responsible for hosting its users public keys on an
HTTPS web directory. For example, in order to retrieve the key for `john.doe@example.org`, they key can be located at
https://openpgpkey.example.org/.well-known/openpgpkey/example.org/hu/iy9q119eutrkn8s1mk4r39qejnbu3n5q?l=john.doe
In order to get the keys there, GnuPG developed an email-based protocol named [**Web Key Service**][wks] (WKS), which
lets users publish their public keys once they have proven ownership of the key using an email-based challenge-responce
mechanism.
At the time, WKS and WKD aren't yet part of the OpenPGP standard, but there's an [IETF Draft RFC][ietf] that's being
updated from time to time.
## Why EasyWKS?
I've experienced the WKS standard to be extremely cumbersome to conform to. The tools shipped with GnuPG,
`gpg-wks-server` and `gpg-wks-client` are usable well enough as long as you have shell access on a mailserver and pipe
the output of `gpg-wks-client` into `sendmail`. However, I'm usually doing my email via SMTP using a variety of
clients.
No matter which client I tried, I did not manage to get them to send mails in the format required by `gpg-wks-server`.
Even pasting the output of `gpg-wks-client` into `openssl s_client` after manually performing SMTP auth proved to be
difficult in case any line of the PGP-encrypted message happened to start with `Q` or `R`.
So I decided to write a WKS server that's much more lenient regarding the exact format of the mails it receives.
Instead of enforcing the strict format mandated by the standard, EasyWKS only requires:
- For the initial submission request: An unsigned & encrypted PGP/MIME message anywhere in the MIME tree, and the
ASCII-armored PGP-Key anywhere inside the encrypted message.
- For the confirmation response: A signed & encrypted PGP/MIME message anywhere in the MIME tree, and the
confirmation response anywhere inside the encrypted message.
This makes EasyWKS usable with every mail client, no matter whether WKS support is built-in or not.
EasyWKS aims to be a drop-in replacement for gpg-wks-server; see "Bootstrapping" below to learn how to migrate from
gpg-wks-server to EasyWKS.
## Requirements
- Python 3.6 or newer
- PyYAML
- bottle.py
- PGPy
## License
MIT
## Setup
### Installation
TODO
Create a cronjob, e.g. in `/etc/cron.d/easywks`
```crontab
0 3 * * * webkey /path/to/easywks clean
```
### Configuration
Configuration is done in `/etc/easywks.yml` (or any other place as specified by `--config`)
```yaml
---
# EasyWKS works inside this directory. Its PGP keys as well
# as all the submitted and published keys are stored here.
directory: /var/lib/easywks
# Number of seconds after which a pending submission request
# is considered stale and should be removed by easywks clean.
pending_lifetime: 604800
# Port configuration for the webserver. Put this behind a
# HTTPS-terminating reverse proxy!
host: 127.0.0.1
port: 8080
# Defaults to stdout, supported: stdout, smtp
mailing_method: smtp
# Configure smtp client options
smtp:
# Connect to this SMTP server to send a mail.
host: localhost
port: 25
# if tls=True, starttls is ignored
tls: false
starttls: false
# Omit username/password if authentication is not needed.
username: webkey
password: SuperS3curePassword123
# Configure the LMTP server
lmtpds:
host: "::1"
port: 8024
# Every domain served by EasyWKS must be listed here
domains:
example.org:
# Users send their requests to this address. It's up to
# you to make sure that the mails sent their get handed
# to EasyWKS.
submission_address: webkey@example.org
# If you want the PGP key for this domain to be
# password-protected, or if you're supplying your own
# password-protected key, set the passphrase here:
passphrase: "Correct Horse Battery Staple"
# Defaults are gpgwks@<domain> and no password protection.
example.com: {}
```
### Bootstrapping
Run `easywks init` (as the correct user) to initialize all files and directories. This will also generate a PGP key for
each domain, stored in `<workdir>/<domain>/key.pgp`. If you want to, you can replace this key by a key you generated
yourself. If your key is password-protected, you have to supply the passphrase in the config file or remove the
password protection.
If you are migrating from gpg-wks-server to EasyWKS, you can point EasyWKS to gpg-wks-server's working directory
(usually `/var/lib/gnupg/wks`). EasyWKS uses the same directory layout and file formats as gpg-wks-server, so it should
be able to take over where gpg-wks-server stopped. The only thing you need to do is to export the private keys from the
GnuPG keyring and write them to their domain's `key.pgp`.
### Webserver Setup
There are generally two ways to get WKD working:
- The gpg-wks-server approach, i.e. regularly copying the `hu` directories from EasyWKS' working directory to the
webroot.
- Running the EasyWKS web server behind a Reverse Proxy, e.g. using the follwing systemd unit:
```unit file (systemd)
[Unit]
Description=OpenPGP WKS for Human Beings - HTTP Server
[Service]
Type=simple
ExecStart=/path/to/easywks webserver
Restart=on-failure
User=webkey
Group=webkey
WorkingDirectory=/var/lib/easywks
[Install]
WantedBy=multi-user.target
```
Once this service is up and running, you can configure your webserver to proxy requests to EasyWKS. E.g. with Apache2:
```
ProxyPass /.well-known/openpgpkey/ http://127.0.0.1:8080/.well-known/openpgpkey/
ProxyPassReverse /.well-known/openpgpkey/ http://127.0.0.1:8080/.well-known/openpgpkey/
```
Note that the webserver built into EasyWKS validates that the `?l=<uid>` matches the uid hash (the last URL component).
### MTA Setup
#### Postfix
You can either connect EasyWKS using a pipe transport or as a LMTP server.
##### Pipe Transport
Add an entry in `/etc/postfix/master.cf`:
```
webkey unix - n n - - pipe
flags=DRhu user=webkey argv=/path/to/easywks process
```
Then tell postfix to forward mails to the submission addresses to said transport, e.g. in `/etc/postfix/transport`:
```
# The colon at the end is important, it lets postfix know
# that "webkey" is a transport, not a name
gpgwks@example.org webkey:
webkey@example.com webkey:
```
Configure EasyWKS to send outgoing mails via SMTP.
##### LMTP Server
Configure EasyWKS to run the LMTP server, e.g. using the following systemd unit:
```unit file (systemd)
[Unit]
Description=OpenPGP WKS for Human Beings - LMTP Server
[Service]
Type=simple
ExecStart=/path/to/easywks lmtpd
Restart=on-failure
User=webkey
Group=webkey
WorkingDirectory=/var/lib/easywks
[Install]
WantedBy=multi-user.target
```
Also configure EasyWKS to send outgoing mails via SMTP.
Then tell postfix to forward mails to the submission addresses to said transport, e.g. in `/etc/postfix/transport`:
```
gpgwks@example.org lmtp:localhost:10024
webkey@example.com lmtp:localhost:10024
```
[wkd]: https://wiki.gnupg.org/WKD
[wks]: https://wiki.gnupg.org/WKS
[ietf]: https://datatracker.ietf.org/doc/html/draft-koch-openpgp-webkey-service-12