smallstep/step-ca

By smallstep

Updated 7 days ago

🛡️ An online Certificate Authority and ACME server for secure automated certificate management.

Image
Security
80

10M+

smallstep/step-ca repository overview

step-ca

step-ca is a private online certificate authority (CA) for secure, automated X.509 and SSH certificate management.
  • Issue TLS and HTTPS certificates for all your workloads: VMs, containers, APIs, mobile clients, database connections, printers, humans, wifi networks, toaster ovens, and more.
  • Use it with any ACME v2 client—certbot, acme.sh, Traefik, Caddy, Kubernetes cert-manager, etc.
  • Issue SSH certificates for people (in exchange for single sign-on OIDC ID tokens) or hosts (in exchange for cloud instance identity documents or single-use tokens).
  • Supports hardware-bound private keys in PKCS#11 HSMs and Yubikey PIV slots. (See the step-ca-hsm image.)

Tags

The default image is suitable for most users.
It is tagged latest and tagged with the version number, eg. 0.23.0.
This is an Alpine-based image.

The HSM image is for use with keys stored in a PKCS#11 Hardware Security Module (HSM) or in Yubikey PIV slots.
It is tagged hsm and hsm- versions eg. hsm-0.23.0, hsm-0.23.1, ...
The step-ca binary in this image is compiled with CGO enabled.
It's Bullseye-based, so you can integrate a glibc-compatible pkcs11 module from your favorite HSM vendor.


Don't want to run your own CA? To get up and running quickly, or as an alternative to running your own step-ca server, consider creating a free hosted smallstep Certificate Manager authority.


Getting Started

Requirements

  • To interact with step-ca, you'll want to install the step client in your host environment. See our installation docs.

Quickstart

Initialize your PKI

To initialize your PKI, on your Docker host, run:

docker run -it -v step:/home/step \
    -p 9000:9000 \
    -e "DOCKER_STEPCA_INIT_NAME=Smallstep" \
    -e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$(hostname -f)" \
    -e "DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT=true" \
    smallstep/step-ca

👉 Note the CA fingerprint (SHA256), the remote management super admin username, and the remote management password in the output.

The following environment variables are available for initializing the CA configuration:

  • (required) DOCKER_STEPCA_INIT_NAME the name of your CA—this will be the issuer of your CA certificates
  • (required)DOCKER_STEPCA_INIT_DNS_NAMES the hostname(s) or IPs that the CA will accept requests on
  • (recommended) DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT enable remote provisioner management
  • DOCKER_STEPCA_INIT_PROVISIONER_NAME a label for the initial admin (JWK) provisioner. Default: admin
  • DOCKER_STEPCA_INIT_SSH set this to true to enable SSH certificate support
  • DOCKER_STEPCA_INIT_ACME also create an initial ACME provisioner for the CA
  • DOCKER_STEPCA_INIT_PASSWORD_FILE the location of a password file to be used for both private keys and the default CA provisioner. Useful for pointing to a Docker secret located in /run/secrets in the container. If both DOCKER_STEPCA_INIT_PASSWORD and DOCKER_STEPCA_INIT_PASSWORD_FILE are set, only DOCKER_STEPCA_INIT_PASSWORD_FILE will be used.
  • (not recommended) DOCKER_STEPCA_INIT_PASSWORD Normally, CA passwords will be generated for you. With this option, you can specify a password for the encrypted CA keys and the default CA provisioner. Note: Passwords stored in environment variables are not safe. In a production environment, a more secure option for specifying a password is to use the manual installation process, below.

These variables are only evaluated once, to configure step-ca before its first run.

Importing an existing PKI

The init script will always look for /run/secrets/root_ca.crt, /run/secrets/root_ca_key, and /run/secrets/root_ca_key_password, and if these files exist they will be used to import an existing PKI.

DOCKER_STEPCA_ROOT_FILE. DOCKER_STEPCA_INIT_KEY_FILE, and DOCKER_STEPCA_INIT_KEY_PASSWORD_FILE can be supplied if you need to use different filenames for this.

These files are only used once, to configure step-ca before its first run.

Bootstrap step clients

Once your CA is initialized, it will start running and you can connect to it. To connect, clients need to know the CA's URL and SHA256 fingerprint.

Let's bootstrap a step client in the host environment and install the root CA certificate into the host's trust store. In Bash, run:

{
  CA_FINGERPRINT=$(docker run -v step:/home/step smallstep/step-ca step certificate fingerprint certs/root_ca.crt)
  step ca bootstrap --ca-url https://localhost:9000 --fingerprint $CA_FINGERPRINT --install
}

Output:

The root certificate has been saved in /Users/alice/.step/certs/root_ca.crt.
Your configuration has been saved in /Users/alice/.step/config/defaults.json.
Installing the root certificate in the system truststore...
[sudo] password for alice: ....
done.

Your local step CLI is now configured to use the container instance of step-ca, and your root certificate is trusted by our host environment.

Run a health check:

curl https://localhost:9000/health

Output:

{"status":"ok"}

Your CA is ready for use.

Manual installation

This has been tested in Bash on Linux.

1. Pull down the Docker image

Get the latest version of step-ca

docker pull smallstep/step-ca
2. Bring up PKI bootstrapping container

The Docker volume step will hold your CA configuration, keys, and database.

docker run -it -v step:/home/step smallstep/step-ca step ca init --remote-management

The init command will step you through the bootstrapping process. Example output:

✔ 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. [email protected]): [email protected]
✔ What do you want your password to be? [leave empty and we'll generate one]:

Generating root certificate... done!
Generating intermediate certificate... done!

✔ Root certificate: /home/step/certs/root_ca.crt
✔ Root private key: /home/step/secrets/root_ca_key
✔ Root fingerprint: fa08cceda8501b1d93d275cfc614a5af2a37c6c72e674192b4598808c5bae91e
✔ Intermediate certificate: /home/step/certs/intermediate_ca.crt
✔ Intermediate private key: /home/step/secrets/intermediate_ca_key
✔ Database folder: /home/step/db
✔ Default configuration: /home/step/config/defaults.json
✔ Certificate Authority configuration: /home/step/config/ca.json
✔ Admin provisioner: [email protected] (JWK)
✔ Super admin subject: step

Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.

Save the root fingerprint value! You'll need it for client bootstrapping.

3. Place the PKI password in a known safe location.

The image is expecting the intermediate CA private key password to be placed in /home/step/secrets/password. Bring up the shell prompt in the container again and write that file:

docker run -it -v step:/home/step smallstep/step-ca sh

Inside your container, write the password file into the expected location:

 echo -n "<your password here>" > /home/step/secrets/password

Your CA is configured and ready to run.

4. Start step-ca

The CA runs an HTTPS API on port 9000 inside the container. Expose the server address locally and run the step-ca with:

docker run -d -p 9000:9000 -v step:/home/step smallstep/step-ca

Now, in the host environment, bootstrap your step client configuration:

{
CA_FINGERPRINT=$(docker run  -v step:/home/step smallstep/step-ca step certificate fingerprint /home/step/certs/root_ca.crt)
step ca bootstrap --ca-url https://localhost:9000 --fingerprint $CA_FINGERPRINT --install
}

Output:

The root certificate has been saved in /Users/alice/.step/certs/root_ca.crt.
Your configuration has been saved in /Users/alice/.step/config/defaults.json.
Installing the root certificate in the system truststore...
[sudo] password for alice: ...
done.

Your local step CLI is now configured to use the container instance of step-ca and our new root certificate is trusted by the host environment.

Run a health check:

curl https://localhost:9000/health

Output:

{"status":"ok"}
Next steps:

Code Signing

step-ca uses sigstore/cosign for signing and verifying containers. Here is an example of how to use cosign to verify a container:

cosign verify smallstep/step-ca:0.23.1 \
--certificate-identity-regexp "https://github\.com/smallstep/workflows/.*" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com

Setting Up a Development Environment

You will need:

  • A Python 2.7.x interpreter to bring up a standalone webserver (optional)

Run this section on your host machine where Docker is installed.

Once you've bootstrapped your local environment, you can now run web services configured with TLS and mTLS. First, get a certificate for localhost:

step ca certificate localhost localhost.crt localhost.key

Output:

✔ 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

Now save a copy of your root CA certificate:

step ca root root_ca.crt

Output:

The root certificate has been saved in root_ca.crt.

Next, let's launch a web server secured by HTTPS:

{
cat <<EOF > server.py
import BaseHTTPServer, ssl

class HelloHandler(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), HelloHandler)
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

python server.py
}

Open up another terminal to see your server running:

$ curl https://localhost:8443
👋 Hello! Welcome to TLS 🔒✅

Or visit https://localhost:8443 from your browser.

Troubleshooting
Raspberry Pi Badger database errors

When you run step-ca on a Raspberry Pi, you might get the following error in your container logs:

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, edit the db configuration block in the file config/ca.json.

docker run -v step:/home/step -it smallstep/step-ca vi /home/step/config/ca.json

Change the value of badgerFileLoadingMode from "" to "FileIO".

You will end up with this:

    "db": {
          "type": "badger",
          "dataSource": "/home/step/db",
          "badgerFileLoadingMode": "FileIO"
    },

Save and restart the container.

Questions? Ask us on GitHub Discussions or Discord.

Tag summary

Content type

Image

Digest

sha256:fe61f3878

Size

249 Bytes

Last updated

7 days ago

docker pull smallstep/step-ca:sha256-f720ee3a834c0d8cc3f1994be8aa3b7566678321b266b09aa8c0b25da9810780.sig