PAM: Path B actuator, secure-desktop dialog, console redesign, and remote-session privacy fixes#2588
Merged
Merged
Conversation
AP-forward successor to the SendInput/consent.exe actuator (Path A): suppress consent.exe, then launch the target elevated AS ~breeze_elev via LogonUser → CreateProcessAsUser (runas model). Ships dark behind pam_actuator_strategy: token_launch (defaults to sendinput). Core: - pam_actuator_strategy config; pamactuator.Strategy/NewWithStrategy; tokenLaunchActuator (suppress-then-launch orchestration + testable seams); heartbeat strategy selection; target path/cmdline plumbing into actuate_elevation; guaranteed-demote-on-failure. - winTokenLauncher.Launch raw Win32 layer, hardware-validated: UAC split-token → linked elevated token; CREATE_NEW_CONSOLE; two-stage SYSTEM-into-session helper for desktop-DACL/paint (MaybeRunSessionLaunchHelper). - MaybeRunSessionLaunchHelper() called first in agent Main(); non-windows no-op stub so cross-platform builds compile. elevation_requests.subject_username already NOT NULL): - Request.SubjectUsername + reserved SubjectSessionID; pamTarget/actuatePayload carry it; RunPamFlow passes ev.SubjectUsername; actuateElevation.ts echoes the stored subject_username. Resolver: explicit session (reserved) → username→live session (WTSEnumerateSessions/WTSQuerySessionInformation) → console fallback. Precedence in the CI-tested platform-neutral session_resolve.go. Validated on hardware (Win11 dell70601 + Server VM): Case A (console, elevated, paints) and Case E (RDP — resolver auto-selected the requesting user's session). Diagnostic scaffolding (diag_windows.go, cmd/pamlaunchtest) is retained for validation and stripped pre-PR. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Align the /pam console with the app-wide design system: shared ui.tsx primitives (house table chrome, skeleton loading, empty states, unified buttons, status/risk badges, pager, switch), visible dialog headers on all PAM modals, sectioned rule form (Match criteria / Time window), and consistent filter/toolbar styling. All data-testids, roles, exports, and i18n keys preserved; two new pamPamRuleModal.sections keys added across all five locales. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The rule form was a 90vh scroll region with Cancel/Create below the fold and no visible scrollbar, so the modal read as cut off. Widen it to 2xl, cap at 85vh, and pin the action footer (rule + signer-group modals) so only the field area scrolls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the bare MessageBoxW elevation prompt with a purpose-built Win32 window: shield icon + program headline, aligned field grid (now including the command line), a live expiry countdown with progress bar, and Deny-default/Approve buttons. Raw user32/gdi32 only, so it remains legal on the Winlogon secure desktop; any window-creation failure falls back to the original MessageBox so an elevation prompt can never be swallowed. The prompt now also self-dismisses (deny, not user-dismissed) when the request's broker timeout lapses instead of lingering forever. Shared content helpers (headline, field list, fallback body, countdown format) move to an untagged file with unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The form still ran ~1050px tall. Shrink it to ~665px: negate toggles move inline with their field labels, Description shares a row with Scope, the Enabled checkbox and Preview button move into the pinned footer (the preview panel renders only once results exist), and the modal uses denser inputs and rhythm. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The viewer-token desktop WS offer handler (desktopWs.ts) built its start_desktop payload without the prompt block, so sessions started through the web viewer never showed the end-user 'technician connected' notice or the on-screen session indicator banner — despite the policy defaulting both on. Extract the prompt construction from the REST offer route into a shared buildRemoteSessionPromptPayload helper (lookups run in a system DB context so the context-less WS path can't silently read 0 rows under FORCE RLS) and attach it on both paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The API shipped technician identity nested under prompt.technicianDisplay, but every consumer (agent ipc.DesktopPrompt, assist app desktop.rs / ConsentDialog.tsx) deserializes flat technicianName/technicianEmail/orgName — so the banner and consent dialogs always fell back to 'A technician'. Ship the flat contract. Banner overhaul (Windows user-helper): Segoe UI text, live green dot, elapsed-session clock (1s timer), DPI-scaled pill sized to its label with fully rounded ends, and WS_EX_TRANSPARENT so the pill never swallows clicks. The show seam now carries the session start for the clock. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Windows toasts were raised under an unregistered AppUserModelID, which Server SKUs and recent Win11 builds accept and silently never display — the session connect/end notices never appeared. Register a per-user 'Breeze.Agent' AUMID (HKCU, branded 'Breeze') before showing toasts. The remote_access policy's five consent fields (session prompt mode, consent-unavailable behavior, session-end notice, active-session indicator, technician identity level) were fully wired server-side but had no UI. Add an 'End-user privacy & consent' section to the RemoteAccessTab, with locale strings for all five languages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
powershell -Command <script> <args> appends the extra argv tokens to the command TEXT instead of binding script params, so the toast script was a parse error on every invocation and no notification ever showed. Pass the toast XML via an environment variable, wrap the script in try/catch, and log the captured stderr so future failures are visible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploying breeze with
|
| Latest commit: |
fab68b7
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://47b357de.breeze-9te.pages.dev |
| Branch Preview URL: | https://toddhebebrand-pam-testing.breeze-9te.pages.dev |
…ting-3 # Conflicts: # agent/internal/heartbeat/pam_flow.go # agent/internal/pamactuator/actuator.go # agent/internal/sessionbroker/pam_approval_test.go # agent/internal/userhelper/pam_dialog_windows.go # docs/testing/FEATURE_TEST_LOG.md
- gofmt: re-align bareUsername test map after a longer key was added (session_resolve_test.go) - unused: move pamDialogTitle const from the cross-platform pam_dialog_content.go into the windows-only pam_dialog_windows.go — it is referenced only by the Win32 dialog + MessageBox renderings, so on the linux lint host it read as unused. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rolls up the PAM testing branch: the Path B token-launch actuator, the secure-desktop dialog work, a full redesign of the PAM web console and the Windows-side elevation/session UI, and four real bugs found while live-testing remote sessions against an enrolled Windows device.
Agent — elevation UX
MessageBoxW: shield icon, "x.exe is requesting elevation" headline, field grid (program / signer / user / command line), live expiry countdown with progress bar, Deny-default/Approve buttons. Raw user32/gdi32 only (secure-desktop safe), with a hard fallback to the original MessageBox so a prompt can never be swallowed. The prompt now auto-denies when the broker timeout lapses instead of lingering forever.WS_EX_TRANSPARENTso it never swallows clicks.Web — PAM console
/pamtabs on shared primitives (pam/ui.tsx): house table chrome, skeleton loading, proper empty states, unified buttons/badges/pager/switch.Bugs found live-testing and fixed
desktopWs.tsbuilt itsstart_desktoppayload without thepromptblock — only the REST route attached it. Prompt construction is now a sharedbuildRemoteSessionPromptPayloadhelper used by both paths (system DB context so the context-less WS handler can't silently read 0 rows under FORCE RLS), with a regression test on the WS payload.prompt.technicianDisplay, but the agent and assist app deserialize flattechnicianName/technicianEmail/orgName. The nested object was read by nothing. The API now ships the flat contract.powershell -Command <script> -xml <value>appends trailing argv to the command text (it does not bind script params), so the toast script was a parse error on every invocation. The XML now travels via an environment variable, the script is try/catch-wrapped, and stderr is captured into the helper log.Breeze.AgentAUMID (branded "Breeze") before showing toasts.Verification
astro checkclean. API: remote-session + desktopWs suites,tsc --noEmitclean. Agent:go test -raceon userhelper/sessionbroker/heartbeat,go vetand cross-compile for windows/amd64+arm64.🤖 Generated with Claude Code