-
Notifications
You must be signed in to change notification settings - Fork 336
Thorough integration tests for index API authorization #5632
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
base: main
Are you sure you want to change the base?
Conversation
ae07568
to
f8c2544
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #5632 +/- ##
==========================================
- Coverage 72.96% 72.88% -0.08%
==========================================
Files 414 420 +6
Lines 25873 26269 +396
Branches 3934 3974 +40
==========================================
+ Hits 18879 19147 +268
- Misses 5083 5214 +131
+ Partials 1911 1908 -3 🚀 New features to boost your workflow:
|
bdecbde
to
f5c21bf
Compare
* The test suites run on different cluster configurations; the possible cluster configurations are defined here. | ||
*/ | ||
public enum ClusterConfig { | ||
LEGACY_PRIVILEGES_EVALUATION( |
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.
To make sure I understand correctly, legacy
here is related to how DNFOF relates to system index authorization?
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.
Good point.
The naming is already in anticipation of the enhanced privilege evaluation PR which introduces one further element to the enum; thus, the enum looks like this:
security/src/integrationTest/java/org/opensearch/security/privileges/int_tests/ClusterConfig.java
Lines 20 to 38 in b3e2cca
public enum ClusterConfig { | |
LEGACY_PRIVILEGES_EVALUATION( | |
"legacy", | |
c -> c.doNotFailOnForbidden(true).nodeSettings(Map.of("plugins.security.system_indices.enabled", true)), | |
true, | |
false, | |
false | |
), | |
LEGACY_PRIVILEGES_EVALUATION_SYSTEM_INDEX_PERMISSION( | |
"legacy_system_index_perm", | |
c -> c.doNotFailOnForbidden(true) | |
.nodeSettings( | |
Map.of("plugins.security.system_indices.enabled", true, "plugins.security.system_indices.permission.enabled", true) | |
), | |
true, | |
true, | |
false | |
), | |
NEXT_GEN_PRIVILEGES_EVALUATION("next_gen", c -> c.privilegesEvaluationType("next_gen"), false, true, true); |
Thus, currently, this is not really legacy. But maybe we can keep it this way, as it is only temporary and avoids lots of renaming?
But, generally, I am also not sure about a good way to name these things. Also I am not too happy about this "next_gen" name.
Thank you @nibix ! This is quite a large PR (even if only test files). It may make sense to break this up into smaller PRs for sake of review similar to what was done to the |
Well, we have 5 main test classes:
Thus, one could break it down into 5 PRs:
Still, I am not sure if this will be really helpful, as this does not really change the grouping of the changes. Already now, you could review class by class. Also, the test cases themselves are then quite repetetive; if you reviewed the first few test cases, you will likely just skim over the remaining ones. In a few cases, these document some oddities; but in most cases, these will be addressed in the enhanced index resolution PR. In the end, this PR is only a preparation for the next one. |
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
Signed-off-by: Nils Bandener <[email protected]>
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.
Hi @nibix Given that this is a huge PR i did my best to thoroughly review the PR and have left some comments and clarification questions.
Could this be broken down into smaller PRs? i.e. data-stream, index and snapshot tests individually?
integrationTestImplementation 'org.slf4j:slf4j-api:2.0.12' | ||
integrationTestImplementation 'com.selectivem.collections:special-collections-complete:1.4.0' | ||
|
||
integrationTestImplementation ('com.jayway.jsonpath:json-path:2.9.0') { |
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 do we need this? would defaultObjectMapper not work?
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.
JSON path allows you to use expressions like "$.data_streams[*].name" to extract information from JSON documents in a very versatile manner. This is not supported by Jackson (ObjectMapper).
} | ||
|
||
public User adminCertUser() { | ||
this.adminCertUser = true; |
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 confused, how does this validate that "this" user is an adminCert user? or is the point not to validate?
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 evaluated here and has the effect that a admin client certificate is used to create the connection:
Lines 107 to 112 in 2c321d6
default TestRestClient getRestClient(UserCredentialsHolder user, Header... headers) { | |
if (user.isAdminCertUser()) { | |
return getRestClient(getTestCertificates().getAdminCertificateData()); | |
} | |
return getRestClient(user.getName(), user.getPassword(), null, headers); | |
} |
src/integrationTest/java/org/opensearch/test/framework/matcher/RestIndexMatchers.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
if (response.getStatusCode() != 200) { | ||
return true; |
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 return true on non 200 code? is it because of empty list of indices and non-existent status code entry ?
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 the case that an empty set of indices is expected.
If we have a 200 response, we have a valid response and can check this in the response body. But if we do not have 200 response, we must/can just assume that we did not get any indices and stop without further checks.
src/integrationTest/java/org/opensearch/test/framework/matcher/RestIndexMatchers.java
Outdated
Show resolved
Hide resolved
// Additionally, the dnfof implementation has the effect that hidden indices might be included even though not requested | ||
assertThat( | ||
httpResponse, | ||
containsExactly(clusterConfig.systemIndexPrivilegeEnabled ? ALL_INDICES : ALL_INDICES_EXCEPT_SYSTEM_INDICES).at( |
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.
will unlimited user see less results than limited users?
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.
yes (still, both will only see authorized indices), the limited users will just see more than they requested (the request shall request no indices).
// This causes a few more 403 errors where the granted index patterns do not use wildcards | ||
|
||
if (user == LIMITED_USER_B1 || user == LIMITED_USER_ALIAS_AB1) { | ||
assertThat(httpResponse, isForbidden()); |
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.
should it be forbidden for B1 user with dnfof enabled?
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.
That's also a bug, to be fixed in the follow up PR
// out indices without authorization from eligible requests. However, the SystemIndexAccessEvaluator | ||
// is not aware of this and just denies all these requests | ||
// See also https://github.com/opensearch-project/security/issues/5546 | ||
assertThat(httpResponse, isForbidden()); |
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.
both blocks are checking same 403 response. Can be clubbed together?
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.
For the first branch, this is a bug, for the else branch, this is expected behavior. That's why i kept it separate with the comments explaining the behavior.
...st/java/org/opensearch/security/privileges/int_tests/IndexAuthorizationReadOnlyIntTests.java
Show resolved
Hide resolved
// _analyze without index is different from most other operations: | ||
// Usually, the absence of an index means "all indices". For analyze, however, it means: "no index". | ||
// However, the IndexResolverReplacer does not get this right; it assumes that all indices are requested. | ||
// Thus, we get only through to this operation with full privileges for all indices |
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.
should we fix 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.
This will be fixed by #5399
Signed-off-by: Nils Bandener <[email protected]>
Description
This introduces new integration tests for authorization against index APIs.
In order to be as thorough as possible, the test suites use parameters to define several test dimensions:
This is mostly a preparation for #5399; it will give us a good overview over the changed behaviors and allows us to judge whether we want to change a behavior or not.
Check List
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.