You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
smallstep-certificates/docs/acme.md

162 lines
6.4 KiB
Markdown

# Using ACME with `step-ca `
Lets assume youve [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 youve [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.
Thats 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 CAs root certificate
Once certificates are issued, youll also need to ensure theyre renewed before
they expire.
### Pointing Clients at the right ACME Directory URL
Most ACME clients connect to Lets 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 CAs root certificate
Communication between an ACME client and server [always uses
HTTPS](https://tools.ietf.org/html/rfc8555#section-6.1). By default, clients
will validate the servers HTTPS certificate using the public root certificates
in your systems [default
trust](https://smallstep.com/blog/everything-pki.html#trust-stores) store.
Thats fine when youre connecting to Lets Encrypt: its a public CA and its
root certificate is in your systems default trust store already. Your internal
root certificate isnt, 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 systems default trust store (e.g.,
using [`step certificate
install`](https://smallstep.com/docs/cli/certificate/install/))
If youre using your CA for TLS in production, explicitly configuring your ACME
client to only trust your root certificate is a better option. Well
demonstrate this method with several clients below.
If youre simulating Lets 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 systems 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/), its 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.
Post feedback on [our GitHub Discussions tab](https://github.com/smallstep/certificates/discussions),
or [create a bug report issue](https://github.com/smallstep/certificates/issues/new?template=bug_report.md).