Monitor: drop AESFMA-connected from Phase 1 done; webapp: LAPS endpoint
1. Phase 1 done gate was requiring 'AESFMA WLAN connected' in addition to the data-side signals (AAD + Intune + EmTask + baseline). If the bay never reached AESFMA (cert never landed, RADIUS unreachable), Phase 1 stayed IN PROGRESS forever even though Intune registration was actually complete. Reverting to the data-side-only definition. 2. New webapp endpoint POST /imaging/<serial>/laps stores a LAPS password in the session JSON so it survives the 5s dashboard auto-refresh. Empty body clears the field. Daily reset of the server (cron/restart) is the lifetime cap on stored passwords. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -860,27 +860,13 @@ function Format-Snapshot {
|
|||||||
# not just "arriving". Stops the category prompt firing pre-first-reboot
|
# not just "arriving". Stops the category prompt firing pre-first-reboot
|
||||||
# when only ~4 subkeys are present (we tested this empirically; clicking
|
# when only ~4 subkeys are present (we tested this empirically; clicking
|
||||||
# "assign category" at 4 subkeys = imaging stalls + re-image required).
|
# "assign category" at 4 subkeys = imaging stalls + re-image required).
|
||||||
# AESFMA connected = bay has a live corp WLAN association on the
|
|
||||||
# machine-auth profile. That's the natural ground-truth that Phase 1
|
|
||||||
# is operationally done (not just the data-side flags). Check the
|
|
||||||
# WLAN state via netsh wlan show interfaces - look for SSID=AESFMA
|
|
||||||
# with state=connected.
|
|
||||||
$aesfmaConnected = $false
|
|
||||||
try {
|
|
||||||
$wlanOut = netsh wlan show interfaces 2>$null
|
|
||||||
if ($wlanOut -match '(?ms)SSID\s*:\s*AESFMA.*?State\s*:\s*connected') {
|
|
||||||
$aesfmaConnected = $true
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
$p1Done = ($Snap.Phase1.AzureAdJoined -and $Snap.Phase1.IntuneEnrolled -and
|
$p1Done = ($Snap.Phase1.AzureAdJoined -and $Snap.Phase1.IntuneEnrolled -and
|
||||||
$Snap.Phase1.EmTaskExists -and $Snap.Phase1.PoliciesBaselineReady -and
|
$Snap.Phase1.EmTaskExists -and $Snap.Phase1.PoliciesBaselineReady)
|
||||||
$aesfmaConnected)
|
|
||||||
$p1Status = Get-PhaseStatus @(
|
$p1Status = Get-PhaseStatus @(
|
||||||
@{ Ok = $Snap.Phase1.AzureAdJoined; Failed = $false },
|
@{ Ok = $Snap.Phase1.AzureAdJoined; Failed = $false },
|
||||||
@{ Ok = $Snap.Phase1.IntuneEnrolled; Failed = $false },
|
@{ Ok = $Snap.Phase1.IntuneEnrolled; Failed = $false },
|
||||||
@{ Ok = $Snap.Phase1.EmTaskExists; Failed = $false },
|
@{ Ok = $Snap.Phase1.EmTaskExists; Failed = $false },
|
||||||
@{ Ok = $Snap.Phase1.PoliciesBaselineReady; Failed = $false },
|
@{ Ok = $Snap.Phase1.PoliciesBaselineReady; Failed = $false }
|
||||||
@{ Ok = $aesfmaConnected; Failed = $false }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Phase 6 / Lockdown (shared by both flows, rendered last).
|
# Phase 6 / Lockdown (shared by both flows, rendered last).
|
||||||
|
|||||||
@@ -495,6 +495,29 @@ def imaging_delete_session(serial):
|
|||||||
return redirect(url_for("imaging_dashboard"))
|
return redirect(url_for("imaging_dashboard"))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/imaging/<serial>/laps", methods=["POST"])
|
||||||
|
def imaging_set_laps(serial):
|
||||||
|
"""Save (or clear with empty value) the LAPS password for a bay so it
|
||||||
|
survives the dashboard's 5s auto-refresh. JSON body: {"password": "..."}.
|
||||||
|
Empty string removes the field. Daily reset wipes natural risk."""
|
||||||
|
serial = secure_filename(serial)
|
||||||
|
body = request.get_json(silent=True) or {}
|
||||||
|
pw = body.get("password", "")
|
||||||
|
if not isinstance(pw, str):
|
||||||
|
return {"ok": False, "error": "password must be string"}, 400
|
||||||
|
if pw == "":
|
||||||
|
# Clear by direct read-modify-write since update_session skips empty values.
|
||||||
|
state = imaging_status.get_session(serial) or {}
|
||||||
|
if "laps_password" in state:
|
||||||
|
state.pop("laps_password", None)
|
||||||
|
# Re-feed everything (minus laps_password) through update_session.
|
||||||
|
state["serial"] = serial
|
||||||
|
imaging_status.update_session(state)
|
||||||
|
return {"ok": True, "cleared": True}
|
||||||
|
imaging_status.update_session({"serial": serial, "laps_password": pw})
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Routes - Enrollment Packages
|
# Routes - Enrollment Packages
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user