From ada43e3e226cc73eed00b29c738a35896588dab8 Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Mon, 21 Apr 2025 13:10:52 -0400 Subject: [PATCH 1/7] Adds doc for Resource Sharing and Access Control feature Signed-off-by: Darshit Chanpura --- _security/access-control/resources.md | 192 ++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 _security/access-control/resources.md diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md new file mode 100644 index 00000000000..d9386a06146 --- /dev/null +++ b/_security/access-control/resources.md @@ -0,0 +1,192 @@ +--- +layout: default +title: Resource Sharing and Access Control +parent: Access control +nav_order: 130 +--- + +# Resource Sharing and Access Control +**Introduced 3.0** +{: .label .label-purple } + + +Available from version 3.0.0 on fresh clusters only. +{: .info } + +Marked experimental and is disabled by default. +{: .warning } + +To enable, set: +```yaml +plugins.security.resource_sharing.enabled: true +``` +{: .note } + +## 1. Overview + +OpenSearch lacked a fine-grained access control (FGAC) mechanism at the resource level for plugins, forcing each plugin to develop its own custom authorization logic. This lack of standardization led to inconsistent security enforcement, with broad permissions being assigned and an increased risk of unauthorized access. Maintaining separate access control implementations across multiple plugins also resulted in high maintenance overhead. For example, in the Anomaly Detection plugin a user with delete permissions could remove all detectors instead of just their own, illustrating the need for a centralized, standardized solution. + +The Resource Sharing and Access Control extension in the OpenSearch Security Plugin provides fine-grained, resource-level access management for plugin-declared resources. It builds on top of existing index-level authorization to let: + +Resource owners share and revoke access + +Super-admins view and manage all resources + +Plugin authors define custom shareable resources via a standardized SPI interface + +--- + +## 2. Components + +### 2.1 `opensearch-security-spi` + +A Service Provider Interface (SPI) that: + +- Defines `ResourceSharingExtension` for plugin implementations. +- Tracks registered resource plugins at startup. +- Exposes a `ResourceSharingClient` for performing share, revoke, verify, and list operations. + +#### Plugin Requirements + +##### 1. Feature Flag and Protection + - Enable `plugins.security.resource_sharing.enabled: true` + - Resource indices must be system indices with system index protection enabled (`plugins.security.system_indices.enabled: true`). + +##### 2. Build Configuration + Add to `build.gradle`: + ```gradle + compileOnly group: 'org.opensearch', name: 'opensearch-security-spi', version: "${opensearch_build}" + opensearchplugin { + name '' + description '' + classname '' + extendedPlugins = ['opensearch-security;optional=true'] + } + ``` + +##### 3. SPI Registration + Create `src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension` containing your implementation’s fully qualified class name: + ``` + com.example.MyResourceSharingExtension + ``` + +--- + +## 3. API Design + +All sharing metadata is stored in the system index `.opensearch_resource_sharing`. + +| Field | Type | Description | +| ------------- | ------ | ------------------------------------------- | +| `source_idx` | String | System index holding the resource | +| `resource_id` | String | Unique resource identifier | +| `created_by` | Object | Creator information | +| `share_with` | Object | Map of action-groups to access definitions | + +### 3.1 Document Structure + +```json +{ + "source_idx": ".plugins-ml-model-group", + "resource_id": "model-group-123", + "created_by": { + "user": "darshit" + }, + "share_with": { + "default": { + "users": ["user1"], + "roles": ["viewer_role"], + "backend_roles": ["data_analyst"] + } + } +} +``` + +### 3.2 Java Client APIs + +```java +ResourceSharingClient client = ResourceSharingClientAccessor.getResourceSharingClient(); + +// 1. Verify access +client.verifyResourceAccess(resourceId, indexName, listener); + +// 2. Share resource +client.share(resourceId, indexName, recipients, listener); + +// 3. Revoke access +client.revoke(resourceId, indexName, recipients, listener); + +// 4. List accessible IDs +client.getAccessibleResourceIds(indexName, listener); +``` + +--- + +## 4. Action Groups + +- Action-groups define permission levels (currently only default). +- To make a resource public, use wildcards: + ```json + { + "share_with": { + "default": { + "users": ["*"], + "roles": ["*"], + "backend_roles": ["*"] + } + } + } + ``` +- To keep a resource private (only owner and super-admin): + ```json + { "share_with": {} } + ``` + +--- + +## 5. User and Admin Setup + +### 5.1 Cluster Permissions + +In `roles.yml`, grant plugin API permissions: + +```yaml +sample_full_access: + cluster_permissions: + - 'cluster:admin/sample-resource-plugin/*' + +sample_read_access: + cluster_permissions: + - 'cluster:admin/sample-resource-plugin/get' +``` + +### 5.2 Access Rules + +1. Must have plugin API permission to call share, verify, or list. +2. Resource must be shared or the user must be the owner to grant access. +3. No additional index permissions are needed; system indices are protected. + +--- + +## 6. Restrictions + +- Only resource owners or super-admins can share or revoke access. +- Resources must reside in system indices. +- Disabling system index protection exposes resources to direct index-level access. + +--- + +## 7. Best Practices + +- Declare and register extensions correctly. +- Use the SPI client APIs instead of manual index queries. +- Enable only on fresh 3.0.0+ clusters to avoid upgrade issues. +- Grant minimal required scope when sharing. + +--- + +## 8. Additional Notes + +- Requires `plugins.security.resource_sharing.enabled: true`. +- Relies on system index protection (`plugins.security.system_indices.enabled: true`). +- Experimental feature subject to future API changes. From e850c482bcba94e275a38b85b033bed5f4ef4d97 Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Mon, 21 Apr 2025 14:26:54 -0400 Subject: [PATCH 2/7] Adds a line for onboarding plugin Signed-off-by: Darshit Chanpura --- _security/access-control/resources.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index d9386a06146..747a365d638 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -20,7 +20,10 @@ To enable, set: ```yaml plugins.security.resource_sharing.enabled: true ``` -{: .note } +{: .note } + +Each plugin aiming to support this feature must be onboarded onto it. Plugin developers can refer the [RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md](https://github.com/opensearch-project/security/blob/main/RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md) +{: .tip } ## 1. Overview From b736bd5df72755a6ceeaf6a024f83691e80c983f Mon Sep 17 00:00:00 2001 From: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Date: Wed, 23 Apr 2025 13:45:10 -0500 Subject: [PATCH 3/7] Add tech writer review. Signed-off-by: Darshit Chanpura --- _security/access-control/resources.md | 220 ++++++++++++-------------- 1 file changed, 99 insertions(+), 121 deletions(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index 747a365d638..e7024c32339 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -1,92 +1,115 @@ --- layout: default -title: Resource Sharing and Access Control +title: Sharing resources between access roles parent: Access control nav_order: 130 --- -# Resource Sharing and Access Control +# Sharing resources between access roles + **Introduced 3.0** {: .label .label-purple } +This is an experimental feature and we don't recommend using it in a production environment. For updates on the feature's progress or to provide feedback, join the discussion in the [OpenSearch forum](https://forum.opensearch.org/). +{: .warning} + +The Resource Sharing extension in the OpenSearch Security plugin provides fine-grained, resource-level access management for plugin-declared resources. It builds on top of existing index-level authorization to enable you to: + +- Share and revoke access as a resource owner. +- View and manage all resources as a super-admin. +- Define custom shareable resources through a standardized Service Provider Interface (SPI). + +## Enabling the resource sharing extension + +To enable the resource sharing extension, follow these steps. -Available from version 3.0.0 on fresh clusters only. -{: .info } +### Plugin settings -Marked experimental and is disabled by default. -{: .warning } +To enable resource sharing, add the following settings to `opensearch.yaml`: -To enable, set: ```yaml plugins.security.resource_sharing.enabled: true +plugins.security.system_indices.enabled: true ``` -{: .note } +{% include copy.html %} -Each plugin aiming to support this feature must be onboarded onto it. Plugin developers can refer the [RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md](https://github.com/opensearch-project/security/blob/main/RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md) +For information about implementing this feature in your plugin, see [Resource access control for plugins](https://github.com/opensearch-project/security/blob/main/RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md). {: .tip } -## 1. Overview +### Cluster permissions -OpenSearch lacked a fine-grained access control (FGAC) mechanism at the resource level for plugins, forcing each plugin to develop its own custom authorization logic. This lack of standardization led to inconsistent security enforcement, with broad permissions being assigned and an increased risk of unauthorized access. Maintaining separate access control implementations across multiple plugins also resulted in high maintenance overhead. For example, in the Anomaly Detection plugin a user with delete permissions could remove all detectors instead of just their own, illustrating the need for a centralized, standardized solution. +The Security plugin must have the following access: -The Resource Sharing and Access Control extension in the OpenSearch Security Plugin provides fine-grained, resource-level access management for plugin-declared resources. It builds on top of existing index-level authorization to let: +- Permissions to make share, verify, and list requests. +- Shared access to all cluster components, or be the owner of the cluster. -Resource owners share and revoke access +To grant the resource sharing extension these permissions, add the following role to `roles.yaml`: -Super-admins view and manage all resources +```yaml +sample_full_access: + cluster_permissions: + - 'cluster:admin/sample-resource-plugin/*' -Plugin authors define custom shareable resources via a standardized SPI interface +sample_read_access: + cluster_permissions: + - 'cluster:admin/sample-resource-plugin/get' +``` +{% include copy.html %} ---- +## Resource sharing components -## 2. Components +The resource sharing extension consists of key components that work together to provide standardized access management. The primary component is the Service Provider Interface (SPI), which serves as the foundation for plugin integration and resource management. -### 2.1 `opensearch-security-spi` +### opensearch-security-spi -A Service Provider Interface (SPI) that: +The `opensearch-security-spi` component: - Defines `ResourceSharingExtension` for plugin implementations. - Tracks registered resource plugins at startup. - Exposes a `ResourceSharingClient` for performing share, revoke, verify, and list operations. -#### Plugin Requirements - -##### 1. Feature Flag and Protection - - Enable `plugins.security.resource_sharing.enabled: true` - - Resource indices must be system indices with system index protection enabled (`plugins.security.system_indices.enabled: true`). - -##### 2. Build Configuration - Add to `build.gradle`: - ```gradle - compileOnly group: 'org.opensearch', name: 'opensearch-security-spi', version: "${opensearch_build}" - opensearchplugin { - name '' - description '' - classname '' - extendedPlugins = ['opensearch-security;optional=true'] - } - ``` - -##### 3. SPI Registration - Create `src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension` containing your implementation’s fully qualified class name: - ``` - com.example.MyResourceSharingExtension - ``` +You can customize this component based on the SPI implementation. To customize, create an extension file `src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension` containing your SPI's class name: ---- +``` +com.example.MyResourceSharingExtension +``` +{% include copy.html %} + +### API -## 3. API Design +All sharing metadata is stored in the `.opensearch_resource_sharing` system index, as shown in the following table. -All sharing metadata is stored in the system index `.opensearch_resource_sharing`. +| Field | Type | Description | +| :--- | :--- | :--- | +| `source_idx` | String | The system index holding the resource | +| `resource_id` | String | The resource ID | +| `created_by` | Object | The name of the user who created the resource | +| `share_with` | Object | A map of `action-groups` to access definitions | -| Field | Type | Description | -| ------------- | ------ | ------------------------------------------- | -| `source_idx` | String | System index holding the resource | -| `resource_id` | String | Unique resource identifier | -| `created_by` | Object | Creator information | -| `share_with` | Object | Map of action-groups to access definitions | +#### Java client APIs -### 3.1 Document Structure +Use the following classes when interacting with the extension through the Java client: + +```java +ResourceSharingClient client = ResourceSharingClientAccessor.getResourceSharingClient(); + +// Verify access +client.verifyResourceAccess(resourceId, indexName, listener); + +// Share resource +client.share(resourceId, indexName, recipients, listener); + +// Revoke access +client.revoke(resourceId, indexName, recipients, listener); + +// List accessible IDs +client.getAccessibleResourceIds(indexName, listener); +``` +{% include copy.html %} + +### Document structure + +The resource sharing metadata is stored as JSON documents that define ownership, permissions, and access patterns. Each document contains fields that specify the resource location, identifier, creator information, and sharing configuration: ```json { @@ -104,92 +127,47 @@ All sharing metadata is stored in the system index `.opensearch_resource_sharing } } ``` +{% include copy.html %} -### 3.2 Java Client APIs +## Action groups -```java -ResourceSharingClient client = ResourceSharingClientAccessor.getResourceSharingClient(); - -// 1. Verify access -client.verifyResourceAccess(resourceId, indexName, listener); +Action groups define permission levels for shared resources, for example, `default`. To share resources across the action groups, use the `share_with` array in that resource's configuration and add wildcards for each default role: -// 2. Share resource -client.share(resourceId, indexName, recipients, listener); - -// 3. Revoke access -client.revoke(resourceId, indexName, recipients, listener); - -// 4. List accessible IDs -client.getAccessibleResourceIds(indexName, listener); -``` - ---- - -## 4. Action Groups - -- Action-groups define permission levels (currently only default). -- To make a resource public, use wildcards: - ```json - { - "share_with": { - "default": { - "users": ["*"], - "roles": ["*"], - "backend_roles": ["*"] - } +```json +{ + "share_with": { + "default": { + "users": ["*"], + "roles": ["*"], + "backend_roles": ["*"] } } - ``` -- To keep a resource private (only owner and super-admin): - ```json - { "share_with": {} } - ``` - ---- - -## 5. User and Admin Setup - -### 5.1 Cluster Permissions - -In `roles.yml`, grant plugin API permissions: - -```yaml -sample_full_access: - cluster_permissions: - - 'cluster:admin/sample-resource-plugin/*' - -sample_read_access: - cluster_permissions: - - 'cluster:admin/sample-resource-plugin/get' +} ``` +{% include copy.html %} -### 5.2 Access Rules +To keep a resource private, keep the `share_with` array empty: -1. Must have plugin API permission to call share, verify, or list. -2. Resource must be shared or the user must be the owner to grant access. -3. No additional index permissions are needed; system indices are protected. +```json +{ "share_with": {} } +``` +{% include copy.html %} ---- +## Restrictions -## 6. Restrictions +Before implementing resource sharing and access control, be aware of the following limitations that help maintain security and consistency across the system: - Only resource owners or super-admins can share or revoke access. -- Resources must reside in system indices. +- Resources must reside in system indexes. - Disabling system index protection exposes resources to direct index-level access. ---- +## Best practices -## 7. Best Practices +To ensure secure and efficient implementation of resource sharing and access control, follow these recommended practices: - Declare and register extensions correctly. - Use the SPI client APIs instead of manual index queries. - Enable only on fresh 3.0.0+ clusters to avoid upgrade issues. -- Grant minimal required scope when sharing. - ---- - -## 8. Additional Notes +- Grant minimal required permissions when sharing resources. -- Requires `plugins.security.resource_sharing.enabled: true`. -- Relies on system index protection (`plugins.security.system_indices.enabled: true`). -- Experimental feature subject to future API changes. +These practices help maintain security, improve maintainability, and prevent potential issues during upgrades or system changes. From af0d632f0d43a7119973c7575370a956bdad655b Mon Sep 17 00:00:00 2001 From: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Date: Wed, 23 Apr 2025 13:49:26 -0500 Subject: [PATCH 4/7] Apply suggestions from code review Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Signed-off-by: Darshit Chanpura --- _security/access-control/resources.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index e7024c32339..f7a6f8902a2 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -21,7 +21,7 @@ The Resource Sharing extension in the OpenSearch Security plugin provides fine-g ## Enabling the resource sharing extension -To enable the resource sharing extension, follow these steps. +To enable the resource sharing extension, set up the plugin and permission settings. ### Plugin settings @@ -131,7 +131,7 @@ The resource sharing metadata is stored as JSON documents that define ownership, ## Action groups -Action groups define permission levels for shared resources, for example, `default`. To share resources across the action groups, use the `share_with` array in that resource's configuration and add wildcards for each default role: +Action groups define permission levels for shared resources. As of OpenSearch 3.0, the only supposted action group for resource sharing is `default`. To share resources across the action groups, use the `share_with` array in that resource's configuration and add wildcards for each default role: ```json { From 90aaf81dcfc91db4c3ff4c49157d146c80079ad0 Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Wed, 23 Apr 2025 20:09:15 -0400 Subject: [PATCH 5/7] Adds experimental to feature-flag key Signed-off-by: Darshit Chanpura --- _security/access-control/resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index f7a6f8902a2..e0bdfac8222 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -28,7 +28,7 @@ To enable the resource sharing extension, set up the plugin and permission setti To enable resource sharing, add the following settings to `opensearch.yaml`: ```yaml -plugins.security.resource_sharing.enabled: true +plugins.security.experimental.resource_sharing.enabled: true plugins.security.system_indices.enabled: true ``` {% include copy.html %} From f3810bdbebc315e9a9222a2e5b873bd343ab5d7b Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Thu, 20 Nov 2025 11:42:50 -0800 Subject: [PATCH 6/7] Adds resource sharing and access control documentation Signed-off-by: Darshit Chanpura --- _security/access-control/resources.md | 365 ++++++++++++++++++++------ 1 file changed, 283 insertions(+), 82 deletions(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index e0bdfac8222..77ad7649156 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -5,27 +5,35 @@ parent: Access control nav_order: 130 --- -# Sharing resources between access roles +# Resource Sharing and Access Control -**Introduced 3.0** +**Introduced 3.3** {: .label .label-purple } -This is an experimental feature and we don't recommend using it in a production environment. For updates on the feature's progress or to provide feedback, join the discussion in the [OpenSearch forum](https://forum.opensearch.org/). -{: .warning} +This feature is **experimental**. +{: .warning } -The Resource Sharing extension in the OpenSearch Security plugin provides fine-grained, resource-level access management for plugin-declared resources. It builds on top of existing index-level authorization to enable you to: +The **Resource Sharing and Access Control** framework in the OpenSearch Security plugin provides *document-level*, fine-grained access management for plugin-defined resources. It extends OpenSearch’s existing role-based access control (RBAC) by letting resource owners explicitly share individual resources with other principals. -- Share and revoke access as a resource owner. -- View and manage all resources as a super-admin. -- Define custom shareable resources through a standardized Service Provider Interface (SPI). +With this feature, you can: -## Enabling the resource sharing extension +- Share or revoke access to your resources. +- Allow users with share permission to redistribute access. +- View and manage all shareable resources as a super administrator. +- Integrate shareable resource types through a standardized **Resource Sharing SPI**. +- Search resource indices with automatic per-user filtering applied by the Security plugin. -To enable the resource sharing extension, set up the plugin and permission settings. +A **resource** is currently defined as a **document stored in a plugin’s system index**, and sharing information is stored in a **central security-managed system index**. -### Plugin settings +--- + +# Enabling resource sharing + +The feature is controlled through the cluster settings configuration. + +## Cluster settings -To enable resource sharing, add the following settings to `opensearch.yaml`: +To enable resource sharing: ```yaml plugins.security.experimental.resource_sharing.enabled: true @@ -33,17 +41,39 @@ plugins.security.system_indices.enabled: true ``` {% include copy.html %} -For information about implementing this feature in your plugin, see [Resource access control for plugins](https://github.com/opensearch-project/security/blob/main/RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md). -{: .tip } +### Protected resource types + +Administrators must list which resource types use resource-level authorization: + +```yaml +plugins.security.experimental.resource_sharing.protected_types: ["sample-resource", "ml-model"] +``` +{% include copy.html %} + +These types must match the resource types declared by plugins implementing the `ResourceSharingExtension` SPI. + +### Dynamic updates (3.4+) + +Starting with **3.4**, both settings can be updated dynamically: + +```curl +PUT _cluster/settings +{ + "transient": { + "plugins.security.experimental.resource_sharing.enabled": true, + "plugins.security.experimental.resource_sharing.protected_types": ["sample-resource"] + } +} +``` +{% include copy-curl.html %} -### Cluster permissions +In **3.3**, these settings can be updated **only through `opensearch.yml`** and require a restart. -The Security plugin must have the following access: +--- -- Permissions to make share, verify, and list requests. -- Shared access to all cluster components, or be the owner of the cluster. +# Required permissions -To grant the resource sharing extension these permissions, add the following role to `roles.yaml`: +Resource sharing requires plugin-specific cluster permissions. Add the following to `roles.yml`: ```yaml sample_full_access: @@ -56,118 +86,289 @@ sample_read_access: ``` {% include copy.html %} -## Resource sharing components +Users must have both: + +1. Cluster permissions for the plugin APIs +2. Resources shared with them through the sharing APIs + +Sharing alone does **not** grant API access. + +--- + +# Resource sharing components + +The resource sharing framework includes several internal components and APIs. -The resource sharing extension consists of key components that work together to provide standardized access management. The primary component is the Service Provider Interface (SPI), which serves as the foundation for plugin integration and resource management. +## Service Provider Interface (SPI) -### opensearch-security-spi +Plugins integrate through the **`opensearch-security-spi`** package. -The `opensearch-security-spi` component: +Plugins must implement: -- Defines `ResourceSharingExtension` for plugin implementations. -- Tracks registered resource plugins at startup. -- Exposes a `ResourceSharingClient` for performing share, revoke, verify, and list operations. +* `ResourceSharingExtension` + Declares shareable resource types and system indices. +* `ResourceSharingClientAccessor` + Provides access to verification, sharing, and listing operations. -You can customize this component based on the SPI implementation. To customize, create an extension file `src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension` containing your SPI's class name: +Plugins must also register: ``` -com.example.MyResourceSharingExtension +src/main/resources/META-INF/services/org.opensearch.security.spi.ResourceSharingExtension ``` -{% include copy.html %} -### API +Containing only: -All sharing metadata is stored in the `.opensearch_resource_sharing` system index, as shown in the following table. +``` +com.example.MyResourceSharingExtension +``` -| Field | Type | Description | -| :--- | :--- | :--- | -| `source_idx` | String | The system index holding the resource | -| `resource_id` | String | The resource ID | -| `created_by` | Object | The name of the user who created the resource | -| `share_with` | Object | A map of `action-groups` to access definitions | +{% include copy.html %} -#### Java client APIs +## resource-action-groups.yml -Use the following classes when interacting with the extension through the Java client: +Plugins define access levels using action groups: -```java -ResourceSharingClient client = ResourceSharingClientAccessor.getResourceSharingClient(); +```yaml +resource_types: + sample-resource: + sample_read_only: + allowed_actions: + - "cluster:admin/sample-resource-plugin/get" + + sample_read_write: + allowed_actions: + - "cluster:admin/sample-resource-plugin/*" +``` -// Verify access -client.verifyResourceAccess(resourceId, indexName, listener); +These action groups become the valid “access levels” a user may share. -// Share resource -client.share(resourceId, indexName, recipients, listener); +--- -// Revoke access -client.revoke(resourceId, indexName, recipients, listener); +# Data model -// List accessible IDs -client.getAccessibleResourceIds(indexName, listener); -``` -{% include copy.html %} +All sharing metadata is stored in a dedicated *security-owned* system index. -### Document structure +| Field | Description | +|---------------|------------------------------------------------| +| `resource_id` | Unique identifier of the resource | +| `created_by` | Creator username (and tenant if applicable) | +| `share_with` | Mapping of action-groups to allowed principals | +| `source_idx` | Resource index managed by the plugin | -The resource sharing metadata is stored as JSON documents that define ownership, permissions, and access patterns. Each document contains fields that specify the resource location, identifier, creator information, and sharing configuration: +### Example document ```json { - "source_idx": ".plugins-ml-model-group", "resource_id": "model-group-123", "created_by": { - "user": "darshit" + "user": "darshit", + "tenant": "analytics" }, "share_with": { - "default": { - "users": ["user1"], - "roles": ["viewer_role"], - "backend_roles": ["data_analyst"] + "read_only": { + "users": ["alice"], + "roles": ["data_viewer"], + "backend_roles": ["analytics_backend"] } } } ``` -{% include copy.html %} -## Action groups - -Action groups define permission levels for shared resources. As of OpenSearch 3.0, the only supposted action group for resource sharing is `default`. To share resources across the action groups, use the `share_with` array in that resource's configuration and add wildcards for each default role: +To make a resource public: ```json { "share_with": { - "default": { - "users": ["*"], - "roles": ["*"], - "backend_roles": ["*"] + "read_only": { + "users": ["*"] } } } ``` -{% include copy.html %} +NOTE: Resource will be marked public only if "*" is added to user list. +{: .note} yellow -To keep a resource private, keep the `share_with` array empty: +To keep a resource private: ```json { "share_with": {} } ``` -{% include copy.html %} -## Restrictions +--- + +# Access filtering for plugins + +When plugins perform a search on their system index: + +* The plugin performs the search using its system identity +* Security automatically filters documents based on: + + * resource owner + * shared principals + * privileges + +For example, only documents whose `all_shared_principals` list matches the authenticated user or roles will be returned. + +This filtering is done automatically if the plugin: + +* Implements `IdentityAwarePlugin` +* Uses system identity for index access (no `stashContext`) + +--- + +# Java APIs for plugins + +Plugins call the ResourceSharingClient to enforce access. + +### Verify resource access + +``` +client.verifyAccess(resourceId, resourceIndex, action, listener); +``` + +### List accessible resource IDs + +``` +client.getAccessibleResourceIds(resourceIndex, listener); +``` + +### Check if feature enabled for type + +``` +client.isFeatureEnabledForType(resourceType); +``` + +--- + +# REST APIs + +## 1. Share a resource + +Replace the entire sharing configuration. + +```curl +PUT _plugins/_security/api/resource/share +{ + "resource_id": "123", + "resource_type": "sample-resource", + "share_with": { + "read_only": { + "users": ["alice"], + "roles": ["auditor"] + } + } +} +``` +{% include copy-curl.html %} + +--- + +## 2. Modify sharing configuration + +Add or revoke access. -Before implementing resource sharing and access control, be aware of the following limitations that help maintain security and consistency across the system: +```curl +PATCH/POST _plugins/_security/api/resource/share +{ + "resource_id": "123", + "resource_type": "sample-resource", + "add": { + "read_only": { "users": ["bob"] } + }, + "revoke": { + "read_only": { "users": ["alice"] } + } +} +``` +{% include copy-curl.html %} + +--- + +## 3. Get sharing info -- Only resource owners or super-admins can share or revoke access. -- Resources must reside in system indexes. -- Disabling system index protection exposes resources to direct index-level access. +```curl +GET _plugins/_security/api/resource/share?resource_id=&resource_type= +``` +{% include copy-curl.html %} + +--- + +## 4. List resource types -## Best practices +```curl +GET _plugins/_security/api/resource/types +``` +{% include copy-curl.html %} + +Returns action groups declared by plugins. + +--- -To ensure secure and efficient implementation of resource sharing and access control, follow these recommended practices: +## 5. List accessible resources -- Declare and register extensions correctly. -- Use the SPI client APIs instead of manual index queries. -- Enable only on fresh 3.0.0+ clusters to avoid upgrade issues. -- Grant minimal required permissions when sharing resources. +```curl +GET _plugins/_security/api/resource/list?resource_type= +``` +{% include copy-curl.html %} + +Returns only resources visible to the caller. + +--- + +## 6. Migration API (admin-only) + +Used once to import legacy plugin-managed sharing metadata. + +```curl +POST _plugins/_security/api/resources/migrate +{ + "source_index": "", + "username_path": "", # e.g. /owner/name + "backend_roles_path": "", # e.g. /owner/backend_roles + "default_owner": "some_user", + "default_access_level": { + "": "" # if resource-index has more than one resource type add more entries + } +} + +``` +{% include copy-curl.html %} + + +--- + +# Restrictions + +* Only owners, super-admins and users with sharing access can share or revoke access. +* All resource indices must be system indices. +* System index protection must be enabled. +* Users still require plugin-level cluster permissions, specifically for creating resources. +* Action-groups must be declared in plugin configuration. + +--- + +# Best practices + +For developers: + +* Use SPI and ResourceSharingClient instead of custom ACL logic. +* Store only consistent resource types in a resource index. +* Use the implicit DLS filtering by running searches under system identity. + +For admins: + +* Enable the feature on fresh clusters first. +* Keep system index protection enabled. +* Share resources minimally and explicitly. + +--- + +# Conclusion + +The Resource Sharing and Access Control framework provides a unified and secure way to implement document-level access control for plugin-defined resources in OpenSearch. It introduces a standardized SPI, central sharing index, and new REST APIs for fine-grained authorization. + +For implementation examples, see the **sample-resource-plugin** in the security plugin repository. +For more detailed documentation on this feature, please see [RESOURCE_SHARING_AND_ACCESS_CONTROL.md](https://github.com/opensearch-project/security/blob/main/RESOURCE_SHARING_AND_ACCESS_CONTROL.md). + +--- -These practices help maintain security, improve maintainability, and prevent potential issues during upgrades or system changes. From 37763a459bb18bdce374982d1f2cab167758493e Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Thu, 20 Nov 2025 15:03:58 -0800 Subject: [PATCH 7/7] Adds dashboards doc and makes minor mods in backend doc file Signed-off-by: Darshit Chanpura --- _dashboards/security/resource-sharing.md | 308 +++++++++++++++++++++++ _security/access-control/resources.md | 14 +- 2 files changed, 315 insertions(+), 7 deletions(-) create mode 100644 _dashboards/security/resource-sharing.md diff --git a/_dashboards/security/resource-sharing.md b/_dashboards/security/resource-sharing.md new file mode 100644 index 00000000000..542fc00688e --- /dev/null +++ b/_dashboards/security/resource-sharing.md @@ -0,0 +1,308 @@ +--- +layout: default +title: Resource Access Management via Dashboards +nav_order: 145 +--- + +# Resource Access Management via Dashboards + +**Introduced 3.3** +{: .label .label-purple } + +Resource Sharing in OpenSearch Dashboards provides **fine-grained, document-level access control** for plugin-defined resources such as ML model groups, anomaly detectors, reports definitions, and other shareable objects. It extends OpenSearch’s role-based access control (RBAC) by allowing resource owners to specify *who* can access a resource and *what level of access* they have. + +This feature is **experimental**. +{: .warning } + +--- + +## How resource sharing works + +A **resource** is a document created by a plugin and stored in a protected system index. Examples: + +- ML model groups and models +- Anomaly detectors +- Reporting definitions +- Workflows (Flow Framework) +- Any plugin-defined resource type + +Default access: + +| User | Access | +|------------------|-----------------------------------------| +| Resource creator | Full access (view, edit, delete, share) | +| Super-admin | Full access | +| Other users | No access unless shared | + +Once a resource is shared with specific users, roles, or backend roles, it becomes visible to those users inside Dashboards. Dashboards automatically filters resource lists based on your identity, permissions, and the resource sharing configuration. + +--- + +# Requirements + +To use resource sharing in Dashboards, you must have: + +### 1. Plugin-level cluster permissions +These are assigned by an administrator. Required for resource creation. + +### 2. Resource-level sharing access +A resource must be shared with you explicitly unless you are the owner or a super-admin. + +### 3. Security plugin settings enabled + +Admins must enable: + +```yaml +plugins.security.experimental.resource_sharing.enabled: true +plugins.security.experimental.resource_sharing.protected_types: [""] +plugins.security.system_indices.enabled: true +```` + +If you do not see sharing options in Dashboards, contact your administrator. +{: .note } + +--- + +# Sharing resources through the Dashboards UI + +On left-hand navigation page, under Management section `Resource Access Management` app must be visible if the resource-sharing feature is enabled. + +## 1. Open a shareable resource + +Click on `Resource Access Management` app. Once the page loads, you will see a drop-down with a label `Select a type...`. + +Select a resource type that you would like to see your accessible resources for. + +## 2. Open the Sharing panel + +Once you select an available resource type, the Resources table will be populated will all resources you have access to. If you do not see any resources, create one or ask admins or resource owners to share them with you. + + +## 3. Choose an access level + +Dashboards retrieves available access levels (action groups) dynamically from OpenSearch. Examples: +* `ad_read_only` +* `ml_read_write` +* `flow_framework_full_access` + +NOTE: These access levels are plugin-specific levels and vary by resource-type. +{: .note } blue + +Choose the level and proceed to next step. + +## 4. Add users, roles, or backend roles + +You can grant access to: + +* Specific users +* Specific roles +* Specific backend roles + +Example inputs: + +* User: `alice` +* Role: `data_viewer` +* Backend role: `engineering_team` + +Wildcards (`*`) are supported and come into effect only for users field which can be used to mark a resource as a publicly accessible at the chosen access level. + +## 5. Save your changes + +Dashboards updates the backend configuration and immediately applies access changes. + +--- + +# Viewing and managing access + +The Sharing panel shows: + +* The **resource owner** +* All users/roles/backend roles with access +* Their access levels +* Whether you can reshare the resource + +A user can share a resource only if: + +* They are the owner +* Or the owner shared the resource with them *and* granted share permission +* Or they are a super-admin + +Removing access immediately hides the resource from affected users. + +--- + +# Listing resources shared with you + +Dashboards automatically displays only the resources you can access. No special actions are required. Visibility is determined by: + +* Ownership +* Sharing configuration +* Plugin cluster permissions +* Role/backend role membership +* Wildcards (`users: ["*"]` for public resources) + +--- + +# Managing resource sharing using Dev Tools + +You can also manage resource sharing directly using the **Dev Tools Console** in Dashboards. These operations can only be performed if you are the owner, a super-admin or have sharing access to the resource. + +All APIs start with: + +``` +_plugins/_security/api/resource +``` + +--- + +## 1. Migration API (admin-only) + +Used once to import legacy plugin-managed sharing metadata. + +``` +POST _plugins/_security/api/resources/migrate +{ + "source_index": "", + "username_path": "", # e.g. /owner/name + "backend_roles_path": "", # e.g. /owner/backend_roles + "default_owner": "some_user", + "default_access_level": { + "": "" # if resource-index has more than one resource type add more entries + } +} + +``` +{% include copy-curl.html %} + +## 2. View sharing configuration + +``` +GET _plugins/_security/api/resource/share?resource_id=&resource_type= +``` +{% include copy-curl.html %} + +--- + +## 3. Share a resource (replace all access) + +This **overwrites** the entire sharing configuration. + +``` +PUT _plugins/_security/api/resource/share +{ + "resource_id": "model-group-123", + "resource_type": "ml-model-group", + "share_with": { + "read_only": { "users": ["bob"] }, + "read_write": { "users": ["charlie"] } + } +} +``` +{% include copy-curl.html %} + +--- + +## 4. Add or revoke access (non-destructive) + +This updates sharing without removing existing access. + +``` +PATCH _plugins/_security/api/resource/share +{ + "resource_id": "model-group-123", + "resource_type": "ml-model-group", + + "add": { + "read_only": { "users": ["dave"] } + }, + + "revoke": { + "read_write": { "users": ["charlie"] } + } +} +``` +{% include copy-curl.html %} + +--- + +## 5. List all resources you can access + +``` +GET _plugins/_security/api/resource/list?resource_type= +``` +{% include copy-curl.html %} + +--- + +## 6. List all shareable resource types + +``` +GET _plugins/_security/api/resource/types +``` +{% include copy-curl.html %} + +Dashboards uses this to determine supported access levels per resource type. + +--- + +## 7. Making a resource public + +``` +PATCH _plugins/_security/api/resource/share +{ + "resource_id": "model-group-123", + "resource_type": "ml-model-group", + "add": { + "read_only": { "users": ["*"] } + } +} +``` +{% include copy-curl.html %} + +--- + +## 8. Making a resource private + +``` +PUT _plugins/_security/api/resource/share +{ + "resource_id": "model-group-123", + "resource_type": "ml-model-group", + "share_with": {} +} +``` +{% include copy-curl.html %} + +This resets the resource to **owner-only**. + +--- + +# Troubleshooting + +| Issue | Possible cause | Fix | +|----------------------------------------------|----------------------------------------|----------------------------------------------------------------------------| +| `Resource Access Management` app not visible | Feature disabled | Ask admin to enable `resource_sharing.enabled` | +| User can't create resource | Missing plugin API permissions | Ask admin to map to appropriate role | +| User can't access a resource | Resource is not shared with them | Ask owner to share it with them at appropriate access level | +| API returns 403 in Dev Tools | Resource is not shared with them | Ask owner to share it with them at appropriate access level | +| Resource not listed in Dashboards | Resource not marked as protected | Ask admin to mark resource as protected `resource_sharing.protected_types` | +| PATCH does nothing | Access level not defined for that type | Verify plugin’s action-groups | + +--- + +# Summary + +Resource Sharing in Dashboards allows you to: + +* Keep resources private +* Share resources securely with specific users or teams +* Grant read-only or read-write access +* Modify or revoke access at any time +* Automate or batch operations using Dev Tools + +Dashboards provides a simple UI for everyday access management, while Dev Tools offers full control for advanced workflows. + +If resource sharing features are not visible in Dashboards, contact your OpenSearch administrator to enable the capability and assign appropriate permissions. + +Looking for backend concepts, APIs, and YAML setup? See the backend guide: [Resource Sharing and Access Control]({{site.url}}{{site.baseurl}}/security/access-control/resources/) +{: .note} diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index 77ad7649156..62d336fe4cd 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -56,7 +56,7 @@ These types must match the resource types declared by plugins implementing the ` Starting with **3.4**, both settings can be updated dynamically: -```curl +``` PUT _cluster/settings { "transient": { @@ -246,7 +246,7 @@ client.isFeatureEnabledForType(resourceType); Replace the entire sharing configuration. -```curl +``` PUT _plugins/_security/api/resource/share { "resource_id": "123", @@ -267,7 +267,7 @@ PUT _plugins/_security/api/resource/share Add or revoke access. -```curl +``` PATCH/POST _plugins/_security/api/resource/share { "resource_id": "123", @@ -286,7 +286,7 @@ PATCH/POST _plugins/_security/api/resource/share ## 3. Get sharing info -```curl +``` GET _plugins/_security/api/resource/share?resource_id=&resource_type= ``` {% include copy-curl.html %} @@ -295,7 +295,7 @@ GET _plugins/_security/api/resource/share?resource_id=&resource_type= ``` {% include copy-curl.html %} @@ -319,7 +319,7 @@ Returns only resources visible to the caller. Used once to import legacy plugin-managed sharing metadata. -```curl +``` POST _plugins/_security/api/resources/migrate { "source_index": "",