From 92e7e4f49affbbc9ca2e17752dc424e879c72f33 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 17 Dec 2022 23:55:38 +0100 Subject: [PATCH] lanzatool(bootspec): introduce DetSys's bootspec library --- rust/lanzatool/Cargo.lock | 22 ++++++++---- rust/lanzatool/Cargo.toml | 4 ++- rust/lanzatool/bootspec.json | 40 +++++++++++----------- rust/lanzatool/src/bootspec.rs | 32 ------------------ rust/lanzatool/src/esp.rs | 6 ++-- rust/lanzatool/src/generation.rs | 58 ++++++++++++++++++++++---------- rust/lanzatool/src/install.rs | 10 +++--- rust/lanzatool/src/main.rs | 1 - 8 files changed, 89 insertions(+), 84 deletions(-) delete mode 100644 rust/lanzatool/src/bootspec.rs diff --git a/rust/lanzatool/Cargo.lock b/rust/lanzatool/Cargo.lock index 4ef3c12..3ef33e6 100644 --- a/rust/lanzatool/Cargo.lock +++ b/rust/lanzatool/Cargo.lock @@ -66,6 +66,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bootspec" +version = "0.1.0" +source = "git+https://github.com/RaitoBezarius/bootspec-1?branch=secureboot-needs#a5d327ceb25da6ae4147fbf0b15088f44214a91a" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "cc" version = "1.0.77" @@ -208,6 +217,7 @@ version = "0.1.0" dependencies = [ "anyhow", "blake3", + "bootspec", "clap", "goblin", "nix", @@ -349,18 +359,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", @@ -392,9 +402,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.103" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", diff --git a/rust/lanzatool/Cargo.toml b/rust/lanzatool/Cargo.toml index 5ca7a67..b69cfc7 100644 --- a/rust/lanzatool/Cargo.toml +++ b/rust/lanzatool/Cargo.toml @@ -10,7 +10,9 @@ anyhow = "1.0.66" clap = { version = "4.0.26", features = ["derive"] } goblin = "0.6.0" nix = { version = "0.25.0", default-features = false, features = [ "fs" ] } -serde = { version = "1.0.147", features = ["derive"] } +serde = { version = "1.0.151", features = ["derive"] } serde_json = "1.0.89" tempfile = "3.3.0" blake3 = "1.3.3" +# TODO: wait for a upstream release and pin it. +bootspec = { git = "https://github.com/RaitoBezarius/bootspec-1", branch = "secureboot-needs" } diff --git a/rust/lanzatool/bootspec.json b/rust/lanzatool/bootspec.json index 5376acb..5e92499 100644 --- a/rust/lanzatool/bootspec.json +++ b/rust/lanzatool/bootspec.json @@ -1,21 +1,23 @@ { - "init": "/run/current-system/init", - "initrd": "/run/current-system/initrd", - "kernel": "/run/current-system/kernel", - "kernelParams": [ - "amd_iommu=on", - "amd_iommu=pt", - "iommu=pt", - "kvm.ignore_msrs=1", - "kvm.report_ignored_msrs=0", - "udev.log_priority=3", - "systemd.unified_cgroup_hierarchy=1", - "loglevel=4" - ], - "label": "LanzaOS", - "toplevel": "/run/current-system", - "specialisation": {}, - "extension": { - "osRelease": "/etc/os-release" + "v1": { + "init": "/run/current-system/init", + "initrd": "/run/current-system/initrd", + "kernel": "/run/current-system/kernel", + "kernelParams": [ + "amd_iommu=on", + "amd_iommu=pt", + "iommu=pt", + "kvm.ignore_msrs=1", + "kvm.report_ignored_msrs=0", + "udev.log_priority=3", + "systemd.unified_cgroup_hierarchy=1", + "loglevel=4" + ], + "label": "LanzaOS", + "toplevel": "/run/current-system", + "specialisation": {}, + "extensions": { + "org.lanzaboote.osRelease": "/etc/os-release" + } } -} \ No newline at end of file +} diff --git a/rust/lanzatool/src/bootspec.rs b/rust/lanzatool/src/bootspec.rs deleted file mode 100644 index f3e8c7a..0000000 --- a/rust/lanzatool/src/bootspec.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::collections::HashMap; -use std::path::PathBuf; - -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Bootspec { - /// Label for the system closure - pub label: String, - /// Path to kernel (bzImage) -- $toplevel/kernel - pub kernel: PathBuf, - /// list of kernel parameters - pub kernel_params: Vec, - /// Path to the init script - pub init: PathBuf, - /// Path to initrd -- $toplevel/initrd - pub initrd: PathBuf, - /// Path to "append-initrd-secrets" script -- $toplevel/append-initrd-secrets - pub initrd_secrets: Option, - /// config.system.build.toplevel path - pub toplevel: PathBuf, - /// Mapping of specialisation names to their boot.json - pub specialisation: HashMap, - pub extension: Extension, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct Extension { - pub os_release: PathBuf, -} diff --git a/rust/lanzatool/src/esp.rs b/rust/lanzatool/src/esp.rs index 5b10171..5bd340e 100644 --- a/rust/lanzatool/src/esp.rs +++ b/rust/lanzatool/src/esp.rs @@ -1,7 +1,7 @@ use anyhow::{Context, Result}; use std::path::{Path, PathBuf}; -use crate::generation::Generation; +use crate::generation::OSGeneration; pub struct EspPaths { pub esp: PathBuf, @@ -17,7 +17,7 @@ pub struct EspPaths { } impl EspPaths { - pub fn new(esp: impl AsRef, generation: &Generation) -> Result { + pub fn new(esp: impl AsRef, generation: &OSGeneration) -> Result { let esp = esp.as_ref(); let esp_nixos = esp.join("EFI/nixos"); let esp_linux = esp.join("EFI/Linux"); @@ -66,7 +66,7 @@ fn nixos_path(path: impl AsRef, name: &str) -> Result { Ok(PathBuf::from(nixos_filename)) } -fn generation_path(generation: &Generation) -> PathBuf { +fn generation_path(generation: &OSGeneration) -> PathBuf { if let Some(specialisation_name) = generation.is_specialized() { PathBuf::from(format!( "nixos-generation-{}-specialisation-{}.efi", diff --git a/rust/lanzatool/src/generation.rs b/rust/lanzatool/src/generation.rs index 9ff7a5f..10583f9 100644 --- a/rust/lanzatool/src/generation.rs +++ b/rust/lanzatool/src/generation.rs @@ -1,22 +1,46 @@ +use serde::{Deserialize, Serialize}; + use std::fmt; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use anyhow::{Context, Result}; +use bootspec::BootJson; +use bootspec::SpecialisationName; +use bootspec::generation::Generation; -use crate::bootspec::Bootspec; - -#[derive(Debug)] -pub struct Generation { - version: u64, - specialisation_name: Option, - pub bootspec: Bootspec, +// TODO: actually, I'm not sure it's a good thing to have Default +// we should maybe have TryDefault? +// discuss this with upstream. +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct SecureBootExtension { + #[serde(rename="org.lanzaboote.osRelease")] + pub os_release: PathBuf } -impl Generation { +pub type ExtendedBootJson = BootJson; + +#[derive(Debug)] +pub struct OSGeneration { + /// Top-level nixpkgs version + version: u64, + /// Top-level specialisation name + specialisation_name: Option, + /// Top-level bootspec document + pub bootspec: ExtendedBootJson, +} + +fn into_boot_json(generation: Generation) -> Result { + Ok(match generation { + Generation::V1(json) => json, + _ => panic!("Failed") + }) +} + +impl OSGeneration { pub fn from_toplevel(toplevel: impl AsRef) -> Result { - let bootspec_path = toplevel.as_ref().join("bootspec/boot.v1.json"); - let bootspec: Bootspec = serde_json::from_slice( + let bootspec_path = toplevel.as_ref().join("bootspec/boot.json"); + let generation: Generation = serde_json::from_slice( &fs::read(bootspec_path).context("Failed to read bootspec file")?, ) .context("Failed to parse bootspec json")?; @@ -24,24 +48,24 @@ impl Generation { Ok(Self { version: parse_version(toplevel)?, specialisation_name: None, - bootspec, + bootspec: into_boot_json(generation)?, }) } - pub fn specialise(&self, name: &str, bootspec: &Bootspec) -> Self { + pub fn specialise(&self, name: &SpecialisationName, bootspec: &ExtendedBootJson) -> Self { Self { version: self.version, - specialisation_name: Some(String::from(name)), - bootspec: bootspec.clone(), + specialisation_name: Some(name.clone()), + bootspec: bootspec.clone() } } - pub fn is_specialized(&self) -> Option { + pub fn is_specialized(&self) -> Option { self.specialisation_name.clone() } } -impl fmt::Display for Generation { +impl fmt::Display for OSGeneration { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.version) } diff --git a/rust/lanzatool/src/install.rs b/rust/lanzatool/src/install.rs index 822527d..6a5b204 100644 --- a/rust/lanzatool/src/install.rs +++ b/rust/lanzatool/src/install.rs @@ -8,7 +8,7 @@ use nix::unistd::sync; use tempfile::tempdir; use crate::esp::EspPaths; -use crate::generation::Generation; +use crate::generation::OSGeneration; use crate::pe; use crate::signature::KeyPair; @@ -36,7 +36,7 @@ impl Installer { pub fn install(&self) -> Result<()> { for toplevel in &self.generations { - let generation = Generation::from_toplevel(toplevel).with_context(|| { + let generation = OSGeneration::from_toplevel(toplevel).with_context(|| { format!("Failed to build generation from toplevel: {toplevel:?}") })?; @@ -58,7 +58,7 @@ impl Installer { Ok(()) } - fn install_generation(&self, generation: &Generation) -> Result<()> { + fn install_generation(&self, generation: &OSGeneration) -> Result<()> { let bootspec = &generation.bootspec; let esp_paths = EspPaths::new(&self.esp, generation)?; @@ -83,7 +83,7 @@ impl Installer { } let systemd_boot = bootspec - .toplevel + .toplevel.0 .join("systemd/lib/systemd/boot/efi/systemd-bootx64.efi"); [ @@ -102,7 +102,7 @@ impl Installer { let lanzaboote_image = pe::lanzaboote_image( &secure_temp_dir, &self.lanzaboote_stub, - &bootspec.extension.os_release, + &bootspec.extensions.os_release, &kernel_cmdline, &esp_paths.kernel, &esp_paths.initrd, diff --git a/rust/lanzatool/src/main.rs b/rust/lanzatool/src/main.rs index 23278ea..07cdb65 100644 --- a/rust/lanzatool/src/main.rs +++ b/rust/lanzatool/src/main.rs @@ -1,4 +1,3 @@ -mod bootspec; mod cli; mod esp; mod generation;