From 520d4aa791b312077de56b044b18f64cc1e4db07 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Thu, 14 May 2026 20:06:00 -0400 Subject: [PATCH] Monitor: fix AESFMA-connected detection + stop retrying once connected Two bugs causing "AESFMA cert detected, connecting AESFMA..." to log over and over even after AESFMA is already up: 1. Regex 'SSID\s*:\s*AESFMA.*?State\s*:\s*connected' required SSID line BEFORE State line. Actual netsh wlan show interfaces order on Win11 is "Name / State / SSID" - State comes FIRST. The non- greedy match never succeeded. Always thought AESFMA wasn't connected. Refactor to a Test-AESFMAConnected helper that splits output into per-adapter blocks and checks SSID + State independently, tolerating either order. 2. Added a fast-path at top of the WiFi-swap block: if AESFMA is already connected (no help needed from us), just delete INTERNETACCESS if still present and flip the cache flag to stop running this block. Previously the block only set the flag after a successful connect-then-verify-then-delete cycle; if AESFMA was already up at first check, the cycle "succeeded" each tick but the flag never flipped, producing the log spam. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Shopfloor/lib/Monitor-IntuneProgress.ps1 | 88 +++++++++++-------- 1 file changed, 52 insertions(+), 36 deletions(-) diff --git a/playbook/shopfloor-setup/Shopfloor/lib/Monitor-IntuneProgress.ps1 b/playbook/shopfloor-setup/Shopfloor/lib/Monitor-IntuneProgress.ps1 index 573f30b..30ba257 100644 --- a/playbook/shopfloor-setup/Shopfloor/lib/Monitor-IntuneProgress.ps1 +++ b/playbook/shopfloor-setup/Shopfloor/lib/Monitor-IntuneProgress.ps1 @@ -330,49 +330,65 @@ function Get-Phase1 { $script:cache.EmTaskExists -and $policiesBaselineReady) if ($phase1Essential -and -not $script:cache.InternetAccessDeleted) { - # Step 1: deterministic check for the AESFMA machine cert. Walk - # every cert in LocalMachine\My and verify its chain ends at the - # GE RADIUS TrustedRootCA (thumbprint from AESFMA.xml). - # Thumbprint 27F0C9A22B28CE7687B115A29E31BF4B3ABB180F = GE - # Aerospace FreeRADIUS root. Cert chained to it = AESFMA-usable. - $aesfmaRootThumb = '27F0C9A22B28CE7687B115A29E31BF4B3ABB180F' - $hasAesfmaCert = $false - try { - foreach ($cert in (Get-ChildItem 'Cert:\LocalMachine\My' -ErrorAction SilentlyContinue)) { - $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain - $chain.ChainPolicy.RevocationMode = 'NoCheck' - $null = $chain.Build($cert) - foreach ($el in $chain.ChainElements) { - if ($el.Certificate.Thumbprint -eq $aesfmaRootThumb) { - $hasAesfmaCert = $true; break - } + # Helper: split netsh wlan show interfaces output into one block + # per adapter (delimited by lines starting with "Name :"), then + # check whether any block contains SSID=AESFMA AND State=connected + # in either order. + function Test-AESFMAConnected { + $out = netsh wlan show interfaces 2>$null | Out-String + if (-not $out) { return $false } + $blocks = ($out -split '(?ms)(?=^\s*Name\s*:\s*)') + foreach ($b in $blocks) { + if (($b -match 'SSID\s*:\s*AESFMA\b') -and ($b -match 'State\s*:\s*connected\b')) { + return $true } - if ($hasAesfmaCert) { break } } - } catch {} + return $false + } - if (-not $hasAesfmaCert) { - # SCEP hasn't delivered the GE-rooted machine cert yet. - # INTERNETACCESS stays put. Retry next tick. + # Fast path: AESFMA already connected (cert + WLAN service handled + # it without our help, or a prior tick connected). Delete + # INTERNETACCESS if still present, flip cache flag, stop trying. + if (Test-AESFMAConnected) { + Write-Host "AESFMA already connected - cleaning up INTERNETACCESS..." + $null = netsh wlan delete profile name="INTERNETACCESS" 2>&1 | Out-String + $script:cache.InternetAccessDeleted = $true } else { - # Step 2: cert is here, AESFMA EAP-TLS should succeed. Try - # the connect with INTERNETACCESS still up as fallback. + # Slow path: walk LocalMachine\My for any cert chained to the + # GE Aerospace FreeRADIUS root (thumbprint from AESFMA.xml). + $aesfmaRootThumb = '27F0C9A22B28CE7687B115A29E31BF4B3ABB180F' + $hasAesfmaCert = $false try { - Write-Host "AESFMA cert detected (chains to GE RADIUS root) - connecting AESFMA..." - $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 - $script:cache.InternetAccessDeleted = $true - } else { - Write-Host "AESFMA cert present but connect not yet operational - retry next tick." + foreach ($cert in (Get-ChildItem 'Cert:\LocalMachine\My' -ErrorAction SilentlyContinue)) { + $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain + $chain.ChainPolicy.RevocationMode = 'NoCheck' + $null = $chain.Build($cert) + foreach ($el in $chain.ChainElements) { + if ($el.Certificate.Thumbprint -eq $aesfmaRootThumb) { + $hasAesfmaCert = $true; break + } + } + if ($hasAesfmaCert) { break } + } + } catch {} + + if ($hasAesfmaCert) { + try { + Write-Host "AESFMA cert detected (chains to GE RADIUS root) - connecting AESFMA..." + $null = netsh wlan connect name="AESFMA" ssid="AESFMA" 2>&1 | Out-String + Start-Sleep -Seconds 8 + if (Test-AESFMAConnected) { + Write-Host "AESFMA connected. Deleting INTERNETACCESS profile..." + $null = netsh wlan delete profile name="INTERNETACCESS" 2>&1 | Out-String + $script:cache.InternetAccessDeleted = $true + } else { + Write-Host "AESFMA cert present but connect not yet operational - retry next tick." + } + } catch { + Write-Warning "AESFMA connect/swap attempt failed: $_" } - } catch { - Write-Warning "AESFMA connect/swap attempt failed: $_" } + # else: cert not delivered yet. INTERNETACCESS stays. Retry next tick. } } # idx=7 push fires AS SOON AS DeviceId is captured. We want the QR