-
Notifications
You must be signed in to change notification settings - Fork 25.7k
[Authz] Allow update settings action for system user #34030
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 from 3 commits
5c31415
f030090
a118ab7
cddd75e
6549ceb
bf477ea
27d96c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -154,7 +154,10 @@ public void authorize(Authentication authentication, String action, TransportReq | |
| auditTrail.accessGranted(authentication, action, request, new String[] { SystemUser.ROLE_NAME }); | ||
| return; | ||
| } | ||
| throw denial(authentication, action, request, new String[] { SystemUser.ROLE_NAME }); | ||
| auditTrail.accessDenied(authentication, action, request, new String[] { SystemUser.ROLE_NAME }); | ||
| ElasticsearchSecurityException e = denialException(authentication, action); | ||
|
||
| assert false : e.getMessage(); | ||
bizybot marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| throw e; | ||
| } | ||
|
|
||
| // get the roles of the authenticated user, which may be different than the effective | ||
|
|
@@ -568,9 +571,12 @@ private ElasticsearchSecurityException denialException(Authentication authentica | |
| } | ||
| // check for run as | ||
| if (authentication.getUser().isRunAs()) { | ||
| logger.debug("action [{}] is unauthorized for user [{}] run as [{}]", action, authUser.principal(), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really see much value in having these log messages when we have an audit log. Can you explain how they help?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think while debugging it is easier to see the logs than correlating with another file, also audit logging is disabled by default (yes no one would run prod without audit logs disabled but still). |
||
| authentication.getUser().principal()); | ||
| return authorizationError("action [{}] is unauthorized for user [{}] run as [{}]", action, authUser.principal(), | ||
| authentication.getUser().principal()); | ||
| } | ||
| logger.debug("action [{}] is unauthorized for user [{}]", action, authUser.principal()); | ||
| return authorizationError("action [{}] is unauthorized for user [{}]", action, authUser.principal()); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -240,53 +240,58 @@ private void authorize(Authentication authentication, String action, TransportRe | |||||||||||||
| future.actionGet(); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public void testActionsSystemUserIsAuthorized() { | ||||||||||||||
| TransportRequest request = mock(TransportRequest.class); | ||||||||||||||
| public void testActionsForSystemUserIsAuthorized() { | ||||||||||||||
| final TransportRequest request = mock(TransportRequest.class); | ||||||||||||||
|
|
||||||||||||||
| // A failure would throw an exception | ||||||||||||||
| Authentication authentication = createAuthentication(SystemUser.INSTANCE); | ||||||||||||||
| authorize(authentication, "indices:monitor/whatever", request); | ||||||||||||||
| verify(auditTrail).accessGranted(authentication, "indices:monitor/whatever", request, | ||||||||||||||
| new String[]{SystemUser.ROLE_NAME}); | ||||||||||||||
|
|
||||||||||||||
| authentication = createAuthentication(SystemUser.INSTANCE); | ||||||||||||||
| authorize(authentication, "internal:whatever", request); | ||||||||||||||
| verify(auditTrail).accessGranted(authentication, "internal:whatever", request, new String[]{SystemUser.ROLE_NAME}); | ||||||||||||||
| final Authentication authentication = createAuthentication(SystemUser.INSTANCE); | ||||||||||||||
| final String[] actions = { "indices:monitor/whatever", "internal:whatever", "cluster:monitor/whatever", "cluster:admin/reroute", | ||||||||||||||
| "indices:admin/mapping/put", "indices:admin/template/put", "indices:admin/seq_no/global_checkpoint_sync", | ||||||||||||||
| "indices:admin/settings/update" }; | ||||||||||||||
| for (String action : actions) { | ||||||||||||||
| authorize(authentication, action, request); | ||||||||||||||
| verify(auditTrail).accessGranted(authentication, action, request, new String[] { SystemUser.ROLE_NAME }); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| verifyNoMoreInteractions(auditTrail); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public void testIndicesActionsAreNotAuthorized() { | ||||||||||||||
| public void testIndicesActionsForSystemUserWhichAreNotAuthorized() { | ||||||||||||||
| final TransportRequest request = mock(TransportRequest.class); | ||||||||||||||
| final Authentication authentication = createAuthentication(SystemUser.INSTANCE); | ||||||||||||||
| assertThrowsAuthorizationException( | ||||||||||||||
| assertThrowsAssertionErrorWhenAccessDeniedToSystemUser( | ||||||||||||||
| () -> authorize(authentication, "indices:", request), | ||||||||||||||
| "indices:", SystemUser.INSTANCE.principal()); | ||||||||||||||
| verify(auditTrail).accessDenied(authentication, "indices:", request, new String[]{SystemUser.ROLE_NAME}); | ||||||||||||||
| verifyNoMoreInteractions(auditTrail); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public void testClusterAdminActionsAreNotAuthorized() { | ||||||||||||||
| public void testClusterAdminActionsForSystemUserWhichAreNotAuthorized() { | ||||||||||||||
| final TransportRequest request = mock(TransportRequest.class); | ||||||||||||||
| final Authentication authentication = createAuthentication(SystemUser.INSTANCE); | ||||||||||||||
| assertThrowsAuthorizationException( | ||||||||||||||
| assertThrowsAssertionErrorWhenAccessDeniedToSystemUser( | ||||||||||||||
| () -> authorize(authentication, "cluster:admin/whatever", request), | ||||||||||||||
| "cluster:admin/whatever", SystemUser.INSTANCE.principal()); | ||||||||||||||
| verify(auditTrail).accessDenied(authentication, "cluster:admin/whatever", request, | ||||||||||||||
| new String[]{SystemUser.ROLE_NAME}); | ||||||||||||||
| verify(auditTrail).accessDenied(authentication, "cluster:admin/whatever", request, new String[] { SystemUser.ROLE_NAME }); | ||||||||||||||
| verifyNoMoreInteractions(auditTrail); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| public void testClusterAdminSnapshotStatusActionIsNotAuthorized() { | ||||||||||||||
| public void testClusterAdminSnapshotStatusActionForSystemUserWhichIsNotAuthorized() { | ||||||||||||||
| final TransportRequest request = mock(TransportRequest.class); | ||||||||||||||
| final Authentication authentication = createAuthentication(SystemUser.INSTANCE); | ||||||||||||||
| assertThrowsAuthorizationException( | ||||||||||||||
| assertThrowsAssertionErrorWhenAccessDeniedToSystemUser( | ||||||||||||||
| () -> authorize(authentication, "cluster:admin/snapshot/status", request), | ||||||||||||||
| "cluster:admin/snapshot/status", SystemUser.INSTANCE.principal()); | ||||||||||||||
| verify(auditTrail).accessDenied(authentication, "cluster:admin/snapshot/status", request, | ||||||||||||||
| new String[]{SystemUser.ROLE_NAME}); | ||||||||||||||
| verify(auditTrail).accessDenied(authentication, "cluster:admin/snapshot/status", request, new String[] { SystemUser.ROLE_NAME }); | ||||||||||||||
| verifyNoMoreInteractions(auditTrail); | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| private static void assertThrowsAssertionErrorWhenAccessDeniedToSystemUser(ThrowingRunnable throwingRunnable, | ||||||||||||||
| String action, String user) { | ||||||||||||||
| AssertionError assertionError = expectThrows(AssertionError.class, throwingRunnable); | ||||||||||||||
|
||||||||||||||
| // pkg private method that we can override for testing | |
| boolean assertBuilderClosed(XContentBuilder xContentBuilder) { | |
| assert xContentBuilder.generator().isClosed() : "callers should ensure the XContentBuilder is closed themselves"; | |
| return true; | |
| } |
For reference, this is the PR that introduced this method.
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 do not even think the proposal to add an assertion here would have caught the issue that has led to this PR. This is because we run our standalone tests with the flood stage set to one byte (so that we never trip in CI, on our local machines, etc.):
elasticsearch/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy
Line 330 in 190ea9a
| esConfig['cluster.routing.allocation.disk.watermark.flood_stage'] = '1b' |
So we are adding something that is mildly contentious that would not have helped with the problem that got us here.
I think that we need to go back to the drawing board.
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.
@jasontedor are you saying you do not think we should add an assertion here at all? I see your point about how this would not have caught the flood stage issue; do you have suggestions for a better alternative?
@bizybot I suggest we revert this assertion change from this PR, keep the unit test to validate the system user can perform the update settings action, and we move discussion about how to catch these problems to an issue for discussion.
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, @jaymode, and @jasontedor. I can revert the assertion change from this PR and we can discuss for alternatives.
I have tested scenarios earlier where we would be able to annotate the code with the required privileges so that would ease the testing as we just need to verify whether the user was able to execute the code. But in our case, we would not be able to annotate code as the open source ES code cannot have x-pack annotations or something similar. I will keep thinking about the alternatives but just thought of sharing this one if someone has any ideas around it. Thank you.
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.
@jaymode I agree that we should defer consideration on how to address this to a separate discussion. Let us focus on getting the fix in here for the update settings 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.
Typo in comment ->
DiskThresholdMonitorThere 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.
Corrected this, Thank you.