#!/usr/bin/env bash # bootstrap.sh — one-time setup of the bench CA after `docker compose up -d step-ca`. # # 1. wait for step-ca, export its root to pki/root_ca.crt (-> image radius-ca.pem) # 2. ensure an enrolment provisioner exists (signs each host's TPM CSR) # 3. issue the RADIUS server cert/key into pki/radius/ (FreeRADIUS mounts it) # # Runs the `step` CLI against the running CA. Flags vary a little across step # versions — BENCH-VERIFY against your `step version` and adjust. Reads .env. set -euo pipefail cd "$(dirname "$0")/.." [ -f .env ] && . ./.env CA_DNS=${CA_DNS:-ca.fleet.lab} CA_PORT=${CA_PORT:-8443} CA_URL="https://${CA_DNS}:${CA_PORT}" PKI=pki mkdir -p "$PKI/radius" # The CA's password (auto-init wrote it from this file in the container volume). PW="$PKI/stepca/secrets/password" [ -f "$PW" ] || { echo "CA not initialised yet ($PW missing) — is step-ca up?" >&2; exit 1; } step() { docker compose exec -T step-ca step "$@"; } # --- 1. export the root (becomes files/etc/dot1x/radius-ca.pem) -------------- echo "==> exporting CA root" docker compose exec -T step-ca cat /home/step/certs/root_ca.crt > "$PKI/root_ca.crt" FP=$(step certificate fingerprint "$PKI/root_ca.crt" 2>/dev/null || \ openssl x509 -in "$PKI/root_ca.crt" -noout -fingerprint -sha256 | cut -d= -f2) echo " root fingerprint: $FP" echo " copy to: files/etc/dot1x/radius-ca.pem (image trust anchor)" # --- 2. enrolment provisioner (idempotent) ---------------------------------- # JWK provisioner 'enrol' is created by auto-init (DOCKER_STEPCA_INIT_PROVISIONER_NAME). # Enrolment authorizes a CSR with a one-time token: # step ca token --provisioner enrol → passed to `step ca sign` # That token-gated sign is what enrol/tpm-provision.sh uses. echo "==> provisioners:" step ca provisioner list --ca-url "$CA_URL" --root "$PKI/root_ca.crt" \ | grep -E '"(name|type)"' || true # To UPGRADE to TPM attestation later, add an ACME attestation provisioner and # switch enrolment to device-attest-01 (key residency is then PROVEN, not trusted): # step ca provisioner add acme-attest --type ACME \ # --challenge device-attest-01 \ # --attestation-format tpm \ # --attestation-root # (then `step ca acme` / an ACME client on the host instead of `step ca sign`.) # --- 3. RADIUS server cert (FreeRADIUS serves this; supplicant validates it) -- echo "==> issuing RADIUS server cert (radius.${CA_DNS#ca.})" RADIUS_CN="radius.${CA_DNS#ca.}" step ca certificate "$RADIUS_CN" \ "$PKI/radius/server.pem" "$PKI/radius/server.key" \ --ca-url "$CA_URL" --root "$PKI/root_ca.crt" \ --provisioner enrol --provisioner-password-file "$PW" \ --not-after 720h --force cp "$PKI/root_ca.crt" "$PKI/radius/ca.pem" echo "==> done. FreeRADIUS will read pki/radius/{server.pem,server.key,ca.pem}." echo " Next: cp $PKI/root_ca.crt ../../files/etc/dot1x/radius-ca.pem && rebuild secure-path image."