Remove deprecated docs directory

This commit is contained in:
max furman 2022-11-07 20:18:42 -08:00
parent 80cbcb652b
commit dde9330244
No known key found for this signature in database
19 changed files with 0 additions and 3121 deletions

View file

@ -1,740 +0,0 @@
# Getting Started
Demonstrates setting up your own public key infrastructure (PKI) and certificate authority (CA) using `step ca`
and getting certificates using the `step` command line tool and SDK.
Check out [Getting started with docker](docker.md) to run [step certificates](https://github.com/smallstep/certificates)
using docker.
![Animated terminal showing step ca init in practice](https://smallstep.com/images/blog/2018-12-04-unfurl.gif)
## Prerequisites
* [Step CA](#installation-guide)
## Terminology
### PKI - Public Key Infrastructure
A set of roles, policies, and procedures needed to create, manage, distribute,
use, store, and revoke digital certificates and manage public-key encryption.
The purpose of a PKI is to facilitate the secure electronic transfer of
information for a range of network activities.
### Provisioners
Provisioners are people or code that are registered with the CA and authorized
to issue "provisioning tokens". Provisioning tokens are single use tokens that
can be used to authenticate with the CA and get a certificate.
See [provisioners.md](provisioners.md) for more information on the supported
provisioners and its options.
## Initializing PKI and configuring the Certificate Authority
To initialize a PKI and configure the Step Certificate Authority run:
> **NOTE**: `step ca init` only initialize an x509 CA. If you
> would like to initialize an SSH CA as well, add the `--ssh` flag.
```
step ca init [--ssh]
```
You'll be asked for a name for your PKI. This name will appear in your CA
certificates. It doesn't really matter what you choose. The name of your
organization or your project will suffice.
If you run:
```
tree $(step path)
```
You should see:
```
.
├── certs
│   ├── intermediate_ca.crt
│   ├── root_ca.crt
│   ├── ssh_host_key.pub (--ssh only)
│   └── ssh_user_key.pub (--ssh only)
├── config
│   ├── ca.json
│   └── defaults.json
└── secrets
├── intermediate_ca_key
├── root_ca_key
├── ssh_host_key (--ssh only)
└── ssh_user_key (--ssh only)
```
The files created include:
* `root_ca.crt` and `root_ca_key`: the root certificate and private key for
your PKI.
* `intermediate_ca.crt` and `intermediate_ca_key`: the intermediate certificate
and private key that will be used to sign leaf certificates.
* `ssh_host_key.pub` and `ssh_host_key` (`--ssh` only): the SSH host pub/priv key
pair that will be used to sign new host SSH certificates.
* `ssh_user_key.pub` and `ssh_user_key` (`--ssh` only): the SSH user pub/priv key
pair that will be used to sign new user SSH certificates.
* `ca.json`: the configuration file necessary for running the Step CA.
* `defaults.json`: file containing default parameters for the `step` CA cli
interface. You can override these values with the appropriate flags or
environment variables.
All of the files ending in `_key` are password protected using the password
you chose during PKI initialization. We advise you to change these passwords
(using the `step crypto change-pass` utility) if you plan to run your CA in a
non-development environment.
## What's Inside `ca.json`?
`ca.json` is responsible for configuring communication, authorization, and
default new certificate values for the Step CA. Below is a short list of
definitions and descriptions of available configuration attributes.
* `root`: location of the root certificate on the filesystem. The root certificate
is used to mutually authenticate all api clients of the CA.
* `crt`: location of the intermediate certificate on the filesystem. The
intermediate certificate is returned alongside each new certificate,
allowing the client to complete the certificate chain.
* `key`: location of the intermediate private key on the filesystem. The
intermediate key signs all new certificates generated by the CA.
* `password`: optionally store the password for decrypting the intermediate private
key (this should be the same password you chose during PKI initialization). If
the value is not stored in configuration then you will be prompted for it when
starting the CA.
* `address`: e.g. `127.0.0.1:8080` - address and port on which the CA will bind
and respond to requests.
* `dnsNames`: comma separated list of DNS Name(s) for the CA.
* `logger`: the default logging format for the CA is `text`. The other option
is `json`.
* `db`: data persistence layer. See [database documentation](./database.md) for more
info.
* `type`: `badger`, `bbolt`, `mysql`, etc.
* `dataSource`: string that can be interpreted differently depending on the
type of the database. Usually a path to where the data is stored. See the
[database configuration docs](./database.md#configuration) for more info.
* `database`: name of the database. Used for backends that may have multiple
databases. e.g. MySQL
* `valueDir`: directory to store the value log in (Badger specific).
* `crl`: Certificate Revocation List settings:
* `enable`: enables CRL generation (`true` to generate, `false` to disable)
* `generateOnRevoke`: a revoke will generate a new CRL if the crl is enabled.
* `cacheDuration`: the duration until next update of the CRL, defaults to 24h.
* `renewPeriod`: the time between CRL regeneration. If not set ~2/3 of the
cacheDuration will be used.
* `tls`: settings for negotiating communication with the CA; includes acceptable
ciphersuites, min/max TLS version, etc.
* `authority`: controls the request authorization and signature processes.
- `template`: default ASN1DN values for new certificates.
- `claims`: default validation for requested attributes in the certificate request.
Can be overriden by similar claims objects defined by individual provisioners.
* `minTLSCertDuration`: do not allow certificates with a duration less
than this value.
* `maxTLSCertDuration`: do not allow certificates with a duration greater
than this value.
* `defaultTLSCertDuration`: if no certificate validity period is specified,
use this value.
* `disableIssuedAtCheck`: disable a check verifying that provisioning
tokens must be issued after the CA has booted. This is one prevention
against token reuse. The default value is `false`. Do not change this
unless you know what you are doing.
SSH CA properties
* `minUserSSHDuration`: do not allow certificates with a duration less
than this value.
* `maxUserSSHDuration`: do not allow certificates with a duration
greater than this value.
* `defaultUserSSHDuration`: if no certificate validity period is specified,
use this value.
* `minHostSSHDuration`: do not allow certificates with a duration less
than this value.
* `maxHostSSHDuration`: do not allow certificates with a duration
greater than this value.
* `defaultHostSSHDuration`: if no certificate validity period is specified,
use this value.
* `enableSSHCA`: enable all provisioners to generate SSH Certificates.
The deault value is `false`. You can enable this option per provisioner
by setting it to `true` in the provisioner claims.
- `provisioners`: list of provisioners.
See the [provisioners documentation](./provisioners.md). Each provisioner
has an optional `claims` attribute that can override any attribute defined
at the level above in the `authority.claims`.
`step ca init` will generate one provisioner. New provisioners can be added by
running `step ca provisioner add`.
## Running the CA
To start the CA run:
```
export STEPPATH=$(step path)
step-ca $STEPPATH/config/ca.json
```
### Systemctl
Consider adding a service user that will only be used by `systemctl` to manage
the service.
```
$ useradd step
$ passwd -l step
```
Use the following example as a base for your `systemctl` service file:
```
[Unit]
Description=step-ca
After=syslog.target network.target
[Service]
User=step
Group=step
ExecStart=/bin/sh -c '/bin/step-ca /home/step/.step/config/ca.json --password-file=/home/step/.step/pwd >> /var/log/step-ca/output.log 2>&1'
Type=simple
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
```
The following are a few example commands you can use to check the status,
enable on restart, and start your `systemctl` service.
```
# Check the current status of the `step-ca` service
$ systemctl status step-ca
# Configure the `step-ca` process to startup on reboot automatically
$ systemctl enable step-ca
# Start the `step-ca` service.
$ systemctl start step-ca
```
## Configure Your Environment
**Note**: Configuring your environment is only necessary for remote servers
(not the server on which the `step ca init` command was originally run).
Many of the cli utilities under `step ca [sub-command]` interface directly with
a running instance of the Step CA. The CA exposes an HTTP API and clients are
required to connect using HTTP over TLS (aka HTTPS). As part of bootstraping
the Step CA, a certificate was generated using the root of trust that was
created when you initilialized your PKI. In order to properly validate this
certificate clients need access to the public root of trust, aka the public root
certificate. If you are using the `step cli` on the same host where you
initialized your PKI (the `root_ca.crt` is stored on disk locally), then you can
continue to [setting up your environment](#setup-env),
otherwise we will show you how to easily download your root certificate in the
following step.
#### Download the Root Certificate
The next few steps are a guide for downloading the root certificate of your PKI
from a running instance of the CA. First we'll define two servers:
* **remote server**: This is the server where the Step CA is running. This may
also be the server where you initialized your PKI, but for security reasons
you may have done that offline.
* **local server**: This is the server that wants access to the `step ca [sub-command]`
* **ca-url**: This is the url at which the CA is listening for requests. This
should be a combination of the DNS name and port entered during PKI initialization.
In the examples below we will use `https://ca.smallstep.com:8080`.
1. Get the Fingerprint.
From the **remote server**:
```
$ FP=$(step certificate fingerprint $(step path)/certs/root_ca.crt)
```
2. Bootstrap your environment.
From the **local server**:
```
$ step ca bootstrap --fingerprint $FP --ca-url "https://ca.smallstep.com:8080"
$ cat $(step path)/config/defaults.json
```
3. Test.
```
$ step ca health
```
<a name="setup-env"></a>
#### Setting up Environment Defaults
This is optional, but we recommend you populate a `defaults.json` file with a
few variables that will make your command line experience much more pleasant.
You can do this manually or with the step command `step ca bootstrap`:
```
$ step ca bootstrap \
--ca-url https://ca.smallstep.com:8080 \
--fingerprint 0d7d3834cf187726cf331c40a31aa7ef6b29ba4df601416c9788f6ee01058cf3
# Let's see what we got...
$ cat $STEPPATH/config/defaults.json
{
"ca-url": "https://ca.smallstep.com:8080",
"fingerprint": "628cfc85090ca65bb246d224f1217445be155cfc6167db4ed8f1b0e3de1447c5",
"root": "/Users/<you>/src/github.com/smallstep/step/.step/certs/root_ca.crt"
}
# Test it out
$ step ca health
```
* **ca-url** is the DNS name and port that you used when initializing the CA.
* **root** is the path to the root certificate on the file system.
* **fingerprint** is the root certificate fingerprint (SHA256).
You can always override these values with command-line flags or environment
variables.
To manage the CA provisioners you can also add the property **ca-config** with
the path to the CA configuration file, with that property you won't need to add
it in commands like `step ca provisioners [add|remove]`.
**Note**: to manage provisioners you must be on the host on which the CA is
running. You need direct access to the `ca.json` file.
### Hot Reload
It is important that the CA be able to handle configuration changes with no downtime.
Our CA has a built in `reload` function allowing it to:
1. Finish processing existing connections while blocking new ones.
2. Parse the configuration file and re-initialize the API.
3. Begin accepting blocked and new connections.
`reload` is triggered by sending a SIGHUP to the PID (see `man kill`
for your OS) of the Step CA process. A few important details to note when using `reload`:
* The location of the modified configuration must be in the same location as it
was in the original invocation of `step-ca`. So, if the original command was
```
$ step-ca ./.step/config/ca.json
```
then, upon `reload`, the Step CA will read it's new configuration from the same
configuration file.
* Step CA requires the password to decrypt the intermediate certificate, again,
upon `reload`. You can automate this in one of two ways:
* Use the `--password-file` flag in the original invocation.
* Use the top level `password` attribute in the `ca.json` configuration file.
### Let's issue a certificate!
There are two steps to issuing a certificate at the command line:
1. Generate a provisioning token using your provisioning credentials.
2. Generate a CSR and exchange it, along with the provisioning token, for a certificate.
If you would like to generate a certificate from the command line, the Step CLI
provides a single command that will prompt you to select and decrypt an
authorized provisioner and then request a new certificate.
```
$ step ca certificate "foo.example.com" foo.crt foo.key
```
If you would like to generate certificates on demand from an automated
configuration management solution (no user input) you would split the above flow
into two commands.
```
$ TOKEN=$(step ca token foo.example.com \
--kid 4vn46fbZT68Uxfs9LBwHkTvrjEvxQqx-W8nnE-qDjts \
--ca-url https://ca.example.com \
--root /path/to/root_ca.crt --password-file /path/to/provisioner/password)
$ step ca certificate "foo.example.com" foo.crt foo.key --token "$TOKEN"
```
You can take a closer look at the contents of the certificate using `step certificate inspect`:
```
$ step certificate inspect foo.crt
```
### List|Add|Remove Provisioners
The Step CA configuration is initialized with one provisioner; one entity
that is authorized by the CA to generate provisioning tokens for new certificates.
We encourage you to have many provisioners - ideally one for each entity in your
infrastructure.
**Why should I be using multiple provisioners?**
* Each certificate generated by the Step CA contains the ID of the provisioner
that issued the *provisioning token* authorizing the creation of the cert. This
ID is stored in the X.509 ExtraExtensions of the certificate under
`OID: 1.3.6.1.4.1.37476.9000.64.1` and can be inspected by running `step
certificate inspect foo.crt`. These IDs can and should be used to debug and
gather information about the origin of a certificate. If every member of your
ops team and the configuration management tools all use the same provisioner
to authorize new certificates you lose valuable visibility into the workings
of your PKI.
* Each provisioner should require a **unique** password to decrypt it's private key
-- we can generate unique passwords for you but we can't force you to use them.
If you only have one provisioner then every entity in the infrastructure will
need access to that one password. Jim from your dev ops team should not be using
the same provisioner/password combo to authorize certificates for debugging as
Chef is for your CICD - no matter how trustworthy Jim says he is.
Let's begin by listing the existing provisioners:
```
$ bin/step ca provisioner list
```
Now let's add a provisioner for Jim.
```
$ bin/step ca provisioner add jim@smallstep.com --create
```
**NOTE**: This change will not affect the Step CA until a `reload` is forced by
sending a SIGHUP signal to the process.
List the provisioners again and you will see that nothing has changed.
```
$ bin/step ca provisioner list
```
Now let's `reload` the CA. You will need to re-enter your intermediate
password unless it's in your `ca.json` or you are using `--password-file`.
```
$ ps aux | grep step-ca # to get the PID
$ kill -1 <pid>
```
Once the CA is running again, list the provisioners, again.
```
$ bin/step ca provisioner list
```
Boom! Magic.
Now suppose Jim forgets his password ('come on Jim!'), and he'd like to remove
his old provisioner. Get the `kid` (Key ID) of Jim's provisioner by listing
the provisioners and finding the appropriate one. Then run:
```
$ bin/step ca provisioner remove jim@smallstep.com --kid <kid>
```
Then `reload` the CA and verify that Jim's provisioner is no longer returned
in the provisioner list.
We can also remove all of Jim's provisioners, supposing Jim forgot all the passwords
('really Jim?'), by running the following:
```
$ bin/step ca provisioner remove jim@smallstep.com --all
```
The same entity may have multiple provisioners for authorizing different
types of certs. Each of these provisioners must have unique keys.
## Use Custom Claims for Provisioners to Control Certificate Validity etc
It's possible to configure provisioners on the CA to issue certs using
properties specific to their target environments. Most commonly different
validity periods and disabling renewals for certs. Here's how:
```bash
$ step ca init
# complete the init steps
$ step ca provisioner add --create dev@smallstep.com
# lets create a provisioner for dev certs
Please enter a password to encrypt the provisioner private key? password
# add claims inside a provisioner element in ~/.step/config/ca.json
~/.step/config/ca.json
[...]
"authority": {
"provisioners": [
{
"name": "you@smallstep.com",
"type": "jwk",
"key": {
"use": "sig",
"kty": "EC",
"kid": "Kg43gSukHnl8f5NztLPDxqpz_9TNUILnMrIMIa70jOU",
"crv": "P-256",
"alg": "ES256",
"x": "So0JVWFFXo-6GmDwq6WWZZk-AFZt5GKTx5PzdLhdsrQ",
"y": "kVz8pCl2Qx9fZmJZhXGrHpufwNDTp7oHwi8Zaj7rhiQ"
},
"encryptedKey": "...",
+ "claims": {
+ "minTLSCertDuration": "5s",
+ "maxTLSCertDuration": "12h",
+ "defaultTLSCertDuration": "2h",
+ "disableRenewal": true
+ }
}
]
},
[...]
## launch CA...
$ step-ca $(step path)/config/ca.json
Please enter the password to decrypt ~/.step/secrets/intermediate_ca_key: password
2019/02/21 12:09:51 Serving HTTPS on :9443 ...
```
See the [`provisioner doc`][1] for details on all available provisioner claims.
The durations are strings which are a sequence of decimal numbers, each with
optional fraction and a unit suffix, such as "300ms" or "2h45m". Valid time
units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
Now certs issued by the `dev@smallstep.com` provisioner will be valid for two
hours and deny renewals. Command line flags allow validity extension up to 12h,
please see [`step ca certificate`][2]'s docs for details.
[1]: ./provisioners.md
[2]: https://smallstep.com/docs/cli/ca/certificate/
```bash
# grab a cert, will also work with 'step ca token' flow
$ step ca certificate localhost site.crt site.key
Use the arrow keys to navigate: ↓ ↑ → ←
What provisioner key do you want to use?
IY7gYg_cDKmXtcs1sbhdBDDb9K9YvLO5aHzArjaayso (sebastian@smallstep.com)
▸ uBYWYDCpeJu_IYzMGPZ1LJJTdlaiJQfdpkOVewbjy-8 (dev@smallstep.com)
✔ Please enter the password to decrypt the provisioner key: password
✔ CA: https://ca.smallstep.com:9443/1.0/sign
✔ Certificate: site.crt
✔ Private Key: site.key
$ step certificate inspect site.crt --format json | jq .validity
{
"start": "2019-02-21T20:19:06Z",
"end": "2019-02-21T22:19:06Z",
"length": 7200
}
# renewals will be denied for certs issued by this provisioner
$ step ca renew site.crt site.key
error renewing certificate: Unauthorized
```
## Use Oauth OIDC to obtain personal certificates
To authenticate users with the CA you can leverage services that expose OAuth
OpenID Connect identity providers. One of the most common providers, and the
one we'll use in this example, is G-Suite.
Navigate to the Google APIs developer console and pick a suitable project from the
top navbar's dropdown.
![Google Dev Console](./images/oidc1.png)
In the masthead navigation click **Credentials** (key symbol) and then "OAuth
consent screen" from the subnav. Fill out naming details, all mandatory fields,
and decide if your app is of type **Public** or **Internal**. Internal
will make sure the access scope is bound to your G-Suite organization.
**Public** will let anybody with a Google Account log in, incl.
`gmail.com` accounts.
Move back to **Credentials** on the subnav and choose "OAuth client ID" from the
**Create credentials** dropdown. Since OIDC will be used from the `step CLI` pick **Other**
from the available options and pick a name (e.g. **Step CLI**).
![Create credential](./images/oidc2.png)
On successful completion, a confirmation modal with both `clientID` and
`clientSecret` will be presented. Please note that the `clientSecret` will
allow applications access to the configured OAuth consent screen. However, it
will not allow direct authentication of users without their own MfA credentials
per account.
![OIDC credentials](./images/oidc3.png)
Now using `clientID` and `clientSecret` run the following command to add
G-Suite as a provisioner to `step certificates`. Please see [`step ca
provisioner add`](https://smallstep.com/docs/cli/ca/provisioner/add/)'s docs
for all available configuration options and descriptions.
```bash
$ step ca provisioner add Google --type oidc --ca-config $(step path)/config/ca.json \
--client-id 972437157139-ssiqna0g4ibuhafl3pkrrcb52tbroekt.apps.googleusercontent.com \
--client-secret RjEk-GwKBvdsFAICiJhn_RiF \
--configuration-endpoint https://accounts.google.com/.well-known/openid-configuration \
--domain yourdomain.com --domain gmail.com
```
Start up the online CA or send a HUP signal if it's already running to reload
the configuration and pick up the new provisioner. Now users should be able to
obtain certificates using the familiar `step ca certificate` flow:
```bash
$ step ca certificate sebastian@smallstep.com personal.crt personal.key
Use the arrow keys to navigate: ↓ ↑ → ←
What provisioner key do you want to use?
fYDoiQdYueq_LAXx2kqA4N_Yjf_eybe-wari7Js5iXI (admin)
▸ 972437157139-ssiqna0g4ibuhafl3pkrrcb52tbroekt.apps.googleusercontent.com (Google)
✔ Key ID: 972437157139-ssiqna0g4ibuhafl3pkrrcb52tbroekt.apps.googleusercontent.com (Google)
✔ CA: https://localhost
✔ Certificate: personal.crt
✔ Private Key: personal.key
$ step certificate inspect --short personal.crt ⏎
X.509v3 TLS Certificate (ECDSA P-256) [Serial: 6169...4235]
Subject: 106202051347258973689
sebastian@smallstep.com
Issuer: Local CA Intermediate CA
Provisioner: Google [ID: 9724....com]
Valid from: 2019-03-26T20:36:28Z
to: 2019-03-27T20:36:28Z
```
Now it's easy for anybody in the G-Suite organization to obtain valid personal
certificates!
## Notes on Securing the Step CA and your PKI.
In this section we recommend a few best practices when it comes to
running, deploying, and managing your own online CA and PKI. Security is a moving
target and we expect out recommendations to change and evolve as well.
### Initializing your PKI
When you initialize your PKI two private keys are generated; one intermediate
private key and one root private key. It is very important that these private keys
are kept secret. The root private key should be moved around as little as possible,
preferably not all - meaning it never leaves the server on which it was created.
### Passwords
When you initialize your PKI (`step ca init`) the root and intermediate
private keys will be encrypted with the same password. We recommend that you
change the password with which the intermediate is encrypted at your earliest
convenience.
```
$ step crypto change-pass $STEPPATH/secrets/intermediate_ca_key
```
Once you've changed the intermediate private key password you should never have
to use the root private key password again.
We encourage users to always use a password manager to generate random passwords
or let Step CLI generate passwords for you.
The next important matter is how your passwords are stored. We recommend using a
[password manager](https://en.wikipedia.org/wiki/List_of_password_managers).
There are many to choose from and the choice will depend on the risk & security
profile of your organization.
In addition to using a password manager to store all passwords (private key,
provisioner, etc.) we recommend using a threshold cryptography algorithm like
[Shamir's Secret Sharing](https://en.wikipedia.org/wiki/Shamir's_Secret_Sharing)
to divide the root private key password across a handful of trusted parties.
### Provisioners
When you initialize your PKI (`step ca init`) a default provisioner will be created
and it's private key will be encrypted using the same password used to encrypt
the root private key. Before deploying the Step CA you should remove this
provisioner and add new ones that are encrypted with new, secure, random passwords.
See the section on [managing provisioners](#listaddremove-provisioners).
### Deploying
* Refrain from entering passwords for private keys or provisioners on the command line.
Use the `--password-file` flag whenever possible.
* Run the Step CA as a new user and make sure that the config files, private keys,
and passwords used by the CA are stored in such a way that only this new user
has permissions to read and write them.
* Use short lived certificates. Our default validity period for new certificates
is 24 hours. You can configure this value in the `ca.json` file. Shorter is
better - less time to form an attack.
* Short lived certificates are **not** a replacement for CRL and OCSP. CRL and OCSP
are features that we plan to implement, but are not yet available. In the mean
time short lived certificates are a decent alternative.
* Keep your hosts secure by enforcing AuthN and AuthZ for every connection. SSH
access is a big one.
<a name="step-ca-ha"></a>
## Notes on Running Step CA as a Highly Available Service
**CAUTION**: `step-ca` is built to scale horizontally. However, the creators
and maintainers do not regularly test in an HA environment using mulitple
instances. You may run into issues we did not plan for. If this happens, please
[open an issue][3].
### Considerations
A few things to consider / implement when running multiple instances of `step-ca`:
* Use `MySQL` DB: The default `Badger` DB cannot be read / written by more than one
process simultaneously. The only supported DB that can support multiple instances
is `MySQL`. See the [database documentation][4] for guidance on configuring `MySQL`.
* The ACME server has known concurrency limitations when using the same account to
manage multiple orders. The recommended temporary workaround is to generate
an ephemeral account keypair for each new ACME order, or to ensure that ACME
orders owned by the same account are managed serially. The issue tracking
this limitation can be found [here](https://github.com/smallstep/certificates/issues/341).
* Synchronize `ca.json` across instances: `step-ca` reads all of it's
configuration (and all of the provisioner configuration) from the `ca.json` file
specified on the command line. If the `ca.json` of one instance is modified
(either manually or using a command like `step ca provisioner (add | remove)`)
the other instances will not pick up on this change until the `ca.json` is
copied over to the correct location for each instance and the instance itself
is `SIGHUP`'ed (or restarted). It's recommended to use a configuration management
(ansible, chef, salt, puppet, etc.) tool to synchronize `ca.json` across instances.
[3]: https://github.com/smallstep/certificates/issues
[4]: ./database.md

View file

@ -1,41 +0,0 @@
# Step Certificates Documentation
## Note: Much of [our documentation has moved](https://smallstep.com/docs)
Index of Documentation and Tutorials for using and deploying the `step certificates`.
[![GitHub release](https://img.shields.io/github/release/smallstep/certificates.svg)](https://github.com/smallstep/certificates/releases)
[![CA Image](https://images.microbadger.com/badges/image/smallstep/step-ca.svg)](https://microbadger.com/images/smallstep/step-ca)
[![Go Report Card](https://goreportcard.com/badge/github.com/smallstep/certificates)](https://goreportcard.com/report/github.com/smallstep/certificates)
[![Build Status](https://travis-ci.com/smallstep/certificates.svg?branch=master)](https://travis-ci.com/smallstep/certificates)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![CLA assistant](https://cla-assistant.io/readme/badge/smallstep/certificates)](https://cla-assistant.io/smallstep/certificates)
[![GitHub stars](https://img.shields.io/github/stars/smallstep/certificates.svg?style=social)](https://github.com/smallstep/certificates/stargazers)
[![Twitter followers](https://img.shields.io/twitter/follow/smallsteplabs.svg?label=Follow&style=social)](https://twitter.com/intent/follow?screen_name=smallsteplabs)
## Table of Contents
* **General Info**
* [Website](https://smallstep.com)
* [Installation Guide](https://smallstep.com/docs/step-ca/installation)
* [Getting Started](https://smallstep.com/docs/step-ca/getting-started): in depth guide on getting started
with `step-ca`, including all configuration options.
* [Contributor's Guide](./CONTRIBUTING.md)
* [Sane Defaults](https://smallstep.com/docs/step-ca/certificate-authority-server-production#sane-cryptographic-defaults): default algorithms and attributes used
in cryptographic primitives and why they were selected.
* [Frequently Asked Questions](./questions.md)
* Check out our [Blog](https://smallstep.com/blog/). We post quality
educational content as well as periodic updates on new releases.
* **API**: Guides to using the API via the `step` CLI.
* [Revoking Certificates](https://smallstep.com/docs/step-ca/revocation)
* [Persistence Layer](https://smallstep.com/docs/step-ca/configuration#databases): description and guide to using `step certificates`'
persistence layer for storing certificate management metadata.
* **Tutorials**: Guides for deploying and getting started with `step` in various environments.
* [Docker](./docker.md)
* [Kubernetes](../autocert/README.md)
## Further Reading
* [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html)
* [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html)

View file

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

View file

@ -1,217 +0,0 @@
# Registration Authorities
This document describes how to use an external registration authority (RA), aka
certificate authority service (CAS) to sign X.509 certificates requests.
A CAS is a system that implements an API to sign certificate requests, the
difference between CAS and KMS is that the latter can sign any data, while CAS
is intended to sign only X.509 certificates.
`step-ca` defines an interface that can be implemented to support other
registration authorities, currently only CloudCAS and the default SoftCAS are
implemented.
The `CertificateAuthorityService` is defined in the package
`github.com/smallstep/certificates/cas/apiv1` and it is:
```go
type CertificateAuthorityService interface {
CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error)
RenewCertificate(req *RenewCertificateRequest) (*RenewCertificateResponse, error)
RevokeCertificate(req *RevokeCertificateRequest) (*RevokeCertificateResponse, error)
}
```
The same package defines another interface that is used to get the root
certificates from the CAS:
```go
type CertificateAuthorityGetter interface {
GetCertificateAuthority(req *GetCertificateAuthorityRequest) (*GetCertificateAuthorityResponse, error)
}
```
## SoftCAS
SoftCAS is the default implementation supported by `step-ca`. No special
configurations are required to enable it.
SoftCAS generally uses certificates and keys in the filesystem, but a KMS can
also be used instead of a key file for signing certificates. See [KMS](kms.md)
for more information.
## CloudCAS
CloudCAS is the implementation of the `CertificateAuthorityService` and
`CertificateAuthorityGetter` interfaces using [Google's Certificate Authority
Service](https://cloud.google.com/certificate-authority-service/).
Before enabling CloudCAS in `step-ca` you do some steps in Google Cloud Console
or using `gcloud` CLI:
1. Create or define a project to use. Let's say the name is `smallstep-cas-test`.
2. Create the KMS keyring and keys for root and intermediate certificates:
```sh
# Create key ring
gcloud kms keyrings create kr1 --location us-west1
# Create key for Root certificate
gcloud kms keys create k1 \
--location us-west1 \
--keyring kr1 \
--purpose asymmetric-signing \
--default-algorithm ec-sign-p256-sha256 \
--protection-level software
# Create key for Intermediate certicate
gcloud kms keys create k2 \
--location us-west1 \
--keyring kr1 \
--purpose asymmetric-signing \
--default-algorithm ec-sign-p256-sha256 \
--protection-level software
# Put the resource name for version 1 of the new KMS keys into a shell variable.
# This will be used in the other instructions below.
KMS_ROOT_KEY_VERSION=$(gcloud kms keys versions describe 1 --key k1 --keyring kr1 --location us-west1 --format "value(name)")
KMS_INTERMEDIATE_KEY_VERSION=$(gcloud kms keys versions describe 1 --key k2 --keyring kr1 --location us-west1 --format "value(name)")
```
3. Enable the CA service API. You can do it on the console or running:
```sh
gcloud services enable privateca.googleapis.com
```
4. Configure IAM. Create a service account using Google Console or running:
```sh
# Create service account
gcloud iam service-accounts create step-ca-sa \
--project smallstep-cas-test \
--description "Step-CA Service Account" \
--display-name "Step-CA Service Account"
# Add permissions to use the privateca API
gcloud projects add-iam-policy-binding smallstep-cas-test \
--member=serviceAccount:step-ca-sa@smallstep-cas-test.iam.gserviceaccount.com \
--role=roles/privateca.caManager
gcloud projects add-iam-policy-binding smallstep-cas-test \
--member=serviceAccount:step-ca-sa@smallstep-cas-test.iam.gserviceaccount.com \
--role=roles/privateca.certificateRequester
# Download the credentials.file
gcloud iam service-accounts keys create credentials.json \
--iam-account step-ca-sa@smallstep-cas-test.iam.gserviceaccount.com
```
5. Create a Root CA. You can do this on the console or running:
```sh
gcloud beta privateca roots create prod-root-ca \
--location us-west1 \
--kms-key-version "$KMS_ROOT_KEY_VERSION" \
--subject "CN=Example Root CA, O=Example LLC" \
--max-chain-length 2
```
6. Create an Intermediate CA. You can do this on the console or running:
```sh
gcloud beta privateca subordinates create prod-intermediate-ca \
--location us-west1 \
--issuer prod-root-ca \
--issuer-location us-west1 \
--kms-key-version "$KMS_INTERMEDIATE_KEY_VERSION" \
--subject "CN=Example Intermediate CA, O=Example LLC" \
--reusable-config "subordinate-server-tls-pathlen-0"
```
Now it's time to enable it in `step-ca` by adding some new files in the
`"authority"` section of the `ca.json`.
```json
{
"authority": {
"type": "cloudCAS",
"credentialsFile": "/path/to/credentials.json",
"certificateAuthority": "projects/<name>/locations/<loc>/certificateAuthorities/<ca-name>",
}
}
```
* **type** defines the name of the CAS to use, _cloudCAS_ must be used to enable it.
* **credentialsFile** defines the path to a Google Cloud credential file with
access to Google's Certificate AuthorityService. We created this file before
in step 4. Instead of setting this property, the environment variable
`GOOGLE_APPLICATION_CREDENTIALS` can be pointed to the file to use. Or if the
`step-ca` is running in Google Cloud, the default service account in the
machine can also be used.
* **certificateAuthority** defines the Google Cloud resource to the intermediate
(or subordinated) certificate to use. We created this resource in step 6.
As we said before, the CloudCAS implementation in `step-ca` also defines the
interface `CertificateAuthorityGetter`, this allows `step-ca` to automatically
download the root certificate from Cloud CAS. In the `ca.json` now you don't
need to configure `"root"`, and because the intermediate is in Google Cloud,
`"crt"` and `"key"` are no needed. A full `ca.json` can look like:
```json
{
"address": ":443",
"dnsNames": ["ca.example.com"],
"logger": {"format": "text"},
"db": {
"type": "badger",
"dataSource": "/home/jane/.step/db",
},
"authority": {
"type": "cloudCAS",
"credentialsFile": "/home/jane/.step/credentials.json",
"certificateAuthority": "projects/smallstep-cas-test/locations/us-west1/certificateAuthorities/prod-intermediate-ca",
"provisioners": [
{
"type": "JWK",
"name": "jane@example.com",
"key": {
"use": "sig",
"kty": "EC",
"kid": "ehFT9BkVOY5k_eIiMax0ZxVZCe2hlDVkMwZ2Y78av4s",
"crv": "P-256",
"alg": "ES256",
"x": "GtEftN0_ED1lNc2SEUJDXV9EMi7JY-kqINPIEQJIkjM",
"y": "8HYFdNe1MbWcbclF-hU1L80SCmMcZQI6vZfTOXfPOjg"
},
"encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiSjBSWnY5UFZrM3JKRUJkem5RbExzZyJ9.Fiwvo-RIKU5G6v5udeCT1nlX87ElxrocP2FcgNs3AqEz5OH9H4suew.NmzUJR_9xv8ynQC8.dqOveA_G5kn5lxjxnEZoJCystnJMVYLkZ_8CVzfJQhYchbZfNk_-FKdIuQxeWWBzvmomsILFNtLOIUoqSt30qk83lFyGQWN8Ke2bK5DhuwojF7RI_UqkMyiKP0F28Z4ZFhfQP5D2ZT_stoFaMlU8eak0-T8MOiBIfdAJTWM9x2DN-68mtUBuL5z5eU8bqsxELnjGauD_GHTdnduOosmYsw8vp_PmffTTwqUzDFH1RhkeSmRFRZntAizZMGYkxLamquHI3Jvuqiv4eeJ3yLqh3Ppyo_mVQKnxM7P9TyTxcvLkb2dB3K-cItl1fpsz92cy8euKsKG8n5-hKFRyPfY.j7jBN7nUwatoSsIZuNIwHA"
}
]
},
"tls": {
"cipherSuites": [
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
],
"minVersion": 1.2,
"maxVersion": 1.3,
"renegotiation": false
}
}
```
The we only need to run `step-ca` as usual, but this time, the CA will print the
root fingerprint too:
```sh
$ step-ca /home/jane/.step/config/ca.json
2020/09/22 13:17:15 Using root fingerprint '3ef16343cf0952eedbe2b843066bb798fa7a7bceb16aa285e8b0399f661b28b7'
2020/09/22 13:17:15 Serving HTTPS on :9000 ...
```
We will need to bootstrap once our environment using the printed fingerprint:
```sh
step ca bootstrap --ca-url https://ca.example.com --fingerprint 3ef16343cf0952eedbe2b843066bb798fa7a7bceb16aa285e8b0399f661b28b7
```
And now we can sign sign a certificate as always:
```sh
step ca certificate test.example.com test.crt test.key
```

View file

@ -1,106 +0,0 @@
# Step Certificates Database
`step certificates` uses a simple key-value interface over popular database
implementations to store persistent certificate management meta-data.
Our recommended default database implementation is
[nosql-Badger](https://github.com/smallstep/nosql/badger) - a NoSQL interface
over the popular [Badger](https://github.com/dgraph-io/badger) database.
## What will the database store?
As a first pass, the database layer will store every certificate (along with
metadata surrounding the provisioning of the certificate) and revocation data
that will be used to enforce passive revocation.
## Implementations
Current implementations include Badger (default), BoltDB, and MysQL.
- [ ] Memory
- [x] No database
- [x] [BoltDB](https://github.com/etcd-io/bbolt) -- etcd fork.
- [x] [Badger](https://github.com/dgraph-io/badger)
- [x] [MySQL/MariaDB](https://github.com/go-sql-driver/mysql)
- [ ] PostgreSQL
- [ ] Cassandra
Let us know which integration you would like to see next by opening an issue or PR.
## Configuration
Configuring `step certificates` to use a database is as simple as adding a
top-level `db` stanza to `$(step path)/config/ca.json`. Below are a few examples for supported databases:
### Badger
```
{
...
"db": {
"type": "badger",
"dataSource": "./.step/db",
"valueDir": "./.step/valuedb"
"badgerFileLoadingMode": "MemoryMap"
},
...
}
```
#### Options for `db`:
* `type`
* `badger` - currently refers to Badger V1. However, as Badger V1 is deprecated,
this will refer to Badger V2 starting with a the next major version release.
* `badgerV1` - explicitly select Badger V1.
* `badgerV2` - explicitly select Badger V2. Anyone looking to use Badger V2
will need to set it explicitly until it becomes the default.
* `dataSource` - path, database directory.
* `valueDir` [optional] - path, value directory, only if different from `dataSource`.
* `badgerFileLoadingMode` [optional] - can be set to `FileIO` (instead of the default
`MemoryMap`) to avoid memory-mapping log files. This can be
useful in environments with low RAM. Make sure to use `badgerV2` as the
database `type` if using this option.
* `MemoryMap` - default.
* `FileIO` - This can be useful in environments with low RAM.
### BoltDB
```
{
...
"db": {
"type": "bbolt",
"dataSource": "./stepdb"
},
...
},
```
### MySQL
```
{
...
"db": {
"type": "mysql",
"dataSource": "user:password@tcp(127.0.0.1:3306)/",
"database": "myDatabaseName"
},
...
},
```
## Schema
As the interface is a key-value store, the schema is very simple. We support
`tables`, `keys`, and `values`. An entry in the database is a `[]byte value`
that is indexed by `[]byte table` and `[]byte key`.
## Data Backup
Backing up your data is important, and it's good hygiene. We chose
[Badger](https://github.com/dgraph-io/badger) as our default file based data
storage backend because it has mature tooling for running common database
tasks. See the [documentation](https://github.com/dgraph-io/badger#database-backup)
for a guide on backing up your data.

View file

@ -1,227 +0,0 @@
# Default Algorithms and Attributes for Tokens, Keys, Certificates, etc.
The `step` ecosystem aims to be a "easy to use and hard to misuse" suite of PKI
tools. This means we need to select sane defaults for the myriad
configuration options that exist when using cryptographic primitives and higher
order abstractions (e.g. JWTs).
Below we document significant configuration options that we have selected as
defaults. These selections will change and evolve over time; security and
cryptography are constantly changing in response to real world pressures. We
intend for this document be an accurate representation of current best practices
in the industry, and to have these practices codified as defaults in the `step
certificates` code base. If you have questions, suggestions, or comments about
any of these decisions please let us know by opening an issue on this repo,
reaching out through [GitHub Discussions](https://github.com/smallstep/certificates/discussions).
## Tokens
We use JWTs (JSON Web Tokens) to prove authenticity and identity within the
Step ecosystem. JWTs have received negative attention because they are easy to
misuse and misconfigure. We agree! But lots of things are easy to misuse. We also
believe that when configured well JWTs are a great way to sign and encode data.
Our JWT's are, by default, short-lived (5 minute lifespan) and one time use
during the lifetime of the Step CA. We use a 1 minute clock drift leeway
because that was the recommended default in the reputable JWT package that we
chose. If using Step JWTs or your own JWTs in your code be sure to verify and
validate every single standard attribute of the JWT. JWTs, like all
cryptographic tools, are useless without proper attention to configuration and
guidelines.
## Keys
RSA keys don't scale very well. To get 128 bits of security, you need 3,072-bit
RSA keys, which are noticeably slower. ECDSA keys provide an alternative
that offers better security and better performance. At 256 bits, ECDSA keys
provide 128 bits of security. A small number of older clients don't support
ECDSA, but most modern clients do.
**Default Key Type**: ECDSA
**Default Curve Bits**: P-256
We've chosen the AES encryption algorithm (aka Rijndael) for writing private
keys to disk because it was the official choice of the Advanced
Encryption Standard contest. The three supported key sizes are 128, 192, and
256. Each of these is considered to be unbreakable for the forseeable future,
therefore we chose 128 bits as our default because the performance is
better (as compared to the greater key sizes) and because we agree, with
the designers of the algorithm, that 128 bits are quite sufficient for
most security needs.
**Default PEMCipher**: AES128
## X.509 Certificate Defaults
### Root Certificate
* Validity (10 year window)
* **Not Before**: Now
* **Not After**: Now + 10 years
A 10 year window seems advisable until software and tools can be written
for rotating the root certificate.
* **Basic Constraints**
* **CA**: TRUE
The root certificate is a Certificate Authority, it will be used to sign
other Certificates.
* **pathlen**: 1
The path length constraint expresses the number of possible intermediate
CA certificates in a path built from an end-entity certificate up to the
CA certificate. An absent path length constraint means that there is no
limitation to the number of intermediate certificates from end-entity to
the CA certificate. The smallstep PKI has only one intermediate CA
certificate between end-entity certificates and the root CA certificcate.
* **Key Usage** describes how the certificate can be used.
* **Certificate Sign**
Indicates that our root public key will be used to verify a signature on
certificates.
* **CRL Sign**
Indicates that our root public key will be used to verify a signature on
revocation information, such as CRL.
### Intermediate Certificate
* Validity (10 year window)
* **Not Before**: Now
* **Not After**: Now + 10 years
A 10 year window seems advisable until software and tools can be written
for rotating the root certificate.
* **Basic Constraints**
* **CA**: TRUE
The intermediate certificate is a Certificate Authority, used to sign
end-entity (service, process, job, etc.) certificates.
* **pathlen**: 0
The path length constraint expresses the number of possible intermediate
CA certificates in a path built from an end-entity certificate up to the
CA certificate. An absent path length constraint means that there is no
limitation to the number of intermediate certificates from end-entity to
the CA certificate. There are no additional intermediary certificates in
the path between the smallstep intermediate CA and end-entity certificates.
* **Key Usage**
* **Certificate Signing**
Indicates that our the intermediate private key can be used to sign
certificate requests.
* **CRL Sign**
Indicates that this public key can be used to verify a signature on
revocation information, such as CRL.
### Leaf Certificate - End Entity Certificate (certificates returned by the CA)
* Validity (24 hour window)
* **Not Before**: Now
* **Not After**: Now + 24 hours
The default is a 24hr window. This value is somewhat arbitrary, however,
our goal is to have seamless end-entity certificate rotation (we are
getting close). Rotating certificates frequently is good security hygiene
because it gives bad actors very little time to form an attack and limits
the usefulness of any single private key in the system. We will continue
to work towards decreasing this window because we believe it significantly
reduces probability and effectiveness of any attack.
* **Key Usage**
* **Key Encipherment**
Indicates that a certificate will be used with a protocol that encrypts keys.
* **Digital Signature**
Indicates that this public key may be used as a digital signature to
support security services that enable entity authentication and data
origin authentication with integrity.
* **Extended Key Usage**
* **TLS Web Server Authentication**
Certificate can be used as the server side certificate in the TLS protocol.
* **TLS Web Client Authentication**
Certificate can be used as the client side certificate in the TLS protocol.
## Default TLS Configuration Options
* **Min TLS Version**: TLS 1.2
* **Max TLS Version**: TLS 1.2
The PCI Security Standards Council required all payment processors
and merchants to move to TLS 1.2 and above by June 30, 2018. By setting
TLS 1.2 as the default for all tls protocol negotiation we encourage our
users to adopt the same security conventions.
* **Default Cipher Suites**:
```
[
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
]
```
The default 'ciphersuites' are a list of two cipher combinations. For
communication between services running step there is no need for cipher suite
negotiation. The server can specify a single cipher suite which the client is
already known to support.
Reasons for selecting `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305`:
* ECDHE key exchange algorithm has perfect forward secrecy
* ECDSA has smaller keys and better performance (than RSA)
* CHACHA20 with POLY1305 is the cipher mode used by google.
* CHACHA20's performance is better than GCM and CBC.
The http2 spec requires the `TLS_ECDHE_(RSA|ECDSA)_WITH_AES_128_GCM_SHA256`
ciphersuite be accepted by the server, therefore it makes our list of
default ciphersuites until we build the functionality to modify our defaults
based on http version.
* **Approved Cipher Suites**:
```
[
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
]
```
Above is a list of step approved cipher suites. Not all communication
can be mediated with step TLS functionality. For those connections the list of
server supported cipher suites must have more options - in case older clients
do not support our favored cipher suite.
Reasons for selecting these cipher suites can be found in the following
[ssllabs article](https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices#23-use-secure-cipher-suites).
* **Renegotation**: Never
TLS renegotiation significantly complicates the state machine and has been
the source of numerous, subtle security issues. Therefore, by default we
disable it.

View file

@ -1,186 +0,0 @@
# Getting started with Docker
## NOTE: This guide is deprecated. Please see [smallstep/step-ca](https://hub.docker.com/r/smallstep/step-ca) on Docker Hub for instructions.
This guide shows how to set up [step certificates](https://github.com/smallstep/certificates) using docker.
For short, we will use **step-ca** to refer to [step certificates](https://github.com/smallstep/certificates).
## Requirements
1. To follow this guide you will need to [install step
cli](https://github.com/smallstep/cli#installation-guide).
2. Get the docker image.
Get the latest version of **step-ca** from the [step-ca docker
hub](https://hub.docker.com/r/smallstep/step-ca):
```sh
$ docker pull smallstep/step-ca
```
3. Create the required volumes.
We need to create a volume in docker where we will store our PKI as well as
the step-ca configuration file.
```sh
$ docker volume create step
```
4. Initialize the PKI.
The simple way to do this is to run an interactive terminal:
```sh
$ docker run -it -v step:/home/step smallstep/step-ca sh
~ $ step ca init
✔ What would you like to name your new PKI? (e.g. Smallstep): Smallstep
✔ What DNS names or IP addresses would you like to add to your new CA? (e.g. ca.smallstep.com[,1.1.1.1,etc.]): localhost
✔ What address will your new CA listen at? (e.g. :443): :9000
✔ What would you like to name the first provisioner for your new CA? (e.g. you@smallstep.com): admin
✔ What do you want your password to be? [leave empty and we'll generate one]: <your password here>
Generating root certificate...
all done!
Generating intermediate certificate...
all done!
✔ Root certificate: /home/step/certs/root_ca.crt
✔ Root private key: /home/step/secrets/root_ca_key
✔ Root fingerprint: f9e45ae9ec5d42d702ce39fd9f3125372ce54d0b29a5ff3016b31d9b887a61a4
✔ Intermediate certificate: /home/step/certs/intermediate_ca.crt
✔ Intermediate private key: /home/step/secrets/intermediate_ca_key
✔ Default configuration: /home/step/config/defaults.json
✔ Certificate Authority configuration: /home/step/config/ca.json
Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.
```
5. Place the PKI root password in a known location.
Our image is expecting the password to be placed in `/home/step/secrets/password`
you can simply go in to the terminal again and write that file:
```sh
$ docker run -it -v step:/home/step smallstep/step-ca sh
~ $ echo <your password here> > /home/step/secrets/password
```
At this time everything is ready to run step-ca!
## Running step certificates
Now that we have configured our environment we are ready to run step-ca.
Expose the server address locally and run the step-ca with:
```sh
$ docker run -d -p 127.0.0.1:9000:9000 -v step:/home/step smallstep/step-ca
```
Let's verify that the service is running with curl:
```sh
$ curl https://localhost:9000/health
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
HTTPS-proxy has similar options --proxy-cacert and --proxy-insecure.
```
It's working but curl complains because the certificate is not signed by an
accepted certificate authority.
### Notes for running on a Raspberry Pi
When you run step-ca on a Raspberry Pi, you might get the following error in
your continaer logs:
```sh
step-ca | badger 2021/05/08 20:13:12 INFO: All 0 tables opened in 0s
step-ca | Error opening database of Type badger with source /home/step/db: error opening Badger database: Mmap value log file. Path=/home/step/db/000000.vlog. Error=cannot allocate memory
```
To fix it, adjust the `db` configuration in the file `config/ca.json`.
Change the value of `badgerFileLoadingMode` from `""` to `"FileIO"`.
```sh
docker run -it -v step:/home/step smallstep/step-ca sh
~ $ vi config/ca.json
```
You will end up with this:
```json
"db": {
"type": "badger",
"dataSource": "/root/.step/db",
"badgerFileLoadingMode": "FileIO"
},
```
## Dev environment bootstrap
To initialize the development environment we need to grab the Root fingerprint
from the [Initializing the PKI](#initializing-the-pki) step earlier. In the
case of this example:
`f9e45ae9ec5d42d702ce39fd9f3125372ce54d0b29a5ff3016b31d9b887a61a4`. With the
fingerprint we can bootstrap our dev environment.
```sh
$ step ca bootstrap --ca-url https://localhost:9000 --fingerprint f9e45ae9ec5d42d702ce39fd9f3125372ce54d0b29a5ff3016b31d9b887a61a4 --install
The root certificate has been saved in ~/.step/certs/root_ca.crt.
Your configuration has been saved in ~/.step/config/defaults.json.
Installing the root certificate in the system truststore... done.
```
Now [step cli](https://github.com/smallstep/cli) is configured to use step-ca
and our new root certificate is trusted by our local environment.
```sh
$ curl https://localhost:9000/health
{"status":"ok"}
```
And we are able to run web services configured with TLS (and mTLS):
```sh
~ $ step ca certificate localhost localhost.crt localhost.key
✔ Key ID: aTPGWP0qbuQdflR5VxtNouDIOXyNMH1H9KAZKP-UcHo (admin)
✔ Please enter the password to decrypt the provisioner key:
✔ CA: https://localhost:9000/1.0/sign
✔ Certificate: localhost.crt
✔ Private Key: localhost.key
~ $ step ca root root_ca.crt
The root certificate has been saved in root_ca.crt.
~ $ python <<EOF
import BaseHTTPServer, ssl
class H(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200); self.send_header('content-type', 'text/html; charset=utf-8'); self.end_headers()
self.wfile.write(b'\n\xf0\x9f\x91\x8b Hello! Welcome to TLS \xf0\x9f\x94\x92\xe2\x9c\x85\n\n')
httpd = BaseHTTPServer.HTTPServer(('', 8443), H)
httpd.socket = ssl.wrap_socket (httpd.socket, server_side=True, keyfile="localhost.key", certfile="localhost.crt", ca_certs="root_ca.crt")
httpd.serve_forever()
EOF
```
Test from another terminal:
```sh
$ curl https://localhost:8443
👋 Hello! Welcome to TLS 🔒✅
```
Or visit `https://localhost:8443` from your browser.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 MiB

View file

@ -1,237 +0,0 @@
# Key Management Services
This document describes how to use a key management service or KMS to store the
private keys and sign certificates.
Support for multiple KMS are planned, but currently the only Google's Cloud KMS,
and Amazon's AWS KMS are supported. A still experimental version for YubiKeys is
also available if you compile [step-ca](https://github.com/smallstep/certificates)
yourself.
## Google's Cloud KMS
[Cloud KMS](https://cloud.google.com/kms) is the Google's cloud-hosted KMS that
allows you to store the cryptographic keys, and sign certificates using their
infrastructure. Cloud KMS supports two different protection levels, SOFTWARE and
HSM.
To configure Cloud KMS in your CA you need add the `"kms"` property to you
`ca.json`, and replace the property`"key"` with the Cloud KMS key name of your
intermediate key:
```json
{
...
"key": "projects/<project-id>/locations/global/keyRings/<ring-id>/cryptoKeys/<key-id>/cryptoKeyVersions/<version-number>",
...
"kms": {
"type": "cloudkms",
"credentialsFile": "path/to/credentials.json"
}
}
```
In a similar way, for SSH certificate, the SSH keys must be Cloud KMS names:
```json
{
...
"ssh": {
"hostKey": "projects/<project-id>/locations/global/keyRings/<ring-id>/cryptoKeys/<key-id>/cryptoKeyVersions/<version-number>",
"userKey": "projects/<project-id>/locations/global/keyRings/<ring-id>/cryptoKeys/<key-id>/cryptoKeyVersions/<version-number>"
},
}
```
Currently [step](https://github.com/smallstep/cli) does not provide an automatic
way to initialize the public key infrastructure (PKI) using Cloud KMS, but an
experimental tool named `step-cloudkms-init` is available for this use case. At
some point this tool will be integrated into `step` and it will be deleted.
To use `step-cloudkms-init` just enable Cloud KMS in your project and run:
```sh
$ export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
$ step-cloudkms-init --project your-project-id --ssh
Creating PKI ...
✔ Root Key: projects/your-project-id/locations/global/keyRings/pki/cryptoKeys/root/cryptoKeyVersions/1
✔ Root Certificate: root_ca.crt
✔ Intermediate Key: projects/your-project-id/locations/global/keyRings/pki/cryptoKeys/intermediate/cryptoKeyVersions/1
✔ Intermediate Certificate: intermediate_ca.crt
Creating SSH Keys ...
✔ SSH User Public Key: ssh_user_ca_key.pub
✔ SSH User Private Key: projects/your-project-id/locations/global/keyRings/pki/cryptoKeys/ssh-user-key/cryptoKeyVersions/1
✔ SSH Host Public Key: ssh_host_ca_key.pub
✔ SSH Host Private Key: projects/your-project-id/locations/global/keyRings/pki/cryptoKeys/ssh-host-key/cryptoKeyVersions/1
```
See `step-cloudkms-init --help` for more options.
## AWS KMS
[AWS KMS](https://docs.aws.amazon.com/kms/index.html) is the Amazon's managed
encryption and key management service. It creates and store the cryptographic
keys, and use their infrastructure for signing operations. Amazon KMS operations
are always backed by hardware security modules (HSMs).
To configure AWS KMS in your CA you need add the `"kms"` property to you
`ca.json`, and replace the property`"key"` with the AWS KMS key name of your
intermediate key:
```json
{
...
"key": "awskms:key-id=f879f239-feb6-4596-9ed2-b1606277c7fe",
...
"kms": {
"type": "awskms",
"region": "us-east-1"
}
}
```
By default it uses the credentials in `~/.aws/credentials`, but this can be
overridden using the `credentialsFile` option, `region` and `profile` can also
be configured as options. These can also be configured using environment
variables as described by their [session
docs](https://docs.aws.amazon.com/sdk-for-go/api/aws/session/).
To configure SSH certificate signing we do something similar, and replace the
ssh keys with the ones in the KMS:
```json
{
...
"ssh": {
"hostKey": "awskms:key-id=d48e502a-09bc-4bf7-9af8-ae1bccedc931",
"userKey": "awskms:key-id=cf28e942-1e10-4a08-b84c-5359af1b5f12"
},
}
```
The keys can also be just the Amazon's Key ID or the ARN, but using the format
based on the [RFC7512](https://tools.ietf.org/html/rfc7512) will allow more
flexibility for future releases of `step`.
Currently [step](https://github.com/smallstep/cli) does not provide an automatic
way to initialize the public key infrastructure (PKI) using AWS KMS, but an
experimental tool named `step-awskms-init` is available for this use case. At
some point this tool will be integrated into `step` and it will be deleted.
To use `step-awskms-init` make sure to have to have your [environment
configured](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)
running `aws configure` and then just run:
```sh
$ bin/step-awskms-init --ssh --region us-east-1
Creating PKI ...
✔ Root Key: awskms:key-id=f53fb767-4029-40ff-b650-0dd35fb661df
✔ Root Certificate: root_ca.crt
✔ Intermediate Key: awskms:key-id=f879f239-feb6-4596-9ed2-b1606277c7fe
✔ Intermediate Certificate: intermediate_ca.crt
Creating SSH Keys ...
✔ SSH User Public Key: ssh_user_ca_key.pub
✔ SSH User Private Key: awskms:key-id=cf28e942-1e10-4a08-b84c-5359af1b5f12
✔ SSH Host Public Key: ssh_host_ca_key.pub
✔ SSH Host Private Key: awskms:key-id=cf28e942-1e10-4a08-b84c-5359af1b5f12
```
The `--region` parameter is only required if your aws configuration does not
define a region. See `step-awskms-init --help` for more options.
## YubiKey
And incomplete and experimental support for [YubiKeys](https://www.yubico.com)
is also available. Support for YubiKeys is not enabled by default and only TLS
signing can be configured.
The YubiKey implementation requires cgo, and our build system does not produce
binaries with it. To enable YubiKey download the source code and run:
```sh
make build GOFLAGS=""
```
The implementation uses [piv-go](https://github.com/go-piv/piv-go), and it
requires PCSC support, this is available by default on macOS and Windows
operating systems, but on Linux piv-go requires PCSC lite.
To install on Debian-based distributions, run:
```sh
sudo apt-get install libpcsclite-dev
```
On Fedora:
```sh
sudo yum install pcsc-lite-devel
```
On CentOS:
```sh
sudo yum install 'dnf-command(config-manager)'
sudo yum config-manager --set-enabled PowerTools
sudo yum install pcsc-lite-devel
```
The initialization of the public key infrastructure (PKI) for YubiKeys, is not
currently integrated into [step](https://github.com/smallstep/cli), but an
experimental tool named `step-yubikey-init` is available for this use case. At
some point this tool will be integrated into `step` and it will be deleted.
To configure your YubiKey just run:
```sh
$ bin/step-yubikey-init
What is the YubiKey PIN?:
Creating PKI ...
✔ Root Key: yubikey:slot-id=9a
✔ Root Certificate: root_ca.crt
✔ Intermediate Key: yubikey:slot-id=9c
✔ Intermediate Certificate: intermediate_ca.crt
```
See `step-yubikey-init --help` for more options.
Finally to enable it in the ca.json, point the `root` and `crt` to the generated
certificates, set the `key` with the yubikey URI generated in the previous step
and configure the `kms` property with the `type` and your `pin` in it.
```json
{
"root": "/path/to/root_ca.crt",
"crt": "/path/to/intermediate_ca.crt",
"key": "yubikey:slot-id=9c",
"kms": {
"type": "yubikey",
"pin": "123456"
},
...
}
```
## SSHAgentKMS
SSHAgentKMS is a KMS that wrapps a ssh-agent which has access to the keys to
sign ssh certificates. This was primarly written to be able to use gpg-agent
to provide the keys stored in a YubiKeys openpgp interface.
```json
{
"kms": {
"type": "sshagentkms"
},
"ssh": {
"hostKey": "sshagentkms:cardno:000123456789",
"userKey": "sshagentkms:cardno:000123456789",
},
...
}
```
This KMS requires that "root", "crt" and "key" are stored in plain files as for
SoftKMS.

View file

@ -1,586 +0,0 @@
# Provisioners
> Note: The canonical documentation for `step-ca` provisioners now lives at
> https://smallstep.com/docs/step-ca/provisioners. Documentation
> found on this page may be out of date.
Provisioners are people or code that are registered with the CA and authorized
to issue "provisioning tokens". Provisioning tokens are single-use tokens that
can be used to authenticate with the CA and get a certificate.
See `step ca provisioner add --help` for documentation and examples on adding
provisioners.
> Attn: We strongly recommend using the `step ca provisioner add ...`
> utility to generate provisioners in your `ca.json` configuration. We often
> encode fields differently in the JSON than you might expect. And you can
> always come in and modify the configuration manually after using the utility.
## Claims
Each provisioner can define an optional `claims` attribute. The settings in this
attribute override any settings in the global `claims` attribute in the authority
configuration.
Example `claims`:
```
...
"claims": {
"minTLSCertDuration": "5m",
"maxTLSCertDuration": "24h",
"defaultTLSCertDuration": "24h",
"disableRenewal": false,
"minHostSSHCertDuration": "5m",
"maxHostSSHCertDuration": "1680h",
"defaultHostSSHCertDuration": "720h",
"minUserSSHCertDuration": "5m",
"maxUserSSHCertDuration": "24h",
"defaultUserSSHCertDuration": "16h",
"enableSSHCA": true
},
...
```
* `claims` (optional): overwrites the default claims set in the authority.
You can set one or more of the following claims:
* `minTLSCertDuration`: do not allow certificates with a duration less than
this value.
* `maxTLSCertDuration`: do not allow certificates with a duration greater than
this value.
* `defaultTLSCertDuration`: if no certificate validity period is specified,
use this value.
* `disableIssuedAtCheck`: disable a check verifying that provisioning tokens
must be issued after the CA has booted. This claim is one prevention against
token reuse. The default value is `false`. Do not change this unless you
know what you are doing.
SSH CA properties
* `minUserSSHCertDuration`: do not allow certificates with a duration less
than this value.
* `maxUserSSHCertDuration`: do not allow certificates with a duration
greater than this value.
* `defaultUserSSHCertDuration`: if no certificate validity period is specified,
use this value.
* `minHostSSHCertDuration`: do not allow certificates with a duration less
than this value.
* `maxHostSSHCertDuration`: do not allow certificates with a duration
greater than this value.
* `defaultHostSSHCertDuration`: if no certificate validity period is specified,
use this value.
* `enableSSHCA`: enable all provisioners to generate SSH Certificates.
The default value is `false`. You can enable this option per provisioner
by setting it to `true` in the provisioner claims.
## Provisioner Types
Each provisioner has a different method of authentication with the CA.
- A JWK provisioner uses a JWT signed by a JWK.
- An OIDC provisioner uses a OIDC token signed by an Identity Provider e.g. Google, Okta, Azure.
- An AWS provisioner uses an Instance Identity Document signed by AWS.
- etc.
### Capabilities by Type
Provisioners are used to authenticate certificate signing requests, and every
provisioner has a slightly different scope of authorization. Below is a table
detailing the authorization capabilities of each provisioner.
Provisioner Capabilities| x509-sign | x509-renew | x509-revoke | ssh-user-cert-sign | ssh-host-cert-sign | ssh-user-cert-renew | ssh-host-cert-renew | ssh-revoke | ssh-rekey
----------- | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-:
JWK | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫
OIDC | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ <sup id="a1">[1](#f1)</sup> | 𝗫 | 𝗫 | ✔️ | 𝗫
X5C | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫
K8sSA | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫
ACME | ✔️ | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫
SSHPOP | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | 𝗫 | ✔️ | ✔️ | ✔️
AWS | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫
Azure | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫
GCP | ✔️ | ✔️ | 𝗫 | 𝗫 | ✔️ | 𝗫 | 𝗫 | 𝗫 | 𝗫
<b id="f1">1</b> Admin OIDC users can generate Host SSH Certificates. Admins can be configured in the OIDC provisioner. [](#a1)
### JWK
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` is used, and it also contains commands to add
(`step ca provisioner add`) and remove (`step ca provisioner remove`) JWK
provisioners.
In the ca.json configuration file, a complete JWK provisioner example looks like:
```json
{
"type": "JWK",
"name": "you@smallstep.com",
"key": {
"use": "sig",
"kty": "EC",
"kid": "NPM_9Gz_omTqchS6Xx9Yfvs-EuxkYo6VAk4sL7gyyM4",
"crv": "P-256",
"alg": "ES256",
"x": "bBI5AkO9lwvDuWGfOr0F6ttXC-ZRzJo8kKn5wTzRJXI",
"y": "rcfaqE-EEZgs34Q9SSH3f9Ua5a8dKopXNfEzDD8KRlU"
},
"encryptedKey": "eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjdHkiOiJqd2sranNvbiIsImVuYyI6IkEyNTZHQ00iLCJwMmMiOjEwMDAwMCwicDJzIjoiTlV6MjlEb3hKMVdOaFI3dUNjaGdYZyJ9.YN7xhz6RAbz_9bcuXoymBOj8bOg23ETAdmSCRyHpxGekkV0q3STYYg.vo1oBnZsZjgRu5Ln.Xop8AvZ74h_im2jxeaq-hYYWnaK_eF7MGr4xcZGodMUxp-hGPqS85oWkyprkQLYt1-jXTURfpejtmPeB4-sxgj7OFxMYYus84BdkG9BZgSBmMN9SqZItOv4pqg_NwQA0bv9g9A_e-N6QUFanxuYQsEPX_-IwWBDbNKyN9bXbpEQa0FKNVsTvFahGzOxQngXipi265VADkh8MJLjYerplKIbNeOJJbLd9CbS9fceLvQUNr3ACGgAejSaWmeNUVqbho1lY4882iS8QVx1VzjluTXlAMdSUUDHArHEihz008kCyF0YfvNdGebyEDLvTmF6KkhqMpsWn3zASYBidc9k._ch9BtvRRhcLD838itIQlw",
"claims": {
"minTLSCertDuration": "5m",
"maxTLSCertDuration": "24h",
"defaultTLSCertDuration": "24h",
"disableRenewal": false,
"minHostSSHCertDuration": "5m",
"maxHostSSHCertDuration": "1680h",
"minUserSSHCertDuration": "5m",
"maxUserSSHCertDuration": "24h",
"enableSSHCA": true
}
}
```
* `type` (mandatory): for a JWK provisioner it must be `JWK`, this field is case
insensitive.
* `name` (mandatory): 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.
* `key` (mandatory): is the JWK (JSON Web Key) representation of a public key
used to validate a signed token.
* `encryptedKey` (recommended): is the encrypted private key used to sign a
token. It's a JWE compact string containing the JWK representation of the
private key.
We can use [step](https://github.com/smallstep/cli) to see the private key
encrypted with the password `asdf`:
```sh
$ echo ey...lw | step crypto jwe decrypt | jq
Please enter the password to decrypt the content encryption key:
{
"use": "sig",
"kty": "EC",
"kid": "NPM_9Gz_omTqchS6Xx9Yfvs-EuxkYo6VAk4sL7gyyM4",
"crv": "P-256",
"alg": "ES256",
"x": "bBI5AkO9lwvDuWGfOr0F6ttXC-ZRzJo8kKn5wTzRJXI",
"y": "rcfaqE-EEZgs34Q9SSH3f9Ua5a8dKopXNfEzDD8KRlU",
"d": "rsjCCM_2FQ-uk7nywBEQHl84oaPo4mTpYDgXAu63igE"
}
```
If the ca.json does not contain the encryptedKey, the private key must be
provided using the `--key` flag of the `step ca token` to be able to sign the
token.
### OIDC
An OIDC provisioner allows a user to get a certificate after authenticating
with an OAuth OpenID Connect identity provider. The ID token provided
will be used on the CA authentication, and by default, the certificate will only
have the user's email as a Subject Alternative Name (SAN) Extension.
One of the most common providers and the one we'll use in the following example
is G-Suite.
```json
{
"type": "OIDC",
"name": "Google",
"clientID": "1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com",
"clientSecret": "udTrOT3gzrO7W9fDPgZQLfYJ",
"configurationEndpoint": "https://accounts.google.com/.well-known/openid-configuration",
"admins": ["you@smallstep.com"],
"domains": ["smallstep.com"],
"listenAddress": ":10000",
"claims": {
"maxTLSCertDuration": "8h",
"defaultTLSCertDuration": "2h",
"disableRenewal": true
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `OIDC`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `clientID` (mandatory): the client id provided by the identity provider used
to initialize the authentication flow.
* `clientSecret` (mandatory): the client secret provided by the identity
provider used to get the id token. Some identity providers might use an empty
string as a secret.
* `configurationEndpoint` (mandatory): is the HTTP address used by the CA to get
the OpenID Connect configuration and public keys used to validate the tokens.
* `admins` (optional): is the list of emails that will be able to get
certificates with custom SANs. If a user is not an admin, it will only be able
to get a certificate with its email in it.
* `domains` (optional): is the list of domains valid. If provided only the
emails with the provided domains will be able to authenticate.
* `listenAddress` (optional): is the loopback address (`:port` or `host:port`)
where the authorization server will redirect to complete the authorization
flow. If it's not defined `step` will use `127.0.0.1` with a random port. This
configuration is only required if the authorization server doesn't allow any
port to be specified at the time of the request for loopback IP redirect URIs.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
### X5C
An X5C provisioner allows a client to get an x509 or SSH certificate using
an existing x509 certificate that is trusted by the X5C provisioner.
An X5C provisioner is configured with a root certificate, supplied by the user,
at the time the provisioner is created. The X5C provisioner can authenticate
X5C tokens.
An X5C token is a JWT, signed by the certificate private key, with an `x5c`
header that contains the chain.
If you would like any certificate signed by `step-ca` to become a provisioner,
you can configure the X5C provisioner using the root certificate used by
`step-ca`, like so:
```
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, giving provisioner
capabilities to a completely separate PKI.
Below is an example of an X5C provisioner in the `ca.json`:
```json
...
{
"type": "X5C",
"name": "x5c",
"roots": "LS0tLS1 ... Q0FURS0tLS0tCg==",
"claims": {
"maxTLSCertDuration": "8h",
"defaultTLSCertDuration": "2h",
"disableRenewal": true
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `X5C`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `roots` (mandatory): a base64 encoded list of root certificates used for
validating X5C tokens.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
### SSHPOP
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.
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
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.
Below is an example of an SSHPOP provisioner in the `ca.json`:
```json
...
{
"type": "SSHPOP",
"name": "sshpop-smallstep",
"claims": {
"enableSSHCA": true
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `SSHPOP`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
### ACME
An ACME provisioner allows a client to request a certificate from the server
using the [ACME Protocol](https://tools.ietf.org/html/rfc8555). The ACME
provisioner can only request X509 certificates. All authentication of the CSR
is managed by the ACME protocol.
Below is an example of an ACME provisioner in the `ca.json`:
```json
...
{
"type": "ACME",
"name": "my-acme-provisioner",
"forceCN": true,
"requireEAB": false,
"claims": {
"maxTLSCertDuration": "8h",
"defaultTLSCertDuration": "2h",
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `ACME`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `forceCN` (optional): force one of the SANs to become the Common Name, if a
common name is not provided.
* `requireEAB` (optional): require clients to provide External Account Binding
credentials when creating an ACME Account.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
See our [`step-ca` ACME tutorial](https://app.smallstep.com/docs/[product]/tutorials/acme-provisioners)
for more guidance on configuring and using the ACME protocol with `step-ca`.
### K8sSA - Kubernetes Service Account
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,
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
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.
Below is an example of a K8sSA provisioner in the `ca.json`:
```json
...
{
"type": "K8sSA",
"name": "my-kube-provisioner",
"publicKeys": "LS0tLS1...LS0tCg==",
"claims": {
"maxTLSCertDuration": "8h",
"defaultTLSCertDuration": "2h",
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `K8sSA`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `publicKeys` (mandatory): a base64 encoded list of public keys used to validate
K8sSA tokens.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
### Provisioners for Cloud Identities
[Step certificates](https://github.com/smallstep/certificates) can grant
certificates to code running in a machine without any other authentication than
the one provided by the cloud. Usually, this is implemented with some kind of
signed document, but the information contained on them might not be enough to
generate a certificate. Due to this limitation, the cloud identities use by
default a trust model called Trust On First Use (TOFU).
The Trust On First Use model allows the use of more permissive CSRs that can
have custom SANs that cannot be validated. But it comes with the limitation that
you can only grant a certificate once. After this first grant, the same machine
will need to renew the certificate using mTLS, and the CA will block any other
attempt to grant a certificate to that instance.
#### AWS
The AWS provisioner allows granting a certificate to an Amazon EC2 instance
using the [Instance Identity Documents](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html)
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.
In the ca.json, an AWS provisioner looks like:
```json
{
"type": "AWS",
"name": "Amazon Web Services",
"accounts": ["1234567890"],
"disableCustomSANs": false,
"disableTrustOnFirstUse": false,
"instanceAge": "1h",
"iidRoots": "/path/to/aws.crt",
"claims": {
"maxTLSCertDuration": "2160h",
"defaultTLSCertDuration": "2160h"
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `AWS`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `accounts` (optional): the list of AWS account numbers that are allowed to use
this provisioner. If none is specified, all AWS accounts will be valid.
* `disableCustomSANs` (optional): by default custom SANs are valid, but if this
option is set to true only the SANs available in the instance identity
document will be valid, these are the private IP and the DNS
`ip-<private-ip>.<region>.compute.internal`.
* `disableTrustOnFirstUse` (optional): by default only one certificate will be
granted per instance, but if the option is set to true this limit is not set
and different tokens can be used to get different certificates.
* `instanceAge` (optional): the maximum age of an instance to grant a
certificate. The instance age is a string using the duration format.
* `iidRoots` (optional): the path to one or more public certificates in PEM
format used to validate the signature of the instance identity document.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
#### GCP
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.
In the ca.json, a GCP provisioner looks like:
```json
{
"type": "GCP",
"name": "Google Cloud",
"serviceAccounts": ["1234567890"],
"projectIDs": ["project-id"],
"disableCustomSANs": false,
"disableTrustOnFirstUse": false,
"instanceAge": "1h",
"claims": {
"maxTLSCertDuration": "2160h",
"defaultTLSCertDuration": "2160h"
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `GCP`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `serviceAccounts` (optional): the list of service account numbers that are
allowed to use this provisioner. If none is specified, all service accounts
will be valid.
* `projectIDs` (optional): the list of project identifiers that are allowed to
use this provisioner. If non is specified all project will be valid.
* `disableCustomSANs` (optional): by default custom SANs are valid, but if this
option is set to true only the SANs available in the instance identity
document will be valid, these are the DNS
`<instance-name>.c.<project-id>.internal` and
`<instance-name>.<zone>.c.<project-id>.internal`
* `disableTrustOnFirstUse` (optional): by default only one certificate will be
granted per instance, but if the option is set to true this limit is not set
and different tokens can be used to get different certificates.
* `instanceAge` (optional): the maximum age of an instance to grant a
certificate. The instance age is a string using the duration format.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.
#### Azure
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.
In the ca.json, an Azure provisioner looks like:
```json
{
"type": "Azure",
"name": "Microsoft Azure",
"tenantId": "b17c217c-84db-43f0-babd-e06a71083cda",
"resourceGroups": ["backend", "accounting"],
"audience": "https://management.azure.com/",
"disableCustomSANs": false,
"disableTrustOnFirstUse": false,
"claims": {
"maxTLSCertDuration": "2160h",
"defaultTLSCertDuration": "2160h"
}
}
```
* `type` (mandatory): indicates the provisioner type and must be `Azure`.
* `name` (mandatory): a string used to identify the provider when the CLI is
used.
* `tenantId` (mandatory): the Azure account tenant id for this provisioner. This
id is the Directory ID available in the Azure Active Directory properties.
* `audience` (optional): defaults to `https://management.azure.com/` but it can
be changed if necessary.
* `resourceGroups` (optional): the list of resource group names that are allowed
to use this provisioner. If none is specified, all resource groups will be
valid.
* `disableCustomSANs` (optional): by default custom SANs are valid, but if this
option is set to true only the SANs available in the token will be valid, in
Azure only the virtual machine name is available.
* `disableTrustOnFirstUse` (optional): by default only one certificate will be
granted per instance, but if the option is set to true this limit is not set
and different tokens can be used to get different certificates.
* `claims` (optional): overwrites the default claims set in the authority, see
the [top](#provisioners) section for all the options.

View file

@ -1,409 +0,0 @@
# Frequently Asked Questions
These are some commonly asked questions on the topics of PKI, TLS, X509,
cryptography, threshold-cryptography, etc.
Hopefully we will reduce the amount of hand-waving in these responses as we add
more features to the Step toolkit over time.
> We encourage you to read
> [our blog post on everything relating to PKI](https://smallstep.com/blog/everything-pki.html)
> as we believe it to be a solid resource that answers many of of the questions
> listed below.
## What are TLS & PKI?
TLS stands for *transport layer security*. It used to be called *secure sockets
layer* (or SSL), but technically SSL refers to an older version of the protocol.
Normal TCP connections communicate in plain text, allowing attackers to
eavesdrop and spoof messages. If used properly, TLS provides *confidentiality*
and *integrity* for TCP traffic, ensuring that messages can only be seen by their
intended recipient, and cannot be modified in transit.
TLS is a complicated protocol with lots of options, but the most common mode of
operation establishes a secure channel using *asymmetric cryptography* with
*digital certificates* (or just certificates for short).
First, some quick definitions:
* *Asymmetric cryptography* (a.k.a., public key cryptography) is an underappreciated
gift from mathematics to computer science. It uses a *key pair*: a private key
known only to the recipient of the message, and a public key that can be broadly
distributed, even to adversaries, without compromising security.
* *Digital certificates* are data structures that map a public key to the
well-known name of the owner of the corresponding private key (e.g., a DNS host name).
They *bind* a name to the public key so you can address recipients by name instead of
using public keys directly (which are big random numbers).
Briefly, there are two functions that can be achieved using asymmetric cryptography:
* Messages can be *encrypted* using the public key to ensure that only the
private key holder can *decrypt* them, and
* Messages can be *signed* using the private key so that anyone with the *public
key* knows the message came from the private key holder.
With digital certificates, you can replace "private key holder" with "named entity,"
which makes things a whole lot more useful. It lets you use names, instead of
public keys, to address messages.
PKI stands for *public key infrastructure*. Abstractly, it's a set of policies
and procedures for managing digital certificates (i.e., managing the bindings
between names and public keys). Without proper secure PKI, an attacker can fake
a binding and undermine security.
## What's a certificate authority?
A certificate authority (CA) stores, issues, and signs digital certificates. CAs
have their own key pair, with the private key carefully secured (often offline).
The CA binds its name to its public key by signing a digital certificate using
its own private key (called *self signing*). The CA's self-signed certificate,
or *root certificate*, is distributed to all principals in the system (e.g., all
of the clients and servers in your infrastructure).
So, the CA is tasked with securely binding names to public keys. Here's how that process works.
1. When a named principal wants a certificate, it generates its own key pair.
Nobody else ever needs to know the private key, not even the CA.
2. The principal creates a certificate signing request (CSR), containing its
name and public key (and some other stuff), and submits it to the CA. The CSR is
self-signed, like the root certificate, so the CA knows that the requestor has
the corresponding private key.
3. The CA performs some form of *identity proofing*, certifying that the request
is coming from the principal named in the CSR.
4. Once satisfied, the CA issues a certificate by using its own private key to
sign a certificate binding the name and public key from the CSR.
Certificates signed by the CA are used to securely introduce principals that
don't already know one anothers' public keys. Assuming both principals agree on
a trusted CA, they can exchange digital certificates and authenticate the
signatures to gain some assurance that they are communicating with the named entity.
Technically, smallstep's certificate authority is more than just a certificate
authority. It combines several PKI roles into one simple, flexible package. It
acts as a *registration authority*, accepting requests for digital certificates
and verifying the identity of the requesting entities before establishing bindings.
It also acts as a *central directory* and more generally as a *certificate
management system*, a secure location for storing and distributing key material.
## Why not just use Verisign, Entrust, Let's Encrypt, etc?
The web's *open public key infrastructure* (web PKI), while far from perfect,
is an important foundation for securing the web. So why not use it for securing
communication for your own internal infrastructure? There are several reasons:
* It's expensive to provision certificates from a public CA for all of your services
* Public CAs can't handle client certificates (mutual TLS)
* It's much harder (and more expensive) to revoke or roll certificates from public CAs
* It relies on a third party that can subvert your security
More broadly, the answer is that web PKI was designed for the web. A lot of the
web PKI design decisions aren't appropriate for internal systems.
## How does identity proofing work?
In general, trust will always flow back out to you, the operator of your system.
With that in mind, the simplest form of identity proofing is manual: [describe
token-based manual mechanism here]. As your system grows, this process can become
onerous. Automated identity proofing requires careful coordination between
different parts of your system. Smallstep provides additional tooling, and vetted
designs, to help with this. If you integrate with our other tools its easy to
start with a manual identity proofing mechanism and move to a more sophisticated
automated method as your system grows.
## What are the security risks of exposing the OAuth Client Secret in the output of `step ca provisioner list`?
It would be nice if we could have the CA operate as an OAuth confidential
client, keeping the client secret private and redirecting back to the CA
instead of to loopback. But, to be clear, this is not an abuse of the OAuth
spec. The way this was implemented in step, as an OAuth native application
using a public client, is standard, was intentional, (mostly) conforms to best
current practices, and the flow we're using is widely used in practice. A
confidential client is (strictly?) more secure. But a public client that
redirects to loopback isnt a significant security risk under a normal threat
model.
### The current flow
The advantage of the current flow is that its more general purpose. For
example, `step oauth` works without any additional infrastructure. An issued
access token can be used from the command line, and OIDC identity tokens can be
safely used to authenticate to remote services (including remote services that
dont speak OAuth OIDC, or dont even speak HTTP, but can validate a
JWT). `step-ca` is one example of a remote service that can authenticate
step users via OIDC identity token. You can also use `step crypto jwt verify` to
authenticate using OIDC at the command line.
The particular details of the OAuth flow we selected has pros & cons, as does
any flow. The relevant security risks are:
1. Since the OAuth access token isnt issued directly to a remote server (e.g.,
`step-ca`), remote servers cant safely use the issued access tokens
without significant care. If they did, an attacker might be able to maliciously
trick the remote server into using an access token that was issued to a
different client.
2. The redirect back from the OAuth authorization server to the
client can be intercepted by another process running on the local machine. This
isnt really necessary though, because...
3. The `client_secret` is public, so anyone can initiate (and complete) an OAuth
flow using our client (but it will always redirect back to 127.0.0.1).
The first threat is moot since we don't actually use the access token for
anything when we're connecting to `step-ca`. Unfortunately there's no way to not
get an access token. So we just ignore it.
Note that it *is* safe to use the access token from the command line to access
resources at a remote API. For example, its safe to user `step oauth` to obtain
an OAuth access token from Google and use it to access Googles APIs in a bash
script.
More generally, access tokens are for accessing resources (authorization) and
are not useful for authenticating a user since they're not audience-addressed.
If you and I both have a Google OAuth client, I could get Alice to OAuth into
my app and use the issued access token to masquerade as Alice to you. But OIDC
identity tokens are audience-addressed. An identity token is a JWT with the
`client_id` baked in as the `aud` (audience) parameter. As long as clients check
this parameter (which `step-ca` does) they're not susceptible to this attack. In
fact, OIDC identity tokens were designed and developed precisely to solve this
problem.
So it's completely safe for one entity to obtain an *identity token* from an IdP
on behalf of a user and use it to authenticate to another entity (like `step`
does). That's exactly the use case OIDC was designed to support.
The second and third threats are related. They involve a malicious attempt to
initiate an OAuth OIDC flow using our client credentials. There's a lot of
analysis we could do here comparing this situation to a non-native (e.g., *web*)
client and to other flows (e.g., the *implicit flow*, which also makes the
client secret public). Skipping that detail, we know two things for sure:
1. OAuth flows generally require user consent to complete (e.g., a user has to
"approve" an application's authentication / authorization request)
2. An OAuth flow initiated using our client will always redirect back to 127.0.0.1
So a malicious attacker trying to obtain an *identity token* needs two things:
1. They need to get user consent to complete an OAuth flow
2. They need to have local access to the user's machine
This is already a pretty high bar. Its worth noting, however, that the first
part is *much* easier if the user is already logged in and the identity provider
is configured to not require consent (i.e., the OAuth flow is automatically
completed without the user having to click any buttons). Okta seems to
do this for some applications by default.
It's also worth noting that a process with local access could probably obtain
an access/identity token for a *confidential client* without knowing the client
secret. That's the main reason I don't think the flow we're using has a
meaningful security impact under most threat models. The biggest difference is
that attacking a confidential client would probably require privileged (root)
access, whereas our flow could be attacked by an unprivileged process. But
the fruit of our OAuth flow — the SSH certificate — is also available for
use by an unprivileged process running locally via the `ssh-agent`. So the
only thing possibly gained is the ability to exfiltrate.
### Stuff we should consider doing
There are at least three OAuth features that are relevant to this discussion.
Two have already been mentioned:
1. OAuth *public clients* for *native applications* can be (er, are *supposed*
to be) created without a client secret
2. Proof Key for Code Exchange (PKCE) helps ensure that the process requesting the access token / identity token is the same process that initiated the flow
The first feature, clients without secrets, is mostly cosmetic. There's no real
difference between a public secret and no secret, except that it's confusing to
have something called a "secret" that's not actually secret. (Caveat: IdPs that
support "native applications" without secrets typically enforce other rules for
these clients — they often require PKCE and might not issue a renew token, for
example. But these features can often be turned on/of for other client types,
too.)
The reason we don't assume a *public client* without a secret is that,
unfortunately, not all IdPs support them. Significantly, Google does not. In
fact, gcloud (Google Cloud's CLI tool) uses OAuth OIDC and uses the exact same
technique we're using. If you look at the source you'll find their
"NOTSOSECRET" All of that said, we should support "native clients" without
secrets at some point.
We should also implement Proof Key for Code Exchange (PKCE). This has been on
our backlog for a while, and it's actually really simple and useful. It's
definitely low-hanging fruit. Before initiating the OAuth flow your client
generates a random number. It hashes that number and passes the hash to the IdP
as part of the authorization request (the URL that users are sent to for
login). After authenticating and consenting, when the user is
redirected back to the client, the client makes a request to the IdP to get an
access token & identity token. In *that* request the client must include the
*unhashed* random number. The IdP re-hashes it and compares it to the value it
received in the authorization request. If they match, the IdP can be certain
that the entity making the access token request is the same entity that
initiated the flow. In other words, the request has not been intercepted by
some malicious intermediary.
The last hardening mechanism to be aware of are the `acr` and `amr` parameters.
Basically, when the OAuth flow is initiated the client can request that the IdP
require consent, do 2FA, and a bunch of other stuff. The issued identity token
includes parameters to indicate that these processes did, indeed, occur.
Leveraging this mechanism one could configure `step-ca` to check these parameters
and be sure that users have consented and undergone a 2FA presence check (e.g.,
tapped a security token). Unfortunately, like a bunch of other optional
OAuth features, many IdPs (*cough* Google *cough*) don't support this stuff.
### Summary
Implementing PKCE should be our highest priority item. Support for "native"
clients without secrets would also be nice. Forcing 2FA & consent via `acr` & `amr`
is also a good idea. Support for non-native clients that redirect back to the
CA, and where the secret is *actually* secret, would also be nice. But it's a
bigger architectural change and the security implications aren't actually that
severe.
## I already have PKI in place. Can I use this with my own root certificate?
Yes. There's a easy way, and a longer but more secure way to do this.
### Option 1: The easy way
If you have your root CA signing key available, you can run:
```bash
step ca init --root=[ROOT_CERT_FILE] --key=[ROOT_PRIVATE_KEY_FILE]
```
The root certificate can be in PEM or DER format, and the signing key can be a PEM file containing a PKCS#1, PKCS#8, or RFC5915 (for EC) key.
### Option 2: More secure
That said, CAs are usually pretty locked down and it's bad practice to move the private key around. So I'm gonna assume that's not an option and give you the more complex instructions to do this "the right way", by generating a CSR for `step-ca`, getting it signed by your existing root, and configuring `step-ca` to use it.
When you run `step ca init` we create a couple artifacts under `~/.step/`. The important ones for us are:
- `~/.step/certs/root_ca.crt` is your root CA certificate
- `~/.step/secrets/root_ca_key` is your root CA signing key
- `~/.step/certs/intermediate_ca.crt` is your intermediate CA cert
- `~/.step/secrets/intermediate_ca_key` is the intermediate signing key used by `step-ca`
The easiest thing to do is to run `step ca init` to get this scaffolding configuration in place, then remove/replace these artifacts with new ones that are tied to your existing root CA.
First, `step-ca` does not actually need the root CA signing key. So you can simply remove that file:
```bash
rm ~/.step/secrets/root_ca_key
```
Next, replace `step-ca`'s root CA cert with your existing root certificate:
```bash
mv /path/to/your/existing/root.crt ~/.step/certs/root_ca.crt
```
Now you need to generate a new signing key and intermediate certificate, signed by your existing root CA. To do that we can use the `step certificate create` subcommand to generate a certificate signing request (CSR) that we'll have your existing root CA sign, producing an intermediate certificate.
To generate those artifacts run:
```bash
step certificate create "Intermediate CA Name" intermediate.csr intermediate_ca_key --csr
```
Next, you'll need to transfer the CSR file (`intermediate.csr`) to your existing root CA and get it signed.
Now you need to get the CSR executed by your existing root CA.
**Active Directory Certificate Services**
```bash
certreq -submit -attrib "CertificateTemplate:SubCA" intermediate.csr intermediate.crt
```
**AWS Certificate Manager Private CA**
Here's a Python script that uses [issue-certificate](https://docs.aws.amazon.com/acm-pca/latest/userguide/PcaIssueCert.html) to process the CSR:
```python
import boto3
import sys
AWS_CA_ARN = '[YOUR_PRIVATE_CA_ARN]'
csr = ''.join(sys.stdin.readlines())
client = boto3.client('acm-pca')
response = client.issue_certificate(
CertificateAuthorityArn=AWS_CA_ARN,
Csr=csr,
SigningAlgorithm='SHA256WITHRSA',
TemplateArn='arn:aws:acm-pca:::template/SubordinateCACertificate_PathLen1/V1',
Validity={
'Value': 5,
'Type': 'YEARS'
}
)
print(f"Creating certificate with ARN {response['CertificateArn']}...", file=sys.stderr, end='')
waiter = client.get_waiter('certificate_issued')
waiter.wait(
CertificateAuthorityArn=AWS_CA_ARN,
CertificateArn=response['CertificateArn']
)
print('done.', file=sys.stderr)
response = client.get_certificate(
CertificateArn=response['CertificateArn'],
CertificateAuthorityArn=AWS_CA_ARN
)
print(response['Certificate'])
```
To run it, fill in the ARN of your CA and run:
```bash
python issue_certificate.py < intermediate.csr > intermediate.crt
```
**OpenSSL**
```bash
openssl ca -config [ROOT_CA_CONFIG_FILE] \
-extensions v3_intermediate_ca \
-days 3650 -notext -md sha512 \
-in intermediate.csr \
-out intermediate.crt
```
**CFSSL**
For CFSSL you'll need a signing profile that specifies a 10-year expiry:
```bash
cat > ca-smallstep-config.json <<EOF
{
"signing": {
"profiles": {
"smallstep": {
"expiry": "87660h",
"usages": ["signing"]
}
}
}
}
EOF
```
Now use that config to sign the intermediate certificate:
```bash
cfssl sign -ca ca.pem \
-ca-key ca-key.pem \
-config ca-smallstep-config.json \
-profile smallstep
-csr intermediate.csr | cfssljson -bare
```
This process will yield a signed `intermediate.crt` certificate (or `cert.pem` for CFSSL). Transfer this file back to the machine running `step-ca`.
Finally, replace the intermediate .crt and signing key produced by `step ca init` with the new ones we just created:
```bash
mv intermediate.crt ~/.step/certs/intermediate_ca.crt
mv intermediate_ca_key ~/.step/secrets/intermediate_ca_key
```
That should be it! You should be able to start `step-ca` and the certificates should be trusted by anything that trusts your existing root CA.
## Further Reading
* [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html)
* [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html)

View file

@ -1,211 +0,0 @@
# Revocation
**Active Revocation**: A certificate is no longer valid from the moment it has
been actively revoked. Clients are required to check against centralized
sources of certificate validity information (e.g. by using CRLs (Certificate
Revocation Lists) or OCSP (Online Certificate Status Protocol)) to
verify that certificates have not been revoked. Active Revocation requires
clients to take an active role in certificate validation for the benefit of
real time revocation.
**Passive Revocation**: A certificate that has been passively revoked can no
longer be renewed. It will still be valid for the remainder of it's validity period,
but cannot be prolonged. The benefit of passive revocation is that clients
can verify certificates in a simple, decentralized manner without relying on
centralized 3rd parties. Passive revocation works best with short
certificate lifetimes.
`step certificates` currently only supports passive revocation. Active revocation
is on our roadmap.
Run `step help ca revoke` from the command line for full documentation, list of
command line flags, and examples.
## How It Works
Certificates can be created and revoked through the `step cli`. Let's walk
through an example.
### Requirements
* `step` (>=v0.10.0) ([install instructions](../README.md#installation-guide))
### Let's Get To It
1. Bootstrap your PKI.
> If you've already done this before and you have a `$STEPPATH` with certs,
> secrets, and configuration files then you can move on to step 2.
Run `step ca init`.
<pre><code>
<b>$ step ca init --name "Local CA" --provisioner admin --dns localhost --address ":443"</b>
</code></pre>
Move on to step 3.
2. Configure a persistence layer in your `ca.json`.
> If you did step 1 with `step` v0.10.0 or greater then your db will
> have been configured in the previous step.
Get your full step path by running `echo $(step path)`. Now edit
your `ca.json` by adding the following stanza as a top-level attribute:
> Your `ca.json` should be in `$(step path)/config/ca.json`.
```
...
"db": {
"type": "badger",
"dataSource": "<full step path>/db"
},
...
```
Check out our [database documentation](./database.md) to see all available
database backends and adapters.
3. Run the CA
<pre><code>
<b>$ step-ca $(step path)/config/ca.json</b>
</code></pre>
4. Create a certificate for localhost
<pre><code>
<b>$ step ca certificate localhost localhost.crt localhost.key</b>
✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
✔ Please enter the password to decrypt the provisioner key:
✔ CA: https://ca.smallstep.com
✔ Certificate: localhost.crt
✔ Private Key: localhost.key
<b>$ step certificate inspect --short localhost.crt</b>
X.509v3 TLS Certificate (ECDSA P-256) [Serial: 2400...2409]
Subject: localhost
Issuer: Smallstep Intermediate CA
Provisioner: sebastian@smallstep.com [ID: n2kq...Viy8]
Valid from: 2019-04-23T22:55:54Z
to: 2019-04-24T22:55:54Z
</code></pre>
5. Renew the certificate (just to prove we can!)
<pre><code>
<b>$ step ca renew localhost.crt localhost.key</b>
✔ Would you like to overwrite localhost.crt [y/n]: y
Your certificate has been saved in localhost.crt.
# Make sure the from timestamp is "newer"
<b>$ step certificate inspect --short localhost.crt</b>
X.509v3 TLS Certificate (ECDSA P-256) [Serial: 5963...8406]
Subject: localhost
Issuer: Smallstep Intermediate CA
Provisioner: sebastian@smallstep.com [ID: n2kq...Viy8]
Valid from: 2019-04-23T22:57:50Z
to: 2019-04-24T22:57:50Z
</pre></code>
6. Now let's revoke the certificate
<pre><code>
<b>$ step certificate inspect --format=json localhost.crt | jq .serial_number</b>
"59636004850364466675608080466579278406"
# the serial number is unique
<b>$ step ca revoke 59636004850364466675608080466579278406</b>
✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
✔ Please enter the password to decrypt the provisioner key:
✔ CA: https://ca.smallstep.com
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
7. Awesome! But did it work?
<pre><code>
<b>$ step ca renew localhost.crt localhost.key</b>
error renewing certificate: Unauthorized
# log trace from CA:
[...]
WARN[0569] duration="82.782µs" duration-ns=82782
error="renew: certificate has been revoked"
fields.time="2019-04-23T16:03:01-07:00" method=POST
name=ca path=/renew protocol=HTTP/1.1 referer=
remote-address=127.0.0.1 request-id=bivpj9a3q563rpjheh5g
size=40 status=401 user-agent=Go-http-client/1.1 user-id=
[...]
</pre></code>
8. Other ways to revoke a Certificate
Use the certificate and key. This method does not require a provisioner
because it uses the certificate and key to authenticate the request.
<pre><code>
<b>$ step ca revoke --cert localhost.crt --key localhost.key</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
Or, revoke a certificate in two steps by first creating a revocation token and
then exchanging that token in a revocation request.
<pre><code>
<b>$ TOKEN=$(step ca token --revoke 59636004850364466675608080466579278406)</b>
✔ Key ID: n2kqNhicCCqVxJidspCQrjXWBtGwsa9zk3eBObrViy8 (sebastian@smallstep.com)
✔ Please enter the password to decrypt the provisioner key:
<b>$ echo $TOKEN | step crypto jwt inspect --insecure</b>
{
"header": {
"alg": "ES256",
"kid": "uxEunU9UhUo96lRvKgpEtRevkzbN5Yq88AFFtb1nSGg",
"typ": "JWT"
},
"payload": {
"aud": "https://localhost:443/1.0/revoke",
"exp": 1556395590,
"iat": 1556395290,
"iss": "sebastian@smallstep.com",
"jti": "1f222fc1a22530b7bcd2a40d7308c566c8e49f90413bc350e07bfabc8002b79b",
"nbf": 1556395290,
"sha": "fef4c75a050e1f3a31175ca4f4fdb711cbef1efcd374fcae4700596604eb8e5a",
"sub": "59636004850364466675608080466579278406"
},
"signature": "M1wX0ea3VXwS5rIim0TgtcCXHDtvP1GWD15cJSvVkrHNO6XMYl6m3ZmnWdwMi976msv-n2GTG3h6dJ3j2ImdfQ"
}
<b>$ step ca revoke --token $TOKEN 59636004850364466675608080466579278406</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
Or, revoke a certificate in offline mode:
<pre><code>
<b>$ step ca revoke --offline 59636004850364466675608080466579278406</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
<b>$ step ca revoke --offline --cert localhost.crt --key localhost.key</b>
Certificate with Serial Number 59636004850364466675608080466579278406 has been revoked.
</pre></code>
> NOTE: you can only revoke a certificate once. Any repeated attempts to revoke
> the same serial number will fail.
Run `step help ca revoke` from the command line for full documentation, list of
command line flags, and examples.
## What's next?
[Use TLS Everywhere](https://smallstep.com/blog/use-tls.html) and let us know
what you think of our tools. Get in touch over
[Twitter](twitter.com/smallsteplabs) or through our
[GitHub Discussions](https://github.com/smallstep/certificates/discussions) to find answers to frequently asked questions.
[Discord](https://bit.ly/step-discord) to chat with us in real time.
## Further Reading
* [Use TLS Everywhere](https://smallstep.com/blog/use-tls.html)
* [Everything you should know about certificates and PKI but are too afraid to ask](https://smallstep.com/blog/everything-pki.html)