Skip to content

Commit

Permalink
Running step ca docker (#10)
Browse files Browse the repository at this point in the history
* Adds step-ca docker yubikey post

* Edits step-ca docker yubikey post

* Language fix

* Fix layout

* Fix bolding

* Fix formatting

* Fix wording

* Minor edits to step-ca docker instructions
  • Loading branch information
andrewmzhang authored Apr 18, 2024
1 parent f4690fd commit 7e07d83
Showing 1 changed file with 206 additions and 0 deletions.
206 changes: 206 additions & 0 deletions _posts/2023-07-24-running-step-ca-in-docker-w-yubikey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
---
layout: post
title: Running step-ca in docker w/ Yubikey
tags: [AndyWebServices, Certificate, Authority, Yubikey, smallstep, step-ca]
category: tech
description: How to run step-ca in docker while storing private keys on Yubikey
giscus_comments: true
author: Andrew M. Zhang

---

#### Abstract

Carl Tashian of Smallstep wrote a blog post regarding [Building a Tiny Certificate Authority For Your Homelab](https://smallstep.com/blog/build-a-tiny-ca-with-raspberry-pi-yubikey/).
This guide provides very complete instructions on how to install a step-ca certificate authority on a Raspberry Pi 4
and how to store the private keys securely on a Yubikey. This post is written assuming familiarity with this guide.
Namely, be familiar with the process of running the `step ca init` twice, once to setup the private keys off-host (ie usb)
, then again to setup the directory structure. Certs must then be copied from the off-host device to the directory
structure. Private keys on the off-host device are loaded into a Yubikey.

The only problem is I like using Docker and I generally dislike running stuff on bare metal. Unfortunately, there are
not any clear instructions on how to use the `smallstep/step-ca:hsm` image with a Raspberry Pi with a Yubikey. My guide
will roughly follow the same steps except using docker.

***NOTE*** There is currently a bug in step-ca's `dockerfile.hsm`. See the final step of the guide for a quick fix.

Read the following to understand the parts of a PKI https://smallstep.com/blog/everything-pki/

## Requirements
* Rpi
* Yubikey
* USB stick

## Setup Rpi

I tried this using both Ubuntu and Raspbian on Rpi. I think it'll work on any Rpi OS that supports Docker. Do whatever
you need to do to install Docker.

## Setup Root and Intermediate keys onto USB stick

The goal is to have the root and intermediate keys on a USB stick, just like in Carl's guide. Though, I recommend
using a LUKS encrypted USB stick to hold the keys. You can steal the commands for setting that up here: https://github.com/drduh/YubiKey-Guide#backup

For the remainder of the guide I'll assume your usb, encrypted or otherwise, is mounted here `/mnt/usb/`

```bash
# modified from `Manual Installation` here https://hub.docker.com/r/smallstep/step-ca

docker pull smallstep/step-ca:hsm

# Fill out the prompts with your own answers
docker run -it -v /home/pi/docker/data/step:/home/step andywebservices/step-ca:hsm step ca init --name="AndyWebServices CA"\
--dns="awsca.aws,172.19.0.100" --address=":443" --provisioner="[email protected]" --deployment-type standalone \
--remote-management --acme --admin-name [email protected]
there is no ca.json config file; please run step ca init, or provide config parameters via DOCKER_STEPCA_INIT_ vars
✔ Deployment Type: Standalone # Select Standalone
What would you like to name your new PKI?
✔ (e.g. Smallstep): TinyCA # Give it a name. This will appear in yoru certs
What DNS names or IP addresses will clients use to reach your CA?
✔ (e.g. ca.example.com[,10.1.2.3,etc.]): ca.internal,192.168.0.101,10.10.10.10 # You can list a bunch of these. Values can be adjusted layer in /mnt/usb/config/ca.json
What IP and port will your new CA bind to? (:443 will bind to 0.0.0.0:443)
✔ (e.g. :443 or 127.0.0.1:443): :443 # You probably want :443
✔ (e.g. [email protected]): [email protected] # Your email
Choose a password for your CA keys and first provisioner.
✔ [leave empty and we'll generate one]:
✔ Password: my.password.is.unique # Pick a sensible password
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: 0d134a66060ff7540f3cd304c81d354ded26d4b57d4d33f5b445ad555b7c0335
✔ Intermediate certificate: /home/step/certs/intermediate_ca.crt
✔ Intermediate private key: /home/step/secrets/intermediate_ca_key
badger 2023/07/26 06:04:17 INFO: All 0 tables opened in 0s
✔ 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'.
FEEDBACK 😍 🍻
The step utility is not instrumented for usage statistics. It does not phone
home. But your feedback is extremely valuable. Any information you can provide
regarding how you’re using `step` helps. Please send us a sentence or two,
good or bad at [email protected] or join GitHub Discussions
https://github.com/smallstep/certificates/discussions and our Discord
https://u.step.sm/discord.
```
### Optional: Set up name contraints
Follow the instructions here to setup up name constraints if you're going to set it up for the root cert. This is probably
good practice. If you don't use name constraints and your CA is hijacked, then it can issue certs for any domains (ie google.com).
Usually name constraints are set on the intermediate cert but for custom TLDs and internal stuff, constraining the
root cert is acceptable and is the only way to show clients that you're not going to sign for stuff you don't own (ie google.com).
I use an internal TLD. You should set the permitted domains to also include the one you use for emails or else I think
you could get issues. Ie I setup my name constraints to sign `.customtld`, `mydomain.com` (I own this), and `.mydomain.com`
## Load the keys onto the yubikey
Check the instructions in the Carl Tashian guide for how to import the keys onto the yubikey. You might need to install
`yubikey-manager` (ie ykman) and `pcscd`
https://smallstep.com/blog/build-a-tiny-ca-with-raspberry-pi-yubikey/#import-the-ca-into-the-yubikey
## Remove pcscd from the bare metal machine. Other cleanup
Uninstall the yubikey stuff after this step. The `pcscd` service on the host machine will lock up the yubikey to the
host meaning we can't pass it to the docker container.

Unmount the encrypted drive. You don't need it anymore
## Create a skeleton setup without secret keys
I'm going to assume that the docker mount for your step-ca server will be under `/home/pi/docker/mnt/step`

Run the following. Answer the prompts / set CLI variables the same way you answered them before
```bash
# modified from `Manual Installation` here https://hub.docker.com/r/smallstep/step-ca
docker pull smallstep/step-ca:hsm
docker run -it -v /home/pi/docker/mnt/step/:/home/step smallstep/step-ca:hsm step ca init --remote-management
# Follow the prompt the same way you filled out before
# Delete the secret keys from the skeleton. Copy the configs and certs. Do NOT copy the secret keys. These are on the Yubikey
rm -rf /home/pi/docker/mnt/secrets/*
cp /mnt/usb/config/* /home/pi/docker/mnt/step/config/
cp /mnt/usb/certs/* /home/pi/docker/mnt/step/certs/
```

Edit the file in `config/ca.json` to read something like. Edit values where appropriate
```json
{
"root": "/home/pi/docker/mnt/step/certs/root_ca.crt",
"federatedRoots": [],
"crt": "/home/pi/docker/mnt/step/certs/intermediate_ca.crt",
"key": "yubikey:slot-id=9c",
"kms": {
"type": "yubikey",
"pin": "123456"
},
"address": ":443"
// [...]
```
At this point, we're fully setup to run the cert auth
## Random stuff
You need a password file. It's just a thing the docker entrypoint for `step-ca` expects.
```bash
touch /home/pi/docker/mnt/step/secrets/password
```
## Start step-ca and pass Yubikey
***I'm hoping that this section becomes fixed in the future. Track the PR here: <insert PR here>***
Clone the repo `github.com/smallstep/certificates.git`. Copy `docker/Dockerfile.hsm` to repo root.
So there's a bug as of the writing of this guide 07/25/23. The issue is that the user `step` in the container doesn't
have adequate permission to run pcscd service. Thus you're going to need to include these 3 lines in the Dockerfile
```dockerfile
# Change the first line to use golang:bullseye. Otherwise it might not build right on your RPI due to GLibC versioning issues
# If we're building on the rpi, this ensures we have the right glibc version.
# You may need to adjust as raspbian moves to newer versions
FROM golang:bullseye AS builder
# Insert this after `RUN chown step:step /run/pcscd` but before `USER step`
RUN groupadd pcscd # Create the pcscd group
RUN usermod -aG pcscd step # Adds the user step to pcscd group
```
Then build this image and launch
```
# Execute the following from repo root
docker build --no-cache -t some-catchy-name:hsm . # build docker image
# You can figure out the bus and usb id via `lsusb` command. This does tend to change when you unplug and replug. You can
# maybe use udevadm to set up a symlink. See the Carl Tashian guide for that setup. I think passing the --privileged
# flag will let the contianer access all devices
docker run -d -p 443:443 -v /home/pi/docker/mnt/step:/home/step --device /dev/bus/usb/001/008:/dev/bus/usb/001/008 some-catchy-name:hsm
```
## Messing with the udev rules
The above *should* work, but if it doesn't, try running the container as root user with the option `-u 0`
I got mine to work with the `step` user (in the container) by setting these udev rules in the host. I'm not a udev expert
but I think these changes let `pcscd` work correctly in the container without the `-u 0` option.
```
# IN file /etc/udev/rules.d/75-yubikey.rules
ACTION=="add", SUBSYSTEM=="usb", ENV{PRODUCT}=="1050/406/*", TAG+="systemd", SYMLINK+="yubikey", GROUP="pcscd", MODE="0666", RUN+="/bin/chgrp pcscd $root/$parent"
ACTION=="remove", SUBSYSTEM=="usb", ENV{PRODUCT}=="1050/406/*", TAG+="systemd"
```
## My image
You can get a copy of my rpi step-ca image via `docker pull andywebservices/step-ca:hsm`.

0 comments on commit 7e07d83

Please sign in to comment.