Skip to content

Commit 90aca93

Browse files
committed
Handle restricted indices
1 parent 3202566 commit 90aca93

File tree

3 files changed

+42
-14
lines changed

3 files changed

+42
-14
lines changed

test/test-clusters/src/main/resources/default_test_roles.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ _es_test_root:
66
- names: [ "*" ]
77
allow_restricted_indices: true
88
privileges: [ "ALL" ]
9+
- names: [ "*::failures" ]
10+
allow_restricted_indices: true
11+
privileges: [ "ALL" ]
912
run_as: [ "*" ]
1013
applications:
1114
- application: "*"

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/permission/IndicesPermission.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,21 @@ public boolean hasFieldOrDocumentLevelSecurity() {
147147
private IsResourceAuthorizedPredicate buildIndexMatcherPredicateForAction(String action) {
148148
final Set<String> dataAccessOrdinaryIndices = new HashSet<>();
149149
final Set<String> failureAccessOrdinaryIndices = new HashSet<>();
150-
final Set<String> restrictedIndices = new HashSet<>();
150+
final Set<String> dataAccessRestrictedIndices = new HashSet<>();
151+
final Set<String> failureAccessRestrictedIndices = new HashSet<>();
152+
153+
// TODO do we need to worry about failure access here?
151154
final Set<String> grantMappingUpdatesOnIndices = new HashSet<>();
152155
final Set<String> grantMappingUpdatesOnRestrictedIndices = new HashSet<>();
153156
final boolean isMappingUpdateAction = isMappingUpdateAction(action);
154157
for (final Group group : groups) {
155158
if (group.actionMatcher.test(action)) {
156159
if (group.allowRestrictedIndices) {
157-
restrictedIndices.addAll(Arrays.asList(group.indices()));
160+
if (group.failureStoreOnly) {
161+
failureAccessRestrictedIndices.addAll(Arrays.asList(group.indices()));
162+
} else {
163+
dataAccessRestrictedIndices.addAll(Arrays.asList(group.indices()));
164+
}
158165
} else {
159166
if (group.failureStoreOnly) {
160167
failureAccessOrdinaryIndices.addAll(Arrays.asList(group.indices()));
@@ -172,9 +179,8 @@ private IsResourceAuthorizedPredicate buildIndexMatcherPredicateForAction(String
172179
}
173180
}
174181
}
175-
final StringMatcher dataAccessNameMatcher = indexMatcher(dataAccessOrdinaryIndices, restrictedIndices);
176-
// TODO handle restricted indices for failure access
177-
final StringMatcher failureAccessNameMatcher = indexMatcher(failureAccessOrdinaryIndices, Set.of());
182+
final StringMatcher dataAccessNameMatcher = indexMatcher(dataAccessOrdinaryIndices, dataAccessRestrictedIndices);
183+
final StringMatcher failureAccessNameMatcher = indexMatcher(failureAccessOrdinaryIndices, failureAccessRestrictedIndices);
178184
final StringMatcher bwcSpecialCaseMatcher = indexMatcher(grantMappingUpdatesOnIndices, grantMappingUpdatesOnRestrictedIndices);
179185
return new IsResourceAuthorizedPredicate(dataAccessNameMatcher, failureAccessNameMatcher, bwcSpecialCaseMatcher);
180186
}

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authz/store/CompositeRolesStore.java

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -569,15 +569,33 @@ public static void buildRoleFromDescriptors(
569569
}
570570
});
571571
restrictedIndicesPrivilegesMap.forEach((key, privilege) -> {
572-
// TODO handle failure indices
573-
builder.add(
574-
fieldPermissionsCache.getFieldPermissions(privilege.fieldPermissionsDefinition),
575-
privilege.query,
576-
IndexPrivilege.get(privilege.privileges),
577-
true,
578-
false,
579-
privilege.indices.toArray(Strings.EMPTY_ARRAY)
580-
);
572+
// TODO double-check if this is always the case
573+
assert privilege.indices.isEmpty() == false : "indices must not be empty";
574+
575+
// For a privilege with both failure and non-failure indices, we need to split them into two separate groups
576+
if (privilege.failureIndices.isEmpty() == false) {
577+
var failureIndices = newHashSet(privilege.failureIndices);
578+
builder.add(
579+
fieldPermissionsCache.getFieldPermissions(privilege.fieldPermissionsDefinition),
580+
privilege.query,
581+
IndexPrivilege.get(privilege.privileges),
582+
true,
583+
true,
584+
failureIndices.stream().map(CompositeRolesStore::stripFailuresSuffix).toList().toArray(Strings.EMPTY_ARRAY)
585+
);
586+
privilege.removeFailureIndices();
587+
}
588+
// If we still have privileges left, add a group for them
589+
if (privilege.indices.isEmpty() == false) {
590+
builder.add(
591+
fieldPermissionsCache.getFieldPermissions(privilege.fieldPermissionsDefinition),
592+
privilege.query,
593+
IndexPrivilege.get(privilege.privileges),
594+
true,
595+
false,
596+
privilege.indices.toArray(Strings.EMPTY_ARRAY)
597+
);
598+
}
581599
});
582600

583601
remoteIndicesPrivilegesByCluster.forEach((clusterAliasKey, remoteIndicesPrivilegesForCluster) -> {
@@ -635,6 +653,7 @@ private static String stripFailuresSuffix(String input) {
635653
if (input.endsWith(literalSuffix)) {
636654
return input.substring(0, input.length() - literalSuffix.length());
637655
} else if (input.endsWith(regexSuffix)) {
656+
// TODO need to add back "/" since otherwise we break the regex
638657
return input.substring(0, input.length() - regexSuffix.length());
639658
}
640659
assert false : "unexpected failure index name: " + input;

0 commit comments

Comments
 (0)