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

_security/user/_has_privileges may appear to return false for some privilges when the expectation is to return true #106926

Open
jakelandis opened this issue Mar 29, 2024 · 1 comment
Labels
>bug :Security/Security Security issues without another label Team:Security Meta label for security team

Comments

@jakelandis
Copy link
Contributor

jakelandis commented Mar 29, 2024

There is an expectation that privileges generally adhere to some hierarchy w.r.t. to their naming.

For example, there is an expectation that if you have permissions to the cluster level privilege monitor then you should also have privileges to monitor_enrich. This expectation holds for checking action the action names, but does not always hold when checking with _has_privileges.

For example, the monitor privilege deconstructed is effectively cluster:monitor/*, so when checking action name cluster:monitor/xpack/enrich/stats or cluster:monitor/xpack/enrich/esql/resolve_policy always matches expectations and returns true since we effectively resolve cluster:monitor/xpack/enrich/stats against cluster:monitor/* and it passes. Technically, this is implemented with Lucene automatons with pseudo code such as:

Automatons.predicate("cluster:monitor/*").test("cluster:monitor/xpack/enrich/stats")

So the exceptions for the hierarchy in the naming conventions holds true when checking action names (the primary use).

However, you would expect the same hierarchy w.r.t. naming to still hold true when using the _has_privileges API. It would be expected, that if you have monitor cluster permission and ask the _has_privileges API if you have privileges to monitor_enrich, you would expect the result to be true. But, it is not. The answer is false.

The _has_privileges works slightly differently than when checking action names. _has_privileges doesn't resolve static strings against Automatons (nor can it). In the _has_privileges there are 2 Automatons, not one. One automaton represents monitor and another represents monitor_enrich. So, if your role allows you permissions to the monitor cluster privilege and you check if you have monitor_enrich via _has_privileges the implementation looks to see if monitor_enrich is a subset of monitor. So the psuedo code is

// Returns true if the language of the first parameter is a subset of the language of the second parameter.
Operations.subsetOf(monitor_enrich, monitor)

This may return true or it may return false. It depends on exactly what permissions make up the Automatons. It will return true under the following conditions:

  • monitor Automaton represents cluster:monitor/*
  • monitor_enrich Automaton represents cluster:monitor/xpack/enrich/*

In the above case, per the view of the Automaton, cluster:monitor/xpack/enrich/* is a subset of cluster:monitor/*

The problem arises when the automaton represents multiple permissions and one or more permission is not a direct subset of the first. The following condition will return false

  • monitor Automaton represents cluster:monitor/*
  • monitor_enrich Automaton represents cluster:monitor/xpack/enrich/* AND cluster:admin/xpack/enrich/get

In the above case, per the view of the Automaton, cluster:monitor/xpack/enrich/* AND cluster:admin/xpack/enrich/get is NOT a subset of cluster:monitor/*

From the Automaton perceptive this correct behavior. However, from the expectations of permissions this is arguably a bug and most certainly defies usage expectations.

The example chosen here is a real example, but there are cases where the expectations of hierarchy w.r.t. to their naming don't roll up correctly when using the _has_privileges API .

Steps to Reproduce

To reproduce:

create a role like this:

{
    "cluster": ["monitor"]
}

Assign that to a user, then with that user call _security/user/_has_privileges with

{
  "cluster": [ "monitor_enrich" ]
}

Note the false response:

    "cluster": {
        "monitor_enrich": false
    },

Logs (if relevant)

No response

@jakelandis jakelandis added >bug :Security/Security Security issues without another label labels Mar 29, 2024
@elasticsearchmachine elasticsearchmachine added the Team:Security Meta label for security team label Mar 29, 2024
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-security (Team:Security)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Security/Security Security issues without another label Team:Security Meta label for security team
Projects
None yet
Development

No branches or pull requests

2 participants