From ada43e3e226cc73eed00b29c738a35896588dab8 Mon Sep 17 00:00:00 2001 From: Darshit Chanpura Date: Mon, 21 Apr 2025 13:10:52 -0400 Subject: [PATCH 1/8] 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/8] 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/8] 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/8] 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/8] 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 c6a11323ee9cbdc6364444d1cf03b102700f3188 Mon Sep 17 00:00:00 2001 From: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Date: Tue, 29 Apr 2025 13:02:53 -0500 Subject: [PATCH 6/8] Remove developer specific information. --- _security/access-control/resources.md | 36 +-------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index e0bdfac8222..ddcbb5d8654 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -58,22 +58,8 @@ sample_read_access: ## Resource sharing 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. +The resource sharing extension consists of key components that work together to provide standardized access management. -### opensearch-security-spi - -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. - -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 @@ -86,26 +72,6 @@ All sharing metadata is stored in the `.opensearch_resource_sharing` system inde | `created_by` | Object | The name of the user who created the resource | | `share_with` | Object | A map of `action-groups` to access definitions | -#### Java client APIs - -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 From d72a8b3e4a6a3267a0274114da03c3210eb7ced7 Mon Sep 17 00:00:00 2001 From: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Date: Fri, 2 May 2025 09:24:20 -0500 Subject: [PATCH 7/8] Apply suggestions from code review Signed-off-by: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> --- _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 ddcbb5d8654..b0cf77606f7 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -43,7 +43,7 @@ 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. -To grant the resource sharing extension these permissions, add the following role to `roles.yaml`: +To grant the resource sharing extension these permissions, add the following roles to `roles.yaml`. These roles will be assigned to anyone conducting resource sharing: ```yaml sample_full_access: @@ -97,7 +97,7 @@ The resource sharing metadata is stored as JSON documents that define ownership, ## 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: +Action groups define permission levels for shared resources. As of OpenSearch 3.0, the only supported 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 08e3e27c429dcbbc05de48fad18e197d0e961038 Mon Sep 17 00:00:00 2001 From: Naarcha-AWS <97990722+Naarcha-AWS@users.noreply.github.com> Date: Fri, 2 May 2025 09:25:36 -0500 Subject: [PATCH 8/8] Remove more developer specific information --- _security/access-control/resources.md | 38 --------------------------- 1 file changed, 38 deletions(-) diff --git a/_security/access-control/resources.md b/_security/access-control/resources.md index b0cf77606f7..9d30d175412 100644 --- a/_security/access-control/resources.md +++ b/_security/access-control/resources.md @@ -56,44 +56,6 @@ sample_read_access: ``` {% include copy.html %} -## Resource sharing components - -The resource sharing extension consists of key components that work together to provide standardized access management. - - -### API - -All sharing metadata is stored in the `.opensearch_resource_sharing` system index, as shown in the following table. - -| 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 | - - -### 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 -{ - "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"] - } - } -} -``` -{% include copy.html %} ## Action groups