installtest/src/medium.rs
//! **What is actually INSIDE a composed medium** — the ESP's boot PEs, who
//! signed them, and every name in the initramfs.
//!
//! # Why a reader and not a build assertion
//!
//! The 2026-09-05 fixture-key leak was not found by a test. The appliance ISO
//! built green, booted, and served — carrying `data/control.git/secrets.kek`,
//! a test-minted key, in its initramfs. Every check in the chain looked at
//! what the build INTENDED. The only thing that found it was opening the
//! artifact and listing what came out, and that was a shell pipeline in a
//! scratch directory, which is debt rather than a guard.
//!
//! So this module opens the medium. It is the second, independent point in the
//! chain: `korp_installer::forge` refuses a seeded staging TREE, and this
//! reads the produced MEDIUM. A defect that defeats one has to defeat the
//! other separately.
//!
//! # Reused, never twinned
//!
//! Every piece already existed and none of it is re-implemented here:
//! [`crate::firmware::iso_root_file`] finds the ESP in the ISO-9660 volume,
//! `kvmproof::read_esp_image_file` reads a file out of the FAT,
//! `korp_installer::forge::initramfs_entries` picks the framing (an
//! appliance's `\initrd` is a raw zstd frame, an installer's a plain cpio),
//! and `korp_installer::secureboot::signer_names` says WHO signed a PE rather
//! than merely that somebody did.
use std::path::Path;
use korp_installer::kvmproof;
/// The ESP path of the first-stage bootloader an enforcing firmware verifies.
pub const ESP_BOOTX64: &str = "EFI/BOOT/BOOTX64.EFI";
/// The ESP path of the image the first stage chainloads.
pub const ESP_VMLINUZ: &str = "vmlinuz";
/// The ESP path of the initramfs.
pub const ESP_INITRD: &str = "initrd";
/// What one PE on the ESP is, and who vouched for it.
#[derive(Debug, Clone)]
pub struct PeReport {
/// The ESP path it was read from.
pub path: String,
/// Does it carry an attribute certificate table at all?
pub signed: bool,
/// Every certificate's `subject` — empty when unsigned, and ALSO empty
/// when a table is present but unparseable, which is why `signed` is kept
/// beside it rather than derived from this.
pub signers: Vec<korp_installer::secureboot::SignerName>,
}
impl PeReport {
/// A one-line summary that names the signer rather than counting bytes.
pub fn line(&self) -> String {
match (self.signed, self.signers.first()) {
(false, _) => format!("{:22} UNSIGNED", self.path),
(true, None) => format!("{:22} SIGNED, but no name could be read off it", self.path),
(true, Some(s)) => format!(
"{:22} SIGNED by {}{}",
self.path,
s.subject,
if s.is_self_signed() {
" (self-signed)"
} else {
""
}
),
}
}
}
/// Everything this reader can say about one composed medium.
#[derive(Debug, Clone)]
pub struct MediumCensus {
/// The medium's file name.
pub name: String,
/// Its size on disk.
pub bytes: u64,
/// The boot PEs found on the ESP, in the order asked for.
pub pes: Vec<PeReport>,
/// Every name in the initramfs, in stream order.
pub initramfs: Vec<String>,
}
impl MediumCensus {
/// The initramfs names under `data/` — the appliance's persistent state,
/// which a RELEASE medium ships EMPTY. `.keep` and `.gitignore` are the
/// two files that spell "this directory ships empty" and are not content;
/// the same rule, and the same two exceptions, as
/// `korp_installer::forge::seeded_data_files`, which refuses them at the
/// staging tree.
pub fn seeded_data(&self) -> Vec<&str> {
self.initramfs
.iter()
.map(String::as_str)
.filter(|n| {
n.starts_with("data/")
&& *n != "data/.keep"
&& *n != "data/.gitignore"
&& !n.ends_with('/')
})
.collect()
}
/// Does the medium say, from the INSIDE, that it is a fixture?
pub fn marked_fixture(&self) -> bool {
self.initramfs
.iter()
.any(|n| n == korp_installer::forge::FIXTURE_SEED_MARK)
}
}
/// **Open a composed ISO and report what is in it.**
///
/// `Err` carries the reason as a sentence. Nothing here degrades to a partial
/// answer: a medium whose ESP cannot be found, or whose initramfs no framing
/// parses, is an error rather than a census with empty fields — an empty
/// field is shaped exactly like a clean medium.
pub fn census(iso: &Path) -> Result<MediumCensus, String> {
let bytes = std::fs::metadata(iso)
.map_err(|e| format!("{}: {e}", iso.display()))?
.len();
let (lba, len) = crate::firmware::iso_root_file(iso, crate::firmware::ESP_IMAGE_NAME)
.ok_or_else(|| {
format!(
"{}: no root-level `{}` in the ISO-9660 volume, so there is no ESP to read",
iso.display(),
crate::firmware::ESP_IMAGE_NAME
)
})?;
let esp = crate::firmware::read_range(
iso,
lba * crate::firmware::ISO_BLOCK,
usize::try_from(len).map_err(|_| format!("{}: absurd ESP length {len}", iso.display()))?,
)
.ok_or_else(|| format!("{}: the ESP extent is not readable", iso.display()))?;
let mut pes = Vec::new();
for path in [ESP_BOOTX64, ESP_VMLINUZ] {
let Some(pe) = kvmproof::read_esp_image_file(&esp, path) else {
continue;
};
pes.push(PeReport {
path: path.to_string(),
signed: korp_installer::secureboot::is_signed(&pe),
signers: korp_installer::secureboot::signer_names(&pe),
});
}
let raw = kvmproof::read_esp_image_file(&esp, ESP_INITRD)
.ok_or_else(|| format!("{}: no `{ESP_INITRD}` on the ESP", iso.display()))?;
let initramfs = korp_installer::forge::initramfs_entries(&raw)
.map_err(|e| format!("{}: {e:#}", iso.display()))?
.into_iter()
.map(|(n, _, _)| n)
.collect();
Ok(MediumCensus {
name: iso
.file_name()
.unwrap_or_default()
.to_string_lossy()
.into_owned(),
bytes,
pes,
initramfs,
})
}