Make a YubiKey a DevID CA
Generate a DevID CA key on the YubiKey of an anchor, have Atlantis certify it under the FML intermediate, and write the certificate into the card.
Use this runbook to make the YubiKey on spore or capsule a hardware DevID CA, as PKI describes. Do it once for each anchor: the YubiKey 5 goes in spore, and the YubiKey 4c goes in capsule.
<host> is spore or capsule, and <target> is <host>.<tailnet>. <tailnet> is the tailnet key in terraform/network/tailscale/fleet.tf.json.
warning
This procedure changes live state by hand. It is an exception to the GitOps rule because only a process on the anchor can program the YubiKey. The script refuses a card whose PIV applet holds a key, and resets nothing.
Before you start#
- You need the operator key in
~/.config/age/keys.txt, as Manage SOPS secrets describes. - Sign in to 1Password with
op, with write access to thehomelabvault. - You need Google credentials that read the
terraform/pkistate. <host>setshomelab.devidCa.yubikey.enable, and runs a configuration frommainthat sets it.- The PIV applet of the YubiKey holds no key and has the factory PIN, PUK and management key.
Generate the key#
Put the YubiKey in a USB port of
<host>.Make sure that the anchor sees one YubiKey.
ssh <target> sudo ykman listResult: one line that names the YubiKey and its serial.
On a branch, initialize the key.
export SOPS_AGE_KEY_FILE=~/.config/age/keys.txt mise run devid:yubikey:init <host>Result:
Done: terraform/pki/csr/folly-devid-ca-<host>.csr holds the CSR of folly-devid-ca-<host>.and the serial of the YubiKey.In
nix/hosts/<host>.nix, sethomelab.devidCa.yubikey.serialto that serial.Commit the CSR,
nix/secrets/<host>.sops.yamlandnix/hosts/<host>.nix, and open a pull request.
Certify the key#
note
The pull request changes no .tf file, so Atlantis does not plan it by itself.
Comment
atlantis plan -d terraform/pkion the pull request.Result: a plan that adds
tls_locally_signed_cert.devid_ca_yubikey["<host>"]and changes nothing else.Comment
atlantis apply. Atlantis applies the plan and merges the pull request.Deploy
<host>, as Deploy a NixOS host describes. sops-nix then writes the PIN for thedevid-cagroup.
Install the certificate#
Initialize the
terraform/pkiroot with its state.tofu -chdir=terraform/pki initOn a new branch from
main, install the certificate.mise run devid:yubikey:install <host>Result:
Verified OK, the token labelYubiKey PIV #<serial>, and apki:verifyline that starts withok.Commit
folly-devid-ca-<host>.pemand the bundlefolly-devid-ca.peminterraform/pki/certs/, and open a pull request.Merge the pull request after the
pki:verifycheck passes.
If something goes wrong#
| Symptom | Cause | Action |
|---|---|---|
ykman is not found | <host> runs a configuration without the YubiKey module | Deploy <host> from main. |
ykman list prints nothing | pcscd cannot see the card, or the CCID interface is off | Put the YubiKey in again. Run ssh <target> sudo ykman config usb --enable CCID. |
the PIV applet holds a key or certificate | The card holds an earlier key | If nothing on the card is needed, run ssh <target> sudo ykman piv reset, and run init again. |
firmware ... must not generate RSA2048 keys | The firmware is in the ROCA range | Use a different YubiKey. |
| Init fails after it stored the secrets | The card refused a step | Run ykman piv reset on <host>. Delete the 1Password item devid-ca-<host> and the devid-ca keys of the SOPS file. Run init again. |
| Install says that no certificate is issued | Atlantis has not applied the CSR | Apply the pull request with Atlantis. |
the YubiKey on <host> is not serial ... | The serial in nix/hosts/<host>.nix is wrong | Correct the serial from ssh <target> sudo ykman list. |
pki:verify reports the bundle | folly-devid-ca.pem misses a CA | Run mise run devid:bundle, and commit the result. |