Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Resource Access Control] [Part2] Introduces a client for Resource Access Control and adds concrete implementation for resource access control #5194

Open
wants to merge 11 commits into
base: feature/resource-permissions
Choose a base branch
from

Conversation

DarshitChanpura
Copy link
Member

@DarshitChanpura DarshitChanpura commented Mar 20, 2025

#5185 must be merged before merging this.

#5016 is being broken down into smaller pieces. This is part 2.

Description

Introduces a client to be consumed by plugins, and adds concrete implementation of ResourceAccessControl.

There are 4 java APIs as well as 4 REST APIs introduced as part of this PR. Plugins will leverage the client to call the java APIs to implement resource access control.

Refer to the RESOURCE_ACCESS_CONTROL_FOR_PLUGINS.md file to understand in-depth implementation of this feature.

Issues Resolved

Testing

  • automated tests + manual tests

Check List

  • New functionality includes testing
  • New functionality has been documented
  • New Roles/Permissions have a corresponding security dashboards plugin PR
    - [ ] API changes companion pull request created
  • Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@DarshitChanpura DarshitChanpura force-pushed the resource-sharing-client branch from 33c2dc4 to 89d3a63 Compare March 20, 2025 18:33
Signed-off-by: Darshit Chanpura <[email protected]>
Signed-off-by: Darshit Chanpura <[email protected]>
@DarshitChanpura DarshitChanpura force-pushed the resource-sharing-client branch from 597172b to 52f4ac5 Compare March 20, 2025 20:38
@DarshitChanpura DarshitChanpura changed the title [Resource Access Control] [Part2] Introduces a client for Resource Access Control and adds concrete implementation via common package [Resource Access Control] [Part2] Introduces a client for Resource Access Control and adds concrete implementation for resource access control Mar 20, 2025
Copy link
Collaborator

@nibix nibix left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this interesting PR @DarshitChanpura !

I have added a couple of comments and questions. As I went through the code linearly, I also commented both on conceptual things and code level things (which I mostly marked with Nit:). I would recommend that you first have a look on conceptual things ... we can talk about the Nit stuff later.

If you want, we can also schedule a conversation at some point in time.

Comment on lines +266 to +269
POST /_plugins/_security/resources/verify_access
```
- **Description:**
Verifies whether the current user has access to a specified resource within the given index and scopes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate a bit on the use case of this endpoint?

Normally, I can test whether I have access to any RESTful resource by just doing a GET on the resource itself and see if I get a 200 or a 403 status in return.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is intended to be used by plugins via a Java client (or similar) as an alternatively to nodeClient provided by the opensearch-security-client package.

It serves the purpose you described but in a boolean form. As there is no way of blocking access to individual resource, a GET of a resource (or any) will always result in 200 if you have access to the transport action (cluster:..). We are trying to prevent this by adding verification for individual resource.

```json
{
"resource_id": "my-resource",
"resource_index": "resource-index",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exposing the resource-index feels like exposing an implementation detail to me. Am I right that normal users won't be able to access the resource index directly? Then, it should be not visible to them.

Can't we use the resource type here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same holds for the other REST endpoints)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can obfuscate it from the API response. However, in an actual resource-sharing record in the index this information is required. Even if the index name is exposed, a regular user will not be able to access it since we are requiring it to be a system index.

Comment on lines +372 to +378
### **3. Revoke Access**
- **Endpoint:**
```
POST /_plugins/_security/resources/revoke
```
- **Description:**
Revokes access to a resource for specific users, roles, or backend roles under certain scopes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I right in the assumption that only the resource owner is allowed to revoke resource access? This probably should be made explicit in the description.

What happens if I revoke a READ_WRITE scope from a user who has only a READ scope?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, yes. Only users or admin-certificates can update the resource + its access and delete the resource.

if (isSecurityDisabled || !resourceSharingEnabled) {
String message = isSecurityDisabled ? "Security Plugin is disabled." : "ShareableResource Access Control feature is disabled.";

log.warn("{} {}", message, "Access to resource is automatically granted");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Do we need to log a warning in each case?

If users have disabled security or resource sharing they will have deliberately done so (it's difficult to do it accidentally). Logging a warning for each call seems to be quite verbose.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it helpful while debugging hence added it. If consensus is to remove then I can remove it.

Comment on lines +39 to +44
public enum Operation {
LIST,
SHARE,
REVOKE,
VERIFY
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: The whole action combines four operations into one. This leads to a couple of oddities, like the Object response attr in ResourceAccessResponse. IMHO, it would make sense to divide this into four actions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it separated out which results in quite a few redundant files. Let me know if you still think it would be best to split it.

Comment on lines +158 to +167
### **Common Scopes for Plugins to declare**
| Scope | Description |
|-------------|-----------------------------------------------------|
| `PUBLIC` | The resource is accessible to all users. |
| `READ_ONLY` | Users can view but not modify the resource. |
| `READ_WRITE` | Users can view and modify the resource. |

By default, all shareableResources are private and only visible to the owner and super-admins. Resources become accessible to others only when explicitly shared.

SPI provides you an interface, with two default scopes `PUBLIC` and `READ_ONLY`, which can be extended to introduce more plugin-specific values.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table lists a scope READ_WRITE which is not mentioned in any other place. Is this on purpose?

Additionally, could you give an example for a more evolved set of scopes a real-world plugin might use?

I am asking because I am a bit lost what scopes can be. To a certain extent because PUBLIC and READ_ONLY seem to refer to different dimensions in my perception. PUBLIC refers to group of users, while READ_ONLY refers to an allowed action.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these names currently serve semantic purpose only. The context and meaning of these scopes is left to the plugins to determine how they would like to define and utilize them. However, before we proceed on this discussion, let finalize the part forward for scopes as there seems to be confusion around it: #5185 (comment)

Comment on lines +171 to +191
#### **Example: PUBLIC Scoped Document**
If a resource is intended to be publicly accessible, it must be shared using the following structure:

```json
{
"share_with": {
"public": {
"backend_roles": ["*"],
"roles": ["*"],
"users": ["*"]
}
}
}
```

In this structure:
- `"backend_roles": ["*"]` → Grants access to all backend roles.
- `"roles": ["*"]` → Grants access to all roles.
- `"users": ["*"]` → Grants access to all users.

**This ensures that the resource is accessible to everyone.**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate what's here the difference to the following one:

{
    "share_with": {
        "read_only": {
            "backend_roles": ["*"],
            "roles": ["*"],
            "users": ["*"]
        }
    }
}

Copy link
Member Author

@DarshitChanpura DarshitChanpura Mar 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the scope names are only semantic atm. This will in future be mapped to action groups. The discussion can be found under this thread: #5185 (comment)

@DarshitChanpura DarshitChanpura force-pushed the resource-sharing-client branch from e38b67e to e05ae8a Compare March 21, 2025 22:26
Signed-off-by: Darshit Chanpura <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants