From a5fc1256e20ce3c99dc659ef17e8dc8c3b305a2c Mon Sep 17 00:00:00 2001 From: James Shubin Date: Mon, 23 Jun 2025 19:53:52 -0400 Subject: [PATCH] lang: core: embedded: provisioner: Encrypt the filesystem The provisioner should be able to encrypt things. We should use an empty passphrase so that the choosing of the actual passphrase can be done at first boot. --- .../provisioner/files/kickstart.ks.tmpl | 27 ++++++++++++++++--- lang/core/embedded/provisioner/main.mcl | 2 ++ lang/core/embedded/provisioner/provisioner.go | 6 +++++ lang/core/embedded/provisioner/top.mcl | 1 + 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/lang/core/embedded/provisioner/files/kickstart.ks.tmpl b/lang/core/embedded/provisioner/files/kickstart.ks.tmpl index 9b4c7b55..abe35f36 100644 --- a/lang/core/embedded/provisioner/files/kickstart.ks.tmpl +++ b/lang/core/embedded/provisioner/files/kickstart.ks.tmpl @@ -90,16 +90,37 @@ fi %end %include /tmp/ignoredisk.ks +# XXX: We use --passphrase="password" as a temp password since "" doesn't work! zerombr clearpart --all --initlabel --disklabel={{ if .bios }}msdos{{ else }}gpt{{ end }} {{ if eq .part "btrfs" -}} -autopart --type=btrfs --noswap --nohome +autopart --type=btrfs --noswap --nohome{{ if .luks }} --encrypted --passphrase="password"{{ end }} {{- else if eq .part "plain" -}} -autopart --type=plain --nohome +autopart --type=plain --nohome{{ if .luks }} --encrypted --passphrase="password"{{ end }} {{- else -}} -autopart --type=plain --nohome +autopart --type=plain --nohome{{ if .luks }} --encrypted --passphrase="password"{{ end }} {{- end }} +{{ if .luks -}} +%post --interpreter=/bin/bash --log /root/post_partitioning.log --erroronfail +# This runs in our chroot, so this file is /mnt/sysimage/etc/crypttab to the OS. + +# Assume only one LUKS root device for now. +LUKS_DEV=$(blkid -t TYPE=crypto_LUKS -o device --list-one) +echo -n 'password' > /tmp/password +echo -n '' > /tmp/empty +# Get cryptsetup to set this to an empty password! (This was hard.) +#cryptsetup luksAddKey --new-key-slot=1 --force-password --key-file=/tmp/password $LUKS_DEV /tmp/empty +cryptsetup luksChangeKey --key-slot=0 --force-password --key-file=/tmp/password $LUKS_DEV /tmp/empty + +# Add the try-empty-password option to boot non-interactively. +sed -i '/^luks-/ s/$/,try-empty-password=true/' /etc/crypttab + +dracut --force --regenerate-all +#update-initramfs -u # on debian (I think) +%end +{{ end -}} + # # repositories # diff --git a/lang/core/embedded/provisioner/main.mcl b/lang/core/embedded/provisioner/main.mcl index 142b6a11..1185655f 100644 --- a/lang/core/embedded/provisioner/main.mcl +++ b/lang/core/embedded/provisioner/main.mcl @@ -568,6 +568,7 @@ class base:host($name, $config) { panic(len($password) != 0 and len($password) != 106) # length of salted password $part = $config->part || "" # partitioning scheme + $luks = $config->luks || true # enable luks encryption $empty_list_str []str = [] # need an explicit type on empty list definition $packages = $config->packages || $empty_list_str @@ -826,6 +827,7 @@ class base:host($name, $config) { password => $password, # salted bios => $bios, part => $part, + luks => true, # set empty password flavour => $flavour, url => "http://${router_ip}:${http_port_str}/fedora/releases/${version}/Everything/${arch}/os/", repos => { diff --git a/lang/core/embedded/provisioner/provisioner.go b/lang/core/embedded/provisioner/provisioner.go index 883134a1..2d2a7464 100644 --- a/lang/core/embedded/provisioner/provisioner.go +++ b/lang/core/embedded/provisioner/provisioner.go @@ -162,6 +162,12 @@ type localArgs struct { // use the `plain` scheme. Part string `arg:"--part" help:"partitioning scheme, read manual for details" func:"cli_part"` // eg: empty string for plain + // LUKS specifies that we're encrypting the volumes, and using an empty + // password! This is done so that you can non-interactively boot for the + // first time and run your automation tool. You should set the password + // after first boot, either manually or with automation tooling! + LUKS bool `arg:"--luks" default:"true" help:"add an empty LUKS password (change it after first boot)" func:"cli_luks"` + // Packages are a list of additional distro packages to install. It's up // to the user to make sure they exist and don't conflict with each // other or the base installation packages. diff --git a/lang/core/embedded/provisioner/top.mcl b/lang/core/embedded/provisioner/top.mcl index 72d389e7..06aa286a 100644 --- a/lang/core/embedded/provisioner/top.mcl +++ b/lang/core/embedded/provisioner/top.mcl @@ -77,6 +77,7 @@ include base.host("host0", struct{ # TODO: do we need a usable name anywhere? bios => provisioner.cli_bios(), # false or absent means use uefi password => provisioner.cli_password(), # openssl passwd -6 part => provisioner.cli_part(), + luks => provisioner.cli_luks(), packages => provisioner.cli_packages(), #provision => true, # default if unspecified handoff => $handoff, # alternatively some code word or querystring