Add ACME CA capabilities
This commit is contained in:
parent
68ab03dc1b
commit
e3826dd1c3
54 changed files with 15687 additions and 184 deletions
160
docs/acme.md
Normal file
160
docs/acme.md
Normal file
|
@ -0,0 +1,160 @@
|
|||
# Using ACME with `step-ca `
|
||||
|
||||
Let’s assume you’ve [installed
|
||||
`step-ca`](https://smallstep.com/docs/getting-started/#1-installing-step-and-step-ca)
|
||||
(e.g., using `brew install step`), have it running at `https://ca.internal`,
|
||||
and you’ve [bootstrapped your ACME client
|
||||
system(s)](https://smallstep.com/docs/getting-started/#bootstrapping) (or at
|
||||
least [installed your root
|
||||
certificate](https://smallstep.com/docs/cli/ca/root/) at
|
||||
`~/.step/certs/root_ca.crt`).
|
||||
|
||||
## Enabling ACME
|
||||
|
||||
To enable ACME, simply [add an ACME provisioner](https://smallstep.com/docs/cli/ca/provisioner/add/) to your `step-ca` configuration
|
||||
by running:
|
||||
|
||||
```
|
||||
$ step ca provisioner add my-acme-provisioner --type ACME
|
||||
```
|
||||
|
||||
> NOTE: The above command will add a new provisioner of type `ACME` and name
|
||||
> `my-acme-provisioner`. The name is used to identify the provisioner
|
||||
> (e.g. you cannot have two `ACME` provisioners with the same name).
|
||||
|
||||
Now restart or SIGHUP `step-ca` to pick up the new configuration.
|
||||
|
||||
That’s it.
|
||||
|
||||
## Configuring Clients
|
||||
|
||||
To configure an ACME client to connect to `step-ca` you need to:
|
||||
|
||||
1. Point the client at the right ACME directory URL
|
||||
2. Tell the client to trust your CA’s root certificate
|
||||
|
||||
Once certificates are issued, you’ll also need to ensure they’re renewed before
|
||||
they expire.
|
||||
|
||||
### Pointing Clients at the right ACME Directory URL
|
||||
|
||||
Most ACME clients connect to Let’s Encrypt by default. To connect to `step-ca`
|
||||
you need to point the client at the right [ACME directory
|
||||
URL](https://tools.ietf.org/html/rfc8555#section-7.1.1).
|
||||
|
||||
A single instance of `step-ca` can have multiple ACME provisioners, each with
|
||||
their own ACME directory URL that looks like:
|
||||
|
||||
```
|
||||
https://{ca-host}/acme/{provisioner-name}/directory
|
||||
```
|
||||
|
||||
We just added an ACME provisioner named “acme”. Its ACME directory URL is:
|
||||
|
||||
```
|
||||
https://ca.internal/acme/acme/directory
|
||||
```
|
||||
|
||||
### Telling clients to trust your CA’s root certificate
|
||||
|
||||
Communication between an ACME client and server [always uses
|
||||
HTTPS](https://tools.ietf.org/html/rfc8555#section-6.1). By default, client’s
|
||||
will validate the server’s HTTPS certificate using the public root certificates
|
||||
in your system’s [default
|
||||
trust](https://smallstep.com/blog/everything-pki.html#trust-stores) store.
|
||||
That’s fine when you’re connecting to Let’s Encrypt: it’s a public CA and its
|
||||
root certificate is in your system’s default trust store already. Your internal
|
||||
root certificate isn’t, so HTTPS connections from ACME clients to `step-ca` will
|
||||
fail.
|
||||
|
||||
There are two ways to address this problem:
|
||||
|
||||
1. Explicitly configure your ACME client to trust `step-ca`'s root certificate, or
|
||||
2. Add `step-ca`'s root certificate to your system’s default trust store (e.g.,
|
||||
using `[step certificate
|
||||
install](https://smallstep.com/docs/cli/certificate/install/)`)
|
||||
|
||||
If you’re using your CA for TLS in production, explicitly configuring your ACME
|
||||
client to only trust your root certificate is a better option. We’ll
|
||||
demonstrate this method with several clients below.
|
||||
|
||||
If you’re simulating Let’s Encrypt in pre-production, installing your root
|
||||
certificate is a more faithful simulation of production. Once your root
|
||||
certificate is installed, no additional client configuration is necessary.
|
||||
|
||||
> Caution: adding a root certificate to your system’s trust store is a global
|
||||
> operation. Certificates issued by your CA will be trusted everywhere,
|
||||
> including in web browsers.
|
||||
|
||||
### Example using [`certbot`](https://certbot.eff.org/)
|
||||
|
||||
[`certbot`](https://certbot.eff.org/) is the grandaddy of ACME clients. Built
|
||||
and supported by [the EFF](https://www.eff.org/), it’s the standard-bearer for
|
||||
production-grade command-line ACME.
|
||||
|
||||
To get a certificate from `step-ca` using `certbot` you need to:
|
||||
|
||||
1. Point `certbot` at your ACME directory URL using the `--`server flag.
|
||||
2. Tell `certbot` to trust your root certificate using the `REQUESTS_CA_BUNDLE` environment variable.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
$ sudo REQUESTS_CA_BUNDLE=$(step path)/certs/root_ca.crt \
|
||||
certbot certonly -n --standalone -d foo.internal \
|
||||
--server https://ca.internal/acme/acme/directory
|
||||
```
|
||||
|
||||
`sudo` is required in `certbot`'s [*standalone*
|
||||
mode](https://certbot.eff.org/docs/using.html#standalone) so it can listen on
|
||||
port 80 to complete the `http-01` challenge. If you already have a webserver
|
||||
running you can use [*webroot*
|
||||
mode](https://certbot.eff.org/docs/using.html#webroot) instead. With the
|
||||
[appropriate plugin](https://certbot.eff.org/docs/using.html#dns-plugins)
|
||||
`certbot` also supports the `dns-01` challenge for most popular DNS providers.
|
||||
Deeper integrations with [nginx](https://certbot.eff.org/docs/using.html#nginx)
|
||||
and [apache](https://certbot.eff.org/docs/using.html#apache) can even configure
|
||||
your server to use HTTPS automatically (we'll set this up ourselves later). All
|
||||
of this works with `step-ca`.
|
||||
|
||||
You can renew all of the certificates you've installed using `cerbot` by running:
|
||||
|
||||
```
|
||||
$ sudo REQUESTS_CA_BUNDLE=$(step path)/certs/root_ca.crt certbot renew
|
||||
```
|
||||
|
||||
You can automate renewal with a simple `cron` entry:
|
||||
|
||||
```
|
||||
*/15 * * * * root REQUESTS_CA_BUNDLE=$(step path)/certs/root_ca.crt certbot -q renew
|
||||
```
|
||||
|
||||
The `certbot` packages for some Linux distributions will create a `cron` entry
|
||||
or [systemd
|
||||
timer](https://stevenwestmoreland.com/2017/11/renewing-certbot-certificates-using-a-systemd-timer.html)
|
||||
like this for you. This entry won't work with `step-ca` because it [doesn't set
|
||||
the `REQUESTS_CA_BUNDLE` environment
|
||||
variable](https://github.com/certbot/certbot/issues/7170). You'll need to
|
||||
manually tweak it to do so.
|
||||
|
||||
More subtly, `certbot`'s default renewal job is tuned for Let's Encrypt's 90
|
||||
day certificate lifetimes: it's run every 12 hours, with actual renewals
|
||||
occurring for certificates within 30 days of expiry. By default, `step-ca`
|
||||
issues certificates with *much shorter* 24 hour lifetimes. The `cron` entry
|
||||
above accounts for this by running `certbot renew` every 15 minutes. You'll
|
||||
also want to configure your domain to only renew certificates when they're
|
||||
within a few hours of expiry by adding a line like:
|
||||
|
||||
```
|
||||
renew_before_expiry = 8 hours
|
||||
```
|
||||
|
||||
to the top of your renewal configuration (e.g., in `/etc/letsencrypt/renewal/foo.internal.conf`).
|
||||
|
||||
## Feedback
|
||||
|
||||
`step-ca` should work with any ACMEv2
|
||||
([RFC8555](https://tools.ietf.org/html/rfc8555)) compliant client that supports
|
||||
the http-01 or dns-01 challenge. If you run into any issues please let us know
|
||||
[on gitter](https://gitter.im/smallstep/community) or [in an
|
||||
issue](https://github.com/smallstep/certificates/issues/new?template=bug_report.md).
|
Loading…
Add table
Add a link
Reference in a new issue