-
Notifications
You must be signed in to change notification settings - Fork 24.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
Add get-user-privileges API #33928
Add get-user-privileges API #33928
Conversation
This API is intended as a companion to the _has_privileges API. It returns the list of privileges that are held by the current user. This information is difficult to reason about, and consumers should avoid making direct security decisions based solely on this data. For example, each of the following index privileges (as well as many more) would grant a user access to index a new document into the "metrics-2018-08-30" index, but clients should not try and deduce that information from this API. - "all" on "*" - "all" on "metrics-*" - "write" on "metrics-2018-*" - "write" on "metrics-2018-08-30" Rather, if a client wished to know if a user had "index" access to _any_ index, it would be possible to use this API to determine whether the user has any index privileges, and on which index patterns, and then feed those index patterns into _has_privileges in order to determine whether the "index" privilege had been granted. The result JSON is modelled on the Role API, with a few small changes to reflect how privileges are modelled when multiple roles are merged together (multiple DLS queries, multiple FLS grants, multiple global conditions, etc).
Pinging @elastic/es-security |
FYI: @kobelb |
To be handled in separate PRs:
|
@kobelb In 6.4, this happens:
The privileges
The I've fixed that in this PR, so that on this branch we get
which is what you expect.
I don't think that will cause you any issues, but I want to highlight it in advance. What I've just discovered (and will fix) is that this means that |
@tvernum in 6.4, we're only checking whether the user has specific actions and we aren't checking whether they have specific privileges, is it safe to assume that this same behavior that you've noticed doesn't exist in those scenarios? |
@kobelb That's correct. Checking for raw actions is not affected by this change. |
Are we still on track for this to land in 6.5? We'd ideally like to switch to this within 6.5 or else we'll be relying on a rather unperformant alternative. |
Ping @jaymode @albertzaharovits -- Any chance of a review? |
XPackLicenseState licenseState) { | ||
super(settings, licenseState); | ||
this.securityContext = securityContext; | ||
controller.registerHandler(GET, "/_xpack/security/user/{username}/_privileges", this); |
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 handler necessary? Isn't the /_xpack/security/user/_privileges
enough given this is a SAME_USER_PRIVILEGE type of action?
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.
👍
.filter(e -> e.matchesPrivilege(privilege)) | ||
.map(e -> e.resourceNames) | ||
.flatMap(Set::stream) | ||
.collect(Collectors.toSet()); |
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 to me that you went to great lengths to display app privileges in nicely formatted JSON.
What do you think if you also do resource-wildcard-compression here? I mean, to go through
the flatted array and eliminate resources that are a subset of another, eg user/kimchy
is a subset of user/*
so do not print it.
Again, I would not suggest this if you hadn't already reached up to here! Kibana will be thrilled!
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 trickier than it sounds.
The Automatons are (in some cases) already unioned, so calculating subsets is tricky.
In the example from this javadoc:
"read", [ "user/*" ]
"all", [ "user/kimchy", "config/*" ]
the two resources for all
are already merged into a single automaton, so there's nothing that is a pure subset of the read
resource.
We can ignore the union by recompiling each of the resource names, but that would introduce Automaton compilation that we don't otherwise need.
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.
Agreed, it would require compiling the Automaton for every element of the Set.
We can leave it as a homework for when somebody else trips on this and can't do without it.
...c/main/java/org/elasticsearch/xpack/core/security/action/user/GetUserPrivilegesResponse.java
Show resolved
Hide resolved
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.
LGTM!
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 left some minor comments. Otherwise LGTM
...rc/main/java/org/elasticsearch/xpack/core/security/action/user/GetUserPrivilegesRequest.java
Show resolved
Hide resolved
|
||
import static org.hamcrest.Matchers.equalTo; | ||
|
||
public class GetUserPrivilegesResponseTests extends ESTestCase { |
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.
since this response implements equals and hashcode, can you add tests for this?
...main/java/org/elasticsearch/xpack/security/action/user/TransportGetUserPrivilegesAction.java
Show resolved
Hide resolved
This API is intended as a companion to the _has_privileges API. It returns the list of privileges that are held by the current user. This information is difficult to reason about, and consumers should avoid making direct security decisions based solely on this data. For example, each of the following index privileges (as well as many more) would grant a user access to index a new document into the "metrics-2018-08-30" index, but clients should not try and deduce that information from this API. - "all" on "*" - "all" on "metrics-*" - "write" on "metrics-2018-*" - "write" on "metrics-2018-08-30" Rather, if a client wished to know if a user had "index" access to _any_ index, it would be possible to use this API to determine whether the user has any index privileges, and on which index patterns, and then feed those index patterns into _has_privileges in order to determine whether the "index" privilege had been granted. The result JSON is modelled on the Role API, with a few small changes to reflect how privileges are modelled when multiple roles are merged together (multiple DLS queries, multiple FLS grants, multiple global conditions, etc). Backport of: 9200e15, 2283a33, aeb3cda
This API is intended as a companion to the _has_privileges API. It returns the list of privileges that are held by the current user. This information is difficult to reason about, and consumers should avoid making direct security decisions based solely on this data. For example, each of the following index privileges (as well as many more) would grant a user access to index a new document into the "metrics-2018-08-30" index, but clients should not try and deduce that information from this API. - "all" on "*" - "all" on "metrics-*" - "write" on "metrics-2018-*" - "write" on "metrics-2018-08-30" Rather, if a client wished to know if a user had "index" access to _any_ index, it would be possible to use this API to determine whether the user has any index privileges, and on which index patterns, and then feed those index patterns into _has_privileges in order to determine whether the "index" privilege had been granted. The result JSON is modelled on the Role API, with a few small changes to reflect how privileges are modelled when multiple roles are merged together (multiple DLS queries, multiple FLS grants, multiple global conditions, etc).
## Summary This PR solves an issue with `superuser` (or any `*`) role and PLI (product level item) control. Elasticsearch _has_privileges_ API always returns _true_ on any privilege for `superuser` role, even if the privilege has never been registered (more context [here](elastic/elasticsearch#33928 (comment))), causing superuser to be able to access product-restricted APIs (e.g. Routes that should only be available on _complete_ tier, are also available on _essentials_ tier). ## Solution We have the registered AppFeatures configuration locally, so we can solve the problem by checking that the action privilege exists and has been registered in the AppFeatures service, before doing any call to ES _hasPrivileges_ API for RBAC. ### Changes - AppFeatures service now stores a Set with all the (`api` and `ui`) actions registered. - Endpoint authz checks the actions against AppFeatures before checking RBAC. Only for server-side. - Route `access:` tag control has been extended to check actions against AppFeatures for _securitySolution_ prefixed actions. - New `securitySolutionAppFeature:` route tag control for non-RBAC product feature checks. (This is not being used yet, but it will be needed) ### Behavior change - UI: no change, everything should keep working the same way. - API: routes associated with higher product tier features (such as endpoint or entity analytics) won't be accessible for the superuser/admin role when running on lower product tiers, like _security essentials_. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
…176165) ## Summary This PR solves an issue with `superuser` (or any `*`) role and PLI (product level item) control. Elasticsearch _has_privileges_ API always returns _true_ on any privilege for `superuser` role, even if the privilege has never been registered (more context [here](elastic/elasticsearch#33928 (comment))), causing superuser to be able to access product-restricted APIs (e.g. Routes that should only be available on _complete_ tier, are also available on _essentials_ tier). ## Solution We have the registered AppFeatures configuration locally, so we can solve the problem by checking that the action privilege exists and has been registered in the AppFeatures service, before doing any call to ES _hasPrivileges_ API for RBAC. ### Changes - AppFeatures service now stores a Set with all the (`api` and `ui`) actions registered. - Endpoint authz checks the actions against AppFeatures before checking RBAC. Only for server-side. - Route `access:` tag control has been extended to check actions against AppFeatures for _securitySolution_ prefixed actions. - New `securitySolutionAppFeature:` route tag control for non-RBAC product feature checks. (This is not being used yet, but it will be needed) ### Behavior change - UI: no change, everything should keep working the same way. - API: routes associated with higher product tier features (such as endpoint or entity analytics) won't be accessible for the superuser/admin role when running on lower product tiers, like _security essentials_. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
…176165) ## Summary This PR solves an issue with `superuser` (or any `*`) role and PLI (product level item) control. Elasticsearch _has_privileges_ API always returns _true_ on any privilege for `superuser` role, even if the privilege has never been registered (more context [here](elastic/elasticsearch#33928 (comment))), causing superuser to be able to access product-restricted APIs (e.g. Routes that should only be available on _complete_ tier, are also available on _essentials_ tier). ## Solution We have the registered AppFeatures configuration locally, so we can solve the problem by checking that the action privilege exists and has been registered in the AppFeatures service, before doing any call to ES _hasPrivileges_ API for RBAC. ### Changes - AppFeatures service now stores a Set with all the (`api` and `ui`) actions registered. - Endpoint authz checks the actions against AppFeatures before checking RBAC. Only for server-side. - Route `access:` tag control has been extended to check actions against AppFeatures for _securitySolution_ prefixed actions. - New `securitySolutionAppFeature:` route tag control for non-RBAC product feature checks. (This is not being used yet, but it will be needed) ### Behavior change - UI: no change, everything should keep working the same way. - API: routes associated with higher product tier features (such as endpoint or entity analytics) won't be accessible for the superuser/admin role when running on lower product tiers, like _security essentials_. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
The get-user-privileges API (
_xpack/security/user/_privileges
) returnsthe current user's effective privileges in a role-like structure.
Because the effective privileges are the result of merging potentially
multiple roles, the resulting structure has a few differences to the
standard role JSON - some fields that are single values in roles, are
multivariate (arrays) in this API.
It is only possible to return the current user's privileges, but the
es-security-runas-user header can be used to load another user as the
current effective user.
Resolves: #32777