Add windows/iso-builder.md: reproducible custom-packed-ISO pipeline design for
SilverMetal Enhanced - Windows on IoT Enterprise LTSC. Covers the licensing
frame (IoT = blessed channel for preinstalled custom images; self-apply stays a
builder), 7 build stages (verify/extract/DISM-service/inject-unattend/brand/
oscdimg-repack/attest), the offline-vs-first-boot-vs-firmware control split, an
honest reproducibility scope (pinned inputs + SBOM + attestation, NOT bit-
identical on Windows), and M0-M4 milestones.
Scaffold windows/ per the planned layout:
- installer/ build.ps1 (7-stage orchestrator, stages stubbed to M2),
inputs.manifest.json (pinned-input schema), autounattend.xml
(local-account OOBE), oem/SetupComplete.cmd (first-boot runner)
- hardening/ shared §A-H PowerShell modules + Verify-SilverMetalWindows.ps1
(used by BOTH the ISO first-boot path and the self-apply track).
BitLocker module enforces TPM+PIN and blocks TPM-only.
- policies/ wdac/ debloat/ stack-installer/ drivers/ tests/ scaffolded with
READMEs; wdac/ documents audit->enforce; debloat/ flags Tiny11/NTLite as an
anti-pattern; rename applocker/ -> wdac/ realised.
All 11 PowerShell scripts parse clean; manifest JSON + autounattend XML valid.
Module bodies are M1 scaffold (safe: log + policy-set; interactive/firmware
steps documented, not faked).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
132 lines
8.9 KiB
Markdown
132 lines
8.9 KiB
Markdown
# SilverMetal Enhanced — Windows: ISO Builder
|
||
|
||
> **Status**: v1 design — 2026-06-08. Implements the productized SKU build for the hardening defined in [`hardening-spec.md`](hardening-spec.md). Reference device: GPD Pocket 4.
|
||
|
||
This document describes the **reproducible build pipeline** that turns an official Windows 11 IoT Enterprise LTSC ISO plus the SilverMetal config layer into a hardened, branded, UEFI-bootable **custom packed ISO**, with a signed build attestation.
|
||
|
||
It is bound by the same documents as the hardening spec: [`../docs/threat-model.md`](../docs/threat-model.md), [`../docs/design-principles.md`](../docs/design-principles.md), and [`../docs/trust-model.md`](../docs/trust-model.md).
|
||
|
||
## 1. Licensing frame (why this is legitimate)
|
||
|
||
Windows 11 **IoT Enterprise LTSC** is licensed through the OEM / embedded channel, whose explicit purpose is building **customized, locked-down, preinstalled images** on devices a solution-builder ships. Creating a custom packed image and preinstalling it on hardware we sell is the *intended, blessed* use — not a grey area.
|
||
|
||
| Track | Status under IoT Enterprise LTSC |
|
||
|---|---|
|
||
| **Preflashed SilverMetal SKU** (we sell the device) | ✅ Build + ship our custom image — licensed per device, intended use |
|
||
| **Self-apply free track** (user hardens own device) | ⚠️ No public prebuilt-ISO redistribution. Ships as a **builder** that consumes the user's own official ISO + license — the same `hardening/` modules, applied to their image |
|
||
|
||
The Microsoft ISO is therefore always an **input**, never committed to this repo. We ship *our layer*; the licensee provides the base.
|
||
|
||
> **Procurement note (verify before pricing the SKU):** IoT Enterprise LTSC is obtained via authorized OEM distributors; per-device licensing may carry minimum-order / agreement terms. Confirm with the distributor.
|
||
|
||
## 2. Inputs
|
||
|
||
All inputs are pinned by hash in [`installer/inputs.manifest.json`](installer/inputs.manifest.json):
|
||
|
||
| Input | Source | In repo? |
|
||
|---|---|---|
|
||
| Windows 11 IoT Enterprise LTSC ISO | Licensed (operator/distributor) | No — pinned by SHA-256 |
|
||
| GPD Pocket 4 driver pack | GPD (verified source) | `drivers/` or sourced manifest |
|
||
| SilverLABS Stack (native Windows builds) | Stack component repos / artifacts | Referenced by version |
|
||
| SilverMetal config layer | This repo (`hardening/`, `policies/`, `wdac/`, `debloat/`, `autounattend/`, `oem/`, branding) | Yes |
|
||
|
||
## 3. Build stages
|
||
|
||
Orchestrated by [`installer/build.ps1`](installer/build.ps1). Runs on a **Windows host with the Windows ADK** (DISM + `oscdimg`).
|
||
|
||
1. **Verify input** — assert the source ISO SHA-256 matches the pinned manifest (supply-chain integrity).
|
||
2. **Extract** — expand the ISO to a working directory.
|
||
3. **Service the WIM offline (DISM)**:
|
||
- Select the IoT Enterprise LTSC image index.
|
||
- `/Add-Driver` the GPD Pocket 4 driver pack (Strix Point GPU, sensors/auto-rotate, Wi-Fi, fingerprint).
|
||
- `/Add-Package` the latest cumulative update (slipstream).
|
||
- Trim residual provisioned appx (LTSC is already lean — minimal list in `debloat/`).
|
||
- Load offline registry hives → apply the **offline-able baseline** (telemetry floor, service disables) from `policies/`.
|
||
- Stage the Stack installers + first-boot payload into the image.
|
||
- Commit + unmount.
|
||
4. **Inject answer file + first-boot payload**:
|
||
- `autounattend.xml` — OOBE automation, **local account** (no MSA), regional settings, BitLocker-ready disk layout.
|
||
- `$OEM$\SetupComplete.cmd` — first-boot entry point that runs the online `hardening/` modules and installs the Stack.
|
||
5. **Brand** — boot/OOBE wallpaper + computer-name pattern from [`../shared/branding`](../shared/branding).
|
||
6. **Repack** — `oscdimg` produces a UEFI-bootable ISO (efisys boot image, El Torito).
|
||
7. **Attest** — emit output ISO SHA-256, an **SBOM** (every component + version), and a signed build attestation (design-principle #4).
|
||
|
||
## 4. Where each hardening control is applied
|
||
|
||
The control domains in [`hardening-spec.md`](hardening-spec.md) split across three layers:
|
||
|
||
| Layer | Controls | Mechanism |
|
||
|---|---|---|
|
||
| **Baked offline (in WIM)** | Telemetry floor, service disables, appx trim, drivers, baseline registry policy, Stack staging | DISM + offline hive edits |
|
||
| **First-boot (online)** | Local account, VBS/HVCI/Credential Guard, ASR rules, **WDAC (audit)**, firewall, encrypted DNS, Stack + SilverVPN install, scheduled `Verify` task | `SetupComplete.cmd` → `hardening/` modules |
|
||
| **Interactive / firmware — NOT in ISO** | Secure Boot custom-key enrollment, **BitLocker PIN**, BIOS admin password | Operator at provisioning (SKU) or documented user step (self-apply). The ISO *enables* BitLocker and *forces* PIN enrollment; it cannot ship a PIN or touch firmware. |
|
||
|
||
**The `hardening/` modules are shared.** The same module set is invoked by the ISO's first-boot path *and* by the self-apply / milestone-1 standalone path. Write once, used both ways.
|
||
|
||
## 5. Reproducibility (honest scope)
|
||
|
||
Windows image servicing is **not bit-for-bit deterministic** the way the Linux ISO pipeline is (WIM internal timestamps, servicing-stack non-determinism). So for this product, "reproducible" means:
|
||
|
||
- **Pinned inputs** (every source hashed in the manifest)
|
||
- **Recorded tool versions** (ADK, DISM, servicing stack)
|
||
- **Output ISO SHA-256 + SBOM** published per build
|
||
- **Signed build attestation** linking published artifact ↔ published source + inputs
|
||
|
||
Bit-identical rebuild is a **stretch goal**, documented as such — we do not claim it (design-principle #2). This is weaker than the Linux line's reproducible-build guarantee, and we say so to buyers.
|
||
|
||
## 6. Directory layout
|
||
|
||
```
|
||
windows/
|
||
├── installer/
|
||
│ ├── build.ps1 # pipeline orchestrator
|
||
│ ├── inputs.manifest.json # pinned ISO SHA, driver-pack ver, Stack vers, tool vers
|
||
│ ├── autounattend/
|
||
│ │ └── autounattend.xml # OOBE automation + local account + disk layout
|
||
│ ├── oem/
|
||
│ │ └── SetupComplete.cmd # first-boot entry → runs hardening/ modules
|
||
│ └── README.md
|
||
├── hardening/ # §A–H PowerShell modules + Verify ← SHARED (ISO + self-apply)
|
||
│ ├── 00-provisioning.ps1 # A
|
||
│ ├── 01-boot-firmware.ps1 # B (stages keys; firmware steps documented)
|
||
│ ├── 02-data-at-rest.ps1 # C (BitLocker TPM+PIN)
|
||
│ ├── 03-kernel-credential.ps1# D (VBS/HVCI/CredGuard/DMA)
|
||
│ ├── 04-app-control.ps1 # E (WDAC audit, ASR, Defender)
|
||
│ ├── 05-network-radios.ps1 # F (firewall, DNS, WiFi-only)
|
||
│ ├── 06-physical-lock.ps1 # G (lock-screen, DMA lock, cam/mic)
|
||
│ ├── 07-privacy-update.ps1 # H (telemetry trim, update integrity)
|
||
│ ├── 08-stack-install.ps1 # SilverLABS Stack
|
||
│ └── Verify-SilverMetalWindows.ps1
|
||
├── policies/ # GP/ADMX exports + offline .reg/.pol baseline
|
||
├── wdac/ # WDAC base policy (XML) + compiled .cip
|
||
├── debloat/ # appx removal list, service-disable scripts
|
||
├── stack-installer/ # Stack package builders/installers
|
||
├── drivers/ # GPD Pocket 4 driver pack (or sourced manifest)
|
||
└── tests/ # telemetry-leak test, hardening-baseline test
|
||
```
|
||
|
||
## 7. Milestones
|
||
|
||
| Milestone | Deliverable | Needs hardware? |
|
||
|---|---|---|
|
||
| **M0** | This design + scaffolded tree | No |
|
||
| **M1** | `autounattend.xml` + `hardening/` modules runnable standalone — hardens the Pocket 4 with no pipeline | Yes (the unit) |
|
||
| **M2** | DISM servicing + `oscdimg` repack → first packed ISO, built locally on a Windows + ADK box | Driver pack |
|
||
| **M3** | `.gitea/workflows/build-iso-windows.yaml` (Windows runner) + attestation/SBOM + telemetry-leak gate | Windows runner |
|
||
| **M4** | Branding, full Stack integration, all verification gates green | Stack Windows builds |
|
||
|
||
## 8. Build environment & deferred items
|
||
|
||
- **Build host**: Windows + Windows ADK (DISM + `oscdimg`). A Windows CI runner is required for M3 (mirrors the existing Linux `.gitea/workflows/build-iso-linux.yaml`).
|
||
- **Cross-build on Linux** (wimlib + xorriso) is possible but UEFI boot-file assembly is fiddly — **deferred**, Windows-runner path is canonical.
|
||
- **Stack Windows builds**: some Stack components are still "Linux MVP" per [`README.md`](README.md); their native Windows builds may lag M4.
|
||
- **Driver-pack sourcing**: confirm redistribution terms for the GPD Pocket 4 driver pack, or source at build time from the verified GPD location.
|
||
|
||
## 9. Open questions
|
||
|
||
Carried from [`hardening-spec.md`](hardening-spec.md) §8 (resolve on the physical unit), plus builder-specific:
|
||
|
||
1. Does the IoT Enterprise LTSC media expose the expected image index and OOBE bypass path for `autounattend.xml`?
|
||
2. Which Pocket 4 drivers are absent from a vanilla LTSC install and must be injected?
|
||
3. Does `oscdimg` produce a Pocket 4-bootable UEFI image with the device's firmware (test on the unit)?
|