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:
# LUKS Configuration
luks:
tang_url: https://tang.example.com
tang_thumbprint: your-tang-thumbprint
tang_servers:
- url: https://tang1.example.com
thumbprint: your-tang1-thumbprint
- url: https://tang2.example.com
thumbprint: your-tang2-thumbprint
# TPM Configuration
tpm:

150
build.py
View File

@ -78,16 +78,27 @@ if ! tpm2_getcap properties-fixed > /dev/null; then
exit 1
fi
# Check if Tang server is accessible
TANG_URL=$(grep URL /etc/clevis/tang.conf | cut -d= -f2)
if ! curl -s -f "$TANG_URL/adv" > /dev/null; then
echo "Error: Tang server not accessible"
# Check if at least one Tang server is accessible
TANG_AVAILABLE=0
for tang_url in $(grep -h "url" /etc/clevis/sss.conf | grep -o '"url": "[^"]*"' | cut -d'"' -f4); do
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
fi
# Get 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
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
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
echo "Updating TPM bindings..."
for dev in /dev/sda2 /dev/sdb2; do
echo "Processing $dev..."
# Unbind old TPM binding
clevis luks unbind -d "$dev" -s 1 || true
# Unbind old SSS binding
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
clevis luks bind -d "$dev" tpm2 -c /etc/clevis/tpm2.conf || {
echo "Error: Failed to bind TPM to $dev"
exit 1
}
# Create new binding with SSS using the same config
echo "Adding new SSS binding"
echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d "$dev" sss -c /etc/clevis/sss.conf -k-
# Verify Tang binding
if ! clevis luks list -d "$dev" | grep -q "tang"; then
echo "Error: Tang binding not found on $dev"
# Verify binding was successful
if ! clevis luks list -d "$dev" | grep -q "sss"; then
echo "Error: Failed to create SSS binding for $dev"
exit 1
fi
done
@ -221,16 +243,27 @@ if ! tpm2_getcap properties-fixed > /dev/null; then
exit 1
fi
# Check if Tang server is accessible
TANG_URL=$(grep URL /etc/clevis/tang.conf | cut -d= -f2)
if ! curl -s -f "$TANG_URL/adv" > /dev/null; then
echo "Error: Tang server not accessible"
# Check if at least one Tang server is accessible
TANG_AVAILABLE=0
for tang_url in $(grep -h "url" /etc/clevis/sss.conf | grep -o '"url": "[^"]*"' | cut -d'"' -f4); do
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
fi
# Get 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
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
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
echo "Updating TPM bindings..."
for dev in /dev/sda2 /dev/sdb2; do
echo "Processing $dev..."
# Unbind old TPM binding
clevis luks unbind -d "$dev" -s 1 || true
# Unbind old SSS binding
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
clevis luks bind -d "$dev" tpm2 -c /etc/clevis/tpm2.conf || {
echo "Error: Failed to bind TPM to $dev"
exit 1
}
# Create new binding with SSS using the same config
echo "Adding new SSS binding"
echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d "$dev" sss -c /etc/clevis/sss.conf -k-
# Verify Tang binding
if ! clevis luks list -d "$dev" | grep -q "tang"; then
echo "Error: Tang binding not found on $dev"
# Verify binding was successful
if ! clevis luks list -d "$dev" | grep -q "sss"; then
echo "Error: Failed to create SSS binding for $dev"
exit 1
fi
done
@ -265,6 +309,29 @@ echo "TPM bindings updated successfully!"
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
# Generated for Nullpoint
@ -330,16 +397,10 @@ dropbear
%pre
# Create TPM and Tang config files
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
{{
"pcr_bank": "{system['luks']['tpm']['pcr_bank']}",
"pcr_ids": "{','.join(map(str, system['luks']['tpm']['pcr_ids']))}"
}}
# Save SSS config for TPM + Tang servers
cat > /etc/clevis/sss.conf << EOF
{sss_config_json}
EOF
%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
chmod 600 /root/luks-passphrase.txt
# Setup Clevis for TPM and Tang
printf "Configuring Clevis for TPM and Tang...\r\n" > /dev/tty1
clevis luks bind -d /dev/sda2 tpm2 -c /etc/clevis/tpm2.conf
clevis luks bind -d /dev/sda2 tang -c /etc/clevis/tang.conf
clevis luks bind -d /dev/sdb2 tpm2 -c /etc/clevis/tpm2.conf
clevis luks bind -d /dev/sdb2 tang -c /etc/clevis/tang.conf
# Setup Clevis with SSS policy (TPM + at least one Tang server)
printf "Configuring TPM and Tang with SSS policy...\r\n" > /dev/tty1
echo "Using SSS policy: TPM verification AND (at least one Tang server)" > /dev/tty1
echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d /dev/sda2 sss -c /etc/clevis/sss.conf -k-
echo -n "$LUKS_PASSPHRASE" | clevis luks bind -d /dev/sdb2 sss -c /etc/clevis/sss.conf -k-
# 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))