Skip to content

RELOPS-2487: create hardware-imaging stack alongside nucwimfxci (migrate-first phase 1) - #317

Merged
markcor merged 10 commits into
masterfrom
nuc-wim-migrate-phase1
Aug 12, 2026
Merged

RELOPS-2487: create hardware-imaging stack alongside nucwimfxci (migrate-first phase 1)#317
markcor merged 10 commits into
masterfrom
nuc-wim-migrate-phase1

Conversation

@markcor

@markcor markcor commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Phase 1 of the nuc-wim -> hardware-imaging migration (migrate-first, no data loss).

Adds hardware-imaging-storage.tf: a NEW stack (RG rg-central-us-hardware-imaging,
account hardwareimaging, VNet/subnet, UAMI, containers resources/captured/legacy-images,
RBAC) created alongside the existing nucwimfxci0 destroys. This is what's currently
applied; ~30 GB of blobs were then azcopy-migrated old -> new with the folder remap
(base/* -> resources/WIMs|ISOs|drivers|tools; captured/* -> captured/WIMs|ISOs).

Temp labels (captured_hwimg, relops_hwimg_*, *_hwimg) avoid clashing with the old
stack's labels while both coexist. Retire (follow-up): state mv captured_hwimg -> captured, fold into the end-state config (PR #316), and destroy the old nuc-wim stack.

🤖 Generated with Claude Code

markcor and others added 10 commits July 21, 2026 10:35
Tier-1 private storage for NUC install.wim files: public endpoint retained
but network_rules default Deny, allowing only the Packer subnet (Microsoft.Storage
service endpoint) and the MDC1 egress IP(s). No anonymous access; auth via Entra
RBAC (Storage Blob Data Contributor for Packer, Reader on 'captured' for the MDC1
downloader SP) or a read-only SAS from kv-central-us-key.

- azure_fxci/nuc-wim-storage.tf: RG, VNet/subnet (svc endpoint), storage account
  (deny-by-default firewall), base+captured containers, data-plane role assignments.
- azure_ad/sp_nuc_wim_downloader.tf: Entra SP for the on-site MDC1 downloader.

MDC1 egress IP (default 63.245.208.251/32) and SP-vs-SAS auth are parameterized
pending confirmation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e tfplan

- mdc1_egress_cidrs default 63.245.208.129 (bare IP; Azure storage firewall
  rejects /31 and /32 masks)
- nuc_wim_downloader_object_id default set to the applied SP object_id so the
  mdc1_wim_ro Blob Data Reader grant on 'captured' stays active across plans
- fix provider deprecations: role-assignment scope resource_manager_id -> id;
  container storage_account_name -> storage_account_id
- .gitignore: ignore *tfplan* (plan output can embed sensitive values)

Applied to FXCI DevTest: storage nucwimfxci (deny-by-default) + base/captured
containers + packer_wim_rw (Blob Data Contributor) + mdc1_wim_ro (Blob Data
Reader, scoped to captured). SP secret kept off-repo (state only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add admin_egress_cidrs (default = Mozilla VPN netblocks, bare IPs since Azure
storage firewall rejects /32) and merge into the storage firewall ip_rules so
operators on the corp VPN can manage the store (e.g. upload the base WIM) from
outside the MDC1 IP. Deny-by-default posture unchanged. Ref base/outputs.tf
mozilla_vpn_netblocks + mana Mozilla VPN wiki.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…to MDC1 IP

- Grant the Relops Entra group Storage Blob Data Owner + Contributor on the
  account so operators manage the store with their own Entra identity.
- Revert the firewall ip_rules back to the single MDC1 egress IP (drop the
  Mozilla VPN netblocks / admin_egress_cidrs added earlier).

Note: RBAC clears the data-plane auth gate, but the storage firewall still
applies — Relops members must reach the account from an allow-listed network.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…keys)

Rework access so Relops members and the downloader SP reach the store by Entra
identity from any network (split-tunnel VPN made IP allow-listing unworkable):

- network_rules default_action Deny -> Allow; drop ip_rules + the packer subnet
  rule and the now-unused mdc1_egress_cidrs var. Access is gated purely by RBAC.
- shared_access_key_enabled = false (no account key / SAS; Entra-only).
- Manage the account + containers via an aliased azurerm provider with
  storage_use_azuread = true (scoped to this file, so the rest of azure_fxci is
  untouched), since keys are disabled.
- Grant the Relops group Storage Queue Data Contributor + Storage File Data
  Privileged Contributor so whoever runs Terraform can read the account's
  queue/file service properties via AAD (the account itself only uses blob).

RBAC access paths unchanged: Relops (Blob Data Owner+Contributor), downloader SP
(Blob Data Reader on captured), Packer SP (Blob Data Contributor). Verified:
Entra blob access works from a non-allow-listed IP; key auth is refused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a user-assigned managed identity (id-central-us-wim-builder) pre-granted
Storage Blob Data Contributor — attached to each ephemeral build VM so no per-run
role assignment is needed. Grant the workflow SP (worker_images_fxci) modest,
RG-scoped rights: Contributor on rg-central-us-nuc-wim (create/delete VM +
run-command; NOT role-assignment) + Managed Identity Operator on the UAMI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ure containers

Prod-prep: rename the storage account and reorganize the blob layout.
- account nucwimfxci -> hardwareimaging
- container 'base' -> 'resources' (SOURCES): folders WIMs/ ISOs/ drivers/ tools/
- 'captured' (OUTPUTS): folders WIMs/ ISOs/
- new 'legacy-images' container for old/previously-built images (empty at creation)
- TF-managed .keep folder markers for the prefixes above
Data migration (old -> new) and apply are separate, deliberate steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
#	terraform/azure_ad/sp_nuc_wim_downloader.tf
#	terraform/azure_fxci/nuc-wim-storage.tf
Full rebrand (names + resource labels + refs): resource_group, virtual_network,
subnet, and the user-assigned identity, matching the storage-account rename.
Provider alias (nuc_wim_aad), role-assignment labels, and the downloader SP kept.
validate clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@markcor
markcor requested a review from jwmossmoz August 7, 2026 21:03
@markcor
markcor merged commit af7293f into master Aug 12, 2026
1 check passed
markcor added a commit that referenced this pull request Aug 26, 2026
…hardwareimaging

Phase 2 of the nuc-wim -> hardware-imaging migration, completing the phase-1
create-alongside (#317).

Removes nuc-wim-storage.tf entirely: the old 'nucwimfxci' account, its base/ and
captured/ containers, the nuc-wim RG/VNet/subnet, the wim_builder identity and the
nine wim_* role assignments. Every blob the old account held has a verified
counterpart under hardwareimaging resources/ and captured/, and worker-images has
provisioned exclusively into rg-central-us-hardware-imaging since the cutover -
no code in win-hw-wim/ or ci/ references the old RG, VNet, subnet or identity.

Adds azurerm_role_assignment.mdc1_hwimg_ro: Storage Blob Data Reader for the MDC1
downloader SP, scoped to the new account's 'captured' container. That grant existed
only on nucwimfxci, so since the cutover the SP has had no access to the account the
images actually live in. This is the "point the SP at the right ones" fix.

The aliased AAD provider (azurerm.nuc_wim_aad) and the relops_group_object_id /
nuc_wim_downloader_object_id variables lived in the deleted file and are moved into
hardware-imaging-storage.tf unchanged.

Deliberately NOT doing the cosmetic resource renames the phase-1 header proposed
(state mv captured_hwimg -> captured, dropping _hwimg suffixes): hand-run state
surgery adds risk to a change that already destroys a storage account.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
markcor added a commit that referenced this pull request Aug 26, 2026
…hardwareimaging (#326)

Phase 2 of the nuc-wim -> hardware-imaging migration, completing the phase-1
create-alongside (#317).

Removes nuc-wim-storage.tf entirely: the old 'nucwimfxci' account, its base/ and
captured/ containers, the nuc-wim RG/VNet/subnet, the wim_builder identity and the
nine wim_* role assignments. Every blob the old account held has a verified
counterpart under hardwareimaging resources/ and captured/, and worker-images has
provisioned exclusively into rg-central-us-hardware-imaging since the cutover -
no code in win-hw-wim/ or ci/ references the old RG, VNet, subnet or identity.

Adds azurerm_role_assignment.mdc1_hwimg_ro: Storage Blob Data Reader for the MDC1
downloader SP, scoped to the new account's 'captured' container. That grant existed
only on nucwimfxci, so since the cutover the SP has had no access to the account the
images actually live in. This is the "point the SP at the right ones" fix.

The aliased AAD provider (azurerm.nuc_wim_aad) and the relops_group_object_id /
nuc_wim_downloader_object_id variables lived in the deleted file and are moved into
hardware-imaging-storage.tf unchanged.

Deliberately NOT doing the cosmetic resource renames the phase-1 header proposed
(state mv captured_hwimg -> captured, dropping _hwimg suffixes): hand-run state
surgery adds risk to a change that already destroys a storage account.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants