Adding dot1x support

This commit is contained in:
Audiobuzz
2026-06-22 20:50:48 +00:00
parent 1f62e5ab17
commit dea7ca451a
13 changed files with 592 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
# tpm-provision.sh <host-id>
#
# One-shot enrolment for ONE workstation. Models the real flow (invariant #1:
# per-host identity is created at enrolment, never baked into the image):
# 1. generate a signing key INSIDE the TPM, persist it at handle 0x81010001
# 2. build a CSR using that TPM key (private key never leaves the TPM)
# 3. have step-ca sign it (token-gated 'enrol' provisioner)
# 4. write the issued cert (DER) to TPM NV index 0x01800001
# At boot the dracut hook reads the cert from NV and wpa_supplicant signs EAP-TLS
# with the persistent-handle key. hostnqn is later derived from the cert serial.
#
# Run on the workstation (booted into a provisioning env with tpm2-tools, an
# openssl TPM2 provider, and the `step` CLI) on a network that can reach step-ca.
# Works for swtpm (VMs) and a real TPM (820) — same /dev/tpmrm0 in-guest.
#
# Needs in this dir: root_ca.crt + ca-pw (copied from the serving host's
# serving/dot1x-bench/pki/{root_ca.crt,stepca/secrets/password}).
#
# *** BENCH-VERIFY (CLAUDE.md "Known bench-verify items"): the TPM key reference
# *** for openssl AND wpa_supplicant differs by distro build — OpenSSL TPM2
# *** PROVIDER (handle:0x...) vs tpm2-pkcs11 URI. This script uses the provider
# *** form; switch to the engine/pkcs11 form if your build needs it, and keep it
# *** consistent with files/etc/dot1x/wpa_supplicant-dot1x.conf.
set -euo pipefail
HOSTID=${1:?usage: tpm-provision.sh <host-id> e.g. ws-vm-a}
HANDLE=${HANDLE:-0x81010001}
NVINDEX=${NVINDEX:-0x01800001}
export TPM2TOOLS_TCTI="${TPM2TOOLS_TCTI:-device:/dev/tpmrm0}"
CA_DNS=${CA_DNS:-ca.fleet.lab}; CA_PORT=${CA_PORT:-8443}
CA_URL="https://${CA_DNS}:${CA_PORT}"
cd "$(dirname "$0")"
OUT=out; mkdir -p "$OUT"
[ -f root_ca.crt ] || { echo "missing root_ca.crt (copy from serving pki/)" >&2; exit 1; }
[ -f ca-pw ] || { echo "missing ca-pw (copy pki/stepca/secrets/password)" >&2; exit 1; }
# --- 1. persistent TPM signing key ------------------------------------------
if ! tpm2_readpublic -c "$HANDLE" >/dev/null 2>&1; then
echo "==> creating TPM signing key, persisting at $HANDLE"
tpm2_createprimary -C o -G ecc -g sha256 -c "$OUT/primary.ctx" >/dev/null
tpm2_create -C "$OUT/primary.ctx" -G ecc256:ecdsa-sha256 \
-u "$OUT/key.pub" -r "$OUT/key.priv" >/dev/null
tpm2_load -C "$OUT/primary.ctx" -u "$OUT/key.pub" -r "$OUT/key.priv" \
-c "$OUT/key.ctx" >/dev/null
tpm2_evictcontrol -C o -c "$OUT/key.ctx" "$HANDLE" >/dev/null
else
echo "==> reusing existing persistent key at $HANDLE"
fi
# --- 2. CSR signed by the TPM key (key stays in the TPM) ---------------------
echo "==> building CSR (CN=$HOSTID) with the TPM key via the openssl tpm2 provider"
openssl req -new -provider tpm2 -provider default \
-key "handle:$HANDLE" \
-subj "/O=fleet/CN=$HOSTID" \
-out "$OUT/$HOSTID.csr"
# --- 3. step-ca signs the CSR -----------------------------------------------
echo "==> requesting cert from step-ca"
TOKEN=$(step ca token "$HOSTID" --provisioner enrol \
--ca-url "$CA_URL" --root root_ca.crt \
--provisioner-password-file ca-pw --not-after 720h)
step ca sign "$OUT/$HOSTID.csr" "$OUT/$HOSTID.pem" \
--token "$TOKEN" --ca-url "$CA_URL" --root root_ca.crt
openssl x509 -in "$OUT/$HOSTID.pem" -outform DER -out "$OUT/$HOSTID.der"
# --- 4. write cert into TPM NV ----------------------------------------------
SZ=$(stat -c%s "$OUT/$HOSTID.der")
echo "==> writing $SZ-byte cert to NV $NVINDEX"
tpm2_nvundefine "$NVINDEX" -C o 2>/dev/null || true
tpm2_nvdefine "$NVINDEX" -C o -s "$SZ" -a 'ownerread|ownerwrite|authread|authwrite' >/dev/null
tpm2_nvwrite "$NVINDEX" -C o -i "$OUT/$HOSTID.der"
SERIAL=$(openssl x509 -in "$OUT/$HOSTID.pem" -serial -noout | cut -d= -f2 | tr 'A-F' 'a-f')
echo "==> enrolled $HOSTID"
echo " cert serial : $SERIAL"
echo " boot hostnqn: nqn.2026-06.org.example.fleet:host-$SERIAL"
echo " key @ $HANDLE, cert @ NV $NVINDEX — the secure-path image will read these."