aboutsummaryrefslogtreecommitdiffstats
path: root/lacme.md
blob: 5d86f4071561d6c6ee15f8d8c2d10200e8244251 (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
% lacme(1)
% [Guilhem Moulin](mailto:guilhem@fripost.org)
% December 2015

Name
====

lacme - [ACME] client written with process isolation and minimal
privileges in mind

Synopsis
========

`lacme` [`--config=FILENAME`] [`--socket=PATH`] [*OPTION* …] *COMMAND* [*ARGUMENT* …]

Description
===========

`lacme` is a small [ACME] client written with process isolation and
minimal privileges in mind.  It is divided into four components, each
with its own executable:

 1. A [`lacme-accountd`(1)] process to manage the account key and issue
    SHA-256 signatures needed for each [ACME] command.  (This process
    binds to a UNIX-domain socket to reply to signature requests from
    the [ACME] client.)
    One can use the UNIX-domain socket forwarding facility of OpenSSH
    6.7 and later to run [`lacme-accountd`(1)] and `lacme` on different
    hosts.  Alternatively, the [`lacme-accountd`(1)] process can be
    spawned by the “master” `lacme` process below; in that case, the
    two processes communicate through a socket pair.

 2. A “master” `lacme` process, which runs as root and is the only
    component with access to the private key material of the server
    keys.  It is used to fork the [ACME] client (and optionally the
    [ACME] webserver) after dropping root privileges.
    For certificate issuances (`newOrder` command), it also generates
    Certificate Signing Requests, then verifies the validity of the
    issued certificate, and optionally reloads or restarts services when
    the *notify* option is set.

 3. An actual [ACME] client (specified with the *command* option of the
    [`[client]` section](#client-section) of the configuration file),
    which builds [ACME] commands and dialogues with the remote [ACME]
    server.
    Since [ACME] commands need to be signed with the account key, the
    “master” `lacme` process passes the [`lacme-accountd`(1)]
    UNIX-domain socket to the [ACME] client: data signatures are
    requested by writing the data to be signed to the socket.

 4. For certificate issuances (`newOrder` command), an optional
    webserver (specified with the *command* option of the [`[webserver]`
    section](#webserver-section) of the configuration file), which is
    spawned by the “master” `lacme`.  (The only challenge type currently
    supported by `lacme` is `http-01`, which requires a webserver to
    answer challenges.)  That webserver only processes `GET` and `HEAD`
    requests under the `/.well-known/acme-challenge/` URI.
    Moreover temporary [`iptables`(8)] rules can be automatically
    installed to open the HTTP port.

Commands
========

`lacme account` [`--tos-agreed`] [`--register`] [*CONTACT* …]

:   Register (if `--registered` is set) a [`lacme-accountd`(1)]-managed
    account key.  A list of *CONTACT* information (such as `maito:`
    URIs) can be specified in order for the [ACME] server to contact the
    client for issues related to this registration (such as
    notifications about server-initiated revocations).  `--tos-agreed`
    indicates agreement with the [ACME] server's Terms of Service (and
    might be required for registration).

    If the account key is already registered, update the contact info
    with the given list of *CONTACT* information.

    Upon success, `lacme` prints the new or updated Account Object from
    the [ACME] server.

`lacme` [`--config-certs=`*FILE*] [`--min-days=`*INT*] `newOrder` [*SECTION* …]

:   Read the certificate configuration *FILE* (see the **[certificate
    configuration file](#certificate-configuration-file)** section below
    for the configuration options), and request new Certificate Issuance
    for each of its sections (or the given list of *SECTION*s).
    Command alias: `new-order`.

`lacme` `revokeCert` *FILE* [*FILE* …]

:   Request that the given certificate(s) *FILE*(s) be revoked.  For
    this command, [`lacme-accountd`(1)] can be pointed to either the
    account key or the server's private key.
    Command alias: `revoke-cert`.

Generic options
===============

`--config=`*filename*

:    Use *filename* as configuration file.  See the **[configuration
     file](#configuration-file)** section below for the configuration
     options.

`--socket=`*path*

:   Use *path* as the [`lacme-accountd`(1)] UNIX-domain socket to
    connect to for signature requests from the [ACME] client.  `lacme`
    aborts if `path` is readable or writable by other users, or if its
    parent directory is writable by other users.
    This command-line option overrides the *socket* option of the
    [`[client]` section](#client-section) of the configuration file.
    Moreover this option is ignored when the configuration file has an
    [`[accountd]` section](#accountd-section); in that case `lacme`
    spawns [`lacme-accountd`(1)], and the two processes communicate
    through a socket pair.

`-h`, `--help`

:   Display a brief help and exit.

`-q`, `--quiet`

:   Be quiet.

`--debug`

:   Turn on debug mode.

Configuration file
==================

If `--config=` is not given, `lacme` uses the first existing
configuration file among *./lacme.conf*,
*$XDG_CONFIG_HOME/lacme/lacme.conf* (or *~/.config/lacme/lacme.conf* if
the `XDG_CONFIG_HOME` environment variable is not set), and
*/etc/lacme/lacme.conf*.
Valid options are:

Default section
---------------

*config-certs*

:   For certificate issuances (`newOrder` command), specify the
    space-separated list of certificate configuration files or
    directories to use (see the **[certificate configuration
    file](#certificate-configuration-file)** section below for the
    configuration options).

    Paths not starting with `/` are relative to the directory name of
    the **[configuration filename](#configuration-file)**.  The list of
    files and directories is processed in order, with the later items
    taking precedence.  Files in a directory are processed in
    lexicographic order, only considering the ones with suffix `.conf`.

    Default: `lacme-certs.conf lacme-certs.conf.d/`.

`[client]` section
------------------

This section is used for configuring the [ACME] client (which takes care
of [ACME] commands and dialogues with the remote [ACME] server).

*socket*

:   See `--socket=`.
    Default: *$XDG_RUNTIME_DIR/S.lacme* if the `XDG_RUNTIME_DIR`
    environment variable is set.

*user*

:   The username to drop privileges to (setting both effective and real
    uid).  Preserve root privileges if the value is empty (not
    recommended).
    Default: `nobody`.

*group*

:   The groupname to drop privileges to (setting both effective and real
    gid, and also setting the list of supplementary gids to that single
    group).  Preserve root privileges if the value is empty (not
    recommended).
    Default: `nogroup`.

*command*

:   Path to the [ACME] client executable.
    Default: `/usr/lib/lacme/client`.

*server*

:   Root URI of the [ACME] server.
    Default: `https://acme-v02.api.letsencrypt.org/directory`.

*timeout*

:   Timeout in seconds after which the client stops polling the [ACME]
    server and considers the request failed.
    Default: `10`.

*SSL_verify*

:   Whether to verify the server certificate chain.
    Default: `Yes`.

*SSL_version*

:   Specify the version of the SSL protocol used to transmit data.

*SSL_cipher_list*

:   Specify the cipher list for the connection, see [`ciphers`(1ssl)]
    for more information.

`[webserver]` section
---------------------

This section is used to configure how [ACME] challenge responses are
served during certificate issuance.

*listen*

:   Comma- or space-separated list of addresses to listen on.  Valid
    addresses are of the form `IPV4:PORT`, `[IPV6]:PORT` (where the
    `:PORT` suffix is optional and defaults to the HTTP port 80), or an
    absolute path of a UNIX-domain socket (created with mode `0666`).
    Default: `/run/lacme-www.socket`.

    **Note**: The default value is only suitable when an external HTTP
    daemon is publicly reachable and passes all ACME challenge requests
    to the webserver component through the UNIX-domain socket
    `/run/lacme-www.socket` (for instance using the provided
    `/etc/lacme/apache2.conf` or `/etc/lacme/nginx.conf` configuration
    snippets for each virtual host requiring authorization).  If there
    is no HTTP daemon bound to port 80 one needs to set *listen* to
    `[::]` (or `0.0.0.0 [::]` when dual IPv4/IPv6 stack is disabled or
    unavailable), and possibly also set *iptables* to `Yes`.

*challenge-directory*

:   Specify a non-existent directory under which an external HTTP daemon
    is configured to serve `GET` requests for challenge files under
    `/.well-known/acme-challenge/` (for each virtual host requiring
    authorization) as static files.
    This option is required when *listen* is empty.

*user*

:   The username to drop privileges to (setting both effective and real
    uid).  Preserve root privileges if the value is empty (not
    recommended).
    Default: `www-data`.

*group*

:   The groupname to drop privileges to (setting both effective and real
    gid, and also setting the list of supplementary gids to that single
    group).  Preserve root privileges if the value is empty (not
    recommended).
    Default: `www-data`.

*command*

:   Path to the [ACME] webserver executable.  A separate process is
    spawned for each address to *listen* on.  (In particular no
    webserver process is forked when the *listen* option is empty.)
    Default: `/usr/lib/lacme/webserver`.

*iptables*

:   Whether to automatically install temporary [`iptables`(8)] rules to
    open the `ADDRESS[:PORT]` specified with *listen*.  The rules are
    automatically removed once `lacme` exits.
    Default: `No`.

`[accountd]` section
---------------------

This section is used for configuring the [`lacme-accountd`(1)] process.
If the section (including its header) is absent or commented out,
`lacme` connects to an existing UNIX-domain socket bound by a running
[`lacme-accountd`(1)] process.

*user*

:   The username to drop privileges to (setting both effective and real
    uid).  Preserve root privileges if the value is empty.

*group*

:   The groupname to drop privileges to (setting both effective and real
    gid, and also setting the list of supplementary gids to that single
    group).  Preserve root privileges if the value is empty.

*command*

:   Path to the [`lacme-accountd`(1)] executable.
    Default: `/usr/bin/lacme-accountd`.

*config*

:   Path to the [`lacme-accountd`(1)] configuration file.
    Default: `/etc/lacme/lacme-accountd.conf`.

*privkey*

:   The (private) account key to use for signing requests.  See
    [`lacme-accountd`(1)] for details.

*quiet*

:   Be quiet. Possible values: `Yes`/`No`.

Certificate configuration file
==============================

For certificate issuances (`newOrder` command), a separate file is used
to configure paths to the certificate and key, as well as the subject,
subjectAltName, etc. to generate Certificate Signing Requests.
Each section denotes a separate certificate issuance.
Valid options are:

*certificate*

:   Where to store the issued certificate (in PEM format).
    At least one of *certificate* or *certificate-chain* is required.

*certificate-chain*

:   Where to store the issued certificate, concatenated with the content
    of the file specified specified with the *CAfile* option (in PEM
    format).
    At least one of *certificate* or *certificate-chain* is required.

*certificate-key*

:   Path the service's private key.  This option is required.  The
    following command can be used to generate a new 4096-bits RSA key in
    PEM format with mode 0600:

        openssl genrsa 4096 | install -m0600 /dev/stdin /path/to/srv.key

*min-days*

:   For an existing certificate, the minimum number of days before its
    expiration date the section is considered for re-issuance.
    A negative value forces reissuance, while the number `0` limits
    reissuance to expired certificates.
    Default: the value of the CLI option `--min-days`, or `21` if there
    is no such option.

*CAfile*

:   Path to the issuer's certificate.  This is used for
    *certificate-chain* and to verify the validity of each issued
    certificate.
    Specifying an empty value skip certificate validation.
    Default: `/usr/share/lacme/lets-encrypt-x3-cross-signed.pem`.

*hash*

:   Message digest algorithm to sign the Certificate Signing Request
    with.

*keyUsage*

:   Comma-separated list of Key Usages, see [`x509v3_config`(5ssl)].

*subject*

:   Subject field of the Certificate Signing Request, in the form
    `/type0=value0/type1=value1/type2=…`.  This option is required.

*subjectAltName*

:   Comma-separated list of Subject Alternative Names, in the form
    `type0:value1,type1:value1,type2:…`
    The only `type` currently supported is `DNS`, to specify an
    alternative domain name.

*chown*

:   An optional `username[:groupname]` to chown the issued *certificate*
    and *certificate-chain* to.

*chmod*

:   An optional octal mode to chmod the issued *certificate* and
    *certificate-chain* to.

*notify*

:   Command to pass the the system's command shell (`/bin/sh -c`)
    after successful installation of the *certificate* and/or
    *certificate-chain*.

Examples
========

    ~$ sudo lacme account --register --tos-agreed mailto:noreply@example.com
    ~$ sudo lacme newOrder
    ~$ sudo lacme revokeCert /path/to/server/certificate.pem

See also
========

[`lacme-accountd`(1)]

[ACME]: https://tools.ietf.org/html/rfc8555
[`lacme-accountd`(1)]: lacme-accountd.1.html
[`iptables`(8)]: http://linux.die.net/man/8/iptables
[`ciphers`(1ssl)]: https://www.openssl.org/docs/manmaster/apps/ciphers.html
[`x509v3_config`(5ssl)]: https://www.openssl.org/docs/manmaster/apps/x509v3_config.html