-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
[Feature/Identity] Permissions check API #4516
[Feature/Identity] Permissions check API #4516
Conversation
Gradle Check (Jenkins) Run Completed with:
|
Gradle Check (Jenkins) Run Completed with:
|
server/src/main/java/org/opensearch/extensions/rest/RestActionsRequestHandler.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/opensearch/extensions/rest/AuthorizationRequest.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/opensearch/extensions/rest/AuthorizationRequest.java
Outdated
Show resolved
Hide resolved
this.extensionUniqueId = extensionUniqueId; | ||
this.requestIssuerIdentity = requestIssuerIdentity; |
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.
These pieces of information have been added into the request body so the caller could alter they as they saw fit. What about changing the usage so this request is only allowed for the current Subject?
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.
What's the current mechanism for sending PrincipalIdentifierToken from extension -> cluster? I added this in when creating my own extension to pass back the PrincipalIdentifierToken that was sent to the extension.
You're right though, this shouldn't be exposed to the caller so I will remove it.
This class encapsulates the information needed to perform authorization, but currently isn't used. I am thinking that most of the time authorization will happen at the point in time that an action is being performed and we will permit/deny the action just in time and may not use this construct. We will resolve to a subject based on a token embedded in the request/message as you pointed out here (opensearch-project/opensearch-sdk-java#40 (comment)).
In the extensions world, I think we will want to perform authorization in RestSendToExtensionAction.prepareRequest
before the transport service sends the request to the extension node. Is there a central place we can move authorization to in core similar to how all requests go through the security plugin when security is installed today?
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.
@peternied I removed the reference to the requestIssuerIdentity from this class.
server/src/main/java/org/opensearch/extensions/rest/AuthorizationRequest.java
Outdated
Show resolved
Hide resolved
server/src/main/java/org/opensearch/extensions/ExtensionsOrchestrator.java
Outdated
Show resolved
Hide resolved
@cwperks I moved this PR to target |
@peternied Its hard to see the changes this PR is introducing now. Would it be possible to update the |
…thorize any request Signed-off-by: Craig Perkins <[email protected]>
edbfbc1
to
46fb6f9
Compare
Signed-off-by: Craig Perkins <[email protected]>
Gradle Check (Jenkins) Run Completed with:
|
Gradle Check (Jenkins) Run Completed with:
|
Signed-off-by: Craig Perkins <[email protected]>
Gradle Check (Jenkins) Run Completed with:
|
Gradle Check (Jenkins) Run Completed with:
|
Signed-off-by: Craig Perkins <[email protected]>
Gradle Check (Jenkins) Run Completed 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.
I'd like to work out the new package before merging, everything else is optional IMO
* | ||
* @opensearch.experimental | ||
*/ | ||
package org.opensearch.authz; |
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 should this package be used vs the identity package?
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.
Never. You can't have authorization without identity. I didn't want to put these in the base level of the identity
package, can I move this package into identity
as a sub-package?
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.
Yup. lets do it!
/** | ||
* Core classes responsible for handling identity in OpenSearch | ||
* | ||
* @opensearch.internal |
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.
👍
private PrincipalIdentifierToken requestIssuerIdentity; | ||
private String permissionId; | ||
private Map<String, CheckableParameter> params; |
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 looks like with this design the resource id is contained within this map. This means that this API could be used for cluster level permission or specific resources. 👍
* @opensearch.experimental | ||
*/ | ||
public class AuthorizationResponse extends TransportResponse { | ||
private String response; |
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 object is a response, what about changing the name to message
? I take this field is meant to represent a human readable message
|
||
@Override | ||
public String toString() { | ||
return "CheckableParameter{key=" + key + ", value=" + value + "}"; |
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.
Should the typename also be included?
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private CheckableParameter<?> createParameter(ParameterType type, String key, Object value) { |
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 doesn't make sure callers use the correct value with the correct ParameterType so they can get an ugly runtime exception. Instead what about could create a set of overloads like createParameter(String key, TimeValue value)
and createParameter(String key, ByteSizeValue value)
that create the background implementations.
I'm uncertain the worth going back and forth on this, but I think we might want to revisit after we've implemented more classes
String key = in.readString(); | ||
String className = in.readString(); | ||
Object value = in.readGenericValue(); | ||
return new CheckableParameter(key, value, Class.forName(className)); |
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.
Potential performance issue https://stackoverflow.com/q/18231991/533057
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.
Maybe just make a comment around this line and we can revisit, what do you think?
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.
Sounds good, this class and WriteableParameter were inspired by similar work on extensions with settings here: https://github.com/opensearch-project/OpenSearch/blob/feature/extensions/server/src/main/java/org/opensearch/common/settings/WriteableSetting.java
The different between Setting and here is that setting can rely on the type of the default value when determining its data type.
Signed-off-by: Craig Perkins <[email protected]>
Gradle Check (Jenkins) Run Completed with:
|
Signed-off-by: Craig Perkins <[email protected]>
* compatible open source license. | ||
*/ | ||
|
||
/* |
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 this license correct?
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 catching that.
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.
Looks good overall. Thanks Craig. One ask is to add more doc in CheckableParameter.java explaining why is this needed/how is this used?
* | ||
* @opensearch.experimental | ||
*/ | ||
public class CheckableParameter<T> { |
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.
More javadoc explaining how will this be used. Thoughts?
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 expect to iterate on this idea a bit. The AuthorizationRequest is a class that encapsulates all of the information needed to perform authorization which includes the permissionId of the action being performed and any parameters needed to evaluate privileges.
When asking for permission such as: "Can I read documents on index X?", we need to know:
- Who is making the request (current subject)
- What action is being performed?
- On what resource?
Gradle Check (Jenkins) Run Completed with:
|
…heckableParameter Signed-off-by: Craig Perkins <[email protected]>
return new CheckableParameter<>(key, (TimeValue) value, TimeValue.class); | ||
case ByteSizeValue: | ||
return new CheckableParameter<>(key, (ByteSizeValue) value, ByteSizeValue.class); | ||
default: |
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.
Are we planning on supporting custom user object types here? (i.e. have a case
that supports a generic type)
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.
No, I expect we will define a list of parameters that are checkable. We need to support index patterns to support existing index permissions. Other parameters that are needed to perform authorization could be resource identifiers.
Gradle Check (Jenkins) Run Completed with:
|
Signed-off-by: Craig Perkins <[email protected]>
Gradle Check (Jenkins) Run Completed with:
|
Signed-off-by: Craig Perkins <[email protected]>
Gradle Check (Jenkins) Run Completed with:
|
@peternied Any idea what's going on with the CI check here? I see |
I see 2 test failures:
Are these known flaky tests? |
@cwperks Nope! But I'm not going to work about it, as they look supremely unrelated to what we are doing. I am going to merge without passing CI... and I'll fix it if this is actually busted instead of an intermittent failure |
Gradle Check (Jenkins) Run Completed with:
|
Description
Companion PR in
opensearch-sdk-java
that shows this in use: opensearch-project/opensearch-sdk-java#118This PR introduces an
AuthorizationRequest
that is intended to be used to evaluate whether a user is permitted to perform an action. This is experimental and used for prototyping AuthN/AuthZ. TheAuthorizationRequest
is intended to encapsulate all parameters needed to perform authorization on any request in OpenSearch. Where authorization is performed is being determined and this PR proposes a simple interface that encapsulates the information needed for authorization.The
AuthenticationRequest
is a minimal interface that contains information about the requester (PrincipalIdentifierToken introduced in: #4299), a permissionId and a map of parameters that can be checked to see if the request fits within a user's permitted actions and constraints. PermissionId is a new concept and will be expanded on in future PRs. PermissionId can be thought of as action name for this PR.The
AuthorizationResponse
is also minimal and contains a message and anAuthorizationStatus
of granted or denied.I would welcome any feedback on the design of the interface to see if this is suitable for most requests.
Issues Resolved
opensearch-project/opensearch-sdk-java#40
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.