Onboards Alerting Plugin to Centralized Resource Authz - #2180
Conversation
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
5ad666c to
9a6e142
Compare
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
9a6e142 to
b8fba5f
Compare
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
2f06126 to
2576e6b
Compare
…bled Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Skip backend-role validation, permission checks, and filter injection across all transport actions when the resource-sharing client is set. For primary resources (monitors, workflows), rely on the security plugin's DLS at the index layer. For subordinate resources (comments), scope results by accessible monitor IDs via getAccessibleResourceIds. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
…fFoundError Storing the RSC accessor result in a local val that lambdas close over forces the JVM to link ResourceSharingClient when the closure is created. Without the security plugin installed at runtime that class is absent, crashing the node with NoClassDefFoundError. Call the accessor fresh inside the lambda instead. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
| return setOf( | ||
| object : ResourceProvider { | ||
| override fun resourceType(): String = "monitor" | ||
| override fun resourceIndexName(): String = SCHEDULED_JOBS_INDEX |
There was a problem hiding this comment.
How about alerts and comments which are stored in different indices?
There was a problem hiding this comment.
Alerts and comments are treated as subordinate resources rather than registered resource types, so we don't register their indices with the sharing framework. Instead, access is inherited from the underlying monitor:
TransportGetAlertsAction/TransportGetWorkflowAlertsActioncallrsc.getAccessibleResourceIds("monitor", ...)and add amonitor_idterms filter to the alert search.TransportSearchAlertingCommentActiondoes the same via alert IDs derived from accessible monitors.TransportIndexAlertingCommentAction/TransportDeleteAlertingCommentActionrely on the ActionFilter blocking the underlying alert fetch (viaDocRequeston the requests, which points at the monitor).
New tests bob cannot see alice's monitor alerts without share and bob can see alice's monitor alerts after share in SecureResourceSharingMonitorRestApiIT cover this.
resource sharing is enabled Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Rewrites SecureResourceSharingMonitorRestApiIT to exercise the full matrix of security plugin ActionFilter paths that DocRequest enables: - GET / UPDATE / DELETE with insufficient and sufficient share levels - SEARCH DLS filtering per user - alerts subordinate to monitor share via getAccessibleResourceIds - SHARE and REVOKE round-trips Users no longer carry all_access so RSC is the sole authorization gate. Also updates existing unit tests to pass the new PluginClient constructor parameter on the affected transport actions. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
|
Heads up: CI on this branch will fail until common-utils#980 merges. That PR adds |
…s-load time Store the client as Any? and return Any? from getResourceSharingClient() so the JVM does not resolve ResourceSharingClient when loading the accessor class. This prevents NoClassDefFoundError in test clusters that run without the security plugin installed. Callers cast to ResourceSharingClient inside null-guarded blocks where the security plugin is guaranteed to be present. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
- Introduce ResourceSharingUtils with MONITOR_RESOURCE_TYPE constant and shouldUseResourceAuthz() helper, mirroring reporting plugin's pattern. - Replace all `rsc != null` / `rsc == null` checks in transport actions with shouldUseResourceAuthz() so admin flows (and non-RSC deployments) fall through to the existing filter-by-backend-roles path when the security plugin is present but the RSC feature flag is disabled. - Move the "monitor" literal out of every call site into a single constant referenced by both the extension and the utility helper. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Adds tests for scenarios missing from the initial suite: - read-write share: can delete but cannot re-share (share permission belongs only to full-access) - read-write share: owner sees edits made by the shared user - full-access share: owner sees the deletion made by the shared user Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Reorganizes the suite around scenarios rather than API surfaces and adds coverage for cases the earlier version missed: - Owner-side positive controls (owner can always get / update / delete) - Default-deny on every mutating action (get, update, delete, re-share) - Explicit per-access-level positive and negative assertions (read-only, read-write, full-access) including "read-write cannot re-share" — the share permission belongs only to full-access - Third-user isolation: share to bob does not grant carol access - Cross-resource isolation: share on monitor A does not grant access to B - Search DLS visibility (owned, shared, other-users') - Subordinate resources: alerts and comments inherit monitor access; acknowledge and comment require read-write - Downgrade: re-sharing at a lower level narrows permissions - Revoke: removes access; does not affect other users' shares Also introduces carol as a third user and switches to constants (RS_ALICE/RS_BOB/RS_CAROL, READ_ONLY/READ_WRITE/FULL_ACCESS) to keep assertions readable. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
- Map all three users (alice, bob, carol) to alerting_full_access in a
single PUT rolesmapping call; the previous per-user PUTs replaced each
other, leaving only the last-created user with the role.
- Create a shared test index and grant all three users index-level read
access to it, then point the sample monitor's SearchInput at that
index. Without this the monitor create fails at the security plugin's
index-permission check ("User doesn't have read permissions for one or
more configured index []").
- Clean up the test index and its role/rolesmapping in @after.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Removes the default parameter and updates every call site to pass ResourceSharingUtils.MONITOR_RESOURCE_TYPE explicitly. Forces callers to state which resource type they are gating on and future-proofs against alerting registering additional resource types. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
…framework collision
flow-framework already registers a resource type named "workflow" in the shared
resource-sharing registry, so alerting must use a distinct identifier. Rename the
resource type (not the stored doc wrapper key, JSON paths, or transport action
names) from "workflow" to "alerting-workflow":
- ResourceSharingUtils.WORKFLOW_RESOURCE_TYPE constant (propagates to all
workflow transport actions and AlertingResourceSharingExtension.resourceType())
- resource-access-levels.yml top-level type key
- integTest protected_types cluster setting
- extension unit-test assertions and the RSC migrate E2E test's protected_types
and default_access_level map key
typeField()/ownerNamePath() ("/workflow/...") and the cluster:*/workflow/* action
names are unchanged -- they reference the stored ScheduledJob doc structure and
action registry, not the resource-sharing type.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Two fixes surfaced once CI could finally compile (security-spi snapshot caught up with #6323), which exposed the security-enabled WorkflowRestApiIT delete tests: 1. TransportDeleteWorkflowAction restored the caller's ThreadContext in the delete coroutine, making the handler's config-index reads/deletes run as the caller. With resource sharing OFF the caller can't touch that system index (spurious 404 "Workflow not found"); with it ON a caller read races the async share-entry write. The restore was unnecessary: the security plugin's ResourceIndexListener.postDelete cleans up the share entry by resource id only and never reads the caller. Drop the restore so the handler runs on the plugin subject (as it did before RSC onboarding); postDelete cleanup still fires on the shard-level delete regardless of initiator. 2. Under resource sharing, GET-ing a just-deleted workflow/monitor returns 403 (the RSC gate denies once the sharing entry is gone) rather than 404. The post-delete verification in the three delete-workflow tests now accepts either via a shared assertDeletedNotAccessible helper -- both mean "no longer accessible" -- mirroring the pattern already used in the secure monitor ITs. Verified locally against fixed common-utils + security deps: all three delete tests pass in both the plain security and resource-sharing-enabled variants. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
The security workflow ran the full IT suite (--tests '*IT') under both the resource-sharing-disabled and -enabled variants. The backend-role / filterByAccessStrategy secure suites (e.g. SecureMonitorRestApiIT) and the general functional ITs assume the pre-resource-sharing access model, so they fail spuriously under RSC (monitor GET/HEAD/DELETE now requires a sharing entry rather than a backend role). Resource-sharing access is covered by its own dedicated suites. Run the pre-RSC/functional suites only when resource sharing is OFF, and run only the resource-sharing-specific suites (SecureResourceSharingMonitorRestApiIT, RscMigrateE2ERestApiIT -- both already gated on the feature via assumeTrue) when it is ON. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Review: opensearch-project/alerting PR #2180 — Onboards Alerting Plugin to Centralized Resource AuthzOverall this is a well-executed onboarding. The ThreadContext choreography (capture-before-stash → restore for the shard-level A few items below, roughly in priority order. 1. Bug:
|
…, comments stash Review feedback on opensearch-project#2180 (riysaxen-amzn): - Super-admin visibility: the RSC filter branch preceded the `user == null` (super-admin) branch in the alerts/workflow-alerts/comment-search/destinations read paths, so a super-admin got filtered to only shared resources. Check `user == null` first so super-admin (and the security-disabled case) sees everything even under resource sharing. - Bug: getAccessibleAlertIDs (and the legacy getFilteredAlertIDs) never set a search size, capping alert resolution at the default 10 and silently dropping comments for alerts beyond the first 10. Set size to MAX_SEARCH_SIZE. - rbac_roles hardening: validation was skipped under RSC. Since the feature flag is dynamic, validate caller-supplied rbac_roles regardless of RSC so a non-admin can't persist roles they don't hold that would gate access if RSC is later disabled. - Comments-history index bootstrap now runs on the plugin subject (stashed in the comment index action's start()); previously a non-admin caller's indices().exists() threw under RSC and the request hung. - Destinations: super-admin now runs a direct (non-DLS) search so it isn't filtered by the resource-sharing DLS path. - Document the index.max_terms_count bound at the monitor/workflow-id term filters; derive the sharing index name from the config index constant in test helpers rather than hardcoding. Subordinate-resource alert/comment access tests remain @ignore'd pending the child-resource sharing model in opensearch-project/security#6373 (updated the FIXMEs to reference it). Verified SecureResourceSharingMonitorRestApiIT: 31 tests, 3 skipped, 0 failures under the resource-sharing variant. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
PR Code Analyzer ❗AI-powered 'Code-Diff-Analyzer' found issues on commit 30a7584. ⛔ Hard block: Issues at High severity or above will block this PR from merging.
The table above displays the top 10 most important findings. Pull Requests Author(s): Please update your Pull Request according to the report above. Repository Maintainer(s): You can Thanks. |
|
Thanks @riysaxen-amzn — addressed in ad0fbb9:
The subordinate-resource alert/comment access tests stay Verified |
|
Thanks @DarshitChanpura — verified ad0fbb9 against each item and everything checks out:
On #4: agreed, accepting your reasoning. Good to see the The remaining Code-Diff-Analyzer High findings look like inherent-to-onboarding dependency flags (security-spi compile dep, unconditional security zip, common_utils tracking opensearch_build) rather than defects — presumably a maintainer |
Dominant (~most failures): ParsingException: expecting token of type [END_OBJECT] but found [FIELD_NAME] → 500 on monitor GET/PUT. This is the security plugin's injected top-level field (all_shared_principals — the PR itself added it to the scheduled-jobs mapping) appearing in the doc _source, and ScheduledJob.parse choking on the unexpected extra field. The PR hardened JobSweeper.isSweepableJobType for exactly this, but not the transport GET/update parse path — that's the gap. |
…ch-project#984 + opensearch-project#981 Common-utils 3.8 now includes the order-independent ScheduledJob.parse (that tolerates security's ancillary all_shared_principals field) and the DocRequest.type() overrides on alerting request classes (so the security plugin's ResourceAccessEvaluator actually gates transport GET/DELETE/etc. under RSC). Empty commit to force the fresh 3.8.0.0-SNAPSHOT to be pulled on the next CI run. Refs: opensearch-project/common-utils#998 Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
security#6373 (child-resource sharing) merged, so the three subordinate- resource tests no longer need to be ignored. Enabling them surfaced two real gaps that are now fixed: - Alert GET inheritance: GetAlertsRequest already reports type()=monitor / id()=monitorId, so the security ResourceAccessEvaluator gates a by-monitor alerts GET as a monitor access check (a read-only share grants it, no share is 403 before the transport action runs). But TransportGetAlertsAction then executed the alert-index search under the *caller's* restored context, so a read-only-shared, non-owner caller (no direct perms on the system alerts index) got a 500. Run the search on the plugin subject instead; the monitor_id filter, bounded to the caller's accessible monitors, is the resource-sharing boundary. - Comment create: the comment request targets the comments index (not the monitor) so the evaluator does not gate it, and the transport action skipped its own check under RSC — any caller could comment on any alert. Gate the create on the caller's access to the parent monitor via ResourceSharingClient.verifyAccess with the comment write action (granted only at read-write / full-access). Comment delete already restricts to the author/admin, so it needs no change. Un-ignores 'test alerts inherit access when monitor is shared read-only', 'test comment on alert denied without share', and 'test comment on alert allowed with read-write share'. Full SecureResourceSharingMonitorRestApiIT suite: 31 passed, 0 skipped, 0 failed under -Dresource_sharing.enabled=true. Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
|
Root-caused both signatures to the same thing: alerting CI resolves common-utils from the published
Verified locally against build 16 under Subordinate resources: with opensearch-project/security#6373 merged, I enabled the three previously-ignored tests. Two gaps fixed here:
|
dd6ad82
into
opensearch-project:main
Description
Implements resource-access-control for monitor.
Note —
SdkUtils.awaitbehavior change: theCompletionStage.await()helper now unwrapsCompletionException/ExecutionExceptionbefore resuming, so the underlying exception type and REST status survive the async boundary (e.g. a 409VersionConflictEngineExceptionis no longer masked as a 500). This affects all existingawait()call sites, not just the resource-sharing paths.Related Issues
Resolves #2195
Check List
--signoff.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.