refactor(template): §7 — move OS hardening to Deploy, Setup becomes validation-only
§7.1 — Setup Steps 1/3/4b/5b/5c converted to Assert-Step only:
- Deploy post-install.ps1 now owns: Firewall (all profiles disabled),
WinRM MaxMemory=2048MB/IdleTimeout=2h/MaxProcesses=25/StartupType=Automatic,
lock screen (NoLockScreen), SM GPO policy key + scheduled task disable,
DisableCAD in Winlogon, OOBE non-policy key.
- Setup no longer re-applies these — validates them, throws if Deploy missed any.
§7.2 — WU lifecycle Strategy B:
- Deploy: replaces sc.exe disable with GPO locks only (NoAutoUpdate=1,
DisableWindowsUpdateAccess=1); services remain Manual (Windows default).
- Setup Step 6 Step A already clears these locks before COM API; Step 6b
permanently disables services post-update. No Setup changes needed.
§7.3 — Docs updated:
- Deploy .DESCRIPTION reflects full hardening ownership.
- Setup .DESCRIPTION marks validation-only steps, updates step ordering rationale.
- WINDOWS-TEMPLATE-SETUP.md: three-script architecture table, CI-WinBuild.vmx
path, Fase C step list + rationale + validation table updated.
TODO: §7.1/7.2/7.3 marked done. §7.4 e2e pending (requires new VM snapshot).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,12 +9,17 @@ credenziali archiviate, ISO Windows Server presente).
|
||||
|
||||
---
|
||||
|
||||
## Architettura: due script
|
||||
## Architettura: tre script
|
||||
|
||||
| Script | Dove gira | Scopo |
|
||||
| ---------------------------------------- | --------------- | -------------------------------------------------- |
|
||||
| `template/Prepare-WinBuild2025.ps1` | **Host** | Orchestratore: copia + esegue lo script in VM |
|
||||
| `template/Setup-WinBuild2025.ps1` | **Dentro VM** | Provisioning effettivo (firewall, defender, tool) |
|
||||
| Script | Dove gira | Scopo |
|
||||
| ---------------------------------------- | --------------- | ------------------------------------------------------------------- |
|
||||
| `template/Deploy-WinBuild2025.ps1` | **Host** | Opzionale: crea VM e installa Windows unattended da ISO |
|
||||
| `template/Prepare-WinBuild2025.ps1` | **Host** | Orchestratore: copia + esegue Setup nel guest via WinRM |
|
||||
| `template/Setup-WinBuild2025.ps1` | **Dentro VM** | CI toolchain (user, .NET, Python, VS) + validazione hardening Deploy |
|
||||
|
||||
**Confine Deploy / Setup** (refactor §7, 2026-05-10):
|
||||
- `Deploy-WinBuild2025.ps1` si occupa dell'**OS hardening** (Firewall, WinRM, UAC, Defender, UX tweaks, WU GPO locks). Se usato, Setup valida questi come Assert-Step senza re-applicarli.
|
||||
- `Setup-WinBuild2025.ps1` si occupa della **CI customization** (utente `ci_build`, cartelle `C:\CI`, toolchain .NET/Python/VS, Windows Update lifecycle, cleanup, final gate).
|
||||
|
||||
`Prepare-WinBuild2025.ps1` apre una WinRM session, copia `Setup-WinBuild2025.ps1` in
|
||||
`C:\CI\`, lo esegue, raccoglie l'exit code, valida lo stato del guest.
|
||||
@@ -30,7 +35,7 @@ credenziali archiviate, ISO Windows Server presente).
|
||||
| RAM | 6144 MB (6 GB) |
|
||||
| Disco | 80 GB thin provisioned |
|
||||
| NIC | **VMnet8 (NAT)** — internet richiesto per WU + installer |
|
||||
| VMX path | `F:\CI\Templates\WinBuild\WinBuild.vmx` |
|
||||
| VMX path | `F:\CI\Templates\WinBuild\CI-WinBuild.vmx` |
|
||||
| ISO | Windows Server 2025 (da `F:\CI\ISO\`) |
|
||||
|
||||
---
|
||||
@@ -41,7 +46,7 @@ credenziali archiviate, ISO Windows Server presente).
|
||||
- File → New Virtual Machine → Custom
|
||||
- Hardware: 4 vCPU, 6144 MB, 80 GB thin
|
||||
- Network: **VMnet8 (NAT)**
|
||||
- VMX: `F:\CI\Templates\WinBuild\WinBuild.vmx`
|
||||
- VMX: `F:\CI\Templates\WinBuild\CI-WinBuild.vmx`
|
||||
- CD/DVD: monta ISO Windows Server 2025
|
||||
|
||||
### A.2 Installa Windows Server 2025
|
||||
@@ -142,21 +147,22 @@ Ogni step ha validazione `Assert-Step` (throw on failure, `[OK]` su pass):
|
||||
|
||||
## Fase C — Cosa fa `Setup-WinBuild2025.ps1` (dentro la VM)
|
||||
|
||||
Eseguito automaticamente da Prepare in Fase B. Ordine ottimizzato per ridurre overhead:
|
||||
tutti i tweak UI/registro sono raggruppati **prima** di Windows Update (operazione lenta).
|
||||
Ogni step ha validazione `Assert-Step`.
|
||||
Eseguito automaticamente da Prepare in Fase B. Steps 1/2/3/4b/5b/5c sono
|
||||
**validation-only** — verificano che Deploy abbia già applicato l'hardening OS.
|
||||
Steps 4/5/6/6b/7-10 eseguono la CI customization effettiva.
|
||||
Ogni step ha validazione `Assert-Step` (throw on failure).
|
||||
|
||||
```
|
||||
Step 1 Firewall off (Domain/Private/Public) ── primo, rimuove blocchi
|
||||
Step 2 Defender + Antimalware off (Set-MpPreference + GPO)
|
||||
── prima di WinRM e WU
|
||||
Step 3 WinRM hardening (Basic, AllowUnencrypted, 2 GB shell mem, 2h timeout)
|
||||
Step 4 Build user account (ci_build, admin, no expire) ── prima di WU
|
||||
Step 4b UAC off (EnableLUA=0, LocalAccountTokenFilterPolicy=1)
|
||||
Step 1 Firewall: validation only — Deploy disabled all profiles [Assert-Step]
|
||||
Step 2 Defender: validation only — Deploy set DisableAntiSpyware GPO + RTP off [Assert-Step]
|
||||
Step 3 WinRM: validation only — Deploy set Basic/Unencrypted/MaxMem/Timeout [Assert-Step]
|
||||
Step 4 Build user account (ci_build, admin, no expire) ── crea utente CI
|
||||
Step 4b UAC: validation only — Deploy set EnableLUA=0 + TokenFilterPolicy [Assert-Step]
|
||||
Step 5 CI dirs: C:\CI\{build, output, scripts} ── C:\CI deve esistere prima di WU
|
||||
Step 5b Explorer LaunchTo=1 (This PC)
|
||||
Step 5c CI UX hardening: Server Manager off, DisableCAD, OOBE/telemetry off
|
||||
Step 6 Windows Update via Scheduled Task SYSTEM ── senza scan Defender, C:\CI presente
|
||||
Step 5b Explorer LaunchTo=1: validation only — Deploy set HKCU + Default hive [Assert-Step]
|
||||
Step 5c CI UX hardening: validation only — Deploy set lock screen, SM policy/task,
|
||||
DisableCAD, OOBE, telemetry [Assert-Step]
|
||||
Step 6 Windows Update via Scheduled Task SYSTEM ── clears Deploy GPO locks, runs WU
|
||||
Step 6b Windows Update permanently disabled (post-update lockdown)
|
||||
Step 7 .NET SDK install (channel via dotnet-install.ps1)
|
||||
Step 8 Python install (3.13.3, all-users, C:\Python)
|
||||
@@ -168,41 +174,36 @@ Final Pre-snapshot gate — 7 check cross-cutting + no installer leftover
|
||||
|
||||
### Razionale dell'ordine
|
||||
|
||||
- **Firewall first** — Windows blocca alcune chiamate WinRM finché non è classificato il
|
||||
profilo di rete. Off subito → niente race condition durante Step 3.
|
||||
- **Defender second** — disabilitato prima di WinRM e WU. WU scarica/installa update
|
||||
senza scan (5-15 min risparmiati). Step 7-9 (download + install ~200-400 MB di
|
||||
payload .NET/Python/VS) non vengono scansionati.
|
||||
- **WinRM third** — già non interferito da firewall/defender. Hardening pulito.
|
||||
- **User + UAC (4/4b)** — operazioni registro rapide; UAC off prima di dir/tool evita
|
||||
prompt di elevazione; nessun motivo di aspettare WU.
|
||||
- **Steps 1-3 (validazioni)** — verificano prima le precondizioni Deploy (firewall off,
|
||||
Defender off, WinRM pronto) in modo che i failure emergano subito, non a metà toolchain.
|
||||
- **User + UAC (4/4b)** — crea `ci_build`; valida UAC off (set da Deploy); UAC off prima
|
||||
di dir/tool evita prompt di elevazione negli step 7-9.
|
||||
- **CI dirs prima di WU (Step 5)** — il worker WU scrive file temp in `C:\CI\`
|
||||
(`wu_worker.ps1`, `wu_result.txt`, ecc.); la directory deve esistere prima.
|
||||
- **UI tweaks (5b/5c)** — tutti i tweak registro raggruppati prima del WU (lento);
|
||||
scritture veloci, nessuna dipendenza da WU o toolchain.
|
||||
- **WU sixth** — gira con tutto già off + `C:\CI` presente; condizioni ottimali.
|
||||
- **WU disable subito dopo** — snapshot cattura WU permanentemente off.
|
||||
- **UI tweaks (5b/5c)** — validazioni registro rapide; raggruppate prima di WU (lento).
|
||||
- **WU (Step 6)** — clears i GPO lock di Deploy (Step A), avvia COM API via SYSTEM task,
|
||||
poi Step 6b re-disabilita tutto → snapshot cattura WU permanentemente off.
|
||||
- **Toolchain (7-9) last** — WU completato, nessun scan su payload installer.
|
||||
|
||||
### Validazioni per step (sintesi)
|
||||
|
||||
| Step | Check chiave |
|
||||
| ---- | ------------------------------------------------------------------------------- |
|
||||
| 1 | `Get-NetFirewallProfile -Profile Domain/Private/Public → Enabled=False` |
|
||||
| 2 | 6 GPO key + `Set-MpPreference DisableRealtimeMonitoring=true` + ExclusionPath |
|
||||
| 3 | WinRM Running+Automatic, AllowUnencrypted=true, Auth/Basic=true, MaxMem≥2048 |
|
||||
| 4 | User exists, enabled, PasswordNeverExpires, member of Administrators |
|
||||
| 4b | EnableLUA=0, LocalAccountTokenFilterPolicy=1 |
|
||||
| 5 | Ogni dir Test-Path -PathType Container |
|
||||
| 5b | HKCU LaunchTo=1 |
|
||||
| 5c | ServerManager machine policy DoNotOpenAtLogon=1, HKCU DoNotOpenServerManagerAtLogon=1, DisableCAD=1, OOBE DisablePrivacyExperience=1, AllowTelemetry=0 |
|
||||
| 6 | ResultCode ∈ {0,2,3}, no reboot required (else exit 3010) |
|
||||
| 6b | wuauserv StartType=Disabled, NoAutoUpdate=1, DisableWindowsUpdateAccess=1 |
|
||||
| 7 | `dotnet --version` channel match, machine PATH contiene `C:\dotnet` |
|
||||
| 8 | `C:\Python\python.exe` esiste, version match esatto, PATH contiene `C:\Python` |
|
||||
| 9 | MSBuild.exe esiste, esegue, PATH, `\VC\` dir presente |
|
||||
| 10 | dotnet+python+msbuild tutti risolvibili (throw, non più warn) |
|
||||
| Final| WinRM, firewall, user+admin, UAC, WU disabled, tutti tool, no leftover installer in `C:\CI` |
|
||||
| Step | Natura | Check chiave |
|
||||
| ---- | ---------- | ------------------------------------------------------------------------------ |
|
||||
| 1 | Assert | `Get-NetFirewallProfile -Profile Domain/Private/Public → Enabled=False` |
|
||||
| 2 | Assert | GPO DisableAntiSpyware=1 (set da Deploy) |
|
||||
| 3 | Assert | WinRM Running+Automatic, AllowUnencrypted=true, Auth/Basic=true, MaxMem≥2048 |
|
||||
| 4 | Operativo | User exists, enabled, PasswordNeverExpires, member of Administrators |
|
||||
| 4b | Assert | EnableLUA=0, LocalAccountTokenFilterPolicy=1 |
|
||||
| 5 | Operativo | Ogni dir Test-Path -PathType Container |
|
||||
| 5b | Assert | HKCU LaunchTo=1 |
|
||||
| 5c | Assert | NoLockScreen=1, SM policy DoNotOpenAtLogon=1, SM task Disabled, DisableCAD=1, OOBE DisablePrivacyExperience=1, AllowTelemetry=0 |
|
||||
| 6 | Operativo | ResultCode ∈ {0,2,3}, no reboot required (else exit 3010) |
|
||||
| 6b | Operativo | wuauserv StartType=Disabled, NoAutoUpdate=1, DisableWindowsUpdateAccess=1 |
|
||||
| 7 | Operativo | `dotnet --version` channel match, machine PATH contiene `C:\dotnet` |
|
||||
| 8 | Operativo | `C:\Python\python.exe` esiste, version match esatto, PATH contiene `C:\Python` |
|
||||
| 9 | Operativo | MSBuild.exe esiste, esegue, PATH, `\VC\` dir presente |
|
||||
| 10 | Operativo | dotnet+python+msbuild tutti risolvibili (throw) |
|
||||
| Final| Cross-cut | WinRM, firewall, user+admin, UAC, WU disabled, tutti tool, no leftover installer in `C:\CI` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user