Fix DLS query merging when there are groups with/without DLS (elastic/x-pack-elasticsearch#1203)

If a single permission set does not have a query defined then this should be considered as the user
not having document level security for the indices matching that pattern. However, the lack of
document level security was not being taken into account and document level security was being
applied when it should not have been.

Original commit: elastic/x-pack-elasticsearch@f5777c2f37
This commit is contained in:
Jay Modi 2017-04-26 16:06:15 -04:00 committed by GitHub
parent 2a1fd02dcf
commit 69837cd817
2 changed files with 64 additions and 6 deletions

View File

@ -100,7 +100,7 @@ public final class IndicesPermission implements Iterable<IndicesPermission.Group
SortedMap<String, AliasOrIndex> allAliasesAndIndices = metaData.getAliasAndIndexLookup();
Map<String, Set<FieldPermissions>> fieldPermissionsByIndex = new HashMap<>();
Map<String, Set<BytesReference>> roleQueriesByIndex = new HashMap<>();
Map<String, DocumentLevelPermissions> roleQueriesByIndex = new HashMap<>();
Map<String, Boolean> grantedBuilder = new HashMap<>();
for (String indexOrAlias : requestedIndicesOrAliases) {
@ -119,9 +119,15 @@ public final class IndicesPermission implements Iterable<IndicesPermission.Group
for (String index : concreteIndices) {
Set<FieldPermissions> fieldPermissions = fieldPermissionsByIndex.computeIfAbsent(index, (k) -> new HashSet<>());
fieldPermissions.add(group.getFieldPermissions());
DocumentLevelPermissions permissions =
roleQueriesByIndex.computeIfAbsent(index, (k) -> new DocumentLevelPermissions());
if (group.hasQuery()) {
Set<BytesReference> roleQueries = roleQueriesByIndex.computeIfAbsent(index, (k) -> new HashSet<>());
roleQueries.addAll(group.getQuery());
permissions.addAll(group.getQuery());
} else {
// if more than one permission matches for a concrete index here and if
// a single permission doesn't have a role query then DLS will not be
// applied even when other permissions do have a role query
permissions.setAllowAll(true);
}
}
}
@ -139,9 +145,12 @@ public final class IndicesPermission implements Iterable<IndicesPermission.Group
Map<String, IndicesAccessControl.IndexAccessControl> indexPermissions = new HashMap<>();
for (Map.Entry<String, Boolean> entry : grantedBuilder.entrySet()) {
String index = entry.getKey();
Set<BytesReference> roleQueries = roleQueriesByIndex.get(index);
if (roleQueries != null) {
roleQueries = unmodifiableSet(roleQueries);
DocumentLevelPermissions permissions = roleQueriesByIndex.get(index);
final Set<BytesReference> roleQueries;
if (permissions != null && permissions.isAllowAll() == false) {
roleQueries = unmodifiableSet(permissions.queries);
} else {
roleQueries = null;
}
final FieldPermissions fieldPermissions;
@ -206,4 +215,27 @@ public final class IndicesPermission implements Iterable<IndicesPermission.Group
return query != null;
}
}
private static class DocumentLevelPermissions {
private Set<BytesReference> queries = null;
private boolean allowAll = false;
private void addAll(Set<BytesReference> query) {
if (allowAll == false) {
if (queries == null) {
queries = new HashSet<>();
}
queries.addAll(query);
}
}
private boolean isAllowAll() {
return allowAll;
}
private void setAllowAll(boolean allowAll) {
this.allowAll = allowAll;
}
}
}

View File

@ -99,6 +99,32 @@ public class IndicesPermissionTests extends ESTestCase {
assertThat(permissions.getIndexPermissions("_index").getQueries(), equalTo(query));
}
public void testAuthorizeMultipleGroupsMixedDls() {
IndexMetaData.Builder imbBuilder = IndexMetaData.builder("_index")
.settings(Settings.builder()
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 1)
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
)
.putAlias(AliasMetaData.builder("_alias"));
MetaData md = MetaData.builder().put(imbBuilder).build();
FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
Set<BytesReference> query = Collections.singleton(new BytesArray("{}"));
String[] fields = new String[]{"_field"};
Role role = Role.builder("_role")
.add(new FieldPermissions(fieldPermissionDef(fields, null)), query, IndexPrivilege.ALL, "_index")
.add(new FieldPermissions(fieldPermissionDef(null, null)), null, IndexPrivilege.ALL, "*")
.build();
IndicesAccessControl permissions = role.authorize(SearchAction.NAME, Sets.newHashSet("_index"), md, fieldPermissionsCache);
assertThat(permissions.getIndexPermissions("_index"), notNullValue());
assertTrue(permissions.getIndexPermissions("_index").getFieldPermissions().grantsAccessTo("_field"));
assertFalse(permissions.getIndexPermissions("_index").getFieldPermissions().hasFieldLevelSecurity());
// null implies that there is no DLS. Currently a index permissions only has queries defined
// on it and not a true document level permission object like fields
assertNull(permissions.getIndexPermissions("_index").getQueries());
}
public void testIndicesPrivilegesStreaming() throws IOException {
BytesStreamOutput out = new BytesStreamOutput();
String[] allowed = new String[]{randomAlphaOfLength(5) + "*", randomAlphaOfLength(5) + "*", randomAlphaOfLength(5) + "*"};