Adds the Blueforce Field OS provisioning stack on top of the existing fleet architecture, without rewriting the working systems (installer, diagnostics, Ansible, WireGuard/SSH/xRDP/RustDesk, Docker policies, monitoring, Docusaurus). ISO build (the previous builder was a skeleton that produced no medium): - boot layout is read from the base ISO at build time via `xorriso -report_el_torito as_mkisofs` and rebuilt with `-as mkisofs`; `-boot_image any replay` cannot work on Ubuntu live ISOs because the GRUB2 MBR lives in the source image's first 16 sectors and the EFI system partition is an appended partition, neither of which is a file in the ISO9660 tree - preflight now asserts El Torito boot metadata positively: xorriso exits 0 on a non-ISO input, which previously let an arbitrary file pass --check - artifact produced and verified: dist/Blueforce-Field-OS-1.0.0-amd64.iso, 6 481 917 952 bytes, SHA256 cb0cc56f...d431296, BIOS+UEFI entries preserved, /autoinstall.yaml at the media root, casper/minimal.squashfs byte-identical to the base - recorded baseline deviation: the verified medium on the build host is the Desktop flavour, so the manifest carries a baseline_deviation block instead of hiding it; Server remains one flag away Offline and identity: - offline APT contract with concrete package requirements, pin format and an audit table; builds fail closed while pins are UNPINNED - autoinstall keeps interactive-sections: [storage]: the operator confirms the target disk, and no automatic wipe is ever performed - firstboot terminal wizard for the 8-digit dealer id, three-state lifecycle (PROVISIONED_OFFLINE -> ENROLLED -> READY) with fail-closed gates, so a missing internet link or WireGuard handshake cannot fail provisioning but can never produce a false READY Fleet and migration: - five read-only Ansible playbooks for Field OS version, provisioning, enrollment, remote channels and offline readiness, all wave-scoped with a separate production override - Windows pre-migration inventory and data export extended to the full brief scope, read-only, never collecting credentials Tests: tests/run-all.sh -> 8/8 pass, exit 0. Boot acceptance (UEFI, Legacy BIOS, Secure Boot), air-gapped install, real enrollment endpoint and Windows rollback remain LAB work and are listed in IMPLEMENTATION-REPORT.md.
171 lines
9.8 KiB
Markdown
171 lines
9.8 KiB
Markdown
# Windows → Field OS migration tooling (`scripts/migration/windows/`)
|
|
|
|
Read-only inventory and export-manifest tooling that runs **on the Windows
|
|
terminal before it is migrated** to Blueforce Field OS (docs/28). It never
|
|
installs, never writes to the machine, never touches a service, the registry or
|
|
the network configuration, and never collects credentials or secrets.
|
|
|
|
## Files
|
|
|
|
| File | Report type | Purpose |
|
|
|---|---|---|
|
|
| `BF-WindowsPreMigrationInventory.ps1` | `windows-pre-migration-inventory` | Hardware, Windows version, disks/volumes, network (IP/DNS/gateway/routes/profiles/proxy), serial-COM ports, USB devices + hardware IDs, drivers, installed software, services, scheduled tasks, Docker presence, VPN clients, RustDesk/AnyDesk IDs, MEG paths, current hostname. |
|
|
| `BF-WindowsDataExport.ps1` | `windows-pre-migration-data-export-manifest` | Metadata-only review manifest for the manual data transfer: candidate user folders, removable media, mapped network drives, printers, MEG data directories, installed-software review. Copies nothing. |
|
|
|
|
Both scripts emit `BF-<no>-windows-inventory*.json` (machine) and
|
|
`BF-<no>-windows-inventory*.md` (human).
|
|
|
|
## Why this directory and not a root `migration/windows/`
|
|
|
|
The requested layout was `migration/windows/`; this repository keeps every
|
|
operational script under `scripts/` (`scripts/{install,maintenance,diagnostics,recovery,migration}`),
|
|
so the tooling lives in `scripts/migration/windows/`. The deviation is
|
|
deliberate and documented in:
|
|
|
|
- `migration/README.md` (repo root) — pointer file kept at the expected location
|
|
- `docs/32-REPOSITORY-AUDIT-AND-CONFLICTS.md` §B-6 — audit entry for the name and location deviation
|
|
|
|
Filename deviation from the original request (kept, not "fixed", to preserve
|
|
repository consistency). No wrapper scripts are added on purpose: the static
|
|
test `tests/check-migration-static.sh` requires **every** `*.ps1` in this
|
|
directory to carry the dealer-id/JSON/Markdown/`-NoSoftware` contract, so thin
|
|
renamed wrappers would only duplicate the same contract in four files.
|
|
|
|
| Requested filename | Repo artifact | Status |
|
|
|---|---|---|
|
|
| `bf-win-inventory.ps1` | `BF-WindowsPreMigrationInventory.ps1` — identity/hardware/OS/disk blocks | Implemented under the repo name |
|
|
| `bf-win-network-export.ps1` | same script, `network` + `serial_ports` + `usb` sections | Merged, no separate file |
|
|
| `bf-win-software-export.ps1` | same script, `installed_software` / `services` / `scheduled_tasks` / `drivers` / `docker` / `vpn` / `remote_access` / `meg` sections (skippable with `-NoSoftware`) | Merged, no separate file |
|
|
| `bf-win-device-export.ps1` | `BF-WindowsDataExport.ps1` (`BF-<no>-windows-inventory-export.json/.md`) | Implemented under the repo name |
|
|
|
|
This mapping table is the authoritative name/deviation record: one inventory
|
|
report and one export manifest, not four fragmented scripts.
|
|
|
|
## How to run
|
|
|
|
PowerShell 5.1 (Windows PowerShell) and PowerShell 7+ are both supported. The
|
|
scripts are UTF-8 **with BOM** so Windows PowerShell 5.1 reads the Turkish
|
|
report headers correctly.
|
|
|
|
```powershell
|
|
# 1) Dry run first: prints the plan and the output paths, writes nothing.
|
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\BF-WindowsPreMigrationInventory.ps1 `
|
|
-DealerId 12010193 -OutputDirectory C:\Blueforce\migration -Check
|
|
|
|
# 2) Real read-only collection (dealer number known).
|
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\BF-WindowsPreMigrationInventory.ps1 `
|
|
-DealerId 12010193 -OutputDirectory C:\Blueforce\migration
|
|
|
|
# 3) Data-export review manifest (metadata only).
|
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\BF-WindowsDataExport.ps1 `
|
|
-DealerId 12010193 -OutputDirectory C:\Blueforce\migration
|
|
|
|
# 4) Privacy-reduced run: skip the software surface.
|
|
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\BF-WindowsPreMigrationInventory.ps1 `
|
|
-DealerId 12010193 -OutputDirectory C:\Blueforce\migration -NoSoftware
|
|
```
|
|
|
|
### Execution policy
|
|
|
|
`-ExecutionPolicy Bypass` applies to **that one process only**; it does not
|
|
change the machine or user execution policy. If the operator cannot use it,
|
|
either unblock the files (`Unblock-File .\BF-*.ps1`) or run from an already
|
|
permitted location/policy. Elevation is not required: nothing is changed, and
|
|
an unelevated run only reports which CIM sections were incomplete (the `notes`
|
|
array).
|
|
|
|
### Dealer number unknown
|
|
|
|
The report name comes from the **8-digit dealer number** (`^[0-9]{8}$`), never
|
|
from the machine hostname. If the dealer number is genuinely not known yet, use
|
|
the explicit opt-in:
|
|
|
|
```powershell
|
|
.\BF-WindowsPreMigrationInventory.ps1 -DealerIdUnknown -OutputDirectory C:\Blueforce\migration
|
|
```
|
|
|
|
That writes `BF-unknown-windows-inventory.*`, sets `dealer_id_known: false` and
|
|
adds a prominent warning in `notes` and at the top of the Markdown report: the
|
|
file **must not** be uploaded to the central inventory until the dealer number
|
|
is confirmed and the script is re-run with `-DealerId`. Do not guess a dealer
|
|
number to "fix" the filename.
|
|
|
|
## Output contract
|
|
|
|
| Item | Value |
|
|
|---|---|
|
|
| JSON | `<OutputDirectory>/BF-<no>-windows-inventory.json` |
|
|
| Markdown | `<OutputDirectory>/BF-<no>-windows-inventory.md` |
|
|
| Export JSON/MD | `<OutputDirectory>/BF-<no>-windows-inventory-export.{json,md}` |
|
|
| Device ID | `BF-<no>` (from the dealer number) |
|
|
| `report_type` | `windows-pre-migration-inventory` (export manifest: `windows-pre-migration-data-export-manifest`) |
|
|
| `read_only` | `true` — always; the run performs no state change |
|
|
| `dealer_id_known` | `true`, or `false` on an explicit `-DealerIdUnknown` run |
|
|
| `current_hostname` | the existing Windows hostname (unchanged, recorded) |
|
|
| `target_hostname` | `bf-<no>` — the hostname expected after migration (docs/02) |
|
|
| `schema_version` | `1` |
|
|
|
|
Field names are aligned with `scripts/diagnostics/bf-hardware-inventory.sh`
|
|
(docs/02 §9) so central tooling can consume both:
|
|
|
|
| `bf-hardware-inventory.sh` (Linux) | `BF-WindowsPreMigrationInventory.ps1` (Windows) |
|
|
|---|---|
|
|
| `schema_version`, `device_id`, `hostname`, `dealer_id`, `collected_at`, `notes` | same names (`collected_at` + `collected_at_utc`, `notes` is an array) |
|
|
| `manufacturer`, `model`, `serial` | same |
|
|
| `bios{vendor,version,date}` | same (+ `smbios_version`) |
|
|
| `cpu{model,cores,arch}` | same (+ `logical_processors`, `address_width`) |
|
|
| `memory_mb` | same |
|
|
| `disks` | per-disk objects `{name,size_gb,interface_type,media_type,serial}` (doc 02 §9 shape) |
|
|
| `network{interfaces,macs}` | `network.interfaces[]` (per-adapter objects) + `network.macs[]`, plus `ipv4_addresses`, `default_gateways`, `dns_servers`, `routes`, `network_profiles`, `proxy` |
|
|
| `gpu{model}` | same (+ `driver_version`, `video_processor`, `adapter_ram_mb`) |
|
|
| `usb` | `usb{devices[],controllers[]}` (includes USB hardware IDs `USB\VID_xxxx&PID_xxxx`) |
|
|
| `serial_ports` | `serial_ports{cim_serial_ports[],registry_devicemap,pnp_com_devices[]}` (COM ports) |
|
|
| `os{distro,kernel}` | `os{distro,version,build}` + a `windows{}` block (edition, DisplayVersion, build/UBR, hotfixes) |
|
|
| `smart`, `tpm`, `virt`, `temps` | not applicable on Windows; not emitted |
|
|
| — | Windows-only blocks: `windows`, `volumes`, `drivers`, `installed_software`, `services`, `scheduled_tasks`, `docker`, `vpn`, `remote_access`, `meg`, `user_profiles`, `collection_scope` |
|
|
|
|
## Read-only guarantee
|
|
|
|
Asserted mechanically by `tests/check-migration-static.sh` on every run:
|
|
|
|
- **Forbidden primitives** — no `Set-*`/`New-*`/`Remove-*` item or property
|
|
cmdlet, no service control cmdlet, no network-configuration command of any
|
|
kind, no registry write, no download cmdlet, no external process execution
|
|
(the exact forbidden families are enumerated in
|
|
`tests/check-migration-static.sh`). The only write is the report pair under
|
|
`-OutputDirectory` (and `-Check` writes nothing at all).
|
|
- **Never collected** — credentials, passwords, tokens, private keys, DPAPI
|
|
blobs, file contents, browser profiles, event logs, `Windows ProductId`.
|
|
- **Device IDs only** — RustDesk/AnyDesk: exactly one ID value is extracted
|
|
(registry value named `id` / `ad.anynet.id`, else the matching one-line value
|
|
in `RustDesk.toml` / `system.conf`). The RustDesk `id_ed25519` private key,
|
|
AnyDesk password/hash settings and `*.ovpn`/`*.conf.dpapi` contents are never
|
|
read — VPN tunnel/profile files are listed **by name only**.
|
|
- **Registry is read-only** — `Get-ItemProperty`/`Get-ChildItem` only, and
|
|
path-like values are selected by an exact name allow-list so unrelated
|
|
(possibly sensitive) values in the same key are ignored.
|
|
- **Software surface is opt-out** — `-NoSoftware` skips installed software,
|
|
services, scheduled tasks and drivers; hardware, network, device and MEG-path
|
|
sections are still collected.
|
|
- **Dry run** — `-Check` prints the plan and output paths, writes nothing,
|
|
exits `0`.
|
|
|
|
## Verification status (honest note)
|
|
|
|
There is no PowerShell interpreter on the Linux build host, so these scripts are
|
|
statically verified only: syntax/structure review, the `tests/check-migration-static.sh`
|
|
contract (tag names, dealer-id regex, JSON/Markdown output, forbidden-primitive
|
|
greps) and brace/quote balance checking. **They have not been executed on a real
|
|
Windows terminal yet** — first execution belongs to the LAB/pilot step in
|
|
docs/28 §10 (`bf-hardware-inventory.sh` runs after migration and its JSON is
|
|
diffed against this report). Treat the first run output as unvalidated until
|
|
that LAB step is recorded.
|
|
|
|
## Related documentation
|
|
|
|
- `docs/28-WINDOWS-TO-LINUX-MIGRATION.md` — migration gate, test plan, rollback
|
|
- `docs/02-DEVICE-NAMING-AND-INVENTORY.md` — `BF-<no>` identity + JSON contract
|
|
- `docs/17-BACKUP-RECOVERY-AND-REINSTALL.md` — L8 reimage / recovery ladder
|
|
- `scripts/diagnostics/bf-live-hw-check` — read-only hardware gate used **after**
|
|
migration on the Linux side
|
|
- `migration/README.md` (repo root) — location pointer
|