Monitor: AESFMA verify-before-delete - keep INTERNETACCESS until cert ready

Old gate (SCEP cert in LocalMachine\My with Client Auth EKU) was both
too loose (matches non-AESFMA certs) and unable to verify the cert
chains to GE's RADIUS root. INTERNETACCESS got deleted before AESFMA
could actually authenticate, orphaning the bay.

New flow: when Phase 1 essentials (AAD + Intune + EmTask + baseline)
are complete, ATTEMPT netsh wlan connect AESFMA with INTERNETACCESS
still up as fallback. Wait 8s, parse netsh wlan show interfaces for
SSID=AESFMA + State=connected. Only delete INTERNETACCESS after
operational verification. If AESFMA connect fails (cert not provisioned
yet, RADIUS server unreachable, etc), keep INTERNETACCESS and retry
next tick. Loop runs every 5s while DeviceIdReported is false, so the
swap fires as soon as AESFMA is operationally viable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-05-14 17:46:19 -04:00
parent a9260ecadd
commit f013aa2bff

View File

@@ -311,39 +311,35 @@ function Get-Phase1 {
# Once Intune registration is fully landed (AAD-joined + Intune-enrolled
# + EnterpriseMgmt task present + baseline policies arrived):
# - Push idx=7 to PXE dashboard with the DeviceId / QR.
# The INTERNETACCESS -> AESFMA WiFi swap is GATED SEPARATELY on the
# actual SCEP-provisioned machine cert landing in LocalMachine\My
# with Client Authentication EKU. Phase 1 essentials flip earlier
# than the cert delivery, and tearing INTERNETACCESS without the
# cert present leaves the bay with no path (AESFMA EAP-TLS would
# fail). Wait for the cert before swapping.
# The INTERNETACCESS -> AESFMA WiFi swap uses a VERIFY-BEFORE-DELETE
# pattern so the bay never ends up with no path:
# 1. Phase 1 essentials must be COMPLETE (Intune registration done).
# 2. Attempt netsh wlan connect AESFMA while INTERNETACCESS still up.
# 3. Wait ~8s, parse netsh wlan show interfaces for SSID=AESFMA +
# State=connected.
# 4. ONLY after operationally connected to AESFMA, delete INTERNETACCESS.
# 5. If connect fails (cert not provisioned yet, etc), keep
# INTERNETACCESS, retry next tick.
$phase1Essential = ($script:cache.AzureAdJoined -and
$script:cache.IntuneEnrolled -and
$script:cache.EmTaskExists -and
$policiesBaselineReady)
if (-not $script:cache.InternetAccessDeleted) {
# Look for any LocalMachine\My cert with Client Auth EKU
# (1.3.6.1.5.5.7.3.2). That's what AESFMA EAP-TLS uses.
$hasMachineClientAuthCert = $false
if ($phase1Essential -and -not $script:cache.InternetAccessDeleted) {
try {
$clientAuthEku = '1.3.6.1.5.5.7.3.2'
$hasMachineClientAuthCert = [bool](Get-ChildItem 'Cert:\LocalMachine\My' -ErrorAction SilentlyContinue |
Where-Object {
$_.EnhancedKeyUsageList.ObjectId -contains $clientAuthEku
} | Select-Object -First 1)
} catch {}
if ($hasMachineClientAuthCert) {
try {
Write-Host "SCEP machine cert detected - swapping WiFi: delete INTERNETACCESS, connect AESFMA..."
Write-Host "Phase 1 essentials complete - attempting AESFMA join (verify-before-delete)..."
$null = netsh wlan connect name="AESFMA" ssid="AESFMA" 2>&1 | Out-String
Start-Sleep -Seconds 8
$wlanState = netsh wlan show interfaces 2>$null | Out-String
if ($wlanState -match '(?ms)SSID\s*:\s*AESFMA.*?State\s*:\s*connected') {
Write-Host "AESFMA connected. Deleting INTERNETACCESS profile..."
$delOut = netsh wlan delete profile name="INTERNETACCESS" 2>&1 | Out-String
Write-Host $delOut
Start-Sleep -Seconds 2
$conOut = netsh wlan connect name="AESFMA" ssid="AESFMA" 2>&1 | Out-String
Write-Host $conOut
$script:cache.InternetAccessDeleted = $true
} catch {
Write-Warning "WiFi swap (INTERNETACCESS -> AESFMA) failed: $_"
} else {
Write-Host "AESFMA connect not yet operational - keeping INTERNETACCESS, will retry next tick."
}
} catch {
Write-Warning "AESFMA verify-before-delete attempt failed: $_"
}
}
# idx=7 push fires AS SOON AS DeviceId is captured. We want the QR