From 730f645dc0388dbe60a399cedf8ccff62fe25413 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Mon, 10 Aug 2026 13:59:28 -0400 Subject: [PATCH] Defer PCR sealing to first boot If someone wants to seal to a PCR explicitly to prevent booting rescue, the PCR is likely to extend differently during install. Leave the volume sealed to the tpm without any PCRs until first boot. Then wipe the bindings without PCR specified, and seal according to user preferred values. --- .../el8/profiles/default/scripts/firstboot.sh | 6 + .../el8/profiles/default/scripts/tpm_luks.sh | 11 +- .../default/scripts/tpm_luks_reseal.sh | 121 ++++++++++++++++++ 3 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 confluent_osdeploy/el8/profiles/default/scripts/tpm_luks_reseal.sh diff --git a/confluent_osdeploy/el8/profiles/default/scripts/firstboot.sh b/confluent_osdeploy/el8/profiles/default/scripts/firstboot.sh index bcc54719..2ef8830e 100644 --- a/confluent_osdeploy/el8/profiles/default/scripts/firstboot.sh +++ b/confluent_osdeploy/el8/profiles/default/scripts/firstboot.sh @@ -46,6 +46,12 @@ while ! ping -c 1 $confluent_pingtarget >& /dev/null; do sleep 1 done +if [ -e /etc/confluent/luks.key ]; then + pcrs=$(sed -n -e 's/.*tpm2:pcrs=\([0-9,]*\).*/\1/p' /tmp/cryptboot) + if [ -n "$pcrs" ]; then + run_remote tpm_luks_reseal.sh + fi +fi if [ ! -f /etc/confluent/firstboot.ran ]; then touch /etc/confluent/firstboot.ran diff --git a/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh b/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh index a46304b5..dd03314b 100644 --- a/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh +++ b/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh @@ -1,19 +1,12 @@ #!/bin/sh cryptdisk=$(blkid -t TYPE="crypto_LUKS"|sed -e s/:.*//) -pcrs=$(sed -n -e 's/.*tpm2:pcrs=\([0-9,]*\).*/\1/p' /tmp/cryptboot) - if [ -x /bin/systemd-cryptenroll ]; then - PASSWORD=$(cat /etc/confluent/luks.key) systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="$pcrs" $cryptdisk + PASSWORD=$(cat /etc/confluent/luks.key) systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="" $cryptdisk sed -e 's/ discard/ tpm2-device=auto,discard/' -i /etc/crypttab dracut -f else - if [ -n "$pcrs" ]; then - clevispcrs=$(echo "$pcrs" | sed -e 's/,/, /g') - clevis luks bind -f -d $cryptdisk -k - tpm2 "{\"pcr_ids\":\"$clevispcrs\"}" < /etc/confluent/luks.key - else - clevis luks bind -f -d $cryptdisk -k - tpm2 "{}" < /etc/confluent/luks.key - fi + clevis luks bind -f -d $cryptdisk -k - tpm2 "{}" < /etc/confluent/luks.key #cryptsetup luksRemoveKey $cryptdisk < /etc/confluent/confluent.apikey fi chmod 000 /etc/confluent/luks.key diff --git a/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks_reseal.sh b/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks_reseal.sh new file mode 100644 index 00000000..d5b02b6f --- /dev/null +++ b/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks_reseal.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +# Resealing to allow more practical use of, for example, PCR1, which frequently gets changed booting from install environment +# to local disk + +get_requested_pcrs() { + local encryptboot=$(grep ^encryptboot: /etc/confluent/confluent.deploycfg | awk '{print $2}') + IFS=':' read -ra params <<< "$encryptboot" + for param in "${params[@]}"; do + if [[ "$param" =~ ^pcrs= ]]; then + echo "${param#pcrs=}" + return 0 + fi + done +} + +wipe_slots() { + local device="$1" + + if [[ -z "$device" ]]; then + echo "Error: No device specified" >&2 + return 1 + fi + + # Check if device exists + if [[ ! -e "$device" ]]; then + echo "Error: Device $device not found" >&2 + return 1 + fi + + # Wipe existing TPM2 slots using clevis + echo "Wiping TPM2 slots for $device" + if [ -e /bin/systemd-cryptenroll ]; then + systemd-cryptenroll --wipe-slot=tpm2 "$device" + else + clevis luks unbind -d "$device" tpm2 || true + fi + return 0 +} + +seal_tpm() { + local device="$1" + if [[ -z "$device" ]]; then + echo "Error: No device specified" >&2 + return 1 + fi + + if [[ ! -e "$device" ]]; then + echo "Error: Device $device not found" >&2 + return 1 + fi + local pcrs=$(get_requested_pcrs) + if [ -e /bin/systemd-cryptenroll ]; then + PASSWORD=$(cat /etc/confluent/luks.key) systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs="$pcrs" "$device" + else + if [ -n "$pcrs" ]; then + clevispcrs=$(echo "$pcrs" | sed -e 's/,/, /g') + clevis luks bind -f -d "$device" -k - tpm2 "{\"pcr_ids\":\"$clevispcrs\"}" < /etc/confluent/luks.key + else + clevis luks bind -f -d "$device" -k - tpm2 "{}" < /etc/confluent/luks.key + fi + fi + + if [[ $? -eq 0 ]]; then + echo "Successfully enrolled TPM2 for $device" + return 0 + else + echo "Failed to enroll TPM2 for $device" >&2 + return 1 + fi +} + +reseal_luks() { + local device="$1" + + if [[ -z "$device" ]]; then + echo "Error: No device specified" >&2 + return 1 + fi + + # Check if device exists + if [[ ! -e "$device" ]]; then + echo "Error: Device $device not found" >&2 + return 1 + fi + + # Wipe existing TPM2 slots + echo "Wiping TPM2 slots for $device" + wipe_slots "$device" + + # Enroll TPM2 key + + seal_tpm "$device" + +} + +while IFS= read -r line; do + # Skip comments and empty lines + [[ "$line" =~ ^[[:space:]]*# ]] && continue + [[ -z "$line" ]] && continue + + # Check if line contains tpm2-device + if [[ "$line" =~ tpm2-device ]]; then + # Extract the second column (device or UUID) + device=$(echo "$line" | awk '{print $2}') + + # If it's a UUID, convert to device name + if [[ "$device" =~ ^UUID= ]]; then + device=$(blkid -U "${device#UUID=}") + fi + + # Process the device + if [[ -n "$device" ]]; then + reseal_luks "$device" + else + echo "Warning: Could not determine device for line: $line" >&2 + fi + fi +done < /etc/crypttab + +