* Onboards to Resource Sharing and Authorization
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Adds tests for resource sharing feature
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Fix resource types
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Filter alerts by accessible monitor IDs when resource sharing is enabled
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Adds a default access level
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Removes duplicate sec plugin zip loading
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Route access control through resource-sharing framework when enabled
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>
* Avoid capturing ResourceSharingClient in lambdas to prevent NoClassDefFoundError
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>
* Route shared-resource searches through PluginClient when
resource sharing is enabled
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Expand resource-sharing IT coverage over transport-level interception
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>
* Decouple ResourceSharingClientAccessor from security-spi type at class-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>
* Gate resource-sharing paths on isFeatureEnabledForType
- 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>
* Cover full access-level matrix in resource-sharing ITs
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>
* Expand resource-sharing IT coverage to a full behavior matrix
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>
* Fix resource-sharing IT setup: batch role mapping, add index perms
- 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>
* Require explicit resourceType arg to shouldUseResourceAuthz
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>
* Configure protected_types for resource sharing in integTest cluster
The security plugin's share API rejects unknown resource types with
"No allowed values configured for resource_type" when the experimental
resource_sharing feature is on but protected_types is not set. Add the
setting so the plugin recognizes "monitor" as a protected type.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Bump common-utils dependency to track opensearch_build (3.8.0.0)
Alerting was pinned to common-utils 3.7.0.0-SNAPSHOT via a TODO from an
earlier version bump. The DocRequest implementations that the
resource-sharing framework relies on landed on common-utils main
(3.8.0.0-SNAPSHOT), so tests that expect the security plugin to
intercept get/delete/index requests by resource id were seeing 200s
instead of 403s. Removing the pin and tracking opensearch_build keeps
alerting aligned with the OpenSearch line it is built against.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Wire monitors and workflows into resource-sharing framework
Both resource types share `.opendistro-alerting-config`, so both are registered
as `ResourceProvider`s with `typeField = resource_type` — the security plugin
reads that top-level indexed field at shard-write time to route to the right
provider. Adds `resource_type` and `all_shared_principals` to the scheduled-jobs
mapping so the discriminator and DLS filter fields are indexed.
Async writes to internal indices go through `SdkClientExtensions.{put,get,delete}
DataObjectStashed` which stash the caller's transient auth per-call and restore
via `whenComplete` — mirrors ml-commons / flow-framework. Coroutine `.use { }`
around a suspend body doesn't survive resume-on-different-thread; per-call
stashing does.
Legacy `rbac_roles` validation in the monitor/workflow write actions is skipped
when RSC is active; the sharing entry is now the sole gate. The
`alerting_read_only` / `read_write` / `full_access` access levels are declared
for both `monitor` and `workflow` in `resource-access-levels.yml`.
`RSC_MIGRATION.md` documents the two-step upgrade path: alerting-side backfill
of `resource_type` and scratch owner fields via update-by-query, then the
security plugin's `POST /_plugins/_security/api/resources/migrate` seeds
sharing entries.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Fix RSC IT suite: local helpers, revoke via PATCH, downgrade sequencing
The base test helpers (`updateMonitorWithClient` / `deleteMonitorWithClient`)
re-fetch through the admin client after the mutation, which 403s under RSC
because admin holds no share entry. Local `updateMonitorAs` / `deleteMonitorAs`
skip that re-fetch.
Other adjustments so the suite reflects framework semantics:
- Revoke uses `PATCH /_plugins/_security/api/resource/share` with a `revoke`
body, not `POST /revoke` (which doesn't exist).
- The framework's `PUT /share` is add-only, not replace, so access-level
downgrade needs an explicit revoke-then-share sequence.
- `test alerts inherit denial when monitor is not shared` accepts either 403
(cluster-action gate rejects a user with no shares anywhere) or a 200 with
empty results (DLS-filtered) — both satisfy the guarantee.
- User/role setup is idempotent across tests; @after no longer deletes users
since config-cache reloads under repeated PUTs exposed a role-mapping race.
- `waitForResourceSharingEntry` polls the sharing index after monitor create
because the security plugin records the entry asynchronously from postIndex.
- Two comment-flow tests marked `@Ignore` pending a stash inside
`CommentsIndices.createOrUpdateInitialCommentsHistoryIndex` — non-owner
calls throw an uncaught exception mid-coroutine and hang the response.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Remove RSC_MIGRATION.md scratch design doc
Design belongs in the PR description or an internal wiki, not tracked in the
alerting source tree. Content moved out of band.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Add POST /_plugins/_alerting/_migrate_to_rsc for RSC upgrade path
Admin-only endpoint that runs an update-by-query on `.opendistro-alerting-config`
to backfill the fields the security plugin's resource-sharing framework needs on
existing monitor and workflow docs:
1. Top-level `resource_type` = "monitor" or "workflow", copied from the wrapper
key. This is what `AlertingResourceSharingExtension`'s `ResourceProvider.typeField`
points at, so postIndex on future writes can classify docs by type.
2. Top-level `_migration_user_name` and `_migration_backend_roles`, copied from
`<wrapper>.user.*`. These let the security plugin's
`POST /_plugins/_security/api/resources/migrate` address monitors and workflows
in a single call via `username_path: "/_migration_user_name"`.
The Painless script is idempotent — docs already carrying `resource_type` and
docs without either wrapper (metadata records) return `ctx.op = 'noop'`. The
query pre-filters via `must_not exists resource_type` so the noop branch only
runs on rare concurrent-write windows.
Response is a plain counters shape: `updated`, `noops`, `failures`, `took_millis`.
The transport action name `cluster:admin/opensearch/alerting/rsc/migrate` should
be granted only via `all_access` — not through the per-resource access levels.
Ships with an IT that seeds legacy-shape monitor/workflow/metadata/already-
migrated docs directly, hits the endpoint, and verifies each transitions
correctly (or noops).
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Purge legacy metadata docs during migrate + add E2E lifecycle IT
The security plugin's `POST /_plugins/_security/api/resources/migrate` scans the
entire source index and 400s if any doc's `resource_type` is null.
`<monitorId>-metadata` records aren't shareable resources, so alerting's migrate
now deletes them via delete-by-query on `metadata` field existence before the
resource_type backfill. Metadata regenerates on next monitor execution.
Adds `MigrateToRscE2ERestApiIT` covering the full lifecycle:
phase 1: RSC disabled dynamically → alice creates a monitor via alerting REST,
legacy backend-roles path works.
phase 2: strip resource_type + sharing entry to simulate a truly-legacy doc.
phase 3: enable RSC + protected_types → alice's GET returns 403 (no share).
phase 4: call POST /_plugins/_alerting/_migrate_to_rsc, then
POST /_plugins/_security/api/resources/migrate.
phase 5: alice's GET returns 200 again — sharing entry now exists.
Also updates the metadata test in MigrateToRscRestApiIT to expect deletion
instead of untouched.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* JobSweeper: skip ancillary top-level fields when detecting job type
isSweepableJobType inspected only the very first FIELD_NAME to decide if a doc
was schedulable. Under resource-sharing, alerting docs are written with
`resource_type` (and possibly `all_shared_principals` / migration scratch
fields) at the top level before the `monitor`/`workflow` wrapper — so the
sweeper would silently skip newly-written jobs and they'd never be scheduled.
Iterate top-level fields until we find a sweepable type, skipping any extras.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Drop top-level resource_type; classify via nested type paths
opensearch-project/security#6323 changes getResourceTypeForIndexOp to iterate
all matching ResourceProviders and pick the first whose typeField extraction
resolves. That lets us drop the redundant top-level `resource_type` field
and rely on the pre-existing nested `monitor.type` / `workflow.type` fields
as type discriminators.
Changes:
- AlertingResourceSharingExtension: typeField is now `monitor.type` and
`workflow.type` per provider (previously both pointed at the shared
`resource_type` field).
- TransportIndexMonitorAction / TransportIndexWorkflowAction: drop the
`with_resource_type=true` XContent param from storage writes; the stored
doc goes back to just `{"<wrapper>": {...}}`.
- scheduled-jobs.json mapping: drop the `resource_type` keyword field.
- TransportMigrateToRscAction: drop the resource_type backfill from the
Painless script; keep the scratch owner-field copy (still needed by the
security migrate endpoint's `username_path`). Idempotency filter now
gates on `_migration_user_name` existence.
- Migrate ITs updated to match the new doc shape (no resource_type).
Depends on: opensearch-project/security#6323 (must land in opensearch_build
before local E2E ITs on the sharing race path will pass). Migrate UBQ tests
that don't touch the security plugin's classification path continue to pass.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Drop _migrate_to_rsc endpoint; rely on security plugin's classifier
opensearch-project/security#6323 landed two framework capabilities that
render the alerting-side migration pre-processor obsolete:
1. `ResourcePluginInfo.getResourceTypeForIndexOp` now iterates every
registered provider on a shared index and picks the first one whose
`typeField` extraction resolves — no top-level discriminator field
needed on stored docs.
2. `ResourceProvider` gained `ownerNamePath()` / `ownerBackendRolesPath()`
methods. When declared, they override the request-level `username_path`
/ `backend_roles_path` on `POST /_plugins/_security/api/resources/migrate`
for docs classified as that type — so a single migrate call attributes
owners for both monitor and workflow docs sharing one index without any
scratch fields.
Alerting cleanup:
- `AlertingResourceSharingExtension` declares per-type ownerNamePath and
ownerBackendRolesPath (`/monitor/user/name`, `/workflow/user/name`, etc.).
- Delete `TransportMigrateToRscAction`, `RestMigrateToRscAction`,
`MigrateToRscAction`/`Request`/`Response`, and unwire from `AlertingPlugin`
— the endpoint no longer has a job to do.
- Delete the standalone `MigrateToRscRestApiIT` (unit tests for the deleted
endpoint).
- Rename `MigrateToRscE2ERestApiIT` -> `RscMigrateE2ERestApiIT` and update it
to call security's migrate endpoint directly. The security plugin now reads
owner metadata from the per-provider paths so the request body no longer
needs alerting-specific `_migration_*` scratch fields.
Verified locally against a security build carrying #6323: 1/1 E2E test
passes (create legacy monitor with RSC disabled → enable RSC → verify 403 →
run security migrate → verify alice recovers access).
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Post-review cleanups: extension tests cover workflow provider; drop stale comment
- AlertingResourceSharingExtensionTests: previous test asserted a single
provider was registered. Now that the extension registers both monitor and
workflow, replace that assertion and add per-provider coverage that pins
typeField (`monitor.type` / `workflow.type`) and the per-type owner paths
(`/monitor/user/name`, `/workflow/user/name`, and matching backend_roles
paths). These are the contract downstream security PR #6323 reads from.
- JobSweeper.isSweepableJobType: drop mention of `resource_type` and the
alerting migration scratch fields from the skip-loop comment. Neither is
ever emitted after the resource_type revert; only security-injected
top-level fields like `all_shared_principals` are relevant here.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Accept 403|404 on post-delete GET; ignore flaky alerts-inherit test
Two test-expectation adjustments after running the RSC IT suite against the
merged upstream security build (opensearch-project/security#6323):
- 'test owner sees delete performed by read-write shared user': under RSC
the sharing entry is removed alongside the doc, so alice's GET hits the
RSC gate (403) before the transport action can return NOT_FOUND (404).
Accept either — both semantically mean 'no longer accessible'.
- 'test alerts inherit access when monitor is shared read-only': bob has
a read-only share on alice's monitor but the alerts GET returns an empty
result. `getAccessibleResourceIds` correctly reports the monitor as
accessible, so this looks like DLS on the alerts index filtering bob out
even though the alerts index isn't itself a resource-sharing-protected
type. Marked @ignore with a FIXME; needs a separate investigation and
possibly an alerts-index DLS exemption, but doesn't block the core RSC
framework onboarding.
Also add a refresh of `.opendistro-alerting-config-sharing` inside
`shareResource` so downstream `getAccessibleResourceIds` searches see the
newly-written sharing entry without an ad-hoc sleep.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Fix schema-version test expectation and restore stash pattern for comments
- Bump AlertIndicesIT verifyIndexSchemaVersion expectations 8->9 to match
scheduled-jobs.json mapping bump for all_shared_principals.
- Restore stashContext().use wrapper around comment-action coroutine launch
to preserve prior behavior; per-call putDataObjectStashed retained for
ResourceIndexListener.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Unwrap CompletionException in SdkClient await so REST status survives
sdkClient.*Async().await() propagated the raw CompletionException that
CompletableFuture wraps around a failed stage's cause. AlertingException.wrap()
type-switches on the exception to derive the REST status and does not
recognize CompletionException, so it defaulted to 500 INTERNAL_SERVER_ERROR
and masked the real status -- e.g. a 409 CONFLICT from
VersionConflictEngineException on an optimistic-concurrency PUT.
Peel CompletionException/ExecutionException wrappers off the throwable
before resuming the coroutine so the original exception type (and its
status) reaches the wrap() call sites.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Run RSC accessible-resource lookups under caller context; harden comment ITs
Under the resource-sharing framework, the alert/comment search actions filter
results to resources the caller can access via ResourceSharingClient
.getAccessibleResourceIds(). That call resolves the caller from the
authenticated-user header in ThreadContext, but the actions dispatch it from
inside a `stashContext().use { scope.launch { ... } }` block, so it ran under
the stashed (empty) context, saw no user, and returned no accessible
monitors/workflows -- yielding zero alerts/comments even for authorized users.
(Confirmed at runtime: transient user = null, accessibleMonitorIds = [].)
Capture the caller's context before stashing and restore it around only the
getAccessibleResourceIds call, keeping the subsequent system-index search under
the stashed plugin context. Applied to the three actions with this pattern:
- TransportSearchAlertingCommentAction
- TransportGetAlertsAction
- TransportGetWorkflowAlertsAction
Test changes (SecureAlertingCommentsRestApiIT + AlertingRestTestCase):
- Add shareMonitorWithUser / waitForResourceSharingEntry helpers to the base
class. Viewing a monitor's comments is a read gated by resource authz, so the
three "can view comments" tests now share the admin-created monitor with the
viewing user; waitForResourceSharingEntry avoids racing the security plugin's
async postIndex sharing-entry write.
- Tear down the shared/reserved role-mappings in @after so a test that fails
before its own cleanup can't leak a mapping and grant a later test's user
unexpected access (order-dependent flakiness).
- Drop the now-duplicate private waitForResourceSharingEntry in
SecureResourceSharingMonitorRestApiIT in favor of the base-class helper.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Initialize alerts index mapping in comment ITs so RSC monitor_id filter matches
SecureAlertingCommentsRestApiIT creates alerts via the raw _doc API without
first initializing the alerts index. The index then auto-creates with a dynamic
`text` mapping for monitor_id (plus a .keyword subfield), so the RSC comment
search filter's `termsQuery("monitor_id", ...)` on the analyzed field matched
nothing -- a monitor shared with the viewing user returned zero comments.
Call putAlertMappings() in @before (as MonitorRestApiIT already does for the
same "no create alert API" reason) so the alerts index uses the real mapping
where monitor_id is keyword and the term filter matches. Verified: the full
SecureAlertingCommentsRestApiIT suite passes (14/0) against fixed common-utils
and security deps.
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
* Rename workflow RSC resource type to alerting-workflow to avoid flow-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>
* Run workflow delete on plugin subject; accept 403|404 on post-delete GET
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>
* Scope RSC security CI variant to resource-sharing suites only
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>
* Address RSC review: super-admin bypass, alert-search size, rbac_roles, comments stash
Review feedback on #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>
* Trigger CI: pull common-utils 3.8 snapshot after backport of #984 + #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>
* Enforce RSC on subordinate alerts/comments; enable inheritance tests
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>
---------
Signed-off-by: Darshit Chanpura <dchanp@amazon.com>
Description
ResourceIndexListener.postIndexrequires an authenticated user in the thread context to create a resource-sharing entry. When none is present, it fails with an uncaught NPE (null user subject) or skips silently at debug level. Resources written in a genuinely user-less context — scheduled jobs running under job-scheduler (e.g. scheduled report instances), provisioning steps executed under system context — therefore never receive sharing entries and stay permanently invisible to the resource-sharing APIs, including to the owner of the parent resource that triggered them.Changes
parentType/parentIdField): the sharing entry is created by inheritingtenant/created_byfrom the parent's sharing record, linked viaparentType/parentIdsoResourceAccessHandlerdelegates evaluation to the parentTesting
New integration tests (
SystemContextChildResourceTests, sample plugin hierarchy, all passing) index resource documents through the internal node client — no user in context, mirroring plugin/system-subject writes:Investigation note (correction)
This PR was initially motivated by on-demand report instances missing sharing records on a 3.8.0 snapshot. Deeper investigation showed that case was actually caused by listener-attachment timing on that build: the listener attaches per-index in
onIndexModulefiltered byprotected_types, so a type added to the dynamic setting after its index was already open never got a listener until restart (current main attaches based on the unfiltered registered set, so main appears immune). On-demand instance writes do carry the authenticated user and work once the listener is attached. The user-less gap addressed by this PR remains real for scheduled/system-context writes, as covered by the new tests.Companion PRs
Category
Bug fix
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.