support multiple tang urls

This commit is contained in:
Dominik Moritz Roth 2025-05-14 17:18:44 +02:00
parent 03f37e3c74
commit 605653419e
2 changed files with 110 additions and 47 deletions

View File

@ -9,8 +9,11 @@ image:
system: system:
# LUKS Configuration # LUKS Configuration
luks: luks:
tang_url: https://tang.example.com tang_servers:
tang_thumbprint: your-tang-thumbprint - url: https://tang1.example.com
thumbprint: your-tang1-thumbprint
- url: https://tang2.example.com
thumbprint: your-tang2-thumbprint
# TPM Configuration # TPM Configuration
tpm: tpm:

150
build.py
View File

@ -78,16 +78,27 @@ if ! tpm2_getcap properties-fixed > /dev/null; then
exit 1 exit 1
fi fi
# Check if Tang server is accessible # Check if at least one Tang server is accessible
TANG_URL=$(grep URL /etc/clevis/tang.conf | cut -d= -f2) TANG_AVAILABLE=0
if ! curl -s -f "$TANG_URL/adv" > /dev/null; then for tang_url in $(grep -h "url" /etc/clevis/sss.conf | grep -o '"url": "[^"]*"' | cut -d'"' -f4); do
echo "Error: Tang server not accessible" if curl -s -f "$tang_url/adv" > /dev/null; then
echo "Tang server $tang_url is accessible"
TANG_AVAILABLE=1
break
else
echo "Tang server $tang_url is not accessible"
fi
done
if [ $TANG_AVAILABLE -eq 0 ]; then
echo "Error: No Tang servers are accessible"
exit 1 exit 1
fi fi
# Get current PCR values # Get current PCR values
echo "Current PCR values:" echo "Current PCR values:"
tpm2_pcrread sha256:$(cat /etc/clevis/tpm2.conf | jq -r '.pcr_ids' | tr -d '[]' | tr ',' ' ') PCR_IDS=$(grep -h "pcr_ids" /etc/clevis/sss.conf | grep -o '"pcr_ids": "[^"]*"' | cut -d'"' -f4)
tpm2_pcrread sha256:$(echo $PCR_IDS | tr ',' ' ')
# Ask for confirmation # Ask for confirmation
read -p "Have you updated firmware? Continue with TPM binding update? [y/N] " -n 1 -r read -p "Have you updated firmware? Continue with TPM binding update? [y/N] " -n 1 -r
@ -97,23 +108,34 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1 exit 1
fi fi
# Get LUKS passphrase
if [ -f /root/luks-passphrase.txt ]; then
LUKS_PASSPHRASE=$(cat /root/luks-passphrase.txt)
else
echo "LUKS passphrase file not found. Please enter your LUKS passphrase:"
read -s LUKS_PASSPHRASE
echo
fi
# Update TPM bindings # Update TPM bindings
echo "Updating TPM bindings..." echo "Updating TPM bindings..."
for dev in /dev/sda2 /dev/sdb2; do for dev in /dev/sda2 /dev/sdb2; do
echo "Processing $dev..." echo "Processing $dev..."
# Unbind old TPM binding # Unbind old SSS binding
clevis luks unbind -d "$dev" -s 1 || true SLOT=$(clevis luks list -d "$dev" | grep -n "sss" | cut -d: -f1)
if [ -n "$SLOT" ]; then
echo "Removing old SSS binding from slot $SLOT"
clevis luks unbind -d "$dev" -s "$SLOT" || true
fi
# Create new TPM binding # Create new binding with SSS using the same config
clevis luks bind -d "$dev" tpm2 -c /etc/clevis/tpm2.conf || { echo "Adding new SSS binding"
echo "Error: Failed to bind TPM to $dev" echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d "$dev" sss -c /etc/clevis/sss.conf -k-
exit 1
}
# Verify Tang binding # Verify binding was successful
if ! clevis luks list -d "$dev" | grep -q "tang"; then if ! clevis luks list -d "$dev" | grep -q "sss"; then
echo "Error: Tang binding not found on $dev" echo "Error: Failed to create SSS binding for $dev"
exit 1 exit 1
fi fi
done done
@ -221,16 +243,27 @@ if ! tpm2_getcap properties-fixed > /dev/null; then
exit 1 exit 1
fi fi
# Check if Tang server is accessible # Check if at least one Tang server is accessible
TANG_URL=$(grep URL /etc/clevis/tang.conf | cut -d= -f2) TANG_AVAILABLE=0
if ! curl -s -f "$TANG_URL/adv" > /dev/null; then for tang_url in $(grep -h "url" /etc/clevis/sss.conf | grep -o '"url": "[^"]*"' | cut -d'"' -f4); do
echo "Error: Tang server not accessible" if curl -s -f "$tang_url/adv" > /dev/null; then
echo "Tang server $tang_url is accessible"
TANG_AVAILABLE=1
break
else
echo "Tang server $tang_url is not accessible"
fi
done
if [ $TANG_AVAILABLE -eq 0 ]; then
echo "Error: No Tang servers are accessible"
exit 1 exit 1
fi fi
# Get current PCR values # Get current PCR values
echo "Current PCR values:" echo "Current PCR values:"
tpm2_pcrread sha256:$(cat /etc/clevis/tpm2.conf | jq -r '.pcr_ids' | tr -d '[]' | tr ',' ' ') PCR_IDS=$(grep -h "pcr_ids" /etc/clevis/sss.conf | grep -o '"pcr_ids": "[^"]*"' | cut -d'"' -f4)
tpm2_pcrread sha256:$(echo $PCR_IDS | tr ',' ' ')
# Ask for confirmation # Ask for confirmation
read -p "Have you updated firmware? Continue with TPM binding update? [y/N] " -n 1 -r read -p "Have you updated firmware? Continue with TPM binding update? [y/N] " -n 1 -r
@ -240,23 +273,34 @@ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1 exit 1
fi fi
# Get LUKS passphrase
if [ -f /root/luks-passphrase.txt ]; then
LUKS_PASSPHRASE=$(cat /root/luks-passphrase.txt)
else
echo "LUKS passphrase file not found. Please enter your LUKS passphrase:"
read -s LUKS_PASSPHRASE
echo
fi
# Update TPM bindings # Update TPM bindings
echo "Updating TPM bindings..." echo "Updating TPM bindings..."
for dev in /dev/sda2 /dev/sdb2; do for dev in /dev/sda2 /dev/sdb2; do
echo "Processing $dev..." echo "Processing $dev..."
# Unbind old TPM binding # Unbind old SSS binding
clevis luks unbind -d "$dev" -s 1 || true SLOT=$(clevis luks list -d "$dev" | grep -n "sss" | cut -d: -f1)
if [ -n "$SLOT" ]; then
echo "Removing old SSS binding from slot $SLOT"
clevis luks unbind -d "$dev" -s "$SLOT" || true
fi
# Create new TPM binding # Create new binding with SSS using the same config
clevis luks bind -d "$dev" tpm2 -c /etc/clevis/tpm2.conf || { echo "Adding new SSS binding"
echo "Error: Failed to bind TPM to $dev" echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d "$dev" sss -c /etc/clevis/sss.conf -k-
exit 1
}
# Verify Tang binding # Verify binding was successful
if ! clevis luks list -d "$dev" | grep -q "tang"; then if ! clevis luks list -d "$dev" | grep -q "sss"; then
echo "Error: Tang binding not found on $dev" echo "Error: Failed to create SSS binding for $dev"
exit 1 exit 1
fi fi
done done
@ -265,6 +309,29 @@ echo "TPM bindings updated successfully!"
echo "Please reboot to verify the changes." echo "Please reboot to verify the changes."
''' '''
# Create SSS config for TPM + any Tang server
tang_servers = []
for server in system['luks']['tang_servers']:
tang_servers.append({"url": server['url']})
# Convert Tang servers to JSON for SSS config
tang_servers_json = json.dumps(tang_servers)
# Create SSS policy: Require TPM AND at least one Tang server
sss_config = {
"t": 2, # Threshold: Both pins must succeed
"pins": {
"tpm2": {
"pcr_bank": system['luks']['tpm']['pcr_bank'],
"pcr_ids": ','.join(map(str, system['luks']['tpm']['pcr_ids']))
},
"tang": {"t": 1, "tang": tang_servers} # Only one Tang server needed from the list
}
}
# Convert config to JSON string
sss_config_json = json.dumps(sss_config)
kickstart = f"""# Kickstart configuration for Fedora Server kickstart = f"""# Kickstart configuration for Fedora Server
# Generated for Nullpoint # Generated for Nullpoint
@ -330,16 +397,10 @@ dropbear
%pre %pre
# Create TPM and Tang config files # Create TPM and Tang config files
mkdir -p /etc/clevis mkdir -p /etc/clevis
cat > /etc/clevis/tang.conf << EOF
URL={system['luks']['tang_url']}
Thumbprint={system['luks']['tang_thumbprint']}
EOF
cat > /etc/clevis/tpm2.conf << EOF # Save SSS config for TPM + Tang servers
{{ cat > /etc/clevis/sss.conf << EOF
"pcr_bank": "{system['luks']['tpm']['pcr_bank']}", {sss_config_json}
"pcr_ids": "{','.join(map(str, system['luks']['tpm']['pcr_ids']))}"
}}
EOF EOF
%end %end
@ -356,12 +417,11 @@ printf "Current step: Setting up TPM and Tang...\r\n\n" > /dev/tty1
echo "$LUKS_PASSPHRASE" > /root/luks-passphrase.txt echo "$LUKS_PASSPHRASE" > /root/luks-passphrase.txt
chmod 600 /root/luks-passphrase.txt chmod 600 /root/luks-passphrase.txt
# Setup Clevis for TPM and Tang # Setup Clevis with SSS policy (TPM + at least one Tang server)
printf "Configuring Clevis for TPM and Tang...\r\n" > /dev/tty1 printf "Configuring TPM and Tang with SSS policy...\r\n" > /dev/tty1
clevis luks bind -d /dev/sda2 tpm2 -c /etc/clevis/tpm2.conf echo "Using SSS policy: TPM verification AND (at least one Tang server)" > /dev/tty1
clevis luks bind -d /dev/sda2 tang -c /etc/clevis/tang.conf echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d /dev/sda2 sss -c /etc/clevis/sss.conf -k-
clevis luks bind -d /dev/sdb2 tpm2 -c /etc/clevis/tpm2.conf echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d /dev/sdb2 sss -c /etc/clevis/sss.conf -k-
clevis luks bind -d /dev/sdb2 tang -c /etc/clevis/tang.conf
# Get BTRFS UUID (same for all devices in the filesystem) # Get BTRFS UUID (same for all devices in the filesystem)
BTRFS_UUID=$(blkid -s UUID -o value /dev/mapper/luks-$(blkid -s UUID -o value /dev/sda2)) BTRFS_UUID=$(blkid -s UUID -o value /dev/mapper/luks-$(blkid -s UUID -o value /dev/sda2))