Skip to content

feat(agent,agent-installer): add transactional policy store - #1963

Draft
Benoît Cortier (CBenoit) wants to merge 5 commits into
cbenoit-plan-agent-policy-endpointfrom
cbenoit-phase-2-policy-store
Draft

feat(agent,agent-installer): add transactional policy store#1963
Benoît Cortier (CBenoit) wants to merge 5 commits into
cbenoit-plan-agent-policy-endpointfrom
cbenoit-phase-2-policy-store

Conversation

@CBenoit

@CBenoit Benoît Cortier (CBenoit) commented Aug 29, 2026

Copy link
Copy Markdown
Member

Adds authenticated transactional package-policy management to Devolutions Agent, including deterministic validation, optimistic concurrency, atomic JSON persistence, secure path and ACL enforcement, and stable old-or-new runtime snapshots.

Adds structured tracing and Windows Event Log auditing, fail-closed watcher reconciliation, administrator and elevation enforcement for writes, and split unelevated/LocalSystem end-to-end coverage.

Stacked on #1937.
Final Gateway head: c1b72fe33b36dc1d80d79ee6d8d759d76ef9e275.
Shared contract: Devolutions/now-libraries#99 at ec592a91f95a66c8a79b7d612ed73d931ef74aeb.
Downstream integration: draft Devolutions/UniGetUI#5335 at 92e2d8c26ecefd0f9542909530aef228bcd1fa2f.
Validation: CI run 33254105745 passed all jobs.

Add authenticated policy management and validation for the package broker. Persist JSON policies atomically with secure path, ACL, concurrency, receipt, watcher, and audit checks while preserving stable runtime snapshots.

Stacked on #1937. Uses the contract from Devolutions/now-libraries#99. UniGetUI policy management depends on this API.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Implementation notes:

  • Replaces the watcher-owned policy mutation path with one serialized PolicyStore that publishes immutable Active/Missing/Invalid snapshots.
  • Uses the exact ec592a91f95a66c8a79b7d612ed73d931ef74aeb now-libraries contract, keyed validation receipts, opaque disk-state tokens, and explicit Create/Update/Repair/ReplaceIdentity semantics.
  • Restricts writable policy storage to securely resolved JSON paths with SYSTEM/Administrators-only protection, same-directory atomic publication, post-write verification, and synchronous post-publication reconciliation.
  • Requires the existing caller-signature validation plus actual elevation and enabled Administrators membership for writes; the development signature bypass does not bypass authorization.
  • Audits attempts and outcomes through structured tracing and the Agent Windows Event Log without policy content.
  • Validation completed: diff check and rustfmt; 409 default and 413 dev-skip broker tests passed except the existing host-specific Winget AppExecAlias DACL baseline; sysevent-codes (1), sysevent-winevent (8), and win-api-wrappers (25) tests passed; workspace check and Clippy with warnings denied passed; Agent debug and release message-resource builds passed; unelevated Agent policy E2E passed. LocalSystem E2E is wired into Windows CI but could not run in this medium-integrity shell because PsExec could not install PSEXESVC.

Note

Human-tuned, LLM-assisted content.

Resolve policy parents through held handles before comparing leaf names, reject multi-link files using link-count metadata, and run unelevated E2E under a verified restricted token.

Select one validated Windows message compiler path so release resource builds receive a usable SDK directory.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

CI repair update (be3a9edf):

  • Resolves the verified policy parent through its held handle before comparing the leaf, so 8.3 parent aliases and case-only leaf differences are accepted without weakening location checks.
  • Rejects policy files with multiple hard links using FILE_STANDARD_INFO.NumberOfLinks instead of relying on which link name GetFinalPathNameByHandleW reports.
  • Runs the unelevated E2E suite through PsExec -l; the tester now fails immediately unless its token is both non-elevated and lacks enabled Administrators membership. LocalSystem remains a separate mode.
  • Selects and validates one deterministic mc.exe result before exporting WindowsSdkVerBinPath.

Focused validation passed: 37 policy-store Windows tests, 3 token-wrapper tests, agent-policy-tester check, direct unelevated E2E with token assertion, rustfmt, diff check, and targeted Clippy with warnings denied. Workflow assertions for restricted launch and single message-compiler selection also passed; actionlint is not installed locally.

Note

Human-tuned, LLM-assisted content.

Run the low-integrity test workspace from LocalLow and stream PsExec output through the CI parent instead of writing into the protected checkout.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Follow-up CI repair (9c85810a): the restricted PsExec process could not create its transcript in the protected checkout. The wrapper now uses the user's low-integrity LocalLow\Temp directory for test artifacts and streams stdout/stderr back through the parent CI process, preserving the explicit non-elevated/non-admin token assertion and expected 403 behavior.

Local script parsing, workflow assertions, diff/rustfmt, agent-policy-tester check, and targeted Clippy passed.

Note

Human-tuned, LLM-assisted content.

Precreate a low-integrity writable transcript path and pass it explicitly to the restricted tester wrapper so CI can read child failures and results.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Verify that the restricted E2E token has disabled Administrators membership and cannot satisfy the same elevation-plus-membership gate used by policy writes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@CBenoit

Copy link
Copy Markdown
Member Author

Final CI status: run 33254105745 passed at c1b72fe33b36dc1d80d79ee6d8d759d76ef9e275, including the restricted unelevated and LocalSystem Agent policy E2E modes, Windows path/hardlink tests, and Agent release message-resource build. The worktree is clean and the pushed upstream SHA matches locally.

Note

Human-tuned, LLM-assisted content.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant