Merge pull request #109 from nix-community/correctly-update-initrd-secrets

tool: correctly update initrd secrets
This commit is contained in:
nikstur 2023-02-24 01:18:57 +01:00 committed by GitHub
commit ed1676e544
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 4 deletions

View File

@ -145,6 +145,52 @@ in
'';
};
# Test that the secrets configured to be appended to the initrd get updated
# when installing a new generation even if the initrd itself (i.e. its store
# path) does not change.
#
# An unfortunate result of this NixOS feature is that updating the secrets
# without creating a new initrd might break previous generations. Lanzaboote
# has no control over that.
#
# This tests uses a specialisation to imitate a newer generation. This works
# because `lzbt` installs the specialisation of a generation AFTER installing
# the generation itself (thus making the specialisation "newer").
initrd-secrets-update =
let
originalSecret = (pkgs.writeText "oh-so-secure" "uhh-ooh-uhh-security");
newSecret = (pkgs.writeText "newly-secure" "so-much-better-now");
in
mkSecureBootTest {
name = "lanzaboote-initrd-secrets-update";
machine = { pkgs, lib, ... }: {
boot.initrd.secrets = {
"/test" = lib.mkDefault originalSecret;
};
boot.initrd.postMountCommands = ''
cp /test /mnt-root/secret-from-initramfs
'';
specialisation.variant.configuration = {
boot.initrd.secrets = {
"/test" = newSecret;
};
};
};
testScript = ''
machine.start()
machine.wait_for_unit("multi-user.target")
# Assert that only two boot files exists (a single kernel and a single
# initrd). If there are two initrds, the test would not be able to test
# updating the secret of an already existing initrd.
assert int(machine.succeed("ls -1 /boot/EFI/nixos | wc -l")) == 2
# It is expected that the initrd contains the new secret.
machine.succeed("cmp ${newSecret} /secret-from-initramfs")
'';
};
modified-initrd-doesnt-boot-with-secure-boot = mkModifiedInitrdTest {
name = "modified-initrd-doesnt-boot-with-secure-boot";
useSecureBoot = true;

View File

@ -61,16 +61,22 @@ impl Installer {
.map(GenerationLink::from_path)
.collect::<Result<Vec<GenerationLink>>>()?;
// Sort the links by version. The links need to always be sorted to ensure the secrets of
// the latest generation are appended to the initrd when multiple generations point to the
// same initrd.
links.sort_by_key(|l| l.version);
// A configuration limit of 0 means there is no limit.
if self.configuration_limit > 0 {
// Sort the links by version.
links.sort_by_key(|l| l.version);
// Only install the number of generations configured.
// Only install the number of generations configured. Reverse the list to only take the
// latest generations and then, after taking them, reverse the list again so that the
// generations are installed from oldest to newest, i.e. from smallest to largest
// generation version.
links = links
.into_iter()
.rev()
.take(self.configuration_limit)
.rev()
.collect()
};
self.install_generations_from_links(&links)?;