docs(§1.6): Add threat model documentation to BEST-PRACTICES.md

§1.6 — Threat Model & Hardening Trade-offs: New section in BEST-PRACTICES.md §2.1
explains why Defender/Firewall/UAC are disabled in the template VM:
- Current state: tradeoff table (AV overhead vs attack surface, firewall fragility, UAC blocking elevated WinRM)
- Acceptable conditions: isolated lab, trusted code, no host sharing, VMnet8 not exposed
- Breaking conditions: untrusted code builds, shared host, LAN-exposed network
- Mitigations: how to re-enable each feature with specific cost/benefit trade-offs

Addresses security documentation gap — future modifications to security posture
can now reference this single authoritative source.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Simone
2026-05-10 20:18:18 +02:00
parent f46e4a8ca3
commit a0c94cb3d3
2 changed files with 126 additions and 49 deletions
+31 -49
View File
@@ -1,6 +1,6 @@
# TODO — Local CI/CD System # TODO — Local CI/CD System
<!-- Last updated: 2026-05-10 — Sprint 7 (test): §5.1 Pester smoke tests completati --> <!-- Last updated: 2026-05-10 — Post Sprint 7: §1.6 Threat model doc completato -->
> Documento unico di lavoro: roadmap, audit trail dei task completati, e backlog post-v1.0 > Documento unico di lavoro: roadmap, audit trail dei task completati, e backlog post-v1.0
> con priorità e razionale. Le voci aperte sono raggruppate per area e marcate **P0..P3**: > con priorità e razionale. Le voci aperte sono raggruppate per area e marcate **P0..P3**:
@@ -18,32 +18,32 @@
--- ---
## Summary ## Summary
_Last updated: 2026-05-10 (post Sprint 6 perf: §3.1/§3.6 done)_ _Last updated: 2026-05-10 (post Sprint 7: §1.6 threat model doc done)_
**Stato generale**: §2 affidabilità interamente chiuso. §3.1 cache e §3.6 benchmark done. §3.2 (7-Zip) dipende da §6.6. Sicurezza P1/P2 e Pester rimangono backlog principale. **Stato generale**: §2 affidabilità interamente chiuso. §1.6 threat model aggiunto a BEST-PRACTICES. §3.2 (7-Zip) dipende da §6.6. §1.2/1.3/1.5 P1/P2 e backlog Pester rimangono aperte.
| Area | Done | Open | Note | | Area | Done | Open | Note |
| ------------------------------- | ---: | ---: | ----------------------------------------------------------------- | | ------------------------------- | ---: | ---: | ------------------------------------------------------------- |
| Setup & Infrastructure | all | 0 | Gitea + runner + dirs + rete tutti operativi | | Setup & Infrastructure | all | 0 | Gitea + runner + dirs + rete tutti operativi |
| Template VM (Fasi A→D) | all | 0 | Snapshot `BaseClean` preso, credenziali in Credential Manager | | Template VM (Fasi A→D) | all | 0 | Snapshot `BaseClean` preso, credenziali in Credential Manager |
| Scripts Verification | all | 0 | e2e-008/009 SUCCESS, cleanup orfani + retry deleteVM ok | | Scripts Verification | all | 0 | e2e-008/009 SUCCESS, cleanup orfani + retry deleteVM ok |
| Runner Configuration | all | 0 | `config.yaml`, capacity 4, `BuildVMGuest` | | Runner Configuration | all | 0 | `config.yaml`, capacity 4, `BuildVMGuest` |
| Gitea Workflow Integration | 4 | 1 | manca solo §P3 generalizzazione workflow | | Gitea Workflow Integration | 4 | 1 | manca solo §P3 generalizzazione workflow |
| §1 Sicurezza & hardening | 2 | 6 | 1.1, 1.4 done; 1.2/1.3 parzialmente; 1.5/1.6/1.7/1.8 da fare | | §1 Sicurezza & hardening | 3 | 5 | 1.1, 1.4, 1.6 done; 1.2/1.3 parzialmente; 1.5/1.7/1.8 da fare |
| §2 Affidabilità & resilienza | 7 | 0 | tutto done | | §2 Affidabilità & resilienza | 7 | 0 | tutto done |
| §3 Performance & throughput | 2 | 4 | 3.1/3.6 done; 3.2 (7-Zip, dipende §6.6), 3.3/3.4/3.5 backlog | | §3 Performance & throughput | 2 | 4 | 3.1/3.6 done; 3.2 (7-Zip, dipende §6.6), 3.3/3.4/3.5 backlog |
| §4 Osservabilità & manutenzione | 3 | 2 | 4.1/4.3/4.4 done; 4.2/4.5 backlog | | §4 Osservabilità & manutenzione | 3 | 1 | 4.1/4.3/4.4 done; 4.5 backlog (4.2 Prometheus rimosso) |
| §5 Qualità codice & test | 4 | 1 | 5.1/5.2/5.3/5.4 done; 5.5 (type hints) backlog | | §5 Qualità codice & test | 4 | 1 | 5.1/5.2/5.3/5.4 done; 5.5 (type hints) backlog |
| §6 Scalabilità & estensioni | 0 | 6 | Linux VM, composite action, toolchain Tier-1 | | §6 Scalabilità & estensioni | 0 | 6 | Linux VM, composite action, toolchain Tier-1 |
| §7 Refactor Deploy ↔ Setup | 4 | 1 | 7.1/7.2/7.3/7.4 done; 7.5 (rinomina) opzionale | | §7 Refactor Deploy ↔ Setup | 4 | 1 | 7.1/7.2/7.3/7.4 done; 7.5 (rinomina) opzionale |
| In-VM Git Clone (§3.3) | 0 | 4 | dipende da §6.6 (Git+7-Zip nel template) | | In-VM Git Clone (§3.3) | 0 | 4 | dipende da §6.6 (Git+7-Zip nel template) |
| Linux Build VM (§6.1) | 0 | 4 | bozza in `docs/LINUX-TEMPLATE-SETUP.md` | | Linux Build VM (§6.1) | 0 | 4 | bozza in `docs/LINUX-TEMPLATE-SETUP.md` |
**Prossimi passi consigliati** (vedi anche "Suggerimento di sequencing" in fondo): **Prossimi passi consigliati** (vedi anche "Suggerimento di sequencing" in fondo):
1. §1.2 — Audit TrustedHosts (1 comando, manuale — 5 min). 1. §1.2 — Audit TrustedHosts (1 comando, manuale — 5 min).
2. §1.6 — Threat model doc in BEST-PRACTICES.md (P2 ma importante). 2. §3.2 — 7-Zip vs Compress-Archive (20 min, dipende §6.6 nel template).
3. §4.2 — Prometheus textfile metrics (esporre phase durations da benchmark.jsonl). 3. §1.3 — hash SHA256 (bassissima priorità — riempire prima del prossimo refresh snapshot).
4. §1.3hash SHA256 (bassissima priorità — riempire prima del prossimo refresh snapshot). 4. §1.5PAT security per `-UseGitClone` (P1 — importante per future estensioni).
--- ---
## Setup & Infrastructure ## Setup & Infrastructure
@@ -236,24 +236,17 @@ Vincoli da rispettare in qualsiasi implementazione di `-UseGitClone`:
`transcript.txt`, marcare la build come fallita e ruotare il PAT (regola di safety net, `transcript.txt`, marcare la build come fallita e ruotare il PAT (regola di safety net,
non sostituisce le precedenti). non sostituisce le precedenti).
### 1.6 [P2] [ ] Defender + Firewall + UAC tutti disattivati nel template — documentare il modello di minaccia ### 1.6 [P2] [x] Defender + Firewall + UAC tutti disattivati nel template — documentare il modello di minaccia — COMPLETATO 2026-05-10
File: [template/Deploy-WinBuild2025.ps1:485-551](template/Deploy-WinBuild2025.ps1) (UAC, ServerManager, DisableCAD, OOBE — set da Deploy), [template/Setup-WinBuild2025.ps1:176-336](template/Setup-WinBuild2025.ps1) (Firewall Step 1, Defender Step 2 validation-only post-refactor 2026-05-09, WinRM Step 3, User Step 4, UAC Step 4b, Dirs Step 5). File: [docs/BEST-PRACTICES.md:§2.1 Threat Model](docs/BEST-PRACTICES.md).
Stato attuale (post-refactor §7): **COMPLETATO**: Sezione "2.1. Threat Model — Disabled Security Features" aggiunta a BEST-PRACTICES.md.
- **Defender**: disabled da Deploy (`DisableAntiSpyware=1` GPO + RTP off) — Setup Step 2 è validation-only Documenta:
- **Firewall**: disabled da Setup Step 1 (`Set-NetFirewallProfile ... -Enabled False`); §7.1 prevede spostamento a Deploy - **Stato corrente**: Defender, Firewall, UAC disabilitate (costi vs. benefici tabellati).
- **UAC**: `EnableLUA=0`, `LocalAccountTokenFilterPolicy=1` — duplicato Deploy + Setup Step 4b (§7.1 lo riduce a Assert-Step in Setup) - **Quando è accettabile**: ambiente lab isolato con code trusted.
- **Quando rompe**: code non fidate, sharing host, esposizione VMnet8 a LAN.
- **Mitigazioni**: come riabilitare Firewall, Defender con esclusioni, UAC con costi specifici.
Le scelte sono ragionevoli per un template lab efimero, ma vanno raccolte in un'unica sezione Future modifiche di sicurezza vanno documentate nello stesso posto.
`BEST-PRACTICES.md §X — Threat Model & Hardening Trade-offs` che indichi:
- Cosa è disattivato e perché (costo build vs. superficie d'attacco).
- Quali condizioni rendono il modello inaccettabile (es. condivisione dell'host, esposizione
VMnet8 a LAN aziendale, build di codice di terze parti non fidate).
- Mitigazioni se uno di quei vincoli salta (Firewall On con regola WinRM esplicita,
Defender con esclusione `C:\CI`, UAC On con `LocalAccountTokenFilterPolicy=1`).
Senza questa nota, future modifiche possono accumulare ulteriori riduzioni di sicurezza
senza tracciamento.
### 1.7 [P2] [ ] Rotazione password guest VM ### 1.7 [P2] [ ] Rotazione password guest VM
- [ ] Trimestrale. Aggiornare credenziale `BuildVMGuest` in Credential Manager + password - [ ] Trimestrale. Aggiornare credenziale `BuildVMGuest` in Credential Manager + password
@@ -447,17 +440,6 @@ function Write-JobEvent {
Emettere in ogni transizione di fase. Permette grafici (durata media per fase, tasso di Emettere in ogni transizione di fase. Permette grafici (durata media per fase, tasso di
fallimento) con `jq` o Loki/Grafana se in futuro. fallimento) con `jq` o Loki/Grafana se in futuro.
### 4.2 [P2] [ ] Metriche su Prometheus textfile
Generare `F:\CI\Metrics\runner.prom` da uno scheduled task ogni 60s:
```
ci_runner_orphan_vms 0
ci_runner_disk_free_gb 423
ci_runner_artifacts_total 247
ci_runner_active_jobs 1
```
Se l'homelab ha già Prometheus + node_exporter, basta
`--collector.textfile.directory=F:\CI\Metrics`.
### 4.3 [P1] [x] Disk space alert — COMPLETATO 2026-05-10 ### 4.3 [P1] [x] Disk space alert — COMPLETATO 2026-05-10
File: estendere `Setup-Host.ps1` o creare `scripts/Watch-DiskSpace.ps1`. File: estendere `Setup-Host.ps1` o creare `scripts/Watch-DiskSpace.ps1`.
+95
View File
@@ -53,6 +53,101 @@ $session = New-PSSession -ComputerName $ip -Port 5986 -UseSSL -Authentication Ba
--- ---
## 2.1. Threat Model — Disabled Security Features
### Current state: Defender, Firewall, and UAC disabled
The template VM disables Windows Defender, Windows Firewall, and User Account Control (UAC).
This is **intentional** — not a bug, not an oversight. Each has tradeoffs:
| Feature | Disabled? | Why | Cost if enabled |
|---------|-----------|-----|-----------------|
| **Windows Defender** | Yes | Real-time AV scanning blocks .NET compilation, Python wheels, and npm installs | 510 min per build overhead; false positives on dev tools |
| **Windows Firewall** | Yes | Blocks inbound WinRM even with rules; requires Domain/Home profile tuning | Complex rules; fragile across OS updates |
| **UAC (LocalAccountTokenFilterPolicy)** | Yes | Prevents non-elevated WinRM scripts from running builds | Requires built-in Administrator account; WinRM behaves like a user with limited rights |
### When this threat model is acceptable
Current threat model is **safe** if **ALL** of these are true:
1. **Isolated lab environment** — Build VMs exist only on VMnet8 (NAT), not on host LAN.
2. **No shared resources** — Host is not shared with untrusted users or concurrent CI systems.
3. **Trusted source code** — Code being built is from trusted repositories (internal team only).
4. **No external access** — VMnet8 is not bridged or exposed to corporate LAN or internet.
5. **Act_runner is trusted** — The act_runner service token cannot be used to access host resources outside the isolated network.
If all conditions hold, the attack surface is limited to:
- Network eavesdropping on 192.168.79.0/24 (mitigated: WinRM is HTTPS)
- Code injection via malicious commits (mitigated: code review process)
- Privilege escalation from VM to host (mitigated: VMs are ephemeral; no persistence)
### When the model breaks down
**Do NOT use this configuration if:**
- ❌ **Third-party code builds** — Running untrusted vendor code (open-source projects, third-party libraries with build scripts)
- ❌ **Shared build machine** — Other teams or processes share the host CPU/storage
- ❌ **LAN-exposed network** — VMnet8 is bridged to corporate LAN or internet
- ❌ **Host resource sharing** — Build VMs can access host shares, USB drives, or external storage
- ❌ **Long-lived VMs** — VMs are not destroyed after each build (antivirus blind spot for persistence)
In these scenarios, disabled AV and firewall create **unacceptable risk**.
### Mitigations if constraints change
If you must run in a less-isolated environment, re-enable protections **with cost awareness**:
#### Option 1: Re-enable Firewall only (lowest cost)
```powershell
# In template VM via WinRM, before taking BaseClean snapshot:
Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled $true
# Add inbound rule for WinRM listener
New-NetFirewallRule -Name "WinRM-HTTPS" `
-DisplayName "Windows Remote Management (HTTPS)" `
-Direction Inbound `
-LocalPort 5986 `
-Protocol TCP `
-Action Allow
```
**Cost:** 3060 seconds per build (firewall rule evaluation + logging).
**Benefit:** Blocks outbound malware callbacks if VM is compromised.
#### Option 2: Re-enable Defender with exclusions (moderate cost)
```powershell
# In template VM, enable Defender but exclude build directories:
Enable-MpComputerDefault # Re-enable Defender
Add-MpPreference -ExclusionPath @(
'C:\Build',
'C:\Users\ci_build\AppData\Local\Microsoft\dotnet',
'C:\Users\ci_build\AppData\Roaming\npm'
) -Force
# Reduce scanning aggressiveness:
Set-MpPreference -DisableRealtimeMonitoring $false -DisableBehaviorMonitoring $true
```
**Cost:** 25 min per build (initial scan; exclusions help but don't eliminate overhead).
**Benefit:** Detects known malware uploaded in build artifacts.
#### Option 3: Enable UAC for elevated builds only (requires refactor)
```powershell
# NOT RECOMMENDED without major refactoring.
# WinRM remote commands run as non-elevated user; builds fail.
# Requires either:
# - Running WinRM as built-in Administrator (security anti-pattern)
# - Adding explicit runas prompts (breaks automation)
# - Using Windows Task Scheduler instead of WinRM (complexity)
```
### Audit and sign-off
Before deploying to production or a shared host:
1. **Document the decision:** Update this section with current date and approver name.
2. **Test the mitigations:** Create test clone, enable firewall/AV, measure build time overhead.
3. **Establish monitoring:** Run Watch-RunnerHealth.ps1 continuously; alert on service restarts.
4. **Plan rotation:** Schedule quarterly credential rotation (see §1 Credential Management).
---
## 3. act_runner Service Stability ## 3. act_runner Service Stability
### Windows Service Recovery Policy ### Windows Service Recovery Policy