diff --git a/manifest.json b/manifest.json index b955daab..3e108b08 100644 --- a/manifest.json +++ b/manifest.json @@ -1498,6 +1498,10 @@ "title": "Registration Authority Mode", "path": "/step-ca/registration-authority-ra-mode.mdx" }, + { + "title": "Cryptographic Protection", + "path": "/step-ca/cryptographic-protection.mdx" + }, { "title": "Integrations", "path": "/step-ca/integrations.mdx" diff --git a/step-ca/certificate-authority-server-production.mdx b/step-ca/certificate-authority-server-production.mdx index ed06279f..3ba96422 100644 --- a/step-ca/certificate-authority-server-production.mdx +++ b/step-ca/certificate-authority-server-production.mdx @@ -66,7 +66,7 @@ For durability, keep at least two copies of your root key, in separate locations 5. Configure `step-ca` to use the signed root and intermediate certificates 6. Configure `step-ca` to access the cloud HSM or KMS intermediate key for online signing operations -See the [Cryptographic Protection](./configuration.mdx#cryptographic-protection) section of our [Configuration Guide](./configuration.mdx) to learn more about your options for using HSMs or cloud KMS with `step-ca`. +See [Cryptographic Protection](./cryptographic-protection.mdx) to learn more about your options for using HSMs or cloud KMS with `step-ca`. ### Use Strong Passwords and Store Them Well diff --git a/step-ca/configuration.mdx b/step-ca/configuration.mdx index 95e38440..9417423d 100644 --- a/step-ca/configuration.mdx +++ b/step-ca/configuration.mdx @@ -32,12 +32,6 @@ learn how to configure your CA to: - [MySQL](#mysql) - [PostgreSQL](#postgresql) - [Schema](#schema) -- [Cryptographic Protection](#cryptographic-protection) - - [Google Cloud KMS](#google-cloud-kms) - - [AWS KMS](#aws-kms) - - [Azure Key Vault](#azure-key-vault) - - [PKCS #11](#pkcs-11) - - [YubiKey PIV](#yubikey-piv) ## Specify a Configuration File @@ -209,11 +203,11 @@ the `--password-file` flag accepts - **key**: location of the intermediate private key on the filesystem. The intermediate key signs all new certificates generated by the CA. -- **kms**: enables and configures cryptographic protection using cloud key management services or hardware security modules. See [Cryptographic Protection](#cryptographic-protection). +- **kms**: enables and configures cryptographic protection using cloud key management services or hardware security modules. See [Cryptographic Protection](./cryptographic-protection.mdx). - **type**: required. one of `azurekms`, `awskms`, `cloudkms`, `pkcs11`, or `yubikey` - - **uri**: this field can be used to specify other fields in this section, and its value takes precedence over those values. See [cryptographic protection](#cryptographic-protection) for examples. + - **uri**: this field can be used to specify other fields in this section, and its value takes precedence over those values. See [cryptographic protection](./cryptographic-protection.mdx) for examples. - **region**: for `awskms`, the AWS region @@ -527,728 +521,4 @@ At this time `step-ca` does not have any API or interface for easily exporting d [scripted-export-db]: https://gist.github.com/dopey/89ec20f22c66c1333bf38c9b19b89758 -## Cryptographic Protection - -By default, `step-ca` stores its signing keys encrypted on disk. - -For security hardening, -you may desire more advanced cryptographic protection (or hardware protection) -of your CA's signing keys. - -For these scenarios, `step-ca` integrates with the following key management systems: - -- [Google Cloud KMS](#google-cloud-kms) -- [AWS KMS](#aws-kms) -- [Azure Key Vault](#azure-key-vault) -- [PKCS #11 hardware security modules (HSMs)](#pkcs-11) -- [YubiKey PIV](#yubikey-piv) -- ssh-agent -- Microsoft CryptoAPI - -For a complete, end-to-end example using a YubiKey, -see our blog post [Build a Tiny Certificate Authority For Your Homelab](https://smallstep.com/blog/build-a-tiny-ca-with-raspberry-pi-yubikey/). - -### Before You Begin - -The `step ca init` command has very limited support for keys not stored on disk. We've created the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) for managing the keys and certificates on cloud KMSs and on hardware devices. Please install this plugin before continuing with any of the examples below. - -### Google Cloud KMS - -[Cloud KMS](https://cloud.google.com/kms/docs) is Google's cloud-hosted KMS that allows you to store the cryptographic keys and sign certificates using their infrastructure. Cloud KMS supports two key protection levels: `SOFTWARE` and `HSM`. - -#### Creating your PKI in Google Cloud KMS - -Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. - -Also, make sure you have installed [the `gcloud` CLI](https://cloud.google.com/sdk/docs/install) and have [configured Google Cloud application default credentials](https://developers.google.com/accounts/docs/application-default-credentials) in your local environment, eg. by running `gcloud auth application-default login`. - -Next, let's generate a private key for your Root CA. The `step kms create` command will also [create a Cloud KMS key ring](https://cloud.google.com/kms/docs/create-key-ring) for you, if it doesn't exist. Run: - -```shell nocopy -$ step kms create --json --kms 'cloudkms:' \ - 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root' -``` - -To constructe the key name parameter above, use the resource name of the [CryptoKey](https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys#CryptoKey) object you want to create, following the format: - -``` -projects//locations//keyRings//cryptoKeys/ -``` - - -Once the key is generated, `step` outputs the key's name (including a version number), and the public key PEM: - -``` -{ - "name": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root/cryptoKeyVersions/1", - "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERcTjeMNjBs29ReA1nf6Odyn2l4Yt\nXPo4CUOcCrn6yw7LJmzaDiqIErhuS9r6BNg92kJvFUiuiU8+w+WZOyhZdw==\n-----END PUBLIC KEY-----\n" -} -``` - -You'll need this key name for the next step. - - -
- We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, protection level, or other options for your environment. See step kms help create for details. -
-
- -Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: - -```shell nocopy -$ step certificate create --profile root-ca \ - --kms 'cloudkms:' \ - --key 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root/cryptoKeyVersions/1' \ - "Smallstep Root CA" root_ca.crt -``` - -Output: - -``` -Your certificate has been saved in root_ca.crt. -``` - -Great. Next, repeat the process for the Intermediate CA: - -```shell nocopy -$ step kms create --json --kms 'cloudkms:' \ - 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/intermediate' -$ step certificate create --profile intermediate-ca \ - --kms 'cloudkms:' \ - --ca-kms 'cloudkms:' \ - --ca root_ca.crt \ - --ca-key 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root/cryptoKeyVersions/1' \ - --key 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/intermediate/cryptoKeyVersions/1' \ - "Smallstep Intermediate CA" intermediate_ca.crt -``` - -Output: - -``` -Your certificate has been saved in intermediate_ca.crt. -``` - -Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. -Use these files in your CA configuration, below. - -If you want to run an SSH CA, you also need to create SSH CA key pairs: - -```shell nocopy -$ step kms create --json --kms 'cloudkms:' \ - 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-user' -$ step kms create --json --kms 'cloudkms:' \ - 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-host' -``` - -#### Configuring `step-ca` to use Google Cloud KMS - -Next, to configure Cloud KMS in `step-ca`, start with a basic CA configuration created using `step ca init`. Add the `kms` object to your `ca.json` file and replace the property `key` with the Cloud KMS resource name of your intermediate key: - -```json nocopy -{ - "root": "/etc/step-ca/certs/root_ca.crt", - "crt": "/etc/step-ca/certs/intermediate_ca.crt", - "key": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/intermediate/cryptoKeyVersions/1", - "kms": { - "type": "cloudkms", - "uri": "cloudkms:credentials-file=/path/to/gcloud-kms-credentials.json" - } -} -``` - -Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: - -```shell nocopy -$ cp root_ca.crt intermediate_ca.crt $(step path)/certs -``` - -Your X.509 CA is ready. - -To add SSH support, change the SSH key locations to Cloud KMS resource names for the SSH host and user CA keys: - -```json nocopy -{ - "ssh": { - "hostKey": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-host/cryptoKeyVersions/1", - "userKey": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-user/cryptoKeyVersions/1" - } -} -``` - -When you start `step-ca`, it prints your X.509 root fingerprint, and the SSH user and host CA keys in SSH key format: - -``` -2022/09/20 16:28:45 The primary server URL is https://localhost:443 -2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem -2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 -2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= -2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= -2022/09/20 16:28:45 Serving HTTPS on :443 ... -``` - -#### Notes on Google Cloud KMS Permissions - -Following the principle of least privilege, you'll want to define an IAM operational role for step-ca that limits its access. -See [Google Cloud KMS: Access Control with IAM](https://cloud.google.com/kms/docs/iam) for an overview. - -Here are some notes on granting a custom IAM role that provides step-ca with access to Google Cloud KMS: -* You can constrain the role to the key ring that you created for step-ca. -* For day-to-day operation, grant `step-ca` the following default roles: - * [`cloudkms.cryptoOperator`](https://cloud.google.com/iam/docs/understanding-roles#cloudkms.cryptoOperator) - * [`cloudkms.viewer`](https://cloud.google.com/iam/docs/understanding-roles#cloudkms.viewer) -* More specifically, a running `step-ca` needs access to the following KMS APIs: - * `resourcemanager.projects.get` - * `cloudkms.locations.get` - * `cloudkms.keyRings.get` - * `cloudkms.cryptoKeys.get` - * `cloudkms.cryptoKeyVersions.get` - * `cloudkms.cryptoKeyVersions.useToSign` - * `cloudkms.cryptoKeyVersions.useToVerify` - * `cloudkms.cryptoKeyVersions.useToDecrypt` - -### AWS KMS - -[AWS KMS](https://aws.amazon.com/kms/) is Amazon's managed encryption and key management service. It creates and stores the cryptographic keys and uses AWS infrastructure for signing operations. Amazon KMS operations are always backed by HSMs. - -#### Creating your PKI in AWS KMS - -Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. - -Also, make sure you have installed [the `aws` CLI](https://aws.amazon.com/cli/) and have configured AWS credentials in your local environment. - - -
- Avoid storing local AWS credentials in plaintext, if you can. We prefer either AWS Identity Center or aws-vault for securing local credentials. -
-
- - -Next, let's generate a private key for your root CA inside AWS KMS. Run: - -```shell nocopy -$ step kms create --json --kms 'awskms:region=us-east-2' root-ca -``` - -Once the key is generated, `step` outputs the key ID and the public key PEM: - -``` -{ - "name": "awskms:key-id=78980acd-a42d-4d84-97ba-1e50d3082214", - "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH2ls6h1y2jsXV+IeuhDVkb68zkMe\nKPtI7L6vBIa5ThxOyFaZFnUrGWU6B+KQjProAntgKyNTqOnAh7Eyr3RmgQ==\n-----END PUBLIC KEY-----\n" -} -``` - -When creating the key, `step kms create` will also add an AWS key alias `root-ca-78980acd` for the key. -The alias is concatenates the key name and the first segment of the key's ID. - -You'll need this key name for the next step. - - -
- We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, protection level, or other options for your environment. See step kms help create for details. -
-
- -Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: - -```shell nocopy -$ step certificate create --profile root-ca \ - --kms 'awskms:region=us-east-2' \ - --key 'awskms:key-id=78980acd-a42d-4d84-97ba-1e50d3082214' \ - "Smallstep Root CA" root_ca.crt -``` - -Output: - -``` -Your certificate has been saved in root_ca.crt. -``` - -Great. Next, we'll repeat the process for the Intermediate CA: - -```shell nocopy -$ step kms create --json --kms 'awskms:region=us-east-2' intermediate-ca -$ step certificate create --profile intermediate-ca \ - --kms 'awskms:region=us-east-2' \ - --ca-kms 'awskms:region=us-east-2' \ - --ca root_ca.crt \ - --ca-key 'awskms:key-id=78980acd-a42d-4d84-97ba-1e50d3082214' \ - --key 'awskms:key-id=9432458d-1e67-4a74-9a23-8f94708b45fe' \ - "Smallstep Intermediate CA" intermediate_ca.crt -``` - -Here, the `--ca-key` is the root CA key id; the `--key` is the intermediate CA key id. - -Output: - -``` -Your certificate has been saved in intermediate_ca.crt. -``` - -Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. -You'll need these files for your CA configuration, below. - -If you want to run an SSH CA, you'll also need to create SSH CA key pairs: - -```shell nocopy -$ step kms create --json --kms 'awskms:region=us-east-2' ssh-user-ca -$ step kms create --json --kms 'awskms:region=us-east-2' ssh-host-ca -``` - -Hold onto the key IDs from these commands; you'll need them below. - -#### Configuring `step-ca` to use AWS KMS - -To use `step-ca` with AWS KMS, create a scoped IAM role that has `kms:GetPublicKey` permissions on all of your CA keys, and `kms:Sign` permission on your intermediate CA key. - -To configure AWS KMS in your certificate authority, add the `kms` object to `ca.json` and replace the `key` property with the AWS KMS key ID of your intermediate CA key: - -```json nocopy -{ - "root": "/etc/step-ca/certs/root_ca.crt", - "crt": "/etc/step-ca/certs/intermediate_ca.crt", - "key": "awskms:key-id=f879f239-feb6-4596-9ed2-b1606277c7fe", - "kms": { - "type": "awskms", - "uri": "awskms:region=us-east-2;profile=foo;credentials-file=/path/to/credentials" - } -} -``` - -By default, `step-ca` (and, more broadly, AWS's SDK) looks for credentials stored in `~/.aws/credentials`. Use the `credentials-file` option to override. The `region` and `profile` options specify the AWS region and configuration profiles respectively. These options can also be configured using environment variables as described in the [AWS SDK for Go session documentation](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/). - -Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: - -```shell nocopy -$ cp root_ca.crt intermediate_ca.crt $(step path)/certs -``` - -Your X.509 CA is ready. - -To configure an SSH CA, replace the SSH key locations with the SSH CA keys you created above: - -```json nocopy -{ - "ssh": { - "hostKey": "awskms:key-id=d48e502a-09bc-4bf7-9af8-ae1bccedc931", - "userKey": "awskms:key-id=cf28e942-1e10-4a08-b84c-5359af1b5f12" - } -} -``` - -When you start `step-ca`, it prints your X.509 root fingerprint, and the SSH user and host CA keys in SSH key format: - -``` -2022/09/20 16:28:45 The primary server URL is https://localhost:443 -2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem -2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 -2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= -2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= -2022/09/20 16:28:45 Serving HTTPS on :443 ... -``` - -#### Notes on AWS KMS Permissions - -Following the principle of least privilege, you'll want to define an IAM operational role for step-ca that limits its access. -See [Using IAM Policies With AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html) for an overview. - -Here are some notes on granting a custom IAM role that provides step-ca with access to AWS KMS: -* You can constrain the role to specific keys that you created for step-ca, by listing each key's ARN in the Resource block of the JSON policy. -* For day-to-day operation, grant `step-ca` the following permissions: - * `kms:GetPublicKey` - * `kms:Sign` - -### Azure Key Vault - -[Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault) is Microsoft's managed key management service. - -#### Authentication - -When using Azure Key Vault with `step-ca`, first authenticate to Azure. - -Authentication to Azure is handled via environment variables; -we recommend using either [file-based authentication](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-file-based-authentication) via the `AZURE_AUTH_LOCATION` environment variable, -or [using a managed identity](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication-managed-identity?tabs=azure-cli) and setting the `AZURE_TENANT_ID` and `AZURE_CLIENT_ID` variables when starting `step-ca`. -Alternatively, you can create a [service principal](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) and set the `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` variables. -See Option 1 under [Authentication Methods for Azure SDK for Go](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#-option-1-define-environment-variables) for examples of authentication methods and environment variables. - -For local development and testing, Azure CLI credentials are used if no authentication environment variables are set. - -#### Initialize a PKI - -To initialize a PKI backed by Azure Key Vault, start by authenticating to Azure using one of the above approaches. -Set the environment variables necessary for authentication to your tenant. - -Then, run: - -```bash -$ step ca init --kms azurekms -``` - -This walks you through the process of creating root and intermediate CA signing keys in Key Vault, and configuring the CA to use them. -If you're creating an SSH CA, SSH host and user CA keys are created in Key Vault as well. - -#### Manual Configuration - -To configure an existing CA for Azure Key Vault, or to import an existing Azure Key Vault signing key, add the `kms` object to your `ca.json`, and replace the `key` properties with the key name, vault name, and version of your intermediate (signing) key in Azure Key Vault: - -```json nocopy -{ - "root": "/etc/step-ca/certs/root_ca.crt", - "crt": "/etc/step-ca/certs/intermediate_ca.crt", - "key": "azurekms:name=intermediate-ca-key;vault=example-vault-0?version=15faf8b8b80d4f1ead067c6383a38b8f&hsm=true", - "kms": { - "type": "azurekms" - } -} -``` - -* In the `key` URI, the `name` and `vault` refer to the key name and vault name of your intermediate key in Azure Key Vault. -* In the `key` URI, the `version` is the version of the Azure Key Vault key name. Though it is optional, we recommend setting this value explicitly. If omitted, the latest version is used. -* In the `key` URI, the optional `hsm` property can be set to `true` if HSM protection is desired. This is only used when the key is being created by `step-ca`. The default is to use software-protected (non-HSM-backed) keys. See Key Vault's [About Keys](https://docs.microsoft.com/en-us/azure/key-vault/keys/about-keys) page for more details. -* In `kms`, an optional `uri` property can be added to provide client credentials (eg. `azurekms:client-id=fooo;client-secret=bar;tenant-id=9de53416-4431-4181-7a8b-23af3EXAMPLE`) instead of using the environment variables described above. - -#### Notes on Azure Key Vault IAM Permissions - -Following the principle of least privilege, you'll want to define an IAM operational role for step-ca that limits its access. -See [Provide access to Key Vault keys, certificates, and secrets with an Azure role-based access control](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli) for an overview. - -Here are some notes on granting a custom IAM role that provides step-ca with access to Azure Key Vault: -* You can constrain the role to the vault that you created for step-ca. -* For day-to-day operation, grant `step-ca` the following default RBAC roles on the vault: - * Key Vault Crypto User - * Key Vault Reader -* More specifically, a running `step-ca` needs access to the following APIs: - * `GetKey` - * `Sign` - -### PKCS #11 - - -
- The standard `step-ca` binary does not support PKCS #11.
- For PKCS #11 support, you'll need a CGO build of `step-ca`. - When built with CGO, `step-ca` can call native PKCS #11 C libraries.
- You can either:
- - Build `step-ca` yourself. See Building From Source Using CGO, or
- - Use the `step-ca:hsm` Docker image. The `hsm` tag is built with CGO.
-
-
- -A Hardware Security Module (HSM) is a specialized piece of hardware that is designed to generate and store private keys, and sign messages using those keys. -The private keys on an HSM cannot be exported from the device. -One can only run signing operations using the key. -This is an excellent way to protect private keys for a Certificate Authority, -which in normal operation simply needs to be able to sign Certificate Signing Requests. - -[Public-Key Cryptography Standards #11 (PKCS #11)](https://en.wikipedia.org/wiki/PKCS_11) is the most common platform-independent API used to access HSM hardware. -It's supported by most HSM hardware, like Yubico's [YubiHSM2](https://www.yubico.com/product/yubihsm-2/), and the [Nitrokey HSM 2](https://shop.nitrokey.com/shop/product/nk-hsm-2-nitrokey-hsm-2-7). -There's also a software-based "HSM," [SoftHSMv2](https://github.com/opendnssec/SoftHSMv2), which offers a PKCS #11 interface without the hardware. -Finally, you can use PKCS#11 with a Trusted Platform Module (TPM) 2.0 chip on Linux. This requires the [libtpm2_pkcs11.so](https://github.com/tpm2-software/tpm2-pkcs11) library. - -#### 0. Before you begin - -Your HSM or TPM2 may need to be prepared before you can initialize a PKI on it. -Preparation steps depend on the device and are beyond the scope of this documentation. -For example, - -- With YubiHSM2, first create an authentication key with appropriate capabiliites. -- With TPM2, initialize the TPM and create a PKCS#11 token on it. - -Plan how you will backup and restore your CA keys, for offline storage. - -The `step kms` plugin will create CA keys and sign certificates on your device. -To use it, you'll need to provide a PKCS #11 URI for accessing the device, using the `--kms` flag. - -Here are some examples of PKCS #11 URIs for accessing various devices in Linux: - -HSM | URI format --------------------------- | ------------------------------------------------------------------------------------- -YubiHSM2 | `pkcs11:module-path=/usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so;token=YubiHSM` -AWS CloudHSM | `pkcs11:module-path=/opt/cloudhsm/lib/libcloudhsm_pkcs11.so;token=cavium?pin-value=$HSM_USER:$HSM_PASSWORD` -SoftHSM | `pkcs11:module-path=/usr/lib/softhsm/libsofthsm2.so;token=token1?pin-value=$HSM_PASSWORD` -nCipher nShield | `pkcs11:module-path=/opt/nfast/toolkits/pkcs11/libcknfast.so;token=rjk?pin-source=/etc/step-ca/hsm-pin.txt` -TPM2 (via libtpm2_pkcs11) | `pkcs11:module-path=/usr/local/lib/libtpm2_pkcs11.so;token=step-ca?pin-value=$HSM_PASSWORD` - -Substitute `$HSM_USER` and `$HSM_PASSWORD` with your own values. - -In this URI, -* `module-path` points to your PKCS #11 `.dll`, `.so`, or `.dylib` library file, -* `token` is the label (`CKA_LABEL`) of the HSM you're using, -* `pin-value` contains hardcoded HSM credentials. It may be a PIN, username and password, password, or a filename. The YubiHSM2 is special in that the PIN value is the concatenation of the four-digit authorization key ID (eg. `0001`) and the PIN. -* Or, `pin-source` is a filename containing HSM credentials. - -#### 1. Create your PKI - -Once you've constructed the right URI for accessing your device, use it in place of `$PKCS_URI` in the commands below. - -First, please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. - -Next, let's ask the device to generate a private key for your root CA. Run: - -```shell nocopy -$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7331;object=root-ca" -``` - -Once the key is generated, `step` will output the key ID and the public key PEM: - -``` -{ - "name": "pkcs11:id=7331;object=root-ca", - "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH2ls6h1y2jsXV+IeuhDVkb68zkMe\nKPtI7L6vBIa5ThxOyFaZFnUrGWU6B+KQjProAntgKyNTqOnAh7Eyr3RmgQ==\n-----END PUBLIC KEY-----\n" -} -``` - -You'll need this key name for the next step. - - -
- We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, protection level, or other options for your environment. See step kms help create for details. -
-
- -Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: - -```shell nocopy -$ step certificate create --profile root-ca \ - --kms "$PKCS_URI" - --key "pkcs11:id=7331;object=root-ca" \ - "Smallstep Root CA" root_ca.crt -``` - -Output: - -``` -Your certificate has been saved in root_ca.crt. -``` - -Great. Next, we'll repeat the process for the Intermediate CA: - -```shell nocopy -$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7332;object=intermediate-ca" -$ step certificate create --profile intermediate-ca \ - --kms "$PKCS_URI" \ - --ca-kms "$PKCS_URI" \ - --ca root_ca.crt \ - --ca-key "pkcs11:id=7331;object=root-ca" \ - --key "pkcs11:id=7332;object=intermediate-ca" \ - "Smallstep Intermediate CA" intermediate_ca.crt -``` - -Here, the `--ca-key` is the root CA key id; the `--key` is the intermediate CA key id. - -Output: - -``` -Your certificate has been saved in intermediate_ca.crt. -``` - -Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. -You'll need these files for your CA configuration, below. - -If you want to run an SSH CA, you'll also need to create SSH CA key pairs: - -```shell nocopy -$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7333;object=ssh-host-ca" -$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7334;object=ssh-user-ca" -``` - -Hold onto the key IDs from these commands; you'll need them below. - -#### Configuring `step-ca` to use PKCS #11 - -One you've created your PKI on the HSM using `step-kms-plugin`, you'll need to configure `step-ca` to use the HSM. - -To configure your certificate authority, add the `kms` object to `ca.json` and replace the `key` property with the object ID of your intermediate CA key: - -```json nocopy -{ - "root": "/etc/step-ca/certs/root_ca.crt", - "crt": "/etc/step-ca/certs/intermediate_ca.crt", - "key": "pkcs11:id=7332;object=intermediate-ca", - "kms": { - "type": "pkcs11", - "uri": "$PKCS_URI" - } -} -``` - -Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: - -```shell nocopy -$ cp root_ca.crt intermediate_ca.crt $(step path)/certs -``` - -Your X.509 CA is ready. - -To configure an SSH CA, replace the SSH key locations with the SSH CA keys you created above: - -```json nocopy -{ - "ssh": { - "hostKey": "pkcs11:id=7333;object=ssh-host-ca", - "userKey": "pkcs11:id=7334;object=ssh-user-ca" - } -} -``` - -When you start `step-ca`, you will see your X.509 root fingerprint, and the SSH user and host CA keys in SSH key format: - -``` -2022/09/20 16:28:45 The primary server URL is https://localhost:443 -2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem -2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 -2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= -2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= -2022/09/20 16:28:45 Serving HTTPS on :443 ... -``` - -### YubiKey PIV - - -
- The standard `step-ca` binary does not support YubiKey PIV.
- For YubiKey PIV support, you'll need a CGO build of `step-ca`. - When built with CGO, `step-ca` can call native Yubico C libraries.
- You can either:
- - Build `step-ca` yourself. See Building From Source Using CGO, or
- - Use the `step-ca:hsm` Docker image. The `hsm` tag is built with CGO.
-
-
- -You can leverage a hardware [YubiKey](https://www.yubico.com/)—and the [YubiKey PIV application](https://www.yubico.com/authentication-standards/smart-card/)—to store your CA keys and sign TLS and SSH certificates. - -#### Prerequisites and Caveats - -* To enable YubiKey support in `step-ca`, you must follow our [Instructions for building from source using CGO](https://github.com/smallstep/certificates/blob/master/CONTRIBUTING.md#build-step-ca-using-cgo) -* You will need a YubiKey 5 series device that [supports the PIV application](https://www.yubico.com/store/compare/) -* [Certificate slots](https://developers.yubico.com/PIV/Introduction/Certificate_slots.html) 9a, 9c, 9d, 9e, and 82-95 are supported -* You can use the YubiKey for X.509 and SSH CAs - -Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. - -Now, insert your YubiKey. -Let's generate a private key for your root CA in slot 82 on the YubiKey. -Run: - -```shell nocopy -$ step kms create --json 'yubikey:slot-id=82' -``` - -Once the key is generated, `step` outputs the key name and public key PEM: - -``` -{ - "name": "yubikey:slot-id=82", - "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAED3T/7q+p+6239Ri35TBVoChM6VNq\n1buLfql1acRl7F2qf/L96x9XHY5GHoqYNCAm/ocL9hTl8ytWJao+JSNE+Q==\n-----END PUBLIC KEY-----\n" -} -``` - - -
- We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, or other options for your environment. See step kms help create for details. -
-
- -Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: - -```shell nocopy -$ step certificate create --profile root-ca \ - --kms 'yubikey:pin-value=123456' \ - --key 'yubikey:slot-id=82' \ - "Smallstep Root CA" root_ca.crt -``` - -Here we're using the default PIN code of 123456 to access the YubiKey. - -Output: - -``` -Your certificate has been saved in root_ca.crt. -``` - -Great. Next, we'll repeat the process for the Intermediate CA: - -```shell nocopy -$ step kms create --json 'yubikey:slot-id=83' -$ step certificate create --profile intermediate-ca \ - --kms 'yubikey:pin-value=123456' \ - --ca-kms 'yubikey:pin-value=123456' \ - --ca root_ca.crt \ - --ca-key 'yubikey:slot-id=82' \ - --key 'yubikey:slot-id=83' \ - "Smallstep Intermediate CA" intermediate_ca.crt -``` - -Here, the `--ca-key` is the root CA key id; the `--key` is the intermediate CA key id. - -Output: - -``` -Your certificate has been saved in intermediate_ca.crt. -``` - -Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. -You'll need these files for your CA configuration, below. - -for safekeeping, you may wish to import the certificates into the YubiKey. To do this, you'll need Yubico's [`ykman` CLI utility](https://developers.yubico.com/yubikey-manager/). Run: - -```shell nocopy -$ ykman piv certificates import 82 root_ca.crt -$ ykman piv certificates import 83 intermediate_ca.crt -``` - -(While `step-ca` won't use these copies of the certificates, you can always use `ykman piv certificates export` to download the certificates later.) - -Next, if you want to run an SSH CA, you'll also need to create two SSH CA keys: - -```shell nocopy -$ step kms create --json 'yubikey:slot-id=84' -$ step kms create --json 'yubikey:slot-id=85' -``` - -Finally, to enable your CA in `ca.json`, point the `root` and `crt` options to the generated certificates, replace the `key` option with the YubiKey URI generated in the previous part, and configure the `kms` option with the appropriate `type` and `pin`. - -```json nocopy -{ - "root": "/etc/step-ca/certs/root_ca.crt", - "crt": "/etc/step-ca/certs/intermediate_ca.crt", - "key": "yubikey:slot-id=83", - "kms": { - "type": "yubikey", - "uri": "yubikey:management-key=01020304...?pin-value=123456" - } -} -``` - -Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: - -```shell nocopy -$ cp root_ca.crt intermediate_ca.crt $(step path)/certs -``` - -Your X.509 CA is ready. - -To configure an SSH CA, replace the SSH key locations with the SSH CA keys you created in AWS KMS: - -```json nocopy -{ - "ssh": { - "hostKey": "yubikey:slot-id=84", - "userKey": "yubikey:slot-id=85" - } -} -``` - -When you start `step-ca`, it prints your X.509 root fingerprint, and the SSH host and user CA keys in SSH key format: - -``` -2022/09/20 16:28:45 The primary server URL is https://localhost:443 -2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem -2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 -2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= -2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= -2022/09/20 16:28:45 Serving HTTPS on :443 ... -``` - diff --git a/step-ca/cryptographic-protection.mdx b/step-ca/cryptographic-protection.mdx new file mode 100644 index 00000000..021ce704 --- /dev/null +++ b/step-ca/cryptographic-protection.mdx @@ -0,0 +1,826 @@ +--- +title: Cryptographic Protection +html_title: Cryptographic Protection +description: Store your CA private keys in hardware or in a cloud KMS +updated_at: March 26, 2024 +--- + +# Cryptographic Protection + +By default, `step-ca` stores its signing keys encrypted on disk. + +For security hardening, +you may desire more advanced cryptographic protection (or hardware protection) +of your CA's signing keys. + +For these scenarios, `step-ca` integrates with the following key management systems: + +- [Google Cloud KMS](#google-cloud-kms) +- [AWS KMS](#aws-kms) +- [Azure Key Vault](#azure-key-vault) +- [PKCS #11 hardware security modules (HSMs)](#pkcs-11) +- [TPM 2.0](#tpm-20) +- [YubiKey PIV](#yubikey-piv) +- ssh-agent +- Microsoft CryptoAPI + +For a complete, end-to-end example using a YubiKey, +see our blog post [Build a Tiny Certificate Authority For Your Homelab](https://smallstep.com/blog/build-a-tiny-ca-with-raspberry-pi-yubikey/). + +## Before You Begin + +The `step ca init` command has very limited support for keys not stored on disk. We've created the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) for managing the keys and certificates on cloud KMSs and on hardware devices. Please install this plugin before continuing with any of the examples below. + +## Google Cloud KMS + +[Cloud KMS](https://cloud.google.com/kms/docs) is Google's cloud-hosted KMS that allows you to store the cryptographic keys and sign certificates using their infrastructure. Cloud KMS supports two key protection levels: `SOFTWARE` and `HSM`. + +### Creating your PKI in Google Cloud KMS + +Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. + +Also, make sure you have installed [the `gcloud` CLI](https://cloud.google.com/sdk/docs/install) and have [configured Google Cloud application default credentials](https://developers.google.com/accounts/docs/application-default-credentials) in your local environment, eg. by running `gcloud auth application-default login`. + +Next, let's generate a private key for your Root CA. The `step kms create` command will also [create a Cloud KMS key ring](https://cloud.google.com/kms/docs/create-key-ring) for you, if it doesn't exist. Run: + +```shell nocopy +$ step kms create --json --kms 'cloudkms:' \ + 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root' +``` + +To constructe the key name parameter above, use the resource name of the [CryptoKey](https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys#CryptoKey) object you want to create, following the format: + +``` +projects//locations//keyRings//cryptoKeys/ +``` + + +Once the key is generated, `step` outputs the key's name (including a version number), and the public key PEM: + +``` +{ + "name": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root/cryptoKeyVersions/1", + "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERcTjeMNjBs29ReA1nf6Odyn2l4Yt\nXPo4CUOcCrn6yw7LJmzaDiqIErhuS9r6BNg92kJvFUiuiU8+w+WZOyhZdw==\n-----END PUBLIC KEY-----\n" +} +``` + +You'll need this key name for the next step. + + +
+ We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, protection level, or other options for your environment. See step kms help create for details. +
+
+ +Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: + +```shell nocopy +$ step certificate create --profile root-ca \ + --kms 'cloudkms:' \ + --key 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root/cryptoKeyVersions/1' \ + "Smallstep Root CA" root_ca.crt +``` + +Output: + +``` +Your certificate has been saved in root_ca.crt. +``` + +Great. Next, repeat the process for the Intermediate CA: + +```shell nocopy +$ step kms create --json --kms 'cloudkms:' \ + 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/intermediate' +$ step certificate create --profile intermediate-ca \ + --kms 'cloudkms:' \ + --ca-kms 'cloudkms:' \ + --ca root_ca.crt \ + --ca-key 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/root/cryptoKeyVersions/1' \ + --key 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/intermediate/cryptoKeyVersions/1' \ + "Smallstep Intermediate CA" intermediate_ca.crt +``` + +Output: + +``` +Your certificate has been saved in intermediate_ca.crt. +``` + +Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. +Use these files in your CA configuration, below. + +If you want to run an SSH CA, you also need to create SSH CA key pairs: + +```shell nocopy +$ step kms create --json --kms 'cloudkms:' \ + 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-user' +$ step kms create --json --kms 'cloudkms:' \ + 'projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-host' +``` + +### Configuring `step-ca` to use Google Cloud KMS + +Next, to configure Cloud KMS in `step-ca`, start with a basic CA configuration created using `step ca init`. Add the `kms` object to your `ca.json` file and replace the property `key` with the Cloud KMS resource name of your intermediate key: + +```json nocopy +{ + "root": "/etc/step-ca/certs/root_ca.crt", + "crt": "/etc/step-ca/certs/intermediate_ca.crt", + "key": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/intermediate/cryptoKeyVersions/1", + "kms": { + "type": "cloudkms", + "uri": "cloudkms:credentials-file=/path/to/gcloud-kms-credentials.json" + } +} +``` + +Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: + +```shell nocopy +$ cp root_ca.crt intermediate_ca.crt $(step path)/certs +``` + +Your X.509 CA is ready. + +To add SSH support, change the SSH key locations to Cloud KMS resource names for the SSH host and user CA keys: + +```json nocopy +{ + "ssh": { + "hostKey": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-host/cryptoKeyVersions/1", + "userKey": "projects/smallstep/locations/global/keyRings/step-ca/cryptoKeys/ssh-user/cryptoKeyVersions/1" + } +} +``` + +When you start `step-ca`, it prints your X.509 root fingerprint, and the SSH user and host CA keys in SSH key format: + +``` +2022/09/20 16:28:45 The primary server URL is https://localhost:443 +2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem +2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 +2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= +2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= +2022/09/20 16:28:45 Serving HTTPS on :443 ... +``` + +### Notes on Google Cloud KMS Permissions + +Following the principle of least privilege, you'll want to define an IAM operational role for step-ca that limits its access. +See [Google Cloud KMS: Access Control with IAM](https://cloud.google.com/kms/docs/iam) for an overview. + +Here are some notes on granting a custom IAM role that provides step-ca with access to Google Cloud KMS: +* You can constrain the role to the key ring that you created for step-ca. +* For day-to-day operation, grant `step-ca` the following default roles: + * [`cloudkms.cryptoOperator`](https://cloud.google.com/iam/docs/understanding-roles#cloudkms.cryptoOperator) + * [`cloudkms.viewer`](https://cloud.google.com/iam/docs/understanding-roles#cloudkms.viewer) +* More specifically, a running `step-ca` needs access to the following KMS APIs: + * `resourcemanager.projects.get` + * `cloudkms.locations.get` + * `cloudkms.keyRings.get` + * `cloudkms.cryptoKeys.get` + * `cloudkms.cryptoKeyVersions.get` + * `cloudkms.cryptoKeyVersions.useToSign` + * `cloudkms.cryptoKeyVersions.useToVerify` + * `cloudkms.cryptoKeyVersions.useToDecrypt` + +## AWS KMS + +[AWS KMS](https://aws.amazon.com/kms/) is Amazon's managed encryption and key management service. It creates and stores the cryptographic keys and uses AWS infrastructure for signing operations. Amazon KMS operations are always backed by HSMs. + +### Creating your PKI in AWS KMS + +Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. + +Also, make sure you have installed [the `aws` CLI](https://aws.amazon.com/cli/) and have configured AWS credentials in your local environment. + + +
+ Avoid storing local AWS credentials in plaintext, if you can. We prefer either AWS Identity Center or aws-vault for securing local credentials. +
+
+ + +Next, let's generate a private key for your root CA inside AWS KMS. Run: + +```shell nocopy +$ step kms create --json --kms 'awskms:region=us-east-2' root-ca +``` + +Once the key is generated, `step` outputs the key ID and the public key PEM: + +``` +{ + "name": "awskms:key-id=78980acd-a42d-4d84-97ba-1e50d3082214", + "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH2ls6h1y2jsXV+IeuhDVkb68zkMe\nKPtI7L6vBIa5ThxOyFaZFnUrGWU6B+KQjProAntgKyNTqOnAh7Eyr3RmgQ==\n-----END PUBLIC KEY-----\n" +} +``` + +When creating the key, `step kms create` will also add an AWS key alias `root-ca-78980acd` for the key. +The alias is concatenates the key name and the first segment of the key's ID. + +You'll need this key name for the next step. + + +
+ We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, protection level, or other options for your environment. See step kms help create for details. +
+
+ +Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: + +```shell nocopy +$ step certificate create --profile root-ca \ + --kms 'awskms:region=us-east-2' \ + --key 'awskms:key-id=78980acd-a42d-4d84-97ba-1e50d3082214' \ + "Smallstep Root CA" root_ca.crt +``` + +Output: + +``` +Your certificate has been saved in root_ca.crt. +``` + +Great. Next, we'll repeat the process for the Intermediate CA: + +```shell nocopy +$ step kms create --json --kms 'awskms:region=us-east-2' intermediate-ca +$ step certificate create --profile intermediate-ca \ + --kms 'awskms:region=us-east-2' \ + --ca-kms 'awskms:region=us-east-2' \ + --ca root_ca.crt \ + --ca-key 'awskms:key-id=78980acd-a42d-4d84-97ba-1e50d3082214' \ + --key 'awskms:key-id=9432458d-1e67-4a74-9a23-8f94708b45fe' \ + "Smallstep Intermediate CA" intermediate_ca.crt +``` + +Here, the `--ca-key` is the root CA key id; the `--key` is the intermediate CA key id. + +Output: + +``` +Your certificate has been saved in intermediate_ca.crt. +``` + +Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. +You'll need these files for your CA configuration, below. + +If you want to run an SSH CA, you'll also need to create SSH CA key pairs: + +```shell nocopy +$ step kms create --json --kms 'awskms:region=us-east-2' ssh-user-ca +$ step kms create --json --kms 'awskms:region=us-east-2' ssh-host-ca +``` + +Hold onto the key IDs from these commands; you'll need them below. + +### Configuring `step-ca` to use AWS KMS + +To use `step-ca` with AWS KMS, create a scoped IAM role that has `kms:GetPublicKey` permissions on all of your CA keys, and `kms:Sign` permission on your intermediate CA key. + +To configure AWS KMS in your certificate authority, add the `kms` object to `ca.json` and replace the `key` property with the AWS KMS key ID of your intermediate CA key: + +```json nocopy +{ + "root": "/etc/step-ca/certs/root_ca.crt", + "crt": "/etc/step-ca/certs/intermediate_ca.crt", + "key": "awskms:key-id=f879f239-feb6-4596-9ed2-b1606277c7fe", + "kms": { + "type": "awskms", + "uri": "awskms:region=us-east-2;profile=foo;credentials-file=/path/to/credentials" + } +} +``` + +By default, `step-ca` (and, more broadly, AWS's SDK) looks for credentials stored in `~/.aws/credentials`. Use the `credentials-file` option to override. The `region` and `profile` options specify the AWS region and configuration profiles respectively. These options can also be configured using environment variables as described in the [AWS SDK for Go session documentation](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/). + +Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: + +```shell nocopy +$ cp root_ca.crt intermediate_ca.crt $(step path)/certs +``` + +Your X.509 CA is ready. + +To configure an SSH CA, replace the SSH key locations with the SSH CA keys you created above: + +```json nocopy +{ + "ssh": { + "hostKey": "awskms:key-id=d48e502a-09bc-4bf7-9af8-ae1bccedc931", + "userKey": "awskms:key-id=cf28e942-1e10-4a08-b84c-5359af1b5f12" + } +} +``` + +When you start `step-ca`, it prints your X.509 root fingerprint, and the SSH user and host CA keys in SSH key format: + +``` +2022/09/20 16:28:45 The primary server URL is https://localhost:443 +2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem +2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 +2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= +2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= +2022/09/20 16:28:45 Serving HTTPS on :443 ... +``` + +### Notes on AWS KMS Permissions + +Following the principle of least privilege, you'll want to define an IAM operational role for step-ca that limits its access. +See [Using IAM Policies With AWS KMS](https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html) for an overview. + +Here are some notes on granting a custom IAM role that provides step-ca with access to AWS KMS: +* You can constrain the role to specific keys that you created for step-ca, by listing each key's ARN in the Resource block of the JSON policy. +* For day-to-day operation, grant `step-ca` the following permissions: + * `kms:GetPublicKey` + * `kms:Sign` + +## Azure Key Vault + +[Azure Key Vault](https://azure.microsoft.com/en-us/products/key-vault) is Microsoft's managed key management service. + +### Authentication + +When using Azure Key Vault with `step-ca`, first authenticate to Azure. + +Authentication to Azure is handled via environment variables; +we recommend using either [file-based authentication](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-file-based-authentication) via the `AZURE_AUTH_LOCATION` environment variable, +or [using a managed identity](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication-managed-identity?tabs=azure-cli) and setting the `AZURE_TENANT_ID` and `AZURE_CLIENT_ID` variables when starting `step-ca`. +Alternatively, you can create a [service principal](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli) and set the `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` variables. +See Option 1 under [Authentication Methods for Azure SDK for Go](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authentication?tabs=bash#-option-1-define-environment-variables) for examples of authentication methods and environment variables. + +For local development and testing, Azure CLI credentials are used if no authentication environment variables are set. + +### Initialize a PKI + +To initialize a PKI backed by Azure Key Vault, start by authenticating to Azure using one of the above approaches. +Set the environment variables necessary for authentication to your tenant. + +Then, run: + +```bash +$ step ca init --kms azurekms +``` + +This walks you through the process of creating root and intermediate CA signing keys in Key Vault, and configuring the CA to use them. +If you're creating an SSH CA, SSH host and user CA keys are created in Key Vault as well. + +### Manual Configuration + +To configure an existing CA for Azure Key Vault, or to import an existing Azure Key Vault signing key, add the `kms` object to your `ca.json`, and replace the `key` properties with the key name, vault name, and version of your intermediate (signing) key in Azure Key Vault: + +```json nocopy +{ + "root": "/etc/step-ca/certs/root_ca.crt", + "crt": "/etc/step-ca/certs/intermediate_ca.crt", + "key": "azurekms:name=intermediate-ca-key;vault=example-vault-0?version=15faf8b8b80d4f1ead067c6383a38b8f&hsm=true", + "kms": { + "type": "azurekms" + } +} +``` + +* In the `key` URI, the `name` and `vault` refer to the key name and vault name of your intermediate key in Azure Key Vault. +* In the `key` URI, the `version` is the version of the Azure Key Vault key name. Though it is optional, we recommend setting this value explicitly. If omitted, the latest version is used. +* In the `key` URI, the optional `hsm` property can be set to `true` if HSM protection is desired. This is only used when the key is being created by `step-ca`. The default is to use software-protected (non-HSM-backed) keys. See Key Vault's [About Keys](https://docs.microsoft.com/en-us/azure/key-vault/keys/about-keys) page for more details. +* In `kms`, an optional `uri` property can be added to provide client credentials (eg. `azurekms:client-id=fooo;client-secret=bar;tenant-id=9de53416-4431-4181-7a8b-23af3EXAMPLE`) instead of using the environment variables described above. + +### Notes on Azure Key Vault IAM Permissions + +Following the principle of least privilege, you'll want to define an IAM operational role for step-ca that limits its access. +See [Provide access to Key Vault keys, certificates, and secrets with an Azure role-based access control](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli) for an overview. + +Here are some notes on granting a custom IAM role that provides step-ca with access to Azure Key Vault: +* You can constrain the role to the vault that you created for step-ca. +* For day-to-day operation, grant `step-ca` the following default RBAC roles on the vault: + * Key Vault Crypto User + * Key Vault Reader +* More specifically, a running `step-ca` needs access to the following APIs: + * `GetKey` + * `Sign` + +## PKCS #11 + + +
+ The standard `step-ca` binary does not support PKCS #11.
+ For PKCS #11 support, you'll need a CGO build of `step-ca`. + When built with CGO, `step-ca` can call native PKCS #11 C libraries.
+ You can either:
+ - Build `step-ca` yourself. See Building From Source Using CGO, or
+ - Use the `step-ca:hsm` Docker image. The `hsm` tag is built with CGO.
+
+
+ +A Hardware Security Module (HSM) is a specialized piece of hardware that is designed to generate and store private keys, and sign messages using those keys. +The private keys on an HSM cannot be exported from the device. +One can only run signing operations using the key. +This is an excellent way to protect private keys for a Certificate Authority, +which in normal operation simply needs to be able to sign Certificate Signing Requests. + +[Public-Key Cryptography Standards #11 (PKCS #11)](https://en.wikipedia.org/wiki/PKCS_11) is the most common platform-independent API used to access HSM hardware. +It's supported by most HSM hardware, like Yubico's [YubiHSM2](https://www.yubico.com/product/yubihsm-2/), and the [Nitrokey HSM 2](https://shop.nitrokey.com/shop/product/nk-hsm-2-nitrokey-hsm-2-7). +There's also a software-based "HSM," [SoftHSMv2](https://github.com/opendnssec/SoftHSMv2), which offers a PKCS #11 interface without the hardware. + +### 0. Before you begin + +Your HSM may need to be prepared before you can initialize a PKI on it. +Preparation steps depend on the device and are beyond the scope of this documentation. +For example, with YubiHSM2, first create an authentication key with appropriate capabiliites. + +Plan how you will backup and restore your CA keys, for offline storage. + +The `step kms` plugin will create CA keys and sign certificates on your device. +To use it, you'll need to provide a PKCS #11 URI for accessing the device, using the `--kms` flag. + +Here are some examples of PKCS #11 URIs for accessing various devices in Linux: + +HSM | URI format +-------------------------- | ------------------------------------------------------------------------------------- +YubiHSM2 | `pkcs11:module-path=/usr/lib/x86_64-linux-gnu/pkcs11/yubihsm_pkcs11.so;token=YubiHSM` +AWS CloudHSM | `pkcs11:module-path=/opt/cloudhsm/lib/libcloudhsm_pkcs11.so;token=cavium?pin-value=$HSM_USER:$HSM_PASSWORD` +SoftHSM | `pkcs11:module-path=/usr/lib/softhsm/libsofthsm2.so;token=token1?pin-value=$HSM_PASSWORD` +nCipher nShield | `pkcs11:module-path=/opt/nfast/toolkits/pkcs11/libcknfast.so;token=rjk?pin-source=/etc/step-ca/hsm-pin.txt` + +Substitute `$HSM_USER` and `$HSM_PASSWORD` with your own values. + +In this URI, +* `module-path` points to your PKCS #11 `.dll`, `.so`, or `.dylib` library file, +* `token` is the label (`CKA_LABEL`) of the HSM you're using, +* `pin-value` contains hardcoded HSM credentials. It may be a PIN, username and password, password, or a filename. The YubiHSM2 is special in that the PIN value is the concatenation of the four-digit authorization key ID (eg. `0001`) and the PIN. +* Or, `pin-source` is a filename containing HSM credentials. + +### 1. Create your PKI + +Once you've constructed the right URI for accessing your device, use it in place of `$PKCS_URI` in the commands below. + +First, please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. + +Next, let's ask the device to generate a private key for your root CA. Run: + +```shell nocopy +$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7331;object=root-ca" +``` + +Once the key is generated, `step` will output the key ID and the public key PEM: + +``` +{ + "name": "pkcs11:id=7331;object=root-ca", + "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH2ls6h1y2jsXV+IeuhDVkb68zkMe\nKPtI7L6vBIa5ThxOyFaZFnUrGWU6B+KQjProAntgKyNTqOnAh7Eyr3RmgQ==\n-----END PUBLIC KEY-----\n" +} +``` + +You'll need this key name for the next step. + + +
+ We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, protection level, or other options for your environment. See step kms help create for details. +
+
+ +Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: + +```shell nocopy +$ step certificate create --profile root-ca \ + --kms "$PKCS_URI" + --key "pkcs11:id=7331;object=root-ca" \ + "Smallstep Root CA" root_ca.crt +``` + +Output: + +``` +Your certificate has been saved in root_ca.crt. +``` + +Great. Next, we'll repeat the process for the Intermediate CA: + +```shell nocopy +$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7332;object=intermediate-ca" +$ step certificate create --profile intermediate-ca \ + --kms "$PKCS_URI" \ + --ca-kms "$PKCS_URI" \ + --ca root_ca.crt \ + --ca-key "pkcs11:id=7331;object=root-ca" \ + --key "pkcs11:id=7332;object=intermediate-ca" \ + "Smallstep Intermediate CA" intermediate_ca.crt +``` + +Here, the `--ca-key` is the root CA key id; the `--key` is the intermediate CA key id. + +Output: + +``` +Your certificate has been saved in intermediate_ca.crt. +``` + +Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. +You'll need these files for your CA configuration, below. + +If you want to run an SSH CA, you'll also need to create SSH CA key pairs: + +```shell nocopy +$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7333;object=ssh-host-ca" +$ step kms create --json --kms "$PKCS_URI" "pkcs11:id=7334;object=ssh-user-ca" +``` + +Hold onto the key IDs from these commands; you'll need them below. + +### Configuring `step-ca` to use PKCS #11 + +One you've created your PKI on the HSM using `step-kms-plugin`, you'll need to configure `step-ca` to use the HSM. + +To configure your certificate authority, add the `kms` object to `ca.json` and replace the `key` property with the object ID of your intermediate CA key: + +```json nocopy +{ + "root": "/etc/step-ca/certs/root_ca.crt", + "crt": "/etc/step-ca/certs/intermediate_ca.crt", + "key": "pkcs11:id=7332;object=intermediate-ca", + "kms": { + "type": "pkcs11", + "uri": "$PKCS_URI" + } +} +``` + +Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: + +```shell nocopy +$ cp root_ca.crt intermediate_ca.crt $(step path)/certs +``` + +Your X.509 CA is ready. + +To configure an SSH CA, replace the SSH key locations with the SSH CA keys you created above: + +```json nocopy +{ + "ssh": { + "hostKey": "pkcs11:id=7333;object=ssh-host-ca", + "userKey": "pkcs11:id=7334;object=ssh-user-ca" + } +} +``` + +When you start `step-ca`, you will see your X.509 root fingerprint, and the SSH user and host CA keys in SSH key format: + +``` +2022/09/20 16:28:45 The primary server URL is https://localhost:443 +2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem +2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 +2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= +2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= +2022/09/20 16:28:45 Serving HTTPS on :443 ... +``` + +## TPM 2.0 + + +
+ The standard `step-ca` binary does not support TPM 2.0.
+ For native TPM 2.0 support, you'll need a CGO build of `step-ca`. + When built with CGO, `step-ca` can call native Yubico C libraries.
+ You can either:
+ - Build `step-ca` yourself. See Building From Source Using CGO, or
+ - Use the `step-ca:hsm` Docker image. The `hsm` tag is built with CGO.
+
+
+ +You can leverage a TPM 2.0 chip to store your CA key and sign TLS certificates. + +### Prerequisites and Caveats + +* To enable TPM 2.0 support in `step-ca`, you must follow our [Instructions for building from source using CGO](https://github.com/smallstep/certificates/blob/master/CONTRIBUTING.md#build-step-ca-using-cgo) +* You will need a TPM 2.0 chip and (on Linux) the [`tpm2-tss` package](https://github.com/tpm2-software/tpm2-tss) +* You can use the TPM for X.509 CAs +* Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. + +First, let's generate your Root CA on disk. +After this tutorial, you will only need the root private key if you issue another Intermediate CA. + +Run: + +```shell nocopy +$ step certificate create --profile root-ca \ + "Smallstep Root CA" \ + root_ca.crt \ + root_ca.key +``` + +Output: + +``` +Your certificate has been saved in root_ca.crt. +Your private key has been saved in root_ca.key. +``` + +Great. +For a production PKI, +it is recommended that you create this key on an airgapped device with secure backups. + +Next, we'll create an Intermediate CA key on the TPM, +and sign an Intermediate CA certificate: + +```shell nocopy +$ step kms create --json 'tpmkms:name=my-intermediate-ca' +$ step certificate create --profile intermediate-ca \ + --kms 'tpmkms:' \ + --ca root_ca.crt \ + --ca-key root_ca.key \ + --key 'tpmkms:name=my-intermediate-ca' \ + "Smallstep Intermediate CA" intermediate_ca.crt +``` + +Here, the `--ca-key` is your root CA; the `--key` is the intermediate CA key id. + +Output: + +``` +Your certificate has been saved in intermediate_ca.crt. +``` + +Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. +You no longer need your `root_ca.key`, so you can now store it in a safe place. + +Finally, to enable your CA in `ca.json`, point the `root` and `crt` options to the generated certificates, replace the `key` option with the TPM KMS URI: + +```json nocopy +{ + "root": "/etc/step-ca/certs/root_ca.crt", + "crt": "/etc/step-ca/certs/intermediate_ca.crt", + "key": "tpmkms:name=my-intermediate-ca", + "kms": { + "type": "tpmkms", + "uri": "tpmkms:" + } +} +``` + +Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: + +```shell nocopy +$ cp root_ca.crt intermediate_ca.crt $(step path)/certs +``` + +Your X.509 CA is ready. When you start `step-ca`, it prints your X.509 root fingerprint: + +``` +2022/09/20 16:28:45 The primary server URL is https://localhost:443 +2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem +2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 +2022/09/20 16:28:45 Serving HTTPS on :443 ... +``` + +## YubiKey PIV + + +
+ The standard `step-ca` binary does not support YubiKey PIV.
+ For YubiKey PIV support, you'll need a CGO build of `step-ca`. + When built with CGO, `step-ca` can call native Yubico C libraries.
+ You can either:
+ - Build `step-ca` yourself. See Building From Source Using CGO, or
+ - Use the `step-ca:hsm` Docker image. The `hsm` tag is built with CGO.
+
+
+ +You can leverage a hardware [YubiKey](https://www.yubico.com/)—and the [YubiKey PIV application](https://www.yubico.com/authentication-standards/smart-card/)—to store your CA keys and sign TLS and SSH certificates. + +### Prerequisites and Caveats + +* To enable YubiKey support in `step-ca`, you must follow our [Instructions for building from source using CGO](https://github.com/smallstep/certificates/blob/master/CONTRIBUTING.md#build-step-ca-using-cgo) +* You will need a YubiKey 5 series device that [supports the PIV application](https://www.yubico.com/store/compare/) +* [Certificate slots](https://developers.yubico.com/PIV/Introduction/Certificate_slots.html) 9a, 9c, 9d, 9e, and 82-95 are supported +* You can use the YubiKey for X.509 and SSH CAs + +Please install the [`step kms` plugin](https://github.com/smallstep/step-kms-plugin) before you begin. You'll need it to create your PKI. + +Now, insert your YubiKey. +Let's generate a private key for your root CA in slot 82 on the YubiKey. +Run: + +```shell nocopy +$ step kms create --json 'yubikey:slot-id=82' +``` + +Once the key is generated, `step` outputs the key name and public key PEM: + +``` +{ + "name": "yubikey:slot-id=82", + "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAED3T/7q+p+6239Ri35TBVoChM6VNq\n1buLfql1acRl7F2qf/L96x9XHY5GHoqYNCAm/ocL9hTl8ytWJao+JSNE+Q==\n-----END PUBLIC KEY-----\n" +} +``` + + +
+ We have taken care to provide sane defaults in `step kms create`, but you may wish to change the key type, size, or other options for your environment. See step kms help create for details. +
+
+ +Now, let's sign a root CA certificate based on the the key you just created. Substitute the key name output from `step kms create` here: + +```shell nocopy +$ step certificate create --profile root-ca \ + --kms 'yubikey:pin-value=123456' \ + --key 'yubikey:slot-id=82' \ + "Smallstep Root CA" root_ca.crt +``` + +Here we're using the default PIN code of 123456 to access the YubiKey. + +Output: + +``` +Your certificate has been saved in root_ca.crt. +``` + +Great. Next, we'll repeat the process for the Intermediate CA: + +```shell nocopy +$ step kms create --json 'yubikey:slot-id=83' +$ step certificate create --profile intermediate-ca \ + --kms 'yubikey:pin-value=123456' \ + --ca-kms 'yubikey:pin-value=123456' \ + --ca root_ca.crt \ + --ca-key 'yubikey:slot-id=82' \ + --key 'yubikey:slot-id=83' \ + "Smallstep Intermediate CA" intermediate_ca.crt +``` + +Here, the `--ca-key` is the root CA key id; the `--key` is the intermediate CA key id. + +Output: + +``` +Your certificate has been saved in intermediate_ca.crt. +``` + +Now you should have both `root_ca.crt` and `intermediate_ca.crt` certificate PEM files. +You'll need these files for your CA configuration, below. + +for safekeeping, you may wish to import the certificates into the YubiKey. To do this, you'll need Yubico's [`ykman` CLI utility](https://developers.yubico.com/yubikey-manager/). Run: + +```shell nocopy +$ ykman piv certificates import 82 root_ca.crt +$ ykman piv certificates import 83 intermediate_ca.crt +``` + +(While `step-ca` won't use these copies of the certificates, you can always use `ykman piv certificates export` to download the certificates later.) + +Next, if you want to run an SSH CA, you'll also need to create two SSH CA keys: + +```shell nocopy +$ step kms create --json 'yubikey:slot-id=84' +$ step kms create --json 'yubikey:slot-id=85' +``` + +Finally, to enable your CA in `ca.json`, point the `root` and `crt` options to the generated certificates, replace the `key` option with the YubiKey URI generated in the previous part, and configure the `kms` option with the appropriate `type` and `pin`. + +```json nocopy +{ + "root": "/etc/step-ca/certs/root_ca.crt", + "crt": "/etc/step-ca/certs/intermediate_ca.crt", + "key": "yubikey:slot-id=83", + "kms": { + "type": "yubikey", + "uri": "yubikey:management-key=01020304...?pin-value=123456" + } +} +``` + +Finally, copy the `root_ca.crt` and `intermediate_ca.crt` files into the `root` and `crt` locations: + +```shell nocopy +$ cp root_ca.crt intermediate_ca.crt $(step path)/certs +``` + +Your X.509 CA is ready. + +To configure an SSH CA, replace the SSH key locations with the SSH CA keys you created in AWS KMS: + +```json nocopy +{ + "ssh": { + "hostKey": "yubikey:slot-id=84", + "userKey": "yubikey:slot-id=85" + } +} +``` + +When you start `step-ca`, it prints your X.509 root fingerprint, and the SSH host and user CA keys in SSH key format: + +``` +2022/09/20 16:28:45 The primary server URL is https://localhost:443 +2022/09/20 16:28:45 Root certificates are available at https://localhost:443/roots.pem +2022/09/20 16:28:45 X.509 Root Fingerprint: b061dfca1013c074244b0f376e5be70b6eb0bd7f21d5438aa3af71fe62b0acf5 +2022/09/20 16:28:45 SSH Host CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIwmL7aDOJId/9UOVJGhVux6Rlvea+q2017aLsfze+/EwGQ5BdZ4k2Qh+5VekebBKZYLNO0LkSf9bZb4o9GSxIs= +2022/09/20 16:28:45 SSH User CA Key: ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFE0VY9eLxkoHrXoWk5VxeOQTUt53U5xIo89pfsgYHh450cdE4c3mYw5YeOueESyu/lFUHfJoNS6twVR1wuCOdc= +2022/09/20 16:28:45 Serving HTTPS on :443 ... +``` + + diff --git a/step-ca/integrations.mdx b/step-ca/integrations.mdx index 298b4cb4..8756f20b 100644 --- a/step-ca/integrations.mdx +++ b/step-ca/integrations.mdx @@ -107,16 +107,21 @@ Learn more about how to [install and configure `step-sds`][step-sds]. Cloud Key Management Services allow users to store cryptographic keys and sign certificates using cloud storage and APIs. Integrations with Google Cloud KMS, Amazon AWS KMS, and Azure Key Vault are currently supported. -[Learn more.](./configuration.mdx#cryptographic-protection) +[Learn more.](./cryptographic-protection.mdx) ### YubiKey PIV Want to store your CA locally on a YubiKey? `step-ca` supports the YubiKey PIV application. -[Learn more.](./configuration.mdx#yubikey-piv) +[Learn more.](./cryptographic-protection.mdx#yubikey-piv) + +### TPM 2.0 + +`step-ca` supports storing your CA in a hardware Trusted Platform Module (TPM 2.0) +[Learn more.](./cryptographic-protection.mdx#tpm-20) ### PKCS#11 HSMs `step-ca` supports PKCS#11 hardware security modules (HSMs). -[Learn more.](./configuration.mdx#pkcs-11) +[Learn more.](./cryptographic-protection.mdx#pkcs-11) diff --git a/step-ca/provisioners.mdx b/step-ca/provisioners.mdx index ec5dd328..3164579a 100644 --- a/step-ca/provisioners.mdx +++ b/step-ca/provisioners.mdx @@ -302,10 +302,57 @@ 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 -validate a JSON Web Token (JWT). +JSON Web Key (JWK) is the default CA provisioner type, +and the [`step ca certificate`](../step-cli/reference/ca/certificate) client tries to use it by default. +With a JWK provisioner, +a Certificate Signing Request (CSR) is sent to the CA +along with a short-lived JSON Web Token (JWT) which authenticates the request. -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. +The JWK provisioner can be useful for custom integrations. +JWTs are easy to [generate programmatically](https://jwt.io/#libraries-io), +without using `step`. +We have written a few [example clients](https://github.com/smallstep/clients/tree/main) for demonstration purposes. + +Here's an example JWT used by `step-ca`: + +```shell +$ step ca token foo.internal | step crypto jwt inspect --insecure +{ + "header": { + "alg": "ES256", + "kid": "kXLZ2xHQEXAMPLEq4j38N5QzQzNBmOPp0NCLzKAI0yA", + "typ": "JWT" + }, + "payload": { + "aud": "https://ca.internal/1.0/sign", + "exp": 1711479459, + "iat": 1711479159, + "iss": "carl@tashian.com", + "jti": "8211a180b6EXAMPLEed81da54132e9...", + "nbf": 1711479159, + "sans": [ + "foo.internal" + ], + "sha": "c8de28e620ecEXAMPLE4a0c405d92d7350dbec351cec3e4f6a6d1fc9512387aa", + "sub": "foo.internal" + }, + "signature": "MEcSHfmIEXAMPLElNiLoDcHz90..." +} +``` + +The JWT subject (`sub`) specifies a subject Common Name for the issued certificate. +The `sha` and `sans` claims are non-standard: +they specify the root CA certificate fingerprint in SHA256 +and any subject alternative name(s) +that are authorized for inclusion in the issued certificate. + +The JWT is designed to be generated in one context, then passed into the context where it will be used (eg. a container or pod). +Meanwhile, sensitive private key material can remain in the context where it is generated. +Therefore, by default, the JWT is not bound to the CSR, which may not yet exist when the token is created. +The JWT is instead bound to the expected SANs, subject common name, and the CA's root fingerprint. +See [Issue a Certificate Using A Single-Use CA Token](https://smallstep.com/docs/step-ca/basic-certificate-authority-operations/#issue-a-certificate-using-a-single-use-ca-token) for an example. + +Optionally, a confirmation claim (`cnf`) can be added (as defined in [RFC 7800 § 3.4](https://datatracker.ietf.org/doc/html/rfc7800#section-3.4) to bind the JWT to a CSR. See [smallstep/certificates#1637](https://github.com/smallstep/certificates/issues/1637#issuecomment-1871620791) for details. #### Example @@ -404,60 +451,60 @@ Please enter the password to decrypt the content encryption key: 1. Retrieve the current encrypted key. - Run the following, changing the provisioner name in the `jq` command to match your configuration: - - ```shell - OLD_ENCRYPTED_KEY=$(step ca provisioner list \ - | jq -r '.[] | select(.name == "you@smallstep.com").encryptedKey') - ``` + Run the following, changing the provisioner name in the `jq` command to match your configuration: + + ```shell + OLD_ENCRYPTED_KEY=$(step ca provisioner list \ + | jq -r '.[] | select(.name == "you@smallstep.com").encryptedKey') + ``` 2. Update the encrypted key password. - Run: - - ```shell - ENCRYPTED_KEY=$(echo $OLD_ENCRYPTED_KEY | \ - step crypto jwe decrypt | \ - step crypto jwe encrypt --alg PBES2-HS256+A128KW | \ - step crypto jose format) - ``` - - You'll be asked for the old and new passwords. + Run: + + ```shell + ENCRYPTED_KEY=$(echo $OLD_ENCRYPTED_KEY | \ + step crypto jwe decrypt | \ + step crypto jwe encrypt --alg PBES2-HS256+A128KW | \ + step crypto jose format) + ``` + + You'll be asked for the old and new passwords. 3. Update the provisioner. - Run the following, changing the provisioner name in the command to match your configuration: - - ```shell - step ca provisioner update you@smallstep.com \ - --private-key=<(echo -n "$ENCRYPTED_KEY") - ``` + Run the following, changing the provisioner name in the command to match your configuration: + + ```shell + step ca provisioner update you@smallstep.com \ + --private-key=<(echo -n "$ENCRYPTED_KEY") + ``` 4. Send a `SIGHUP` to `step-ca` to reload the configuration file. - (Skip this step if you have enabled remote provisioner administration.) - - ```shell - killall -i -s SIGHUP step-ca - ``` + (Skip this step if you have enabled remote provisioner administration.) + + ```shell + killall -i -s SIGHUP step-ca + ``` #### Rekeying a JWK provisioner 1. Update the provisioner. - Run the following, changing the provisioner name in the command to match your configuration: - - ```shell - step ca provisioner update you@smallstep.com --create - ``` + Run the following, changing the provisioner name in the command to match your configuration: + + ```shell + step ca provisioner update you@smallstep.com --create + ``` 2. Send a `SIGHUP` to `step-ca` to reload the configuration file. - (Skip this step if you have enabled remote provisioner administration.) - - ```shell - killall -i -s SIGHUP step-ca - ``` + (Skip this step if you have enabled remote provisioner administration.) + + ```shell + killall -i -s SIGHUP step-ca + ``` #### Removing the encrypted private key from a JWK provisioner @@ -467,19 +514,19 @@ To remove this key: 1. Update the provisioner. - Run the following, changing the provisioner name in the command to match your configuration: - - ```shell - step ca provisioner update you@smallstep.com --private-key "" - ``` + Run the following, changing the provisioner name in the command to match your configuration: + + ```shell + step ca provisioner update you@smallstep.com --private-key "" + ``` 2. Send a `SIGHUP` to `step-ca` to reload the configuration file. - (Skip this step if you have enabled remote provisioner administration.) - - ```shell - killall -i -s SIGHUP step-ca - ``` + (Skip this step if you have enabled remote provisioner administration.) + + ```shell + killall -i -s SIGHUP step-ca + ``` ### OAuth/OIDC Single Sign-on