diff --git a/step-ca/provisioners.mdx b/step-ca/provisioners.mdx index e9e9de83..f514566e 100644 --- a/step-ca/provisioners.mdx +++ b/step-ca/provisioners.mdx @@ -60,47 +60,66 @@ Azure | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 GCP | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫

- By design, SSH user certificates cannot be renewed by any provisioner. You can re-use the same key to get a new certificate, however. See [smallstep/discussions#1296](https://github.com/smallstep/certificates/discussions/1296). - Privileged OIDC subject names can generate Host SSH Certificates. These can be configured in the OIDC provisioner. -For an example of how to interpret this table, let's take the `JWK` provisioner. -The `JWK` provisioner is capable of signing, renewing, and revoking X.509 -certificates, as well signing user and host SSH certificates. A `JWK` provisioner -_cannot_ renew or rekey SSH certificates. +**Notes:** + +By design, SSH user certificates cannot be renewed by any provisioner. +However, you can re-use the same key to get a new certificate. +See [smallstep/discussions#1296](https://github.com/smallstep/certificates/discussions/1296). + + +Privileged OIDC subject names can generate Host SSH Certificates, +and can be configured in the OIDC provisioner. + -An `SSHPOP` provisioner _can_ revoke and rekey SSH certificates and renew SSH host -certificates. An `SSHPOP` provisioner _cannot_ sign, renew, or revoke X.509 -certificates, and it _cannot_ sign SSH user and host certificates or renew SSH -user certificates. +To illustrate how to interpret this table, let's take the `JWK` and `SSHPOP` provisioner. + +A `JWK` provisioner _can_ sign, renew, and revoke X.509 certificates, as well as sign user and host SSH certificates. +However, it _cannot_ renew SSH user certificates. + +On the other hand, an `SSHPOP` provisioner _can_ revoke and rekey SSH certificates +and renew SSH host certificates. +However, it _cannot_ sign, renew, or revoke X.509 certificates. +Additionally, it _cannot_ sign SSH user and host certificates or renew SSH user certificates. It's important to understand the capabilities and limitations when selecting a provisioner for a given workload. ## Provisioner Management +By default, provisioner configurations reside in the `$(step path)/config/ca.json` file. +However, if Remote Provisioner Management is enabled, +provisioner configurations are stored in [the database](./configuration/#databases) instead of `ca.json`, +while the global CA configuration remains in `ca.json`. + +Remote Provisioner Management is ideal if you have multiple CA administrators, +[run several load-balanced](./certificate-authority-server-production.mdx#load-balancing-or-proxying-step-ca-traffic) `step-ca` instances, +or if you want to manage your provisioners remotely (eg. with Infrastructure as Code (IaC) tools; [see below](#unattended-remote-provisioner-management)). +See [Remote Provisioner Management](#remote-provisioner-management) for more info on tradeoofs and benefits. -Use the [`step ca provisioner`](../step-cli/reference/ca/provisioner) command group to add, remove, or modify provisioner configurations. Run these commands directly on your CA machine. They need to modify the `$(step path)/config/ca.json` configuration file. +The [`step ca provisioner`](../step-cli/reference/ca/provisioner) command group are used for provisioner management. +They can be used to add, remove, or modify provisioner configurations. +Note, you must run these commands directly on your CA machine, +as they need to modify the `$(step path)/config/ca.json` configuration file. + +When you run any step ca provisioner command, it will try to detect where the provisioner configuration is stored. +It will either modify the `ca.json` file or it will update the database, +depending on whether you have enabled Remote Provisioner Management.
-

May I edit ca.json directly?

-

You may edit your ca.json configuration file directly, but we strongly recommend using step ca provisioner commands instead. -Fields in ca.json may be encoded differently than you expect.

-
+

May I edit ca.json directly?

+

You may edit your ca.json configuration file directly, + but we strongly recommend using step ca provisioner commands instead. + Fields in ca.json may be encoded differently than you expect. +

+
-Some provisioner options override global defaults for your CA. -For a list of global options, see the [configuration guide](./configuration.mdx) section for the `authority` configuration block. - -A remote provisioner management API can be enabled in `step-ca`. -It is disabled by default. -With remote provisioner management, the CA's provisioner configuration is stored in the database instead of `ca.json`. (The global CA configuration remains in `ca.json`.) - -This feature can be useful if you -have multiple CA administrators, -[run several load-balanced](./certificate-authority-server-production.mdx#load-balancing-or-proxying-step-ca-traffic) `step-ca` instances, -or if you want to manage your provisioners remotely (eg. with Infrastructure as Code (IaC) tools; [see below](#unattended-remote-provisioner-management)). - -See [Remote Provisioner Management](#remote-provisioner-management) for more. +Within `ca.json` you can define an optional `claims` property for each provisioner. +The settings defined in the `claims` property of individual provisioners under an authority +override the global defaults set for that authority. +For a list of global options, +see the `claims` object under the authority configuration block in the [configuration guide](./configuration/#example-configuration). ### Common Provisioner Operations @@ -111,7 +130,9 @@ Common provisioner operations include: - [Listing all provisioner](#list-all-provisioners) - [Modifying the configuration of an existing provisioner](#modify-a-provisioner) -Unless you are using [remote provisioner management](#remote-provisioner-management), you must send a `SIGHUP` signal, or restart the `step-ca` process, for changes to your provisioner configuration to take effect. +If you are not using [remote provisioner management](#remote-provisioner-management), +you must either restart the `step-ca` process +or send a `SIGHUP` signal to apply changes to your provisioner configuration. #### Add a provisioner @@ -131,8 +152,9 @@ Use [`step ca provisioner remove`](../step-cli/reference/ca/provisioner/remove) step ca provisioner remove acme ``` -You can also edit the `ca.json` configuration file and remove the entire block -containing the provisioner you'd like to remove. +Alternatively, +you can edit the `ca.json` configuration file, +and remove the entire block containing the provisioner you'd like to remove. #### List all provisioners @@ -140,7 +162,7 @@ To get a list of all of your current provisioners, use [`step ca provisioner lis #### Modify a provisioner -Use [`step ca provisioner update`](../step-cli/reference/ca/provisioner/update) to update provisioner configurations: +Use [`step ca provisioner update`](../step-cli/reference/ca/provisioner/update) to update provisioner configurations: ```bash step ca provisioner update acme \ @@ -149,20 +171,21 @@ step ca provisioner update acme \ --x509-default-dur=36h ``` -In this example we've modified the minumum, maximum, and default durations for TLS certificates generated by this provisioner. +The example above modifies the minumum, maximum, and default durations for X.509 certificates generated by the provisioner. +However, the `update` command can be used to modify the lifetimes, extensions, and templates of both X.509 and SSH certificates. -Provisioner configuration can be used to affect X.509 and SSH certificate lifetimes, extensions, and templates. -There are some provisioner-specific options, -which are covered by the documentation for each provisioner type, below. +Additionally, there are some provisioner-specific options, +which are covered by the [documentation for each provisioner type](./provisioners/#provisioner-types). ## Remote Provisioner Management **This feature is disabled by default.** -When remote provisioner management is enabled, your provisioner configuration is -stored in the database, rather than in `ca.json`. -Provisioner configuration is managed by running [`step ca provisioner`](../step-cli/reference/ca/provisioner) commands locally or remotely. -These commands require you to sign in as an Admin user. +When remote provisioner management is enabled, +your provisioner configuration is stored in the database instead of in ca.json. +You can manage the provisioner configuration by running [`step ca provisioner`](../step-cli/reference/ca/provisioner) commands, +either locally or remotely. +However, ***you must sign in as an Admin user***. ### Enable Remote Provisioner Management @@ -175,7 +198,7 @@ To enable remote provisioner management on a new CA, pass `--remote-management` #### On an Existing CA -To migrate your `ca.json` provisioners to the database, and to enable remote provisioner management on an existing CA: +To enable remote provisioner management on an existing CA and migrate your `ca.json` provisioners to the database: 1. Stop `step-ca` if it is running. 2. Update your `"authority"` block in `ca.json` to include the following: @@ -194,11 +217,12 @@ To migrate your `ca.json` provisioners to the database, and to enable remote pro When `step-ca` starts up, it will: * Migrate the provisioners from your `ca.json` to the database - * Repurpose the first JWK provisioner in your `ca.json` as an administrative provisioner. If no JWK provisioner exists, it will add a [JWK](#jwk) provisioner called Admin JWK to the database. You will be prompted for a password that will encrypt the new provisioner key. + * Repurpose the first JWK provisioner in your `ca.json` as an administrative provisioner. +If no JWK provisioner exists, it will add a [JWK](#jwk) provisioner called Admin JWK to the database. You will be prompted for a password that will encrypt the new provisioner key. * Create an initial Super Admin user, with username `step`, and link it to the administrative provisioner. 4. Remove old provisioner configurations from `ca.json`. - Once your provisioners are migrated to the database, the provisioners in `ca.json` are ignored and you can remove them from that file: + Once your provisioners are migrated to the database, the provisioners in `ca.json` are ignored and you can remove them: ```json "authority": { @@ -209,15 +233,16 @@ To migrate your `ca.json` provisioners to the database, and to enable remote pro ### Managing Admin Users -With remote provisioner management, -"Admins" can remotely manage provisioners. -"Super Admins" are Admins that can also manage the list of Admins for the CA using [`step ca admin`](../step-cli/reference/ca/admin). +With remote provisioner management, there are two categories of admin users: "Admins" and "Super Admins". + +"Admins" can remotely manage provisioners. +Then, "Super Admins" are Admins that can also manage the list of Admins for the CA using [`step ca admin`](../step-cli/reference/ca/admin). #### Create An Admin User -To perform CA administrative operations, you sign into that provisioner as an Admin. +To perform CA administrative operations, you must sign into that provisioner as an Admin. -As a Super Admin, lets create an Admin user linked to the Admin JWK provisioner: +As a Super Admin, you can create an Admin user linked to the Admin JWK provisioner: ```bash step ca admin add carl "Admin JWK" @@ -241,13 +266,15 @@ An administrator is just a subject name and a provisioner name. You can authenticate as an administrator via the authentication scheme of the provisioner. For example, for the default JWK provisioner, running administrative commands in `step` will prompt for the provisioner password. -**Tip: Single Sign-On can be used for Admin users.** -To enable SSO CA administration, first add an [OIDC provisioner](#oauthoidc-single-sign-on) linked to your identity provider. -Then, add an Admin user associated with that provisioner, using your email address as the Admin's subject name. +***Tip: Single Sign-On (SSO) can be used for Admin users.*** +To enable CA administration via SSO, follow these steps: -The Admin and Super Admin privileges **are not scoped to a provisioner**: -Admins can modify any provisioner configurations. -Super Admins are Admins that can also modify Admins, regardless of provisioner. +1. Add an [OIDC provisioner](#oauthoidc-single-sign-on) linked to your identity provider. +2. Create an Admin user associated with that provisioner, using your email address as the Admin's subject name. + +It's important to note that the Admin and Super Admin privileges **are not scoped to a specific provisioner**. +Both Admins and Super Admins have the ability to modify configurations for any provisioner. +Then, Super Admins have the additional capability to modify Admins, regardless of the provisioner they are associated with. ### Use Remote Provisioner Management @@ -255,16 +282,15 @@ You're all set. 🎉 You can use the [`step ca provisioner`](../step-cli/reference/ca/provisioner) commands, from any client, to modify your CA's provisioner configuration. -#### Unattended Remote Provisioner Management +### Unattended Remote Provisioner Management -If you want to manage provisioners remotely using a script or an Infrastructure as Code (IaC) tool, -you will need an _administrative certificate_ and key. +To manage provisioners remotely using a script or an Infrastructure as Code (IaC) tool, +you need an _administrative certificate_ and key. An administrative certificate must meet the following criteria: - The Subject (or any SAN) must match the name of an Admin or Super Admin. - The certificate must be issued by the provisioner of the Admin or Super Admin. -- The certificate must be valid and unexpired. -- A passively revoked certificate is valid until it expires; for immediate revocation, remove the admin instead of revoking the certificate. +- The certificate must be valid and unexpired. A passively revoked certificate is valid until it expires; for immediate revocation, remove the admin instead of revoking the certificate. To create an admin certificate, run: @@ -282,7 +308,7 @@ Please enter the password to decrypt the provisioner key: ✔ Private Key: admin.key ``` -With that certificate, you can use it as follows: +Then, use that certificate as follows: ```bash step ca provisioner add ... --admin-cert=admin.crt --admin-key=admin.key @@ -299,14 +325,14 @@ step ca admin add ... --admin-cert=admin.crt --admin-key=admin_key ### JWK -JWK is the default provisioner type. It uses public-key cryptography to sign and +JWK is the default provisioner type. +It uses public-key cryptography to sign and validate a JSON Web Token (JWT). -The [`step`](https://github.com/smallstep/cli) CLI tool will create a JWK provisioner when [`step ca init`](../step-cli/reference/ca/init) is used. - -#### Example +Whenever you run [`step ca init`](../step-cli/reference/ca/init), +the [`step`](https://github.com/smallstep/cli) CLI tool creates a JWK provisioner. -Add a JWK provisioner: +#### Create a JWK provisioner: ```shell step ca provisioner add you@smallstep.com --create @@ -350,9 +376,14 @@ In the ca.json configuration file, a complete JWK provisioner example looks like } ``` -- **type**: for a JWK provisioner it must be `JWK`, this field is case insensitive. +Here's what each property stands for: -- **name**: identifies the provisioner, a good practice is to use an email address or a descriptive string that allows the identification of the owner, but it can be any non-empty string. +- **type**: is a case insensitive field that defines the provisioner type. For a JWK provisioner it must be `JWK`. + +- **name**: identifies the provisioner. +It is recommended to use an email address +or a descriptive string that allows for easy identification of the owner. +However, any non-empty string works. - **key**: is the JWK (JSON Web Key) representation of a public key used to validate a signed token. @@ -362,7 +393,6 @@ It's a JWE compact string containing the JWK representation of the private key. This value is not necessary for CA operation, but is provided for the convenience of clients. Without the `encryptedKey` attribute, the private key must be provided by the client, using the `--key` flag. - - **claims**: overwrites the default claims set in the authority. See [claims](configuration.mdx#claims) for details. @@ -375,7 +405,7 @@ See [claims](configuration.mdx#claims) for details. #### Decrypting the private key -We can use [`step crypto jwe decrypt`](../step-cli/reference/crypto/jwe/decrypt) to see the private key encrypted with the password `asdf`: +You can use [`step crypto jwe decrypt`](../step-cli/reference/crypto/jwe/decrypt) to see the private key encrypted with the password `asdf`:
Why is the OAuth client secret unprotected? - -When using the OIDC provisioner, you may notice that your OAuth client secret is visible to anyone via the CA's /provisioners API endpoint. +When using the OIDC provisioner, +you may notice that your OAuth client secret is visible to anyone via the CA's /provisioners API endpoint. Counterintuitively, this a secure implementation of OAuth that conforms to the OAuth Best Current Practices for Native Apps (RFC8252 / IETF BCP212). -And it is the same approach that Google's gcloud CLI tool uses for Google Cloud Platform authentication: An OAuth client secret is hardcoded into its source code. +And it is the same approach that Google's gcloud CLI tool uses for Google Cloud Platform authentication: +An OAuth client secret is hardcoded into its source code. So, what makes it secure? -The Authorization Code flow for native OAuth apps requires the redirect URI hostname be hardcoded as `127.0.0.1` (or `localhost`) in the client configuration. -This constraint obviates the need for a client secret, because the loopback address is inherently resistant to network attacks that the client secret is designed to mitigate in other, non-native app flows. + +The Authorization Code flow for native OAuth apps +requires the redirect URI hostname be hardcoded as `127.0.0.1` (or `localhost`) in the client configuration. +This constraint obviates the need for a client secret, +because the loopback address is inherently resistant to network attacks +that the client secret is designed to mitigate in other, non-native app flows. An attacker in posession of the client secret would need local access to your device in order to compromise the flow. -OAuth in general is not very resistant to local attacks, so the threat model for the native app flow with an exposed client secret is the same as with any other OAuth flow: -It assumes that if you have a local attacker on your device, it's unlikely that this kind of attack is going to be your biggest threat. +In general, OAuth is not very resistant to local attacks, +so the threat model for the native app flow with an exposed client secret is the same as with any other OAuth flow: +It assumes that if you have a local attacker on your device, +it's unlikely that this kind of attack is going to be your biggest threat. The client secret is superfluous in the Authorization Code flow for native apps. -In fact, BCP212 has recommended that OAuth identity providers offer a special OAuth client type that has no client secret. +BCP212 recommends that OAuth identity providers offer a special OAuth client type that has no client secret. In practice, very few OAuth providers have implemented this "secretless" approach, so we don't yet support it. -Functionally, however, it is equivalent to having a public secret. +However, functionally, it is equivalent to having a public secret. Bottom line, the OAuth flow implemented in `step` and `step-ca` is widely vetted and considered secure.
@@ -671,32 +720,37 @@ Bottom line, the OAuth flow implemented in `step` and `step-ca` is widely vetted ### X5C - X.509 Certificate -With the X5C provisioner, a client can authenticate a certificate request -using an existing X.509 certificate. Configure this provisioner with a root -CA certificate, and any certificate bundle that chains up to that root can +With the X5C provisioner, +a client can authenticate a certificate request using an existing X.509 certificate. +Configure this provisioner with a root CA certificate, +and any certificate bundle that chains up to that root can be used in a certificate request. +Here are some things to keep in mind when using an X5C provisioner: + - Clients may request an X.509 or SSH certificate - Clients must provide an X.509 certificate bundle whose root is trusted by the provisioner -- Clients sign their request with the certificate private key +- Clients must sign their request with the certificate private key - The validity period of the new certificate must fall within the validity period of the certificate used to authenticate the request -The X5C provisioner uses X5C tokens for authentication. An X5C token is a JWT, signed by the certificate private key, with an `x5c` header that contains the certificate bundle. +The X5C provisioner uses X5C tokens for authentication. +An X5C token is a JWT, signed by the certificate private key, +with an `x5c` header that contains the certificate bundle. + +#### Create an X5C provisioner -#### Example +To create an X5C provisioner, there are have two options: -If you would like any certificate signed by `step-ca` to become a provisioner -(have the ability to request new certificates with any name), -you can create an X5C provisioner using the root certificate used by -`step-ca`, like so: +You can use the root certificate used by `step-ca`. This way, any certificate signed by `step-ca` can become a provisioner, +and have the ability to request new certificates with any name. Run: ```shell step ca provisioner add x5c-smallstep --type X5C --x5c-root $(step path)/certs/root_ca.crt ``` -Or, you can configure the X5C provisioner with an outside root, granting provisioner -capabilities to a completely separate PKI. +Alternatively, you can configure the X5C provisioner with an outside root. +But beware, this grants provisioner capabilities to a completely separate PKI. Below is an example of an X5C provisioner in the `ca.json`: @@ -721,6 +775,7 @@ Below is an example of an X5C provisioner in the `ca.json`: } } ``` +And here's what each property stands for: * **type**: indicates the provisioner type and must be `X5C`. @@ -738,8 +793,8 @@ see the [claims](configuration.mdx#claims) section for all the options.
- By default, the `X5C` provisioner will issue a certificates for any Subject names. - If you want to limit or modify the subject names this provisioner will issue, + By default, the `X5C` provisioner will issue certificates for any Subject names. + If you wish to restrict or modify the subject names that this provisioner can issue, you can use a certificate template. For example, say your users will use the X5C provisioner to exchange an X.509 client certificate for an SSH user certificate. @@ -766,25 +821,35 @@ see the [claims](configuration.mdx#claims) section for all the options. **This is an experimental feature.** -If you have a [Nebula overlay network](https://nebula.defined.net/docs/), you can create a Nebula provisioner and configure it with your Nebula root CA certificate. -Clients can then use their Nebula client certificate and private key to request an X.509 or SSH host certificate from `step-ca`. -The Nebula certificate they use for authentication must be issued by the Nebula root CA configured in the provisioner. +If you have a [Nebula overlay network](https://nebula.defined.net/docs/), +you can create a Nebula provisioner, +and configure it with your Nebula root CA certificate. +Clients can then use their Nebula client certificate +and private key to request an X.509 or SSH host certificate from `step-ca`. +However, the Nebula certificate used for authentication +must be issued by the Nebula root CA that is configured in the provisioner. -The Nebula client certificate is used for authorization, too: -The client is allowed to request an X.509 or SSH host certificate with the `name` or any of the `ips` appearing on the Nebula client certificate. +The Nebula client certificate can be used for authorization too. +The client is allowed to request an X.509 or SSH host certificate +with the `name` or any of the `ips` appearing on the Nebula client certificate. To be clear, Nebula certificates can contain a single `name` and a list of `ips`. The `name` field is often a DNS hostname, but it could be an email, IP, or URI. And `ips` contains a list of CIDR blocks. -In `step-ca`, the Nebula provisioner will authorize certificate subjects or SANs that include the `name`, plus IPs in any of the CIDR blocks in `ips` on the Nebula certificate. -To get started, create a Nebula provisioner: +In `step-ca`, the Nebula provisioner will authorize certificate subjects or SANs +that include the `name`, plus IPs in any of the CIDR blocks in `ips` on the Nebula certificate. + +#### Create a Nebula Provisioner +To create a Nebula provisioner, run: ```shell step ca provisioner add --type Nebula --nebula-root /etc/nebula/ca.crt ``` -Now you can get an X509 certificate with the Nebula provisioner, using a Nebula client certificate. Here's an example using the DNS name `host3.example.com`, and two IPs: +Now you can get an X509 certificate with the Nebula provisioner, +using a Nebula client certificate. +Here's an example using the DNS name `host3.example.com`, and two IPs: ```shell step ca certificate host3.example.com host3.crt host3.key \ @@ -797,8 +862,8 @@ step ca certificate host3.example.com host3.crt host3.key \ ### SSHPOP - SSH Certificate An SSHPOP provisioner allows a client to renew, revoke, or rekey an SSH -certificate using that certificate for authentication with the CA. -The renew and rekey methods can only be used on SSH host certificates. +certificate using same SSH certificate for authentication with the CA. +However, the renew and rekey operations are limited to SSH host certificates only. An SSHPOP provisioner is configured with the user and host root ssh certificates from the `ca.json`. The SSHPOP provisioner can only authenticate SSHPOP tokens @@ -807,18 +872,18 @@ generated using SSH certificates created by `step-ca`. An SSHPOP token is a JWT, signed by the certificate private key, with an `sshpop` header that contains the SSH certificate. -When configured with the `--ssh` option (`step ca init --ssh`), the CA -will contain a default SSHPOP provisioner named `sshpop`. +When configured with the `--ssh` option (i.e, `step ca init --ssh`), +the CA will contain a default SSHPOP provisioner named `sshpop`. -#### Example +#### Create an SSHPOP provisioner: -Add an SSHPOP provisioner: +To create an SSHPOP provisioner, run: ```shell step ca provisioner add sshpop --type SSHPOP ``` -An example SSHPOP provisioner in the `ca.json`: +Here's an example SSHPOP provisioner in `ca.json`: ```json ... @@ -835,6 +900,7 @@ An example SSHPOP provisioner in the `ca.json`: } } ``` +And, here's what each property stands for: * **type**: indicates the provisioner type and must be `SSHPOP`. @@ -850,19 +916,25 @@ see the [claims](configuration.mdx#claims) section for all the options. ### ACME -The [ACME Protocol](https://tools.ietf.org/html/rfc8555) can authenticate Certificate Signing Requests (CSRs) in a way that enables automation. +The [ACME Protocol](https://tools.ietf.org/html/rfc8555) can authenticate Certificate Signing Requests (CSRs) +in a way that enables automation. + +ACME clients must answer challenges presented by the ACME server +to prove to the CA that they control the identifiers listed in the CSR. +ACME supports four different types of challenges: `http-01`, `dns-01`, `tls-alpn-01`, and `device-attest-01`. +These are designed for operability in different environments. -ACME clients must answer challenges presented by the ACME server to prove to the CA that they control the identifiers listed in the CSR. -ACME supports four different types of challenges: `http-01`, `dns-01`, `tls-alpn-01`, and `device-attest-01`. These are designed for operability in different environments. See [ACME Basics](./acme-basics.mdx#acme-challenges) for a description of each challenge type and their tradeoffs. -In a typical setup, an ACME server might issue server certificates via the `http-01`, `dns-01`, `tls-alpn-01` challenge types, and client certificates via the `device-attest-01` challenge type. +In a typical setup, +an ACME server might issue server certificates via the `http-01`, `dns-01`, `tls-alpn-01` challenge types, +and client certificates via the `device-attest-01` challenge type. The ACME provisioner in `step-ca` supports issuing X.509 certificates using IP, hostname, and device identifiers. -#### Example +#### Create an ACME provisioner -Add an ACME provisioner: +To add an ACME provisioner: ```shell step ca provisioner add acme --type ACME @@ -902,6 +974,8 @@ An example of an ACME provisioner in the `ca.json`: } ``` +And, here's what each property stands for: + * **type**: indicates the provisioner type and must be `ACME`. * **name**: a string used to identify the provider when the CLI is @@ -941,7 +1015,10 @@ for more guidance on configuring and using the ACME protocol with `step-ca`.
-The `device-attest-01` challenge supports device attestations from iOS, iPadOS, tvOS, and YubiKeys. An attestation certificate is used to satisfy the ACME challenge. The CSR may include a device ID in a `permanentIdentifier` SAN ([RFC 4043](https://www.rfc-editor.org/rfc/rfc4043.html)), depending on the application. +The `device-attest-01` challenge supports device attestations from iOS, iPadOS, tvOS, and YubiKeys. +An attestation certificate is used to satisfy the ACME challenge. +The CSR may include a device ID in a `permanentIdentifier` SAN ([RFC 4043](https://www.rfc-editor.org/rfc/rfc4043.html)), +depending on the application. ##### Managed Device Attestation for Apple Devices @@ -962,13 +1039,13 @@ step ca provisioner add acme-da \ -In your Apple MDM profile, you will need: +In your Apple MDM profile, you need: * A [`CertificateRoot`](https://developer.apple.com/documentation/devicemanagement/certificateroot) payload, containing your root CA certificate PEM block, so that it's trusted by the device. * An [`ACMECertificate`](https://developer.apple.com/documentation/devicemanagement/acmecertificate) payload. For this one, set the `ClientIdentifier` to the UDID or serial number of the device. ##### Device Attestation for YubiKeys -To add a `device-attest-01` provisioner for YubiKey devices, run: +To create a `device-attest-01` provisioner for YubiKey devices, run: ```bash step ca provisioner add acme-da \ @@ -1014,19 +1091,24 @@ To get a client certificate for a hardware-bound private key on your YubiKey: ### SCEP -The SCEP provisioner can sign and renew certificates using the SCEP protocol ([RFC8894](https://datatracker.ietf.org/doc/html/rfc8894)). -SCEP is very popular for use in network equipment and mobile device management (MDM). -It runs over HTTP using POSTed binary data or base64-encoded GET parameters, -using CMS (PKCS#7) and CSR (PKCS#10) data formats. -A (shared) secret authenticates clients to the CA. +The SCEP provisioner can sign and renew certificates +using the Simple Certificate Enrollment Protocol SCEP protocol (SCEP) ([RFC8894](https://datatracker.ietf.org/doc/html/rfc8894)). +SCEP is commonly used for certificate management +in network equipment and mobile device management (MDM). +It runs over HTTP and uses POSTed binary data or base64-encoded GET parameters, +with CMS (PKCS#7) and CSR (PKCS#10) data formats, +and clients are authenticated to the CA using a shared secret. #### Requirements -Your CA must use an RSA intermediate CA, even if your client supports ECDSA. +To create a SCEP provisioner on your CA, +your CA must use an RSA intermediate CA, +even if your client supports ECDSA. The RSA intermediate is used to decrypt the contents of the SCEP `pkcsPKIEnvelope` containing the certificate request. This operation cannot be performed using an ECDSA key. -Because [`step ca init`](../step-cli/reference/ca/init) creates an ECDSA chain by default, you will need to [convert your CA to use an RSA CA chain](../tutorials/rsa-chain.mdx) before using the SCEP provisioner. +[`step ca init`](../step-cli/reference/ca/init) creates an ECDSA chain by default, +so you must [convert your CA to use an RSA CA chain](../tutorials/rsa-chain.mdx) before using the SCEP provisioner.
@@ -1037,9 +1119,9 @@ Because [`step ca init`](../step-cli/reference/ca/init) creates an ECDSA chain b
-#### Configure the Provisioner +#### Configure the SCEP Provisioner -In this example, we will add a SCEP provisioner using challenge secret `secret1234` and `AES-256-CBC` as the [encryption algorithm](https://github.com/smallstep/pkcs7/blob/33d05740a3526e382af6395d3513e73d4e66d1cb/encrypt.go#L63): +In this example, the command below adds a SCEP provisioner using challenge secret `secret1234` and `AES-256-CBC` as the [encryption algorithm](https://github.com/smallstep/pkcs7/blob/33d05740a3526e382af6395d3513e73d4e66d1cb/encrypt.go#L63): ```shell step ca provisioner add my_scep_provisioner \ @@ -1063,15 +1145,19 @@ Here's an example of a SCEP provisioner in `$(step path)/config/ca.json`: } ``` -- The `forceCN` parameter is optional. -It behaves the same as `forceCN` in the ACME provisioner, and it defaults to false. -- `challenge` is the secret shared between the provisioner and SCEP clients. By default no secret is used. -- The `minimumPublicKeyLength` parameter can be used to set the minimum length of public keys submitted by a client. Defaults to 2048. -- When `includeRoot` is set to true, the root CA certificate will be returned in responses to `GetCACert` requests in addition to the intermediate CA certificate. This option was added to support a specific use case for the macOS SCEP client (see [certificates#746](https://github.com/smallstep/certificates/issues/746) for more details). Defaults to false. -- The `encryptionAlgorithmIdentifier` parameter can be used to change the [encryption algorithm](https://github.com/smallstep/pkcs7/blob/33d05740a3526e382af6395d3513e73d4e66d1cb/encrypt.go#L63) used for encrypting the request content. Defaults to 0: `DES-CBC` for legacy compatibility. +And, here's what each property stands for: -If you don't want to rely on a single, static secret, you can [configure a `SCEPCHALLENGE` webhook](./webhooks.mdx#x509-request-body) instead. -When a SCEP client requests a certificate, the webhook server will receive a request with the `scepChallenge` and `scepTransactionID` properties from the SCEP request. +- **`forceCN`**: parameter is optional. +It behaves the same as `forceCN` in the ACME provisioner, and it defaults to false. +- **`challenge`**: is the secret shared between the provisioner and SCEP clients. By default no secret is used. +- **`minimumPublicKeyLength`**: parameter can be used to set the minimum length of public keys submitted by a client. Defaults to 2048. +- **`includeRoot`**: is set to true, the root CA certificate will be returned in responses to `GetCACert` requests in addition to the intermediate CA certificate. This option was added to support a specific use case for the macOS SCEP client (see [certificates#746](https://github.com/smallstep/certificates/issues/746) for more details). Defaults to false. +- **`encryptionAlgorithmIdentifier`**: parameter can be used to change the [encryption algorithm](https://github.com/smallstep/pkcs7/blob/33d05740a3526e382af6395d3513e73d4e66d1cb/encrypt.go#L63) used for encrypting the request content. Defaults to 0: `DES-CBC` for legacy compatibility. + +If you don't want to rely on a single, static secret, +you can [configure a `SCEPCHALLENGE` webhook](./webhooks.mdx#x509-request-body) instead. +When a SCEP client requests a certificate, +the webhook server will receive a request with the `scepChallenge` and `scepTransactionID` properties from the SCEP request. The webhook server can then decide if the request is allowed or not. #### Enable the HTTP Server @@ -1101,27 +1187,28 @@ A K8sSA provisioner allows a client to request a certificate from the server using a Kubernetes Service Account Token. As of the time when this provisioner was coded, the Kubernetes Service Account -API for retrieving the token from a running instance was still in beta. Therefore, +API for retrieving a token from a running instance was still in beta. Therefore, our K8sSA provisioner must be configured with the public key that will be used to validate K8sSA tokens. -K8sSA tokens are very minimal. There is no place for SANs, or other details that -a user may want validated in a CSR. It is essentially a bearer token. Therefore, -at this time a K8sSA token can be used to sign a CSR with any SANs. Said -differently, the **K8sSA provisioner does little to no validation on the CSR +K8sSA (Kubernetes Service Account) tokens can only hold very minimal information, +and do not provide a place to specify SANs or other details +that users may want validated in a Certificate Signing Request (CSR). +This means that a K8sSA token can be used to sign a CSR with any SANs, +as the **K8sSA provisioner does little to no validation on the CSR before signing it**. You should only configure and use this provisioner if you know what you are doing. If a malicious user obtains the private key they will -be able to create certificates with any SANs and Subject. +be able to create certificates with any SANs or Subject. -#### Example +#### Create a K8sSA provisioner -Add a K8sSA provsioner: +To add a K8sSA provsioner, run: ```shell step ca provisioner add my-kube-provisioner --type K8sSA --pem-keys key.pub ``` -An example of a K8sSA provisioner in the `ca.json`: +Here's an example of a K8sSA provisioner in the `ca.json`: ```json ... @@ -1140,6 +1227,7 @@ An example of a K8sSA provisioner in the `ca.json`: } } ``` +And, here's what each property stands for: * **type**: indicates the provisioner type and must be `K8sSA`. @@ -1158,8 +1246,10 @@ see the [claims](configuration.mdx#claims) section for all the options. ## Cloud Provisioners -`step-ca` can be configured to use instance identity documents (IIDs) to authorize certificate signing requests from cloud VMs running on AWS, GCP, or Azure. -IIDs are signed JSON tokens, created when the instance is launched, and made available via the instance metadata API. +`step-ca` can be configured to use instance identity documents (IIDs) +to authorize certificate signing requests from cloud VMs running on AWS, GCP, or Azure. +IIDs are signed JSON tokens, created when the instance is launched, +and made available via the instance metadata API. Here's the contents of an example IID from AWS: @@ -1245,7 +1335,7 @@ The [`step`](https://github.com/smallstep/cli) CLI will generate a custom JWT token containing the instance identity document and its signature and the CA will grant a certificate after validating it. -#### Example +#### Create an AWS Provisioner Find your AWS [account ID](https://docs.aws.amazon.com/general/latest/gr/acct-identifiers.html) to restrict access to our VMs: @@ -1279,6 +1369,8 @@ In the `ca.json`, an AWS provisioner looks like: } ``` +And, here's what each property stands for: + - **type**: indicates the provisioner type and must be `AWS`. - **name**: a string used to identify the provider when the CLI is @@ -1312,7 +1404,7 @@ The GCP provisioner grants certificates to Google Compute Engine instance using its [identity](https://cloud.google.com/compute/docs/instances/verifying-instance-identity) token. The CA will validate the JWT and grant a certificate. -#### Example +#### Create a GCP Provisioner On the host running `step-ca`, add an GCP provisioner to your configuration by running: @@ -1346,6 +1438,8 @@ In the `ca.json`, a GCP provisioner looks like: } ``` +And, here's what each property stands for: + - **type**: indicates the provisioner type and must be `GCP`. - **name**: a string used to identify the provider when the CLI is used. @@ -1383,7 +1477,7 @@ The Azure provisioner grants certificates to Microsoft Azure instances using the [managed identities tokens](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token). The CA will validate the JWT and grant a certificate. -#### Example +#### Create an Azure Provisioner On the host running `step-ca`, add an Azure provisioner to your configuration by running: @@ -1416,6 +1510,8 @@ In the `ca.json`, an Azure provisioner looks like: } ``` +And, here's what each property stands for: + - **type**: indicates the provisioner type and must be `Azure`. - **name**: a string used to identify the provider when the CLI is used.