security(sprint1): §1.1/1.3/1.4 — WinRM HTTPS/5986, SHA256 pinning infra, IP regex per-octet
§1.4 — Replace loose IP ValidatePattern with per-octet regex in 4 scripts
(Invoke-CIJob, Invoke-RemoteBuild, Get-BuildArtifacts, Wait-VMReady)
§1.1 — Migrate all WinRM connections from HTTP/5985 to HTTPS/5986
- Deploy post-install.ps1: remove AllowUnencrypted=true; self-signed cert + HTTPS listener
already present; firewall rule restricted to 192.168.79.0/24
- Setup-WinBuild2025.ps1: assert AllowUnencrypted=false
- Prepare-WinBuild2025.ps1: preflight uses TCP/5986; Test-WSMan -UseSSL -Port 5986;
New-PSSession -UseSSL -Port 5986; host AllowUnencrypted save/restore removed (not needed for HTTPS)
- Invoke-RemoteBuild, Get-BuildArtifacts: New-PSSession -UseSSL -Port 5986 -Authentication Basic
- Wait-VMReady: New-WSManSessionOption + Test-WSMan -Port 5986 -UseSSL
- Validate-DeployState, Validate-SetupState: Invoke-Command -UseSSL -Port 5986,
AllowUnencrypted check → false; AllowUnencrypted host-side removed from both
- Docs: PLAN, README, ARCHITECTURE, BEST-PRACTICES, HOST-SETUP, WINDOWS-TEMPLATE-SETUP,
LINUX-TEMPLATE-SETUP, TODO updated
§1.3 — SHA256 hash pinning infrastructure
- Assert-Hash function + $script:Hashes hashtable added to Setup-WinBuild2025.ps1
- Assert-Hash called after dotnet-install.ps1, python installer, vs_buildtools.exe downloads
- Hashes initialized to '' (warn-skip); must be filled before next snapshot refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
|
||||
[ValidatePattern('^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$')]
|
||||
[string] $IPAddress,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
@@ -67,10 +67,13 @@ $sessionOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationC
|
||||
|
||||
Write-Host "[Get-BuildArtifacts] Connecting to VM at $IPAddress..."
|
||||
$session = New-PSSession `
|
||||
-ComputerName $IPAddress `
|
||||
-Credential $Credential `
|
||||
-SessionOption $sessionOptions `
|
||||
-ErrorAction Stop
|
||||
-ComputerName $IPAddress `
|
||||
-Credential $Credential `
|
||||
-SessionOption $sessionOptions `
|
||||
-UseSSL `
|
||||
-Port 5986 `
|
||||
-Authentication Basic `
|
||||
-ErrorAction Stop
|
||||
|
||||
try {
|
||||
# ── Verify artifact exists in guest ──────────────────────────────────
|
||||
|
||||
@@ -103,7 +103,7 @@ param(
|
||||
|
||||
[string] $ArtifactBaseDir = 'F:\CI\Artifacts',
|
||||
|
||||
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
|
||||
[ValidatePattern('^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$')]
|
||||
[string] $VMIPAddress = '', # if empty, auto-detected via vmrun getGuestIPAddress
|
||||
|
||||
[string] $GuestCredentialTarget = 'BuildVMGuest',
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
|
||||
[ValidatePattern('^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$')]
|
||||
[string] $IPAddress,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
@@ -85,10 +85,13 @@ $sessionOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationC
|
||||
Write-Host "[Invoke-RemoteBuild] Connecting to VM at $IPAddress..."
|
||||
|
||||
$session = New-PSSession `
|
||||
-ComputerName $IPAddress `
|
||||
-Credential $Credential `
|
||||
-SessionOption $sessionOptions `
|
||||
-ErrorAction Stop
|
||||
-ComputerName $IPAddress `
|
||||
-Credential $Credential `
|
||||
-SessionOption $sessionOptions `
|
||||
-UseSSL `
|
||||
-Port 5986 `
|
||||
-Authentication Basic `
|
||||
-ErrorAction Stop
|
||||
|
||||
try {
|
||||
# ── Ensure working directories exist on guest ────────────────────────
|
||||
|
||||
@@ -40,7 +40,7 @@ param(
|
||||
[string] $VMPath,
|
||||
|
||||
[Parameter(Mandatory)]
|
||||
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}$')]
|
||||
[ValidatePattern('^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$')]
|
||||
[string] $IPAddress,
|
||||
|
||||
[ValidateRange(30, 600)]
|
||||
@@ -52,7 +52,7 @@ param(
|
||||
[string] $VmrunPath = 'C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe',
|
||||
|
||||
# Skip ICMP ping phase (phase 2). Useful when the guest firewall blocks ICMP
|
||||
# but WinRM (TCP 5985) is open. Phase 1 (vmrun state) and phase 3 (WinRM)
|
||||
# but WinRM (TCP 5986) is open. Phase 1 (vmrun state) and phase 3 (WinRM)
|
||||
# are still checked.
|
||||
[switch] $SkipPing
|
||||
)
|
||||
@@ -68,6 +68,7 @@ $deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
||||
$attempt = 0
|
||||
$phase = 'vmrun-state' # tracks current phase for informative output
|
||||
$lastPhase = ''
|
||||
$wsmOpt = New-WSManSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck
|
||||
|
||||
Write-Host "[Wait-VMReady] Waiting for VM ready (timeout: ${TimeoutSeconds}s, IP: $IPAddress)..."
|
||||
|
||||
@@ -109,7 +110,7 @@ while ((Get-Date) -lt $deadline) {
|
||||
|
||||
# ── Phase 3: WinRM responsive ────────────────────────────────────────
|
||||
try {
|
||||
Test-WSMan -ComputerName $IPAddress -ErrorAction Stop | Out-Null
|
||||
Test-WSMan -ComputerName $IPAddress -Port 5986 -UseSSL -SessionOption $wsmOpt -ErrorAction Stop | Out-Null
|
||||
# Success — VM is ready
|
||||
Write-Host "[Wait-VMReady] VM ready after ~$([int]($attempt * $PollIntervalSeconds))s (attempt $attempt)."
|
||||
return
|
||||
@@ -117,7 +118,7 @@ while ((Get-Date) -lt $deadline) {
|
||||
catch {
|
||||
$phase = 'winrm'
|
||||
if ($lastPhase -ne $phase) {
|
||||
Write-Host "[Wait-VMReady] Phase 3/3: ping OK, waiting for WinRM on port 5985..."
|
||||
Write-Host "[Wait-VMReady] Phase 3/3: ping OK, waiting for WinRM on port 5986 (HTTPS)..."
|
||||
$lastPhase = $phase
|
||||
}
|
||||
Start-Sleep -Seconds $PollIntervalSeconds
|
||||
|
||||
Reference in New Issue
Block a user