feat(sprint4): operational hardening, diagnostics, VMDK SHA256, runbook
Task 4.1: Invoke-CIJob.ps1 pre-clone disk gate (needs 10 GB free), JobId/ExtraGuestEnv
pattern validation, redacted command logger (already included via _Common.psm1).
Task 4.2: Get-GuestDiagnostics helper invoked from catch block (best-effort, no throw).
Task 4.3: UseSharedCache wired through composite action and orchestrator.
Task 4.4: SSH known_hosts in F:\CI\State\known_hosts for CI jobs; accept-new for templates.
Task 4.5: Deploy-LinuxBuild2404.ps1 verifies Ubuntu VMDK SHA256 before import.
Task 4.6: RUNBOOK.md consolidated template-refresh section: stop runner, backup, boot,
KMS reactivation, Prepare-*, shutdown, snapshot, Validate-DeployState, smoke,
update config, retain prior snapshot 7 days, rollback procedure.
Validate-SetupState.ps1: minor lint fixes and docblock updates.
Wait-VMReady.ps1: Get-BuildArtifacts.ps1: hardening alignment with Sprint 4 objectives.
This commit is contained in:
@@ -79,6 +79,11 @@
|
||||
.PARAMETER VmdkCachePath
|
||||
Local cache path for the downloaded VMDK. Reused across runs.
|
||||
|
||||
.PARAMETER VmdkSha256
|
||||
Expected SHA256 hex digest of the cached VMDK file (case-insensitive).
|
||||
When non-empty the script throws if the computed hash does not match.
|
||||
Leave empty to skip hash verification (useful during development).
|
||||
|
||||
.PARAMETER SeedIsoPath
|
||||
Path for the cloud-init seed ISO. Default: <VMDir>\cloud-init-seed.iso.
|
||||
|
||||
@@ -136,6 +141,9 @@ param(
|
||||
[string] $SshKeyPath = 'F:\CI\keys\ci_linux',
|
||||
[string] $VmdkUrl = 'https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.vmdk',
|
||||
[string] $VmdkCachePath = 'F:\CI\ISO\noble-server-cloudimg-amd64.vmdk',
|
||||
# Expected SHA256 of the downloaded VMDK (hex, case-insensitive).
|
||||
# Leave empty to skip hash verification (not recommended for production).
|
||||
[string] $VmdkSha256 = '',
|
||||
[string] $SeedIsoPath = '',
|
||||
[int] $SshTimeoutSeconds = 300,
|
||||
[int] $SshPollIntervalSeconds = 10,
|
||||
@@ -376,6 +384,16 @@ if (-not (Test-Path $VmdkCachePath)) {
|
||||
}
|
||||
Assert-Step 'PreFlight' "Cloud VMDK cache present: $VmdkCachePath" { Test-Path $VmdkCachePath }
|
||||
|
||||
# Step 1c -- Verify VMDK SHA256 (when caller provides expected hash)
|
||||
if ($VmdkSha256 -ne '') {
|
||||
Write-Host "[Deploy] Verifying VMDK SHA256 ..."
|
||||
$actualHash = (Get-FileHash -LiteralPath $VmdkCachePath -Algorithm SHA256).Hash
|
||||
if ($actualHash -ne $VmdkSha256.ToUpper()) {
|
||||
throw "[Deploy] VMDK SHA256 mismatch!`n Expected: $($VmdkSha256.ToUpper())`n Actual: $actualHash"
|
||||
}
|
||||
Write-Host "[Deploy] VMDK SHA256 OK: $actualHash"
|
||||
}
|
||||
|
||||
} # end Step 1
|
||||
|
||||
# =============================================================================
|
||||
@@ -676,4 +694,4 @@ Write-Host " Next steps (from template\ dir):"
|
||||
Write-Host " .\Prepare-LinuxBuild2404.ps1 -VMXPath '$VMXPath' -VMIPAddress $guestIP"
|
||||
Write-Host ""
|
||||
Write-Host " VM is powered on. cloud-init provisioning complete." -ForegroundColor Green
|
||||
|
||||
|
||||
|
||||
@@ -185,7 +185,8 @@ try {
|
||||
(Get-LocalUser -Name $BuildUsername -EA Stop).Enabled
|
||||
}
|
||||
Chk "user $BuildUsername PasswordNeverExpires" {
|
||||
(Get-LocalUser -Name $BuildUsername -EA Stop).PasswordExpires -eq $null
|
||||
$u = Get-LocalUser -Name $BuildUsername -EA Stop
|
||||
(-not $u.PasswordExpires) -or ($u.PasswordExpires -eq [datetime]::MaxValue)
|
||||
}
|
||||
Chk "user $BuildUsername member of Administrators" {
|
||||
[bool](& net localgroup Administrators 2>&1 | Select-String -SimpleMatch $BuildUsername)
|
||||
@@ -369,7 +370,7 @@ try {
|
||||
Chk 'WU GPO DisableWindowsUpdateAccess=1' { (Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' -Name DisableWindowsUpdateAccess -EA Stop).DisableWindowsUpdateAccess -eq 1 }
|
||||
Chk "user $BuildUsername exists" { $null -ne (Get-LocalUser -Name $BuildUsername -EA Stop) }
|
||||
Chk "user $BuildUsername enabled" { (Get-LocalUser -Name $BuildUsername -EA Stop).Enabled }
|
||||
Chk "user $BuildUsername PasswordNeverExpires" { (Get-LocalUser -Name $BuildUsername -EA Stop).PasswordExpires -eq $null }
|
||||
Chk "user $BuildUsername PasswordNeverExpires" { $u = Get-LocalUser -Name $BuildUsername -EA Stop; (-not $u.PasswordExpires) -or ($u.PasswordExpires -eq [datetime]::MaxValue) }
|
||||
Chk "user $BuildUsername member of Administrators" { [bool](& net localgroup Administrators 2>&1 | Select-String -SimpleMatch $BuildUsername) }
|
||||
foreach ($dir in 'C:\CI\build','C:\CI\output','C:\CI\scripts') { Chk "$dir exists" { Test-Path $dir -PathType Container } }
|
||||
Chk ".NET SDK channel $DotNetChannel" { $v=(& dotnet --version 2>&1) -as [string]; $v -and $v.StartsWith($DotNetChannel) }
|
||||
|
||||
Reference in New Issue
Block a user