-
Notifications
You must be signed in to change notification settings - Fork 25.1k
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
Kibana reserved role app privs #32137
Kibana reserved role app privs #32137
Conversation
Pinging @elastic/es-security |
The
I believe this is occurring because we're creating reserved roles that reference application privileges that won't exist until Kibana starts up and inserts them, so we're explicitly throwing an error when we can't find the |
seems like we might need special app privileges for |
@jaymode for what it's worth, we're assigning the Would it be possible to change the logic to not throw an exception when it doesn't exist in the .security index but just ignore it? Similar to the way that you could assign a user a role that doesn't exist, and it just ignores it? |
I don't really know what I'm doing, but I gave this a shot at 937ec7c and it ostensibly seems to work, but now the tests are failing with:
so, I assume I did something horribly wrong. |
I cannot see anything that was done horribly wrong. @tvernum can you take a look at the issue with roles that have missing application privileges? |
This causes the test to properly close the security index in the @after to ensure we aren't leaving the .security index open
This way the test doesn't transiently load the .security index because it has application privileges and need to close the index when it's done
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.
Let me know if you'd like me to take some of this on.
@@ -193,7 +193,7 @@ private static ApplicationPrivilege resolve(String application, Set<String> name | |||
if (descriptor != null) { | |||
patterns.addAll(descriptor.getActions()); | |||
} else { | |||
throw new IllegalArgumentException("unknown application privilege [" + name + "]"); | |||
patterns.add(name); |
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 think we should just log a warning and skip the name rather than adding it to the patterns.
It's not a pattern, and it isn't supposed to be used as one, but having it there might cause unexpected problems down the track.
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 I changed this to just ignore it, and I created a user with the kibana_user
role (without inserting the privileges), I was seeing it match unexpected privilege names:
PUT {{es}}/_xpack/security/user/kb
Content-Type: application/json
Authorization: Basic elastic changeme
{
"password" : "password",
"roles" : [ "kibana_user" ],
"full_name" : "Admin"
}
POST {{es}}/_xpack/security/user/_has_privileges
Content-Type: application/json
Authorization: Basic kb password
{
"applications":[
{
"application":"kibana-.kibana",
"resources":["*"],
"privileges":[
"read",
"action:foo",
"all",
"i-dont-exist"
]
}
]
}
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-encoding: gzip
content-length: 144
{
"username": "kb",
"has_all_requested": false,
"cluster": {},
"index": {},
"application": {
"kibana-.kibana": {
"*": {
"all": true,
"read": true,
"action:foo": false,
"i-dont-exist": true
}
}
}
}
If you have any available bandwidth, any assistance would be much appreciated.
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 think we just need something like:
if (patterns.isEmpty()) {
return NONE.apply(application);
}
We didn't have it before because get
has a names.isEmpty
check, and it wasn't previously possible for non-empty names to produce non-empty patterns.
Or maybe it was, if the named privileges had no actions in them. That sounds like it was probably always a bug...
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.
OK, it turns out that NONE
doesn't work (in general) - I'll sort out a fix.
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'm tired and my brain hurts, so I'm going to have to leave this for now.
The fundamental problem is that a Privilege with no actions, implies another privilege with no actions.
So if "all" doesn't exist, and "read" doesn't exist, and we treat them as simply not having actions, then they match each other.
That's logical, but not what we want. I think we want to say that a privilege with no actions matches nothing, except up to this point we've said that actions are optional, which clearly wasn't working, so I think we either need to
- say actions are required; or
- the privilege name is an implicit action all the time (so "abc" implies "abc", but not "xyz").
I'm not making a decision on that at 6pm on a Friday, but my inclination is to go with (1).
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 realised option (2) doesn't work. If the privilege name is always an implicit action, then "all" would not imply "read".
The only way something like that would work is we added the privilege name if it had no actions, but in that case we could just require that the person defining the privileges did that explicitly rather than implicitly.
So, I'm going to make actions required, and if some app doesn't need them, then they just give everything a single action of action:<privilege-name>
.
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 opened a PR for this - #32272
I believe the consequence for this PR is two-fold:
- You can stop adding the name to the patterns list if the privilege doesn't exist
- If the privileges have not been defined yet, then "read" will not imply "read" because both are meaningless references to non-existing privileges. So
_has_privileges
will return false for all Kibana privileges until such a time as they have been stored through the API.
I feel like that's the correct response. Treating privileges with the same name as special, even though they haven't been defined is messy. It means "all" implies "all", and "read" implies "read", but "all" does not imply "read". A blanket "these don't exist", so they can't be true is a safer security position.
I would be happy to go back to the previous state where calling _has_privileges with arguments that aren't defined is an error, but I don't want to introduce leniency around special matching of names that aren't defined.
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 great, thanks so much @tvernum!
.build() }, null, MetadataUtils.DEFAULT_RESERVED_METADATA)) | ||
.put("kibana_user", new RoleDescriptor("kibana_user", null, null, new RoleDescriptor.ApplicationResourcePrivileges[] { | ||
RoleDescriptor.ApplicationResourcePrivileges.builder() | ||
.application("kibana-.kibana").resources("*").privileges("all").build() }, |
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 old indices privilege granted .kibana*
but this seems to only grant app privileges to the main/default kibana app, is that intentional?
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, it's intentional, we don't want them to have "direct index access" any longer.
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, I mean old kibana_user
allowed all kibana instances, but this only includes the main kibana instance.
@kobelb I'm curious about your recent change to continue to have the index-level privileges as well as the application privileges. |
Also, I fixed a few checkstyle problems and merged the branch in to try and help get this over the line. |
This looks pretty good other than
|
Done!
So, the current plan is to keep the direct index access for the When user's create their own custom roles that are meant to limit access to a specific Space, or when we implement granular application privileges, they shouldn't be assigning direct index access anymore, as this allows the user to either read or write everything in the .kibana index. Instead, we'll be documenting and recommending using the application privileges. |
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
Begins to implement #32091, some of the security integration tests are failing as a result. This still needs to be investigated.