Build your own tiny Certificate Authority.
The original version of this document was written by Carl Tashian and can be found on the Smallstep Blog. I’m merely copying and repurposing. No attempt to take responsibility for the genius not mine is being made ;)
TL;DR In this tutorial, weâre going to build a tiny, standalone, online Certificate Authority (CA) that will mint TLS certificates and is secured with a YubiKey. It will be an internal ACME server on our local network (ACME is the same protocol used by Letâs Encrypt). The YubiKey will securely store the CA private keys and sign certificates, acting as a cheap alternative to a Hardware Security Module (HSM). Weâll also use an open-source True Random Number Generator, called Infinite Noise TRNG, to spice up the Linux entropy pool.
Because end-to-end TLS is great and you should easily be able to run TLS wherever you need it. Especially in your homelab. Internal networks are no longer perceived as a safe zone where unencrypted traffic is okay. But you need certificates. Because TLS client authentication is becoming more widely supported in different services, and itâs a lot better than passwords. But you need certificates. Because the ACME protocol (used by Letâs Encrypt) can easily be deployed internally, so you can automate renewal and never have to think about your certificates. Because maybe youâve done the âself-signed certificateâ rigmarole with OpenSSL a dozen times already. Might as well formalize things and get your devices to trust a CA that you can use wherever you need it. Because setting up a simple CA is a great learning experience. Still not convinced? Spin up a free hosted homelab CA using our Certificate Manager offering instead.
- Raspberry Pi 4 Model B 2GB + microSD card
- Any YubiKey that supports the Personal Identity Verification (PIV) application, for CA signing operations. Iâm using a YubiKey 5 NFC.
- Optional: Infinite Noise TRNG for outboard random number generation.
- A USB thumb driveâor a second YubiKeyâfor storing an offline backup of our CA
Weâll be running the step-ca open-source online Certificate Authority. Total cost: Around US$100
On your laptop, burn the Ubuntu 20.10 Server 64-bit ARM pre-installed server image onto the microSD card using the Raspberry Pi Imager.
Fire up the Raspberry Pi
plug it into your network and find its initial IP address. You can run
arp -na | grep -e "b8:27:eb" -e "dc:a6:32" -e "e4:5f:01"
to discover Raspberry Pi devices on the local network.Login via SSH (username and password will be
ubuntu
),- Change the password for the
ubuntu
androot
users.
- Change the password for the
Set the hostname
hostnamectl set-hostname tinyca
Set the timezone
timedatectl set-timezone America/Chicago
(or whatever your timezone is;timedatectl list-timezones
will list them all)Validate NTP is working. Check status with timedatectl make sure âNTP Serviceâ is âactiveâ.
If not, you can add some NTP servers to
/etc/systemd/timesyncd.conf
and runsystemctl restart systemd-timesyncd
.
Before proceeding, Your host should be:
- Connected to the network.
- Be reachable via an FQDN.
- Have its’ clock set correctly.
- Have all relevant patches/packages available and installed to proceed.
lets get the required components to allow use of a yubikey installed.
Now, insert your YubiKey. Letâs install the yubikey-manager (and dependency pcscd
) and make sure you can connect to the YubiKey:
apt-get update && apt-get install -y yubikey-manager
Youâll need Golang installed in order to build the step-ca
server.
One easy way is to download a precompiled tarball from golang.org:
cd
curl -LO https://golang.org/dl/go1.15.6.linux-arm64.tar.gz
sudo tar -C /usr/local -xzf go1.15.6.linux-arm64.tar.gz
echo "export PATH=\$PATH:/usr/local/go/bin" >> .profile && source .profile
I’m sure there are instructions for this someplace. dunno.
I’m sure there are instructions for this someplace. dunno.
Hm… okay, not gonna quit my day job… But lets test and make sure Go works as expected:
go version
The output should be similar to:
go version go1.15.6 linux/arm64
Youâll need to install both step-ca
(the CA server software) and step
(the command used to configure and control step-ca).
First, download the source for step-ca
and build it with experimental YubiKey
support enabled:
At time of the original article creation, latest was 0.15.5.
curl -LO https://github.com/smallstep/certificates/archive/v0.15.5.tar.gz
tar xvzf v0.15.5.tar.gz
cd certificates-0.15.5/
At the time of adaptation 10.12.21 the latest version was 0.17.4
curl -LO https://github.com/smallstep/certificates/archive/v0.17.4.tar.gz
tar xvzf v0.17.4.tar.gz
cd certificates-0.17.4/
… Build completes…
TODO: This should be achievable more elegantly via the install cmd
|
|
The output should look similar to:
Check here: https://github.com/smallstep/cli/releases
- 10.21.20
- 0.15.3
- 10.12.21
- 0.17.6
curl -LO https://github.com/smallstep/cli/releases/download/v0.15.3/step_linux_0.15.3_arm64.tar.gz
tar xvzf step_linux_0.15.3_arm64.tar.gz
sudo cp step_0.15.3/bin/step /usr/local/bin
step version
The output should look similar to:
Infinite Noise TRNG is an open-source USB True Random Number Generator.
It uses a âmodular entropy multiplierâ architecture to generate a lot of random data quickly.
For this setup, a daemon will continuously feed entropy into Linuxâs system entropy pool by writing to /dev/random
.
But to validate that this lovely new entropy generator will actually be used by the CA, I needed to answer two questions here:
I had to dig around a little to confirm this. step-ca
uses Goâs crypto/rand
for all of its key generation.
crypto/rand
uses /dev/urandom
as its random data source on Linux systems.
It doesâbecause Linux has only one entropy pool, shared by /dev/random
and /dev/urandom
.
We also need to confirm that the outboard TRNG is actually generating high quality noise.
Weâll do that in a minute.
Youâll need to compile the driver from source, because thereâs no pre-built arm64 package available.
WARNING this is a bad link. find the repo elsewhere.
|
|
|
|
|
|
After a restart, you should see that the driver has started up. It will start and stop based on whether the TRNG is present.
|
|
Finally, letâs run a health check to make sure the TRNG is ready for use:
Entropy is written to /dev/random
by infnoise.service
every second.
Youâre all set on randomness!
Now that you have more than enough entropy, youâre ready to generate your CA keys.
Now youâll create your root and intermediate CA certificates and keys, and store them securely on the YubiKey.
Ideally, your Raspberry Pi should be kept offline for this section. Disconnect the Ethernet cable, and connect directly to the device via HDMI and a keyboard.
No seriously.
Make a double-thick (don’t skimp out… I’ll know.) Hat to cover that noggin of yours for this phase.
This is crucial.
Now Take a picture of yourself wearing your mind-spy-disruptor.
Print the picture out.
Get a sharpie. Red works best
Write on that picture:
I WILL ASSESS, FOR MYSELF, THE LEGITIMACY AND VALIDITY OF ANY AND ALL BULLSHIT I READ. I AM NOT A SHEEP.
You canât just have your CA private keys live only on the YubiKey. Youâll want at least one backup of them, in case the YubiKey breaks!
Insert a USB thumb drive. Youâll generate the keys directly on this drive, so that they never touch the Piâs microSD card. First, find the device name of your USB drive:
|
|
Great, now youâre ready to create your Public Key Infrastructure (PKI). Specifically, youâll be creating CA keys and certificates.
Tiny CA
has a root CA key and certificate, and an intermediate CA key and certificate.
The root CA key signs the Intermediate CA certificate.
The root CA certificate is self-signed (signed with the root CA key)
The intermediate CA key will sign all of your TLS certificates.
By default, step-ca issues certificates with a 24-hour lifetime. I hope this default will compel you to set up automated renewal on your clients. And you can always increase the TLS certificate duration in the CA configuration, if you want something a bit more relaxed.
If a device is configured to trust your root CA, it will trust certificates you create with step-ca.
You can throw away the root CA key if you never need another intermediate.
Need a refresher on X.509
certificates? See Smallstep’s post, Everything you should know about certificates and PKI but are too afraid to ask.
Use a strong password when prompted, and save your password separately, offline, somewhere super duper safe.
|
|
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: feedback@smallstep.com
or join
https://github.com/smallstep/certificates/discussions.
Donât forget to give your CA a cute name! It will appear on all of your certificates. Hold onto your root fingerprint, too;
youâll need it to bootstrap your clients later.
Now, letâs import our PKI to the YubiKey.
|
|
OK! Now youâll copy out the CA certificate files, leave the private keys on the USB stick, and continue creating your CA.
Finally, reconnect your CA to your local network to continue the setup.
Youâre going to re-run step ca init now, but youâre not going to use the certificates or keys that it generates. Youâre just doing this to create the configuration files. The password you choose when prompted will be your admin provisioner password. Anyone who has it will be able to get any certificate from your CA, using the step ca certificate subcommand.
Donât use your root CA password for your provisioner, but pick something strong and store it somewhere safe.
|
|
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: feedback@smallstep.com or join
https://github.com/smallstep/certificates/discussions.
|
|
Finally, youâll need to configure step-ca
to use your YubiKey
to sign certificates, using the intermediate key on the YubiKey
. Notice that the default YubiKey
PIN (123456
) is shown here, too.
You should change your YubiKey PIN, PUK, and management key if you havenât already! Learn how in this guide.
Now edit the file /etc/step-ca/config/ca.json
. Youâll want the top of the file to look like this:
…
In another window, youâll generate a test certificate for localhost.
This is where youâll need the CA fingerprint you created with your initial set of keys:
|
|
Great! You just signed your first X.509 TLS leaf certificate using the YubiKey
and step-ca
.
When you ask the CA to issue a leaf certificate for a TLS endpoint, youâll get a certificate file and an associated private key file. The certificate file will contain both the intermediate CA certificate and the leaf certificate you requested. This way, a device which trusts your root CA can verify the chain of trust from the root to the intermediate, and from the intermediate to the leaf.
|
|
In this section youâll set up a systemd service for step-ca so it starts when the system starts up.
Youâll also configure systemd to stop the CA when the YubiKey is removed, and restart it when the YubiKey is reinserted.
First, you need to tell udev about your YubiKey by adding some udev rules, which will help make the YubiKey visible to systemd as a device.
Here, the format of the ENV{PRODUCT}
value is {vendorId}/{productId}/*
. Yubicoâs vendor ID is 1050, and 407 is the product ID for the YubiKey 5 NFC. If youâre using a different YubiKey, you can find your model number here.
Now youâll set up the CA as a systemd service that will:
run on system startup, when the YubiKey is inserted stop when the YubiKey is removed start again when the YubiKey is reinserted
|
|
Now insert the YubiKey and the service should start:
|
|
Test out removing the YubiKey, and you should see that the CA stops.
Reinsert it, and the CA should start up again.
Your tiny CA will be most secure without any SSH access at all. The only open port will be 443, for the CA. For maintenance, youâll need to plug in a keyboard and a display.
|
|
You did it! Your CA is up and running.
When you run step ca bootstrap
(as above) on a new device, the root certificate root_ca.crt is downloaded from the CA.
If you run
It will install the root certificate into your deviceâs trust store.
You can also use the step
command:
- For easy installation of your root CA certificate
step certificate install
- For ACME enrollment
step ca certificate example.com example.crt example.key --provisioner acme
- For renewal of any certificate that hasnât yet expired
step ca renew example.crt example.key
For mobile devices, you can usually install a certificate by sending it to yourself via Bluetooth or AirDrop, or as an email attachment. Make sure the certificate isnât just installed, but actually trusted by the device.
This usually involves a couple of confirmation steps on the device.
With the ACME provisioner, you can use software like Certbot or LEGO CLI to easily get and renew certificates for any endpoint. Our tutorials on running a private ACME server and configuring popular ACME clients to use a private ACME server will show you how to get ACME certificates from your CA using the most common ACME clients and ACME-supporting services.
Because certificates from your CA have a 24-hour lifetime, youâll want to renew them every 16ish hours. Our renewal documentation has a few options for setting up renewal on your clients.
Now that you have an internal CA, hereâs a few useful resources:
To get more familiar with the step command and how it interfaces with your CA, try out some of the examples in Basic Certificate Authority Operations.
Hello mTLS shows you how to get mutual TLS authentication configured for several common services and programming languages, using the step command.
Thereâs also a lot to learn about the different provisioners you can add to your CA to suit your workflows. See Configuring step-ca.
Bonus: Want to use SSH certificates? You can turn your tiny CA into an SSH CA, and use certificates and single sign-on for your SSH hosts. We have a blog post and video walk-through that describes how to set it up.