-
Notifications
You must be signed in to change notification settings - Fork 24.8k
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
Mirror privileges over data streams to their backing indices #58381
Changes from 24 commits
d30476c
bc0e9b1
1f03278
3c6bac8
bd716a5
6073197
948209e
e0965e4
80d7caf
6caaa1e
f8305c0
233c043
dd8794f
79c5e09
b26c874
2988f7a
c380031
6491913
fa0d1d6
12466c5
129d01c
8f1d8ee
98f222b
022c7c1
2ba65c9
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 |
---|---|---|
|
@@ -130,7 +130,7 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, Metadata | |
if (IndexNameExpressionResolver.isAllIndices(indicesList(indicesRequest.indices()))) { | ||
if (replaceWildcards) { | ||
for (String authorizedIndex : authorizedIndices) { | ||
if (isIndexVisible("*", authorizedIndex, indicesOptions, metadata)) { | ||
if (isIndexVisible("*", authorizedIndex, indicesOptions, metadata, indicesRequest.includeDataStreams())) { | ||
resolvedIndicesBuilder.addLocal(authorizedIndex); | ||
} | ||
} | ||
|
@@ -145,7 +145,7 @@ ResolvedIndices resolveIndicesAndAliases(IndicesRequest indicesRequest, Metadata | |
split = new ResolvedIndices(Arrays.asList(indicesRequest.indices()), Collections.emptyList()); | ||
} | ||
List<String> replaced = replaceWildcardsWithAuthorizedIndices(split.getLocal(), indicesOptions, metadata, | ||
authorizedIndices, replaceWildcards); | ||
authorizedIndices, replaceWildcards, indicesRequest.includeDataStreams()); | ||
if (indicesOptions.ignoreUnavailable()) { | ||
//out of all the explicit names (expanded from wildcards and original ones that were left untouched) | ||
//remove all the ones that the current user is not authorized for and ignore them | ||
|
@@ -337,7 +337,8 @@ private boolean containsWildcards(IndicesRequest indicesRequest) { | |
|
||
//TODO Investigate reusing code from vanilla es to resolve index names and wildcards | ||
private List<String> replaceWildcardsWithAuthorizedIndices(Iterable<String> indices, IndicesOptions indicesOptions, Metadata metadata, | ||
List<String> authorizedIndices, boolean replaceWildcards) { | ||
List<String> authorizedIndices, boolean replaceWildcards, | ||
boolean includeDataStreams) { | ||
//the order matters when it comes to exclusions | ||
List<String> finalIndices = new ArrayList<>(); | ||
boolean wildcardSeen = false; | ||
|
@@ -359,7 +360,7 @@ private List<String> replaceWildcardsWithAuthorizedIndices(Iterable<String> indi | |
// continue | ||
aliasOrIndex = dateMathName; | ||
} else if (authorizedIndices.contains(dateMathName) && | ||
isIndexVisible(aliasOrIndex, dateMathName, indicesOptions, metadata, true)) { | ||
isIndexVisible(aliasOrIndex, dateMathName, indicesOptions, metadata, includeDataStreams, true)) { | ||
if (minus) { | ||
finalIndices.remove(dateMathName); | ||
} else { | ||
|
@@ -377,7 +378,7 @@ private List<String> replaceWildcardsWithAuthorizedIndices(Iterable<String> indi | |
Set<String> resolvedIndices = new HashSet<>(); | ||
for (String authorizedIndex : authorizedIndices) { | ||
if (Regex.simpleMatch(aliasOrIndex, authorizedIndex) && | ||
isIndexVisible(aliasOrIndex, authorizedIndex, indicesOptions, metadata)) { | ||
isIndexVisible(aliasOrIndex, authorizedIndex, indicesOptions, metadata, includeDataStreams)) { | ||
resolvedIndices.add(authorizedIndex); | ||
} | ||
} | ||
|
@@ -412,13 +413,17 @@ private List<String> replaceWildcardsWithAuthorizedIndices(Iterable<String> indi | |
return finalIndices; | ||
} | ||
|
||
private static boolean isIndexVisible(String expression, String index, IndicesOptions indicesOptions, Metadata metadata) { | ||
return isIndexVisible(expression, index, indicesOptions, metadata, false); | ||
private static boolean isIndexVisible(String expression, String index, IndicesOptions indicesOptions, Metadata metadata, | ||
boolean includeDataStreams) { | ||
return isIndexVisible(expression, index, indicesOptions, metadata, includeDataStreams, false); | ||
} | ||
|
||
private static boolean isIndexVisible(String expression, String index, IndicesOptions indicesOptions, Metadata metadata, | ||
boolean dateMathExpression) { | ||
boolean includeDataStreams, boolean dateMathExpression) { | ||
IndexAbstraction indexAbstraction = metadata.getIndicesLookup().get(index); | ||
if (indexAbstraction == null) { | ||
return false; | ||
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 would make it an |
||
} | ||
final boolean isHidden = indexAbstraction.isHidden(); | ||
if (indexAbstraction.getType() == IndexAbstraction.Type.ALIAS) { | ||
//it's an alias, ignore expandWildcardsOpen and expandWildcardsClosed. | ||
|
@@ -433,12 +438,7 @@ private static boolean isIndexVisible(String expression, String index, IndicesOp | |
} | ||
} | ||
if (indexAbstraction.getType() == IndexAbstraction.Type.DATA_STREAM) { | ||
// If indicesOptions.includeDataStreams() returns false then we fail later in IndexNameExpressionResolver. | ||
if (isHidden == false || indicesOptions.expandWildcardsHidden()) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
return includeDataStreams; | ||
} | ||
assert indexAbstraction.getIndices().size() == 1 : "concrete index must point to a single index"; | ||
IndexMetadata indexMetadata = indexAbstraction.getIndices().get(0); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ | |
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.common.util.set.Sets; | ||
import org.elasticsearch.test.ESTestCase; | ||
import org.elasticsearch.transport.TransportRequest; | ||
import org.elasticsearch.xpack.core.security.authz.AuthorizationEngine; | ||
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; | ||
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor.IndicesPrivileges; | ||
import org.elasticsearch.xpack.core.security.authz.permission.FieldPermissions; | ||
|
@@ -35,7 +37,7 @@ public class AuthorizedIndicesTests extends ESTestCase { | |
|
||
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. We need to test that RBACEngine.resolveAuthorizedIndicesFromRole:
We need to repeat the tests for when the request works with data streams or not. |
||
public void testAuthorizedIndicesUserWithoutRoles() { | ||
List<String> authorizedIndices = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(Role.EMPTY, "", Metadata.EMPTY_METADATA.getIndicesLookup()); | ||
RBACEngine.resolveAuthorizedIndicesFromRole(Role.EMPTY, getRequestInfo(""), Metadata.EMPTY_METADATA.getIndicesLookup()); | ||
assertTrue(authorizedIndices.isEmpty()); | ||
} | ||
|
||
|
@@ -71,7 +73,7 @@ public void testAuthorizedIndicesUserWithSomeRoles() { | |
CompositeRolesStore.buildRoleFromDescriptors(descriptors, new FieldPermissionsCache(Settings.EMPTY), null, future); | ||
Role roles = future.actionGet(); | ||
List<String> list = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(roles, SearchAction.NAME, metadata.getIndicesLookup()); | ||
RBACEngine.resolveAuthorizedIndicesFromRole(roles, getRequestInfo(SearchAction.NAME), metadata.getIndicesLookup()); | ||
assertThat(list, containsInAnyOrder("a1", "a2", "aaaaaa", "b", "ab")); | ||
assertFalse(list.contains("bbbbb")); | ||
assertFalse(list.contains("ba")); | ||
|
@@ -81,15 +83,15 @@ public void testAuthorizedIndicesUserWithSomeRoles() { | |
|
||
public void testAuthorizedIndicesUserWithSomeRolesEmptyMetadata() { | ||
Role role = Role.builder("role").add(IndexPrivilege.ALL, "*").build(); | ||
List<String> authorizedIndices = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, Metadata.EMPTY_METADATA.getIndicesLookup()); | ||
List<String> authorizedIndices = RBACEngine.resolveAuthorizedIndicesFromRole(role, getRequestInfo(SearchAction.NAME), | ||
Metadata.EMPTY_METADATA.getIndicesLookup()); | ||
assertTrue(authorizedIndices.isEmpty()); | ||
} | ||
|
||
public void testSecurityIndicesAreRemovedFromRegularUser() { | ||
Role role = Role.builder("user_role").add(IndexPrivilege.ALL, "*").cluster(Set.of("all"), Set.of()).build(); | ||
List<String> authorizedIndices = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, Metadata.EMPTY_METADATA.getIndicesLookup()); | ||
List<String> authorizedIndices = RBACEngine.resolveAuthorizedIndicesFromRole(role, getRequestInfo(SearchAction.NAME), | ||
Metadata.EMPTY_METADATA.getIndicesLookup()); | ||
assertTrue(authorizedIndices.isEmpty()); | ||
} | ||
|
||
|
@@ -114,7 +116,7 @@ public void testSecurityIndicesAreRestrictedForDefaultRole() { | |
.build(); | ||
|
||
List<String> authorizedIndices = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metadata.getIndicesLookup()); | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, getRequestInfo(SearchAction.NAME), metadata.getIndicesLookup()); | ||
assertThat(authorizedIndices, containsInAnyOrder("an-index", "another-index")); | ||
assertThat(authorizedIndices, not(contains(internalSecurityIndex))); | ||
assertThat(authorizedIndices, not(contains(RestrictedIndicesNames.SECURITY_MAIN_ALIAS))); | ||
|
@@ -140,13 +142,21 @@ public void testSecurityIndicesAreNotRemovedFromUnrestrictedRole() { | |
.build(); | ||
|
||
List<String> authorizedIndices = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metadata.getIndicesLookup()); | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, getRequestInfo(SearchAction.NAME), metadata.getIndicesLookup()); | ||
assertThat(authorizedIndices, containsInAnyOrder( | ||
"an-index", "another-index", RestrictedIndicesNames.SECURITY_MAIN_ALIAS, internalSecurityIndex)); | ||
|
||
List<String> authorizedIndicesSuperUser = | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metadata.getIndicesLookup()); | ||
RBACEngine.resolveAuthorizedIndicesFromRole(role, getRequestInfo(SearchAction.NAME), metadata.getIndicesLookup()); | ||
assertThat(authorizedIndicesSuperUser, containsInAnyOrder( | ||
"an-index", "another-index", RestrictedIndicesNames.SECURITY_MAIN_ALIAS, internalSecurityIndex)); | ||
} | ||
|
||
public static AuthorizationEngine.RequestInfo getRequestInfo(String action) { | ||
return getRequestInfo(TransportRequest.Empty.INSTANCE, action); | ||
} | ||
|
||
public static AuthorizationEngine.RequestInfo getRequestInfo(TransportRequest request, String action) { | ||
return new AuthorizationEngine.RequestInfo(null, request, 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.
Suggestion: I would work on the naming and/or javadoc for this to make it clear that such requests over wildcards are meant to (not) expand to data stream names too.