Kickstart file to install Fedora 37 with luks encrypted root
- login is root:root
- luks passphrase is MY-LUKS-PASSPHRASE
- /etc/crypttab setup to autounlock LUKS when we inject SEV secret
luks.ks:
rootpw --plaintext root
firstboot --disable
timezone America/New_York --utc
keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8
reboot
text
skipx
ignoredisk --only-use=vda
clearpart --all --initlabel --disklabel=gpt --drives=vda
part /boot/efi --size=512 --fstype=efi
part /boot --size=512 --fstype=xfs --label=boot
part / --fstype="xfs" --ondisk=vda --encrypted --label=root --luks-version=luks2 --grow --passphrase MY-LUKS-PASSPHRASE
%packages
@^server-product-environment
%end
%post
# Set the secret path as a crypttab keyfile
# Append `keyfile-erase` option to unlink it after unlock
cat /etc/crypttab | awk '{print $1" "$2" /sys/kernel/security/secrets/coco/736869e5-84f0-4973-92ec-06879ce3da0b "$4",keyfile-erase"}' | tee /etc/crypttab
# Put `efi_secret` driver in the initrd
echo 'add_drivers+=" efi_secret "' > /etc/dracut.conf.d/99-efi_secret.conf
# Trigger initrd rebuild
dnf reinstall -y kernel\*
%end
Install the VM on f36 host with the following differences:
- latest libvirt-daemon-kvm, qemu-system-x86, edk2-ovmf from virt-preview repo
cargo install sevctl
- virt-manager/virt-install from git as of Nov 27 2022
- libvirt.git as of Nov 27 2022
# virt-preview packages on f36 host:
# $ rpm -q libvirt-daemon qemu-system-x86 edk2-ovmf
# libvirt-daemon-8.8.0-1.fc36.x86_64
# qemu-system-x86-7.1.0-3.fc36.x86_64
# edk2-ovmf-20220826gitba0e0e4c6a17-1.fc36.noarch
# libvirt.git as of Nov 27 2022
VALIDATE="$HOME/src/libvirt/tools/virt-qemu-sev-validate"
# From virt-manager.git
VIRTXML="$HOME/src/virt-manager/virt-xml"
VIRTINSTALL="$HOME/src/virt-manager/virt-install"
VMNAME=lukstest
# Install the VM, full automated
# SEV is not enabled at this point
sudo $VIRTINSTALL \
--name $VMNAME --ram 8096 --disk size=20 \
--nographics \
--location https://dl.fedoraproject.org/pub/fedora/linux/development/37/Server/x86_64/os/ \
--noreboot \
--initrd-inject luks.ks \
--extra-args "inst.ks=file:/luks.ks console=ttyS0" \
--tpm none \
--boot firmware=efi,loader.stateless=yes \
--memorybacking locked=on \
--launchSecurity sev,policy=$POLICY,kernelHashes=on,session=$SESSION,dhCert=$DHCERT \
--debug
Now we extract the kernel + initrd + cmdline. This needs to be done every time the kernel is updated inside the VM. You should be prompted for the LUKS password.
sudo virt-get-kernel -d $VMNAME --prefix $VMNAME > get-kernel.txt
KERNEL=$(basename $(cat get-kernel.txt | grep vmlin | cut -f4 -d ' '))
INITRD=$(basename $(cat get-kernel.txt | grep initr | cut -f4 -d ' '))
sudo mv $KERNEL $INITRD /var/lib/libvirt/images
# Pull kernel cmdline out of /boot/loader/entries
sudo virt-copy-out -d $VMNAME /boot/loader/entries .
sudo chown $UID entries
CMDLINE=$(sudo cat entries/* | grep options | tail -1 | cut -f 2- -d ' ')
# Update VM config to boot off external kernel+initrd
sudo $VIRTXML $VMNAME --edit \
--boot kernel=/var/lib/libvirt/images/$KERNEL,initrd=/var/lib/libvirt/images/$INITRD,cmdline="$CMDLINE"
The following is the validation process.
- Session blob must be regenerated for every VM run
- Ensure SEV is enabled in the VM config and appropriate firmware config is used
- Use
virt-qemu-sev-validate
to inject the LUKS key
POLICY=5
CERTDIR=$HOME/src/sevcerts/$VMNAME
SEVCTL=$HOME/.cargo/bin/sevctl
# Generate SEV VM config. Must be run on SEV host
rm -rf $CERTDIR; mkdir -p $CERTDIR
sudo $SEVCTL export -f $CERTDIR/sevctl-export.chain
sudo $SEVCTL session $CERTDIR/sevctl-export.chain $POLICY --name $CERTDIR/$VMNAME
DHCERT=`cat $CERTDIR/${VMNAME}_godh.b64`
SESSION=`cat $CERTDIR/${VMNAME}_session.b64`
# Enable SEV and insert session info into the XML
sudo $VIRTXML $VMNAME --edit \
--launchSecurity sev,policy=$POLICY,kernelHashes=on,session=$SESSION,dhCert=$DHCERT
# Switch to OVMF.amdsev.fd firmware
sudo rm -rf /var/lib/libvirt/qemu/nvram/${VMNAME}_VARS.fd
sudo $VIRTXML $VMNAME --edit \
--boot firmware=efi,loader.stateless=yes
# Validate the VM
echo -n MY-LUKS-PASSPHRASE > $HOME/secret.txt
sudo virsh start --paused $VMNAME
sudo $VALIDATE \
--domain $VMNAME \
--tek $CERTDIR/${VMNAME}_tek.bin \
--tik $CERTDIR/${VMNAME}_tik.bin \
--inject-secret 736869e5-84f0-4973-92ec-06879ce3da0b:$HOME/secret.txt \
--insecure \
--debug
# Should go to login prompt, no LUKS passphrase needed
sudo virsh console $VMNAME