-
Notifications
You must be signed in to change notification settings - Fork 25.3k
[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
Conversation
When the `cluster.routing.allocation.disk.watermark.flood_stage` watermark is breached, DiskThresholdMonitor marks the indices as read only. This failed when x-pack security was present as System user does not have privilege for update settings action("indices:admin/settings/update"). This commit adds the required privilege for System user. Also added missing debug logs when access is denied to help future debugging. An assert statement is added to catch any missed privileges required for system user. Closes elastic#33119
Pinging @elastic/es-security |
Pinging @elastic/es-distributed |
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.
Seems about right to me, with a few minor comments.
@@ -23,7 +23,8 @@ | |||
"indices:admin/mapping/put", // needed for recovery and shrink api | |||
"indices:admin/template/put", // needed for the TemplateUpgradeService | |||
"indices:admin/template/delete", // needed for the TemplateUpgradeService | |||
"indices:admin/seq_no/global_checkpoint_sync*" // needed for global checkpoint syncs | |||
"indices:admin/seq_no/global_checkpoint_sync*", // needed for global checkpoint syncs | |||
"indices:admin/settings/update" // needed for DiskThreasholdMonitor.markIndicesReadOnly |
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 -> DiskThresholdMonitor
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.
Corrected this, Thank you.
...core/src/test/java/org/elasticsearch/xpack/core/security/authz/privilege/PrivilegeTests.java
Show resolved
Hide resolved
@@ -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); |
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.
Why did we need to expand denial(..)
into 2 statements?
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 had some different code here and then changed it later, I think I missed to correct this afterwards. Thank you.
...ugin/security/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java
Outdated
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.
I left a comment. I will be traveling until Thursday. I defer to @danielmitterdorfer and @rjernst in my place so that my absence does not block progress.
verifyNoMoreInteractions(auditTrail); | ||
} | ||
|
||
private static void assertThrowsAssertionErrorWhenAccessDeniedToSystemUser(ThrowingRunnable throwingRunnable, | ||
String action, String user) { | ||
AssertionError assertionError = expectThrows(AssertionError.class, throwingRunnable); |
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 think we should do this. For one, it’s asserting on behavior that would not happen in production. For another, someday I would like it that we run tests also with assertions disabled (because we have had problems in the past where our assertions were stateful and impacted production behavior). I think we need to find another way.
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 don't think we really care whether it's an AssertionError
or an ElasticsearchSecurityException
(*) so you could just expectThrows(Throwable.class,
and check the message.
We really only want to know that it failed for the right reason.
(*) well, I guess you could make an argument that do want to know that it's an assert if assertions are enabled, but checking whether assertions are enabled is hacky, and probably not worth worrying about.
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 Jason's point was we shouldn't be using assertions at all here. Why can't we expectThrows ElasticsearchSecurityException?
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.
Earlier we used to do the same, but for the system user, we wanted to make sure that the privileges which it required are available so the assert statement in AuthorizationService. In the case of ES tests since assertions are enabled, we will come to know if someone missed on adding the required privileges for the system user. This is the reason we now have to verify the assertion error. As Tim mentioned we could add a check for assertion and based on that we could verify either AssertionError or ElasticsearchSecurityException.
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.
If it is acceptable to check for ElasticsearchSecurityException if assertions are disabled, why is it not sufficient to check for ElasticsearchSecurityException always (and remove the assertion)?
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 agree that we should not be catching AssertionError here. Instead if we expect to trip this assertion in a unit test, we could add a method that could be overridden for a test like we do in RestBuilderListener.
elasticsearch/server/src/main/java/org/elasticsearch/rest/action/RestBuilderListener.java
Lines 50 to 54 in 80c5d30
// 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.
- Corrected the spelling mistake - Added test case - Added comment for the assert
throw denial(authentication, action, request, new String[] { SystemUser.ROLE_NAME }); | ||
ElasticsearchSecurityException e = denial(authentication, action, originalRequest, new String[] { SystemUser.ROLE_NAME }); | ||
// If this throws AssertionError during ES tests then you probably | ||
// need to update system user's 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.
I would be careful with a comment like this. It may be that something should not run as the system user; there needs to be thought behind why something failed and what the correct thing to do is. A mechanical update system privileges is not what we should do
verifyNoMoreInteractions(auditTrail); | ||
} | ||
|
||
private static void assertThrowsAssertionErrorWhenAccessDeniedToSystemUser(ThrowingRunnable throwingRunnable, | ||
String action, String user) { | ||
AssertionError assertionError = expectThrows(AssertionError.class, throwingRunnable); |
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 agree that we should not be catching AssertionError here. Instead if we expect to trip this assertion in a unit test, we could add a method that could be overridden for a test like we do in RestBuilderListener.
elasticsearch/server/src/main/java/org/elasticsearch/rest/action/RestBuilderListener.java
Lines 50 to 54 in 80c5d30
// 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.
-Removed the assertions and will create a issue for discussion. -Modified tests to verify exception.
@@ -568,9 +568,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(), |
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 don't really see much value in having these log messages when we have an audit log. Can you explain how they help?
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 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).
If you still feel this is of no use I can remove 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.
I am fine with the changes. Please make sure @jasontedor is ok now that the assertion changes have been reverted.
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.
When the cluster.routing.allocation.disk.watermark.flood_stage watermark is breached, DiskThresholdMonitor marks the indices as read-only. This failed when x-pack security was present as system user does not have the privilege for update settings action("indices:admin/settings/update"). This commit adds the required privilege for the system user. Also added missing debug logs when access is denied to help future debugging. An assert statement is added to catch any missed privileges required for system user. Closes #33119
* master: (25 commits) HLRC: ML Adding get datafeed stats API (elastic#34271) Small fixes to the HLRC watcher documentation. (elastic#34306) Tasks: Document that status is not semvered (elastic#34270) HLRC: ML Add preview datafeed api (elastic#34284) [CI] Fix bogus ScheduleWithFixedDelayTests.testRunnableRunsAtMostOnceAfterCancellation Fix error in documentation for activete watch SCRIPTING: Terms set query expression (elastic#33856) Logging: Drop remaining Settings log ctor (elastic#34149) [ML] Remove unused last_data_time member from Job (elastic#34262) Docs: Allow skipping response assertions (elastic#34240) HLRC: Add activate watch action (elastic#33988) [Security] Multi Index Expression alias wildcard exclusion (elastic#34144) [ML] Label anomalies with multi_bucket_impact (elastic#34233) Document smtp.ssl.trust configuration option (elastic#34275) Support PKCS#11 tokens as keystores and truststores (elastic#34063) Fix sporadic failure in NestedObjectMapperTests [Authz] Allow update settings action for system user (elastic#34030) Replace version with reader cache key in IndicesRequestCache (elastic#34189) [TESTS] Set SO_LINGER and SO_REUSEADDR on the mock socket (elastic#34211) Security: upgrade unboundid ldapsdk to 4.0.8 (elastic#34247) ...
* rename-ccr-stats: (25 commits) HLRC: ML Adding get datafeed stats API (elastic#34271) Small fixes to the HLRC watcher documentation. (elastic#34306) Tasks: Document that status is not semvered (elastic#34270) HLRC: ML Add preview datafeed api (elastic#34284) [CI] Fix bogus ScheduleWithFixedDelayTests.testRunnableRunsAtMostOnceAfterCancellation Fix error in documentation for activete watch SCRIPTING: Terms set query expression (elastic#33856) Logging: Drop remaining Settings log ctor (elastic#34149) [ML] Remove unused last_data_time member from Job (elastic#34262) Docs: Allow skipping response assertions (elastic#34240) HLRC: Add activate watch action (elastic#33988) [Security] Multi Index Expression alias wildcard exclusion (elastic#34144) [ML] Label anomalies with multi_bucket_impact (elastic#34233) Document smtp.ssl.trust configuration option (elastic#34275) Support PKCS#11 tokens as keystores and truststores (elastic#34063) Fix sporadic failure in NestedObjectMapperTests [Authz] Allow update settings action for system user (elastic#34030) Replace version with reader cache key in IndicesRequestCache (elastic#34189) [TESTS] Set SO_LINGER and SO_REUSEADDR on the mock socket (elastic#34211) Security: upgrade unboundid ldapsdk to 4.0.8 (elastic#34247) ...
When the cluster.routing.allocation.disk.watermark.flood_stage watermark is breached, DiskThresholdMonitor marks the indices as read-only. This failed when x-pack security was present as system user does not have the privilege for update settings action("indices:admin/settings/update"). This commit adds the required privilege for the system user. Also added missing debug logs when access is denied to help future debugging. An assert statement is added to catch any missed privileges required for system user. Closes #33119
When the
cluster.routing.allocation.disk.watermark.flood_stage
watermarkis breached, DiskThresholdMonitor marks the indices as read-only. This
failed when x-pack security was present as system user does not have the privilege
for update settings action("indices:admin/settings/update").
This commit adds the required privilege for the system user. Also added missing
debug logs when access is denied to help future debugging.
An assert statement is added to catch any missed privileges required for
system user.
Closes #33119