lanzatool: add support for generations and correct naming of kernels a… (#12)

* lanzatool: add support for generations and correct naming of kerels and initrds

* test: use convert_to_esp(extract_bspec_attr(⋅)) for unsigned tests

* lanzatool: ryan is a B class engineer

Co-authored-by: nikstur@outlook.com
This commit is contained in:
Ryan Lahfa 2022-11-26 03:14:21 +01:00 committed by GitHub
parent df9716da7c
commit 95f596f4dc
5 changed files with 100 additions and 14 deletions

View File

@ -139,7 +139,6 @@
machine.start() machine.start()
bootspec = json.loads(machine.succeed("cat /run/current-system/bootspec/boot.v1.json")) bootspec = json.loads(machine.succeed("cat /run/current-system/bootspec/boot.v1.json"))
print(machine.succeed("ls /boot/EFI/nixos"))
src_path = ${path.src} src_path = ${path.src}
dst_path = ${path.dst} dst_path = ${path.dst}
machine.succeed(f"cp -rf {src_path} {dst_path}") machine.succeed(f"cp -rf {src_path} {dst_path}")
@ -187,14 +186,14 @@
name = "unsigned-initrd-do-not-boot-under-secureboot"; name = "unsigned-initrd-do-not-boot-under-secureboot";
path = { path = {
src = "extract_bspec_attr('initrd')"; src = "extract_bspec_attr('initrd')";
dst = "\"/boot/EFI/nixos/initrd\""; dst = "convert_to_esp(extract_bspec_attr('initrd'))";
}; };
}; };
is-kernel-secured = mkUnsignedTest { is-kernel-secured = mkUnsignedTest {
name = "unsigned-kernel-do-not-boot-under-secureboot"; name = "unsigned-kernel-do-not-boot-under-secureboot";
path = { path = {
src = "extract_bspec_attr('kernel')"; src = "extract_bspec_attr('kernel')";
dst = "\"/boot/EFI/nixos/kernel\""; dst = "convert_to_esp(extract_bspec_attr('kernel'))";
}; };
}; };

View File

@ -45,7 +45,7 @@ in
cp -r ${cfg.pkiBundle}/* /tmp/pki cp -r ${cfg.pkiBundle}/* /tmp/pki
${sbctlWithPki}/bin/sbctl enroll-keys --yes-this-might-brick-my-machine ${sbctlWithPki}/bin/sbctl enroll-keys --yes-this-might-brick-my-machine
''} ''}
${cfg.package}/bin/lanzatool install --pki-bundle ${cfg.pkiBundle} --public-key ${cfg.publicKeyFile} --private-key ${cfg.privateKeyFile} "$@" ${cfg.package}/bin/lanzatool install --pki-bundle ${cfg.pkiBundle} --public-key ${cfg.publicKeyFile} --private-key ${cfg.privateKeyFile} "$@" /nix/var/nix/profiles/system-*-link
''}/bin/bootinstall"; ''}/bin/bootinstall";
# ${cfg.package}/bin/lanzatool install ${optionalString cfg.enrollKeys "--auto-enroll"} --pki-bundle ${cfg.pkiBundle} # ${cfg.package}/bin/lanzatool install ${optionalString cfg.enrollKeys "--auto-enroll"} --pki-bundle ${cfg.pkiBundle}
}; };

View File

@ -32,6 +32,8 @@ pub enum Commands {
auto_enroll: bool, auto_enroll: bool,
bootspec: PathBuf, bootspec: PathBuf,
generations: Vec<PathBuf>,
}, },
} }
@ -50,12 +52,14 @@ impl Commands {
pki_bundle, pki_bundle,
auto_enroll, auto_enroll,
bootspec, bootspec,
generations,
} => install( } => install(
&public_key, &public_key,
&private_key, &private_key,
pki_bundle, &pki_bundle,
auto_enroll, auto_enroll,
&bootspec, &bootspec,
generations,
), ),
} }
} }
@ -64,9 +68,10 @@ impl Commands {
fn install( fn install(
public_key: &Path, public_key: &Path,
private_key: &Path, private_key: &Path,
pki_bundle: Option<PathBuf>, pki_bundle: &Option<PathBuf>,
auto_enroll: bool, auto_enroll: bool,
bootspec: &Path, bootspec: &Path,
generations: Vec<PathBuf>,
) -> Result<()> { ) -> Result<()> {
let lanzaboote_stub = let lanzaboote_stub =
std::env::var("LANZABOOTE_STUB").context("Failed to read LANZABOOTE_STUB env variable")?; std::env::var("LANZABOOTE_STUB").context("Failed to read LANZABOOTE_STUB env variable")?;
@ -79,6 +84,7 @@ fn install(
pki_bundle, pki_bundle,
auto_enroll, auto_enroll,
bootspec, bootspec,
generations,
Path::new(&lanzaboote_stub), Path::new(&lanzaboote_stub),
Path::new(&initrd_stub), Path::new(&initrd_stub),
) )

View File

@ -1,5 +1,8 @@
use anyhow::{Context, Result};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use crate::bootspec::Bootspec;
pub struct EspPaths { pub struct EspPaths {
pub esp: PathBuf, pub esp: PathBuf,
pub nixos: PathBuf, pub nixos: PathBuf,
@ -14,24 +17,48 @@ pub struct EspPaths {
} }
impl EspPaths { impl EspPaths {
pub fn new(esp: &str) -> Self { pub fn new(esp: &str, generation: u64, bootspec: &Bootspec) -> Result<Self> {
let esp = Path::new(esp); let esp = Path::new(esp);
let esp_nixos = esp.join("EFI/nixos"); let esp_nixos = esp.join("EFI/nixos");
let esp_linux = esp.join("EFI/Linux"); let esp_linux = esp.join("EFI/Linux");
let esp_systemd = esp.join("EFI/systemd"); let esp_systemd = esp.join("EFI/systemd");
let esp_efi_fallback_dir = esp.join("EFI/BOOT"); let esp_efi_fallback_dir = esp.join("EFI/BOOT");
Self { Ok(Self {
esp: esp.to_owned(), esp: esp.to_owned(),
nixos: esp_nixos.clone(), nixos: esp_nixos.clone(),
kernel: esp_nixos.join("kernel"), kernel: esp_nixos.join(nixos_path(&bootspec.kernel, "bzImage")?),
initrd: esp_nixos.join("initrd"), initrd: esp_nixos.join(nixos_path(&bootspec.initrd, "initrd")?),
linux: esp_linux.clone(), linux: esp_linux.clone(),
lanzaboote_image: esp_linux.join("lanzaboote-image.efi"), lanzaboote_image: esp_linux.join(generation_path(generation)),
efi_fallback_dir: esp_efi_fallback_dir.clone(), efi_fallback_dir: esp_efi_fallback_dir.clone(),
efi_fallback: esp_efi_fallback_dir.join("BOOTX64.EFI"), efi_fallback: esp_efi_fallback_dir.join("BOOTX64.EFI"),
systemd: esp_systemd.clone(), systemd: esp_systemd.clone(),
systemd_boot: esp_systemd.join("systemd-bootx64.efi"), systemd_boot: esp_systemd.join("systemd-bootx64.efi"),
})
} }
} }
fn nixos_path(path: impl AsRef<Path>, name: &str) -> Result<PathBuf> {
let resolved = path.as_ref().read_link().unwrap_or(path.as_ref().into());
let parent = resolved.parent().ok_or(anyhow::anyhow!(format!(
"Path: {} does not have a parent",
resolved.display()
)))?;
let without_store = parent.strip_prefix("/nix/store").with_context(|| {
format!(
"Failed to strip /nix/store from path {}",
path.as_ref().display()
)
})?;
let nixos_filename = format!("{}-{}.efi", without_store.display(), name);
Ok(PathBuf::from(nixos_filename))
}
fn generation_path(generation: u64) -> PathBuf {
PathBuf::from(format!("nixos-generation-{}.efi", generation))
} }

View File

@ -17,7 +17,61 @@ use std::process::Command;
pub fn install( pub fn install(
public_key: &Path, public_key: &Path,
private_key: &Path, private_key: &Path,
_pki_bundle: Option<PathBuf>, pki_bundle: &Option<PathBuf>,
auto_enroll: bool,
bootspec: &Path,
generations: Vec<PathBuf>,
lanzaboote_stub: &Path,
initrd_stub: &Path,
) -> Result<()> {
for generation in generations {
let generation_version = extract_generation_version(&generation).with_context(|| {
format!(
"Failed to extract generation version from generation: {}",
generation.display()
)
})?;
println!("Installing generation {generation_version}");
install_generation(
generation_version,
public_key,
private_key,
pki_bundle,
auto_enroll,
bootspec,
lanzaboote_stub,
initrd_stub,
)?;
}
Ok(())
}
fn extract_generation_version(path: impl AsRef<Path>) -> Result<u64> {
let file_name = path.as_ref().file_name().ok_or(anyhow::anyhow!(
"Failed to extract file name from generation"
))?;
let file_name_str = file_name
.to_str()
.with_context(|| "Failed to convert file name of generation to string")?;
let generation_version = file_name_str
.split("-")
.nth(1)
.ok_or(anyhow::anyhow!("Failed to extract version from generation"))?;
Ok(generation_version
.parse()
.with_context(|| format!("Failed to parse generation version: {}", generation_version))?)
}
fn install_generation(
generation: u64,
public_key: &Path,
private_key: &Path,
_pki_bundle: &Option<PathBuf>,
_auto_enroll: bool, _auto_enroll: bool,
bootspec: &Path, bootspec: &Path,
lanzaboote_stub: &Path, lanzaboote_stub: &Path,
@ -29,7 +83,7 @@ pub fn install(
serde_json::from_slice(&fs::read(bootspec).context("Failed to read bootspec file")?) serde_json::from_slice(&fs::read(bootspec).context("Failed to read bootspec file")?)
.context("Failed to parse bootspec json")?; .context("Failed to parse bootspec json")?;
let esp_paths = EspPaths::new(&bootspec_doc.extension.esp); let esp_paths = EspPaths::new(&bootspec_doc.extension.esp, generation, &bootspec_doc)?;
println!("Assembling lanzaboote image..."); println!("Assembling lanzaboote image...");