summaryrefslogtreecommitdiff
path: root/README.org
blob: bd7359aa611c33f0cdea347c8c0816d4acf62fad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#+title: Email Key Rotation
#+language: en
#+author: Vivien Kraus
#+email: vivien@planete-kraus.eu

I present to you this humble package that can help you rotate your
DKIM keys and SRS secrets.

DKIM rotation can be done in various different ways, but this package
assumes that you have at least a couple of selectors, such as
=selectorA= and =selectorB=. When the current selector is =selectorB=,
the DNS entry for =selectorA= is the previous expired public key, and
the DNS entry for =selectorB= is the current public key. In this case,
after rotation, the DNS entry for =selectorB= does not change, but
that of =selectorA= becomes the new public key, and the email server
starts signing outbound emails with =selectorA= instead of
=selectorB=, provided that you restart it.

This package can:
- rotate DKIM keys;
- rotate SRS secrets for opensmtpd;
- “materialize” the keys.

When materialized, the DKIM key is saved as an openssl private key (so
that it can be used by your DKIM signing SMTP server), the current
selector is written to a file on its only line, the SRS secrets are
written to an OpenSMTPD configuration file, and, if configured, the
Gandi LiveDNS zone is updated.

This package uses the =openssl= program to generate keys and
secrets. You can customize this by parameterizing
=current-openssl-binary= in /(email-key-rotation openssl)/, either to
a program name to invoke, or to a procedure that accepts 1 argument
(the command-line for openssl, without the program name).

This package manages different secrets: both[fn::current and expired]
DKIM keys, both SRS secrets, and the Gandi LiveDNS API key. Files
containing these secrets are always written with mode =0600=, but not
much else is considered for security.

* Initialize the configuration
You initialize the configuration by calling =initialize= in
/(email-key-rotation)/. The arguments are:
- the list of selectors, for instance ='(selectorA selectorB)=;
- the file name for the private opensmtpd configuration file, or =#f=
  if you do not want to configure SRS;
- the name of the file that will contain the current DKIM selector, or
  =#f= if you do not want to configure DKIM;
- the name of the file that will contain the current DKIM private key,
  or =#f= if you do not want to configure DKIM;
- the Gandi LiveDNS API key, or =#f= if you do not wish to publish DNS
  records on Gandi LiveDNS;
- the Gandi domain name.

This function returns a configuration object that you may save to disk
with =materialize=, in /(email-key-rotation)/. This function takes the
configuration object as the first argument, and an optional output
port to save the configuration object itself. If the port is not set,
then it is saved to the current Guile output port. If the port is set,
*and* is set to a file port, then it will be made only readable by the
current owner.

* Rotate the configuration
Every once in a while, say, every week, you would load the current
configuration object, and rotate it with =rotate=, in
/(email-key-rotation)/. The return value is a new configuration object
that you can materialize.

The configuration object is saved to disk as XML. You may convert it
with =xml->sxml= in /(sxml simple)/, and then convert it to a
configuration object with =sxml->configuration= in
/(email-key-rotation)/, or use the shortcut =xml->configuration= in
/(email-key-rotation)/. The latter accept only one optional argument,
the port to read XML from. It defaults to the Guile current input
port.