Skip to content

[AlertZero] Proposal step RBAC and supersededBy - #290706

Draft
patrykkopycinski wants to merge 2 commits into
alertzero/action-catalogfrom
alertzero/proposal-rbac-supersededby
Draft

[AlertZero] Proposal step RBAC and supersededBy#290706
patrykkopycinski wants to merge 2 commits into
alertzero/action-catalogfrom
alertzero/proposal-rbac-supersededby

Conversation

@patrykkopycinski

@patrykkopycinski patrykkopycinski commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements parts 1 and 3 of security-team#19287 — the RBAC and schema half of proposal safety, on top of #290705.

  • Privilege gate on proposal step handlers. investigations.createProposal and investigations.updateProposal now verify the execution's own credentials hold manage_proposals (via security.authz.checkPrivilegesWithRequest(fakeRequest).atSpace(...)) before forwarding to ProposalsService, failing closed on check errors. Mirrors the requiredPrivileges enforcement the HTTP routes already apply — previously any workflow able to resolve the step definition could create or mutate proposals regardless of the caller's privileges.
  • supersededBy field. Added to the proposal schema (zod), create params (immutable, worker-irrelevant), and storage mapping (keyword). ProposalsService.update persists it alongside a failed transition; listByWindow now filters must_not: exists: supersededBy so a recovery chain shows only the live proposal (resolves the pre-wired TODO(Flaky test: visualize lab mode disabling does not break loading saved searches #19258)).
  • security added to agenticInvestigations requiredPlugins (required for checkPrivilegesWithRequest), threaded to the step definitions via a start-resolved getter, matching the context-engine pattern.

Part 2 (clone-based failure recovery writing supersededBy) lands in a follow-up stacked on this PR.

Implementation notes

  • The privilege check uses the serialized form security.authz.actions.api.get('manage_proposals') — the bare string never matches for API-key credentials (api_authorization.ts routes all checks through actions.api.get). Unit-test mock mirrors the serializer so a bare-string regression fails tests.
  • Denial fails the step with ProposalsAuthorizationError → execution failed; grant parks the proposal on the gate as before. Dismissal stays terminal (no clone path in this PR).

End-to-end verification

Dedicated stack (own ES + Kibana, security on), driving the managed system-create-investigation-proposal workflow over HTTP with API keys whose role descriptors grant exactly the privileges under test:

Caller privileges Execution outcome Proposal stored
feature_workflowsManagement.all only failedProposalsAuthorizationError: lacks manage_proposals privilege in space [default] none
+ api:manage_proposals waiting_for_input (parked on approval gate) created, status: pending, expiresAt carried

Gate mutation-tested: removing the assertManageProposals call turns both denial tests red; restoring returns 103/103 green.

Testing

  • step_types.test.ts: gate denial (service never called), fail-closed on check error, pass-through on grant; serializer-accurate security mock
  • proposals_service.test.ts: supersededBy persisted on failed transition, rejected on settled proposals, excluded by listByWindow
  • plugin.test.ts: step definitions registered with security getter; privilege gates wired
  • Full suite 103/103, tsc 0 errors, ESLint clean

@infra-vault-gh-plugin-prod

Copy link
Copy Markdown
🤖 Jobs for this PR can be triggered through checkboxes. 🚧

ℹ️ To trigger the CI, please tick the checkbox below 👇

  • Click to trigger kibana-pull-request for this PR!
  • Click to trigger kibana-deploy-project-from-pr for this PR!
  • Click to trigger kibana-deploy-cloud-from-pr for this PR!
  • Click to trigger kibana-entity-store-performance-from-pr for this PR!
  • Click to trigger kibana-storybooks-from-pr for this PR!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant