From 8e5855e62ebae5fe814367fa85f9bfdc3105213a Mon Sep 17 00:00:00 2001 From: Tim Vernum Date: Tue, 7 Nov 2017 19:31:24 +1100 Subject: [PATCH] Allow XPack user read-only access to index audit log (elastic/x-pack-elasticsearch#2906) The default internal XPack user no longer has access to the security index, but it should have read-only access to the audit log so that watches can be triggered based on audit events (but cannot write audit records) Original commit: elastic/x-pack-elasticsearch@5c37720dad14adeeef68dc55bb6f84481dc42bc0 --- .../xpack/security/user/XPackUser.java | 5 +- .../test/SecurityIntegTestCase.java | 5 +- .../xpack/security/SecurityTribeIT.java | 6 +-- .../xpack/security/user/XPackUserTests.java | 54 +++++++++++++++++++ 4 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 plugin/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/user/XPackUser.java b/plugin/src/main/java/org/elasticsearch/xpack/security/user/XPackUser.java index 56b5ecce224..67e71ddf88a 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/user/XPackUser.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/user/XPackUser.java @@ -5,6 +5,7 @@ */ package org.elasticsearch.xpack.security.user; +import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.authz.RoleDescriptor; import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.support.MetadataUtils; @@ -18,7 +19,9 @@ public class XPackUser extends User { public static final String ROLE_NAME = NAME; public static final Role ROLE = Role.builder(new RoleDescriptor(ROLE_NAME, new String[] { "all" }, new RoleDescriptor.IndicesPrivileges[] { - RoleDescriptor.IndicesPrivileges.builder().indices("/@&~(\\.security*)/").privileges("all").build()}, + RoleDescriptor.IndicesPrivileges.builder().indices("/@&~(\\.security.*)/").privileges("all").build(), + RoleDescriptor.IndicesPrivileges.builder().indices(IndexAuditTrail.INDEX_NAME_PREFIX + "-*").privileges("read").build() + }, new String[] { "*" }, MetadataUtils.DEFAULT_RESERVED_METADATA), null).build(); public static final XPackUser INSTANCE = new XPackUser(); diff --git a/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java index f267f40f228..5d6fba44896 100644 --- a/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java @@ -439,7 +439,10 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { } protected InternalSecurityClient internalSecurityClient() { - Client client = client(); + return internalSecurityClient(client()); + } + + protected InternalSecurityClient internalSecurityClient(Client client) { return new InternalSecurityClient(client.settings(), client.threadPool(), client); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java b/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java index 9025befad16..d59678bbb9f 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java @@ -48,10 +48,8 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.function.Function; @@ -142,8 +140,8 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { try { cluster2.wipe(Collections.emptySet()); try { - // this is a hack to clean up the .security index since only the XPack user or superusers can delete it - cluster2.getInstance(InternalClient.class) + // this is a hack to clean up the .security index since only the XPackSecurity user or superusers can delete it + internalSecurityClient(cluster2.client()) .admin().indices().prepareDelete(IndexLifecycleManager.INTERNAL_SECURITY_INDEX).get(); } catch (IndexNotFoundException e) { // ignore it since not all tests create this index... diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java new file mode 100644 index 00000000000..5cf30e2d499 --- /dev/null +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/user/XPackUserTests.java @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.security.user; + +import java.util.function.Predicate; + +import org.elasticsearch.action.get.GetAction; +import org.elasticsearch.action.index.IndexAction; +import org.elasticsearch.action.search.SearchAction; +import org.elasticsearch.action.update.UpdateAction; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.security.SecurityLifecycleService; +import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; +import org.elasticsearch.xpack.security.audit.index.IndexNameResolver; +import org.hamcrest.Matchers; +import org.joda.time.DateTime; + +public class XPackUserTests extends ESTestCase { + + public void testXPackUserCanAccessNonSecurityIndices() { + final String action = randomFrom(GetAction.NAME, SearchAction.NAME, IndexAction.NAME); + final Predicate predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action); + final String index = randomBoolean() ? randomAlphaOfLengthBetween(3, 12) : "." + randomAlphaOfLength(8); + assertThat(predicate.test(index), Matchers.is(true)); + } + + public void testXPackUserCannotAccessSecurityIndex() { + final String action = randomFrom(GetAction.NAME, SearchAction.NAME, IndexAction.NAME); + final Predicate predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action); + assertThat(predicate.test(SecurityLifecycleService.SECURITY_INDEX_NAME), Matchers.is(false)); + assertThat(predicate.test(SecurityLifecycleService.NEW_SECURITY_INDEX_NAME), Matchers.is(false)); + } + + public void testXPackUserCanReadAuditTrail() { + final String action = randomFrom(GetAction.NAME, SearchAction.NAME); + final Predicate predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action); + assertThat(predicate.test(getAuditLogName()), Matchers.is(true)); + } + + public void testXPackUserCannotWriteToAuditTrail() { + final String action = randomFrom(IndexAction.NAME, UpdateAction.NAME); + final Predicate predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action); + assertThat(predicate.test(getAuditLogName()), Matchers.is(false)); + } + + private String getAuditLogName() { + final DateTime date = new DateTime().plusDays(randomIntBetween(1, 360)); + final IndexNameResolver.Rollover rollover = randomFrom(IndexNameResolver.Rollover.values()); + return IndexNameResolver.resolve(IndexAuditTrail.INDEX_NAME_PREFIX, date, rollover); + } +} \ No newline at end of file