-
Notifications
You must be signed in to change notification settings - Fork 279
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
Changes to make PIT security model granular #2053
Changes to make PIT security model granular #2053
Conversation
@reta @Bukhtawar please review |
Build is failing because all the dependencies are in opensearch main branch ( 3.0.0 ) |
62c6a15
to
66058f1
Compare
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
66058f1
to
d5c482e
Compare
@peternied @cliu123 please review this PR. |
- "indices:data/read/point_in_time/delete" | ||
- "indices:data/read/point_in_time/readall" | ||
- "indices:data/read/search" | ||
- "cluster:admin/point_in_time/read_from_nodes" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, for my understanding what is read_from_nodes
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the parent action that basically reads all active Point in time searches from nodes.
This the action for NodesGetAllPitAction.
We can rename it as well, if the name is confusing.
final ImmutableSet<String> allIndices, | ||
final ImmutableSet<String> originalRequested, | ||
final ImmutableSet<String> remoteIndices, | ||
IndicesOptions indicesOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please avoid the format changes if not necessary.
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
// Skip pit evaluation for "NodesGetAllPITs" action, since it fetches all PITs across the cluster | ||
// for privilege evaluation | ||
if(action.startsWith("cluster:admin")) { | ||
return presponse; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is the permission for NodesGetAllPITs
evaluated if requests bypass privilege evaluator? Or is there no need to have access control on NodesGetAllPITs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll still get evaluated, we are just not evaluating it as part of pit access evaluator.
We're not marking presponse as complete, so it'll continue down the privilegeEvaluator code flow.
In short, User needs the action permission to execute nodes get all pits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bharath-techie looks like the permission for NodesGetAllPITs
is designed to be evaluated in PitPrivilegesEvaluator.java? Would you please point me to where it gets evaluated and explain a bit more about how it gets evaluated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as we don't mark the presponse as complete, it'll continue down the flow in PrivilegesEvaluator
// check access for point in time requests
if(pitAccessEvaluator.evaluate(request, clusterService, user, securityRoles,
action0, resolver, dcm.isDnfofForEmptyResultsEnabled(), presponse).isComplete()) {
return presponse;
}
It'll go inside this if block for evaluation after we return without marking it complete https://github.com/opensearch-project/security/pull/2053/files#diff-e746c76b234a31b6f95d428b7c40dabf805b609b110c560902c967db8f83fa7aR303
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
List<ListPitInfo> pitInfos = getAllPitInfos((GetAllPitNodesRequest) request); | ||
// if cluster has no PITs, then allow the operation to pass with empty response | ||
if(pitInfos.isEmpty()) { | ||
presponse.allowed = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The authorization on a request should not be decided by whether there are PITs in a cluster. It should always be evaluated with permissions instead. If the user does not have right permissions, the request should be denied no matter whether there are PITs in a cluster or how many PITs there are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the user does not have permissions, we do throw exception. I'll add some ITs which can assert the same.
Now this logic makes sure that we don't throw permission exception when there are simply no PITs created in the cluster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now this logic makes sure that we don't throw permission exception when there are simply no PITs created in the cluster.
If a user does not have PIT search permissions, even if there are not PITs in the cluster, the request still should be denied. As I said, authorizing a request or not should only be decided by the permissions the user has(privilege evaluator).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed the comment, we're denying if there are no pits so resolving this and similar ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @cliu123 - we are divulging information to the user they should not have - if PITs exist or not.
If you were building a client to connect with OpenSearch and it called this API and got a 200 because it was empty, but then someone added a PIT your requests would suddenly fail due to a side effect - best to be as consistent as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so as long as the user does not have PITs , we throw 403. The behavior is consistent and the above does not happen.
User might not have PITs because :
- PITs are present in the cluster but the user does not have access
- PITs are not present in the cluster
permittedPits.add(pitToPitInfoMap.get(pitId)); | ||
} | ||
} | ||
if (permittedPits.size() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a user has right permissions, even if permittedPits.size()
equals to 0
, the request also should be authorized and get empty in the response. There could be 0 PITs in the cluster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the case we've handled in the line 124, we authorize the user. Because the whole custom logic just ensures if PIT IDs are present, the user should have associated indices permissions.
If not, at this point the user does have action permissions and there are no PITs present in cluster, so we mark operation as success.
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
} | ||
} | ||
// If there are any PITs for which the user has access to, then allow operation otherwise fail. | ||
if(permittedPits.size() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a user has right permissions, even if permittedPits.size() equals to 0, the request also should be authorized and get empty in the response. There could be 0 PITs in the cluster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cliu123 i tried making this work, but looks like for index actions, there is no way to authorize the user when there are no indices to validate against.
dnfOfEnabled flag is used for indices actions where for empty we permit , otherwise we throw forbidden error.
can you please suggest if there are any alternate approaches ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a potential alternative approach:
- Collect authorization information for the user
- Does the user have access to any PITs? (If no- permission is denied)
- Does the user have access to the PITs in the request? (If no- permission is denied)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is what we are doing currently when the config is false ( which is default ).
This config is used in search and other index actions as well, so can we please take a look at this config? it is designed not to throw forbidden in case of empty results.
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitAccessEvaluator.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
2e94765
to
70c0d02
Compare
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
70c0d02
to
dd830b4
Compare
|
||
OpenSearchSecurityPlugin.GuiceHolder.getPitService().getAllPits(latchedActionListener); | ||
|
||
if(!latch.await(15, TimeUnit.SECONDS)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reta as per this discussion we need to get rid of this latch since this has the potential to block http request handler threads.
Do you have thoughts on how we could have a reference to the response listener or perform non-blocking waits,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry @Bukhtawar , I came a bit late, seems like this code is already gone 🥳
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bharath-techie would you be able to shed some light if you still have that commit handy
@reta apologies let's see if we that commit
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have concerns about the processing in the pit privileges evaluator, if there are updates or bugs create security issues. Please take a look at the individual comments, happy to discuss if there are alternatives or other considerations to weight.
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
src/main/java/org/opensearch/security/privileges/PitPrivilegesEvaluator.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
7463e43
to
4a8ad4c
Compare
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
Signed-off-by: Bharathwaj G <bharath78910@gmail.com>
3b222ef
to
54d80cf
Compare
Hi I want to confirm this will work with relevant predefined roles. This should at minimum work with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates, there are still many unresolved threads please take a look.
One way we could see about reviewing/merging this change faster, I think there is less discussion around the workflows that intersect with handleExplicitPitsAccess
. Consider splitting this PR into multiple parts to so we can make progress independently
permittedPits.add(pitToPitInfoMap.get(pitId)); | ||
} | ||
} | ||
if (permittedPits.size() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By hiding the inaccessible PITs we are making it harder to understand what "ALL" means. While we are just getting this feature off the ground I'd like us to use the most restrictive framing of permissions that we could open up in future revisions.
I understand this change requires more work from the user configuring the cluster; however, I think adding a role like the following better communicates what is secured and what isn't to the operator of the cluster.
point_in_time_all_index_manage:
index_permissions:
- index_patterns:
- "*"
allowed_actions:
- "manage_point_in_time"
hidden: false | ||
description: "Migrated from v6 (all types mapped)" | ||
cluster_permissions: | ||
- "cluster:admin/point_in_time/read_from_nodes" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am concerned about adding cluster level permission it blurs the line between the index based permissions and PIT which are tightly coupled to indices, I know there is some discussion around it and I'd like to focus that discussion separately from the rest of this work to help get this PR merged more quickly - is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without cluster level permission we'd not be able to get all PITs from the cluster, as the request doesn't have indices as part of it. Any suggestions ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a place where all of the different Rest APIs are documented in the form below? I would like to be able to cross-reference the actions and associated permissions that are needed to perform them, I think that might help our understanding.
Create point in time
POST "/<target indices>/point_in_time?*keep_alive*=1h&routing=&expand_wildcards=&preference="
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
opensearch-project/OpenSearch#3960 -- is the design doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc and the comments on this PR have evolved over time and it is not clear to me what the permission setup, user action, and result should be for the many scenarios embodied - please make this as clear as possible.
Not only would this help us understand the specific scope and bounds of your request, this would be of great value for writing the end-user facing permissions documentation for this feature
List<ListPitInfo> pitInfos = getAllPitInfos((GetAllPitNodesRequest) request); | ||
// if cluster has no PITs, then allow the operation to pass with empty response | ||
if(pitInfos.isEmpty()) { | ||
presponse.allowed = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @cliu123 - we are divulging information to the user they should not have - if PITs exist or not.
If you were building a client to connect with OpenSearch and it called this API and got a 200 because it was empty, but then someone added a PIT your requests would suddenly fail due to a side effect - best to be as consistent as possible.
} | ||
} | ||
// If there are any PITs for which the user has access to, then allow operation otherwise fail. | ||
if(permittedPits.size() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is a potential alternative approach:
- Collect authorization information for the user
- Does the user have access to any PITs? (If no- permission is denied)
- Does the user have access to the PITs in the request? (If no- permission is denied)
Signed-off-by: Bharathwaj G bharath78910@gmail.com
Description
As part of point in time opensearch review, we got comments which will help PIT security model more granular - where each PIT can be permitted or rejected based on user's indices permissions.
opensearch-project/OpenSearch#4064 (comment)
Design doc - opensearch-project/OpenSearch#3960
This PR contains the changes for same.
As part of this change ,
New feature - Modification to point in time security model - It is a new feature and not released.
We're making these changes to enhance the security model of PIT as per review comments from opensearch community
Add security changes for point in time API #2033 -- this is the old behavior and the above description gives an idea of new behavior. Basically old model gives user access to all PIT contexts or none of PIT contexts and the new model allows permission for PITs based on the underlying indices.
Issues Resolved
opensearch-project/OpenSearch#3960
Is this a backport? If so, please add backport PR # and/or commits #
2.3 / 2.x backport
Testing
[Please provide details of testing done: unit testing, integration testing and manual testing]
Tested all the changes with opensearch + security plugin locally. All changes are working as expected.
Check List
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.