diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java b/plugin/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java index e39896b60ea..9788ff092d9 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/SecurityLifecycleService.java @@ -23,7 +23,6 @@ import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.authc.esnative.NativeRealmMigrator; import org.elasticsearch.xpack.security.support.IndexLifecycleManager; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.function.Predicate; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/support/IndexLifecycleManager.java b/plugin/src/main/java/org/elasticsearch/xpack/security/support/IndexLifecycleManager.java index 71ce98d9b23..f9edc3d9cf4 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/support/IndexLifecycleManager.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/support/IndexLifecycleManager.java @@ -18,9 +18,11 @@ import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateReque import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.collect.ImmutableOpenMap; @@ -38,12 +40,14 @@ import org.elasticsearch.xpack.template.TemplateUtils; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static org.elasticsearch.common.xcontent.XContentHelper.convertToMap; @@ -64,8 +68,7 @@ public class IndexLifecycleManager extends AbstractComponent { private final AtomicBoolean templateCreationPending = new AtomicBoolean(false); private final AtomicBoolean updateMappingPending = new AtomicBoolean(false); - final AtomicReference migrateDataState = - new AtomicReference<>(UpgradeState.NOT_STARTED); + private final AtomicReference migrateDataState = new AtomicReference<>(UpgradeState.NOT_STARTED); private volatile boolean templateIsUpToDate; private volatile boolean indexExists; @@ -136,7 +139,7 @@ public class IndexLifecycleManager extends AbstractComponent { public void clusterChanged(ClusterChangedEvent event) { final ClusterState state = event.state(); - this.indexExists = event.state().metaData().indices().get(indexName) != null; + this.indexExists = resolveConcreteIndex(indexName, event.state().metaData()) != null; this.indexAvailable = checkIndexAvailable(state); this.templateIsUpToDate = checkTemplateExistsAndIsUpToDate(state); this.mappingIsUpToDate = checkIndexMappingUpToDate(state); @@ -167,11 +170,11 @@ public class IndexLifecycleManager extends AbstractComponent { * Returns the routing-table for this index, or null if the index does not exist. */ private IndexRoutingTable getIndexRoutingTable(ClusterState clusterState) { - IndexMetaData metaData = clusterState.metaData().index(indexName); + IndexMetaData metaData = resolveConcreteIndex(indexName, clusterState.metaData()); if (metaData == null) { return null; } else { - return clusterState.routingTable().index(indexName); + return clusterState.routingTable().index(metaData.getIndex()); } } @@ -249,7 +252,7 @@ public class IndexLifecycleManager extends AbstractComponent { private static Set loadIndexMappingVersions(String indexName, ClusterState clusterState, Logger logger) { Set versions = new HashSet<>(); - IndexMetaData indexMetaData = clusterState.metaData().getIndices().get(indexName); + IndexMetaData indexMetaData = resolveConcreteIndex(indexName, clusterState.metaData()); if (indexMetaData != null) { for (Object object : indexMetaData.getMappings().values().toArray()) { MappingMetaData mappingMetaData = (MappingMetaData) object; @@ -262,6 +265,23 @@ public class IndexLifecycleManager extends AbstractComponent { return versions; } + /** + * Resolves a concrete index name or alias to a {@link IndexMetaData} instance. Requires + * that if supplied with an alias, the alias resolves to at most one concrete index. + */ + private static IndexMetaData resolveConcreteIndex(final String indexOrAliasName, final MetaData metaData) { + final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(indexOrAliasName); + if (aliasOrIndex != null) { + final List indices = aliasOrIndex.getIndices(); + if (aliasOrIndex.isAlias() && indices.size() > 1) { + throw new IllegalStateException("Alias [" + indexOrAliasName + "] points to more than one index: " + + indices.stream().map(imd -> imd.getIndex().getName()).collect(Collectors.toList())); + } + return indices.get(0); + } + return null; + } + private static Version readMappingVersion(String indexName, MappingMetaData mappingMetaData, Logger logger) { try { diff --git a/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java index a6fb958bc7c..b01e83d6597 100644 --- a/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java @@ -14,6 +14,8 @@ import org.elasticsearch.client.Client; import org.elasticsearch.client.node.NodeClient; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.health.ClusterHealthStatus; +import org.elasticsearch.cluster.metadata.AliasOrIndex; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.network.NetworkAddress; @@ -21,6 +23,7 @@ import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.gateway.GatewayService; +import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.xpack.XPackClient; @@ -442,9 +445,12 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { ClusterState clusterState = clusterService.state(); assertFalse(clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)); assertTrue(securityIndexMappingAndTemplateSufficientToRead(clusterState, logger)); - IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(SecurityLifecycleService.SECURITY_INDEX_NAME); - if (indexRoutingTable != null) { - assertTrue(indexRoutingTable.allPrimaryShardsActive()); + Index securityIndex = resolveSecurityIndex(clusterState.metaData()); + if (securityIndex != null) { + IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(securityIndex); + if (indexRoutingTable != null) { + assertTrue(indexRoutingTable.allPrimaryShardsActive()); + } } }); } @@ -456,9 +462,12 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { ClusterState clusterState = clusterService.state(); assertFalse(clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)); assertTrue(securityIndexMappingAndTemplateUpToDate(clusterState, logger)); - IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(SecurityLifecycleService.SECURITY_INDEX_NAME); - if (indexRoutingTable != null) { - assertTrue(indexRoutingTable.allPrimaryShardsActive()); + Index securityIndex = resolveSecurityIndex(clusterState.metaData()); + if (securityIndex != null) { + IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(securityIndex); + if (indexRoutingTable != null) { + assertTrue(indexRoutingTable.allPrimaryShardsActive()); + } } }); } @@ -472,4 +481,12 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { // ignore it since not all tests create this index... } } + + private static Index resolveSecurityIndex(MetaData metaData) { + final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(SecurityLifecycleService.SECURITY_INDEX_NAME); + if (aliasOrIndex != null) { + return aliasOrIndex.getIndices().get(0).getIndex(); + } + return null; + } } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityLifecycleServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityLifecycleServiceTests.java index 10a1ceb6fbd..b8d92192811 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityLifecycleServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityLifecycleServiceTests.java @@ -32,9 +32,7 @@ import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; -import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.service.ClusterService; -import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.test.ESTestCase; @@ -64,22 +62,19 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class SecurityLifecycleServiceTests extends ESTestCase { - private InternalClient client; private TransportClient transportClient; private ThreadPool threadPool; - private ClusterService clusterService; private NativeRealmMigrator nativeRealmMigrator; private SecurityLifecycleService securityLifecycleService; private static final ClusterState EMPTY_CLUSTER_STATE = new ClusterState.Builder(new ClusterName("test-cluster")).build(); - - CopyOnWriteArrayList listeners; + private CopyOnWriteArrayList listeners; @Before public void setup() { DiscoveryNode localNode = mock(DiscoveryNode.class); when(localNode.getHostAddress()).thenReturn(buildNewFakeTransportAddress().toString()); - clusterService = mock(ClusterService.class); + ClusterService clusterService = mock(ClusterService.class); when(clusterService.localNode()).thenReturn(localNode); threadPool = new TestThreadPool("security template service tests"); @@ -106,7 +101,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { return null; }).when(nativeRealmMigrator).performUpgrade(any(Version.class), any(ActionListener.class)); - client = new IClient(transportClient); + InternalClient client = new IClient(transportClient); securityLifecycleService = new SecurityLifecycleService(Settings.EMPTY, clusterService, threadPool, client, nativeRealmMigrator, mock(IndexAuditTrail.class)); listeners = new CopyOnWriteArrayList<>(); @@ -155,8 +150,9 @@ public class SecurityLifecycleServiceTests extends ESTestCase { final int numberOfSecurityIndices = 1; // .security + final ClusterState clusterState = clusterStateBuilder.build(); securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event", - clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); + clusterState, EMPTY_CLUSTER_STATE)); assertThat(securityLifecycleService.securityIndex().isTemplateUpToDate(), equalTo(false)); assertThat(listeners.size(), equalTo(numberOfSecurityIndices)); assertTrue(securityLifecycleService.securityIndex().isTemplateCreationPending()); @@ -165,7 +161,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { ActionListener listener = listeners.get(0); listeners.clear(); securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event", - clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); + clusterState, EMPTY_CLUSTER_STATE)); assertThat(securityLifecycleService.securityIndex().isTemplateUpToDate(), equalTo(false)); assertThat(listeners.size(), equalTo(0)); assertTrue(securityLifecycleService.securityIndex().isTemplateCreationPending()); @@ -177,7 +173,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { // ... we should be able to send a new update securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event", - clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); + clusterState, EMPTY_CLUSTER_STATE)); assertThat(securityLifecycleService.securityIndex().isTemplateUpToDate(), equalTo(false)); assertThat(listeners.size(), equalTo(1)); assertTrue(securityLifecycleService.securityIndex().isTemplateCreationPending()); @@ -192,7 +188,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { // and now let's see what happens if we get back a response listeners.clear(); securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event", - clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); + clusterState, EMPTY_CLUSTER_STATE)); assertThat(securityLifecycleService.securityIndex().isTemplateUpToDate(), equalTo(false)); assertTrue(securityLifecycleService.securityIndex().isTemplateCreationPending()); assertThat(listeners.size(), equalTo(1)); @@ -202,13 +198,9 @@ public class SecurityLifecycleServiceTests extends ESTestCase { } public void testMissingIndexTemplateIsIdentifiedAsMissing() throws IOException { - ClusterState.Builder clusterStateBuilder = new ClusterState.Builder(state()); // add the correct mapping String mappingString = "/" + SECURITY_TEMPLATE_NAME + ".json"; - IndexMetaData.Builder indexMeta = createIndexMetadata(SECURITY_INDEX_NAME, mappingString); - MetaData.Builder builder = new MetaData.Builder(clusterStateBuilder.build().getMetaData()); - builder.put(indexMeta); - clusterStateBuilder.metaData(builder); + ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(mappingString); checkTemplateUpdateWorkCorrectly(clusterStateBuilder); } @@ -221,7 +213,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { public void testOutdatedMappingIsIdentifiedAsNotUpToDate() throws IOException { String templateString = "/wrong-version-" + SECURITY_TEMPLATE_NAME + ".json"; final Version wrongVersion = Version.fromString("4.0.0"); - ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(templateString); + ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); final ClusterState clusterState = clusterStateBuilder.build(); assertFalse(securityIndexMappingAndTemplateUpToDate(clusterState, logger)); assertFalse(securityIndexMappingAndTemplateSufficientToRead(clusterState, logger)); @@ -305,8 +297,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { public void testUpToDateMappingsAreIdentifiedAsUpToDate() throws IOException { String securityTemplateString = "/" + SECURITY_TEMPLATE_NAME + ".json"; - ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping( - securityTemplateString); + ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(securityTemplateString); securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); assertTrue(securityLifecycleService.securityIndex().isMappingUpToDate()); @@ -315,8 +306,7 @@ public class SecurityLifecycleServiceTests extends ESTestCase { public void testMappingVersionMatching() throws IOException { String templateString = "/" + SECURITY_TEMPLATE_NAME + ".json"; - ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(templateString - ); + ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); securityLifecycleService.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); final IndexLifecycleManager securityIndex = securityLifecycleService.securityIndex(); @@ -326,12 +316,12 @@ public class SecurityLifecycleServiceTests extends ESTestCase { public void testMissingVersionMappingThrowsError() throws IOException { String templateString = "/missing-version-" + SECURITY_TEMPLATE_NAME + ".json"; - ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(templateString - ); + ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); final ClusterState clusterState = clusterStateBuilder.build(); IllegalStateException exception = expectThrows(IllegalStateException.class, () -> securityIndexMappingAndTemplateUpToDate(clusterState, logger)); - assertEquals(exception.getMessage(), "Cannot read security-version string in index " + SECURITY_INDEX_NAME); + assertEquals("Cannot read security-version string in index " + SECURITY_INDEX_NAME, + exception.getMessage()); } public void testMissingIndexIsIdentifiedAsUpToDate() throws IOException { @@ -350,24 +340,22 @@ public class SecurityLifecycleServiceTests extends ESTestCase { } private ClusterState.Builder createClusterStateWithMapping(String securityTemplateString) throws IOException { - ImmutableOpenMap.Builder mapBuilder = ImmutableOpenMap.builder(); - IndexMetaData securityIndex = createIndexMetadata(SECURITY_INDEX_NAME, securityTemplateString).build(); - mapBuilder.put(SECURITY_INDEX_NAME, securityIndex); - MetaData.Builder metaDataBuilder = new MetaData.Builder(); - metaDataBuilder.indices(mapBuilder.build()); + final ClusterState clusterState = createClusterStateWithIndex(securityTemplateString).build(); + final String indexName = clusterState.metaData().getAliasAndIndexLookup() + .get(SECURITY_INDEX_NAME).getIndices().get(0).getIndex().getName(); + return ClusterState.builder(clusterState).routingTable(SecurityTestUtils.buildIndexRoutingTable(indexName)); + } + private ClusterState.Builder createClusterStateWithMappingAndTemplate(String securityTemplateString) throws IOException { + ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(securityTemplateString); + MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterStateBuilder.build().metaData()); String securityMappingString = "/" + SECURITY_TEMPLATE_NAME + ".json"; IndexTemplateMetaData.Builder securityTemplateMeta = getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityMappingString); metaDataBuilder.put(securityTemplateMeta); - - ClusterState.Builder clusterStateBuilder = ClusterState.builder(state()); - final RoutingTable routingTable = SecurityTestUtils.buildSecurityIndexRoutingTable(); - clusterStateBuilder.metaData(metaDataBuilder.build()).routingTable(routingTable); - return clusterStateBuilder; + return clusterStateBuilder.metaData(metaDataBuilder); } - private static IndexMetaData.Builder createIndexMetadata( - String indexName, String templateString) throws IOException { + private static IndexMetaData.Builder createIndexMetadata(String indexName, String templateString) throws IOException { String template = TemplateUtils.loadTemplate(templateString, Version.CURRENT.toString(), IndexLifecycleManager.TEMPLATE_VERSION_PATTERN); PutIndexTemplateRequest request = new PutIndexTemplateRequest(); @@ -385,19 +373,30 @@ public class SecurityLifecycleServiceTests extends ESTestCase { return indexMetaData; } - public static ClusterState.Builder createClusterStateWithTemplate(String securityTemplateString) throws IOException { - MetaData.Builder metaDataBuilder = new MetaData.Builder(); - - IndexTemplateMetaData.Builder securityTemplateBuilder = - getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityTemplateString); - metaDataBuilder.put(securityTemplateBuilder); + public ClusterState.Builder createClusterStateWithTemplate(String securityTemplateString) throws IOException { // add the correct mapping no matter what the template - String securityMappingString = "/" + SECURITY_TEMPLATE_NAME + ".json"; - IndexMetaData.Builder securityIndexMeta = - createIndexMetadata(SECURITY_INDEX_NAME, securityMappingString); - metaDataBuilder.put(securityIndexMeta); + ClusterState clusterState = createClusterStateWithIndex("/" + SECURITY_TEMPLATE_NAME + ".json").build(); + final MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterState.metaData()); + metaDataBuilder.put(getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityTemplateString)); + return ClusterState.builder(clusterState).metaData(metaDataBuilder); + } - return ClusterState.builder(state()).metaData(metaDataBuilder.build()); + private ClusterState.Builder createClusterStateWithIndex(String securityTemplate) throws IOException { + final MetaData.Builder metaDataBuilder = new MetaData.Builder(); + final boolean withAlias = randomBoolean(); + final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + metaDataBuilder.put(createIndexMetadata(securityIndexName, securityTemplate)); + + ClusterState.Builder clusterStateBuilder = ClusterState.builder(state()); + if (withAlias) { + // try with .security index as an alias + clusterStateBuilder.metaData(SecurityTestUtils.addAliasToMetaData(metaDataBuilder.build(), securityIndexName)); + } else { + // try with .security index as a concrete index + clusterStateBuilder.metaData(metaDataBuilder); + } + + return clusterStateBuilder; } private static IndexTemplateMetaData.Builder getIndexTemplateMetaData( diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java index 430a05cc396..09791ca3f4c 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/IndicesAndAliasesResolverTests.java @@ -55,6 +55,7 @@ import org.elasticsearch.xpack.security.authz.permission.FieldPermissionsCache; import org.elasticsearch.xpack.security.authz.permission.Role; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; import org.elasticsearch.xpack.security.authz.store.ReservedRolesStore; +import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.elasticsearch.xpack.security.user.AnonymousUser; import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.XPackUser; @@ -66,6 +67,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder; @@ -101,7 +103,10 @@ public class IndicesAndAliasesResolverTests extends ESTestCase { .build(); indexNameExpressionResolver = new IndexNameExpressionResolver(Settings.EMPTY); - metaData = MetaData.builder() + + final boolean withAlias = randomBoolean(); + final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + MetaData metaData = MetaData.builder() .put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar")).settings(settings)) .put(indexBuilder("foobar").putAlias(AliasMetaData.builder("foofoobar")).settings(settings)) .put(indexBuilder("closed").state(IndexMetaData.State.CLOSE) @@ -117,7 +122,12 @@ public class IndicesAndAliasesResolverTests extends ESTestCase { .put(indexBuilder("-index11").settings(settings)) .put(indexBuilder("-index20").settings(settings)) .put(indexBuilder("-index21").settings(settings)) - .put(indexBuilder(SecurityLifecycleService.SECURITY_INDEX_NAME).settings(settings)).build(); + .put(indexBuilder(securityIndexName).settings(settings)).build(); + + if (withAlias) { + metaData = SecurityTestUtils.addAliasToMetaData(metaData, securityIndexName); + } + this.metaData = metaData; user = new User("user", "role"); userDashIndices = new User("dash", "dash"); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java index 8ba74c5567a..a28cfb62efe 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/store/NativeRolesStoreTests.java @@ -42,6 +42,7 @@ import org.elasticsearch.xpack.security.action.role.PutRoleRequest; import org.elasticsearch.xpack.security.audit.index.IndexAuditTrail; import org.elasticsearch.xpack.security.authz.RoleDescriptor; import org.elasticsearch.xpack.security.authz.RoleDescriptor.IndicesPrivileges; +import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.junit.After; import org.junit.Before; @@ -55,6 +56,7 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import static org.elasticsearch.cluster.routing.RecoverySource.StoreRecoverySource.EXISTING_STORE_INSTANCE; +import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.instanceOf; @@ -242,18 +244,26 @@ public class NativeRolesStoreTests extends ESTestCase { } private ClusterState getClusterStateWithSecurityIndex() { + final boolean withAlias = randomBoolean(); + final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); + Settings settings = Settings.builder() .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT) .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) .build(); MetaData metaData = MetaData.builder() - .put(IndexMetaData.builder(SecurityLifecycleService.SECURITY_INDEX_NAME).settings(settings)) + .put(IndexMetaData.builder(securityIndexName).settings(settings)) .put(new IndexTemplateMetaData(SecurityLifecycleService.SECURITY_TEMPLATE_NAME, 0, 0, - Collections.singletonList(SecurityLifecycleService.SECURITY_INDEX_NAME), Settings.EMPTY, ImmutableOpenMap.of(), + Collections.singletonList(securityIndexName), Settings.EMPTY, ImmutableOpenMap.of(), ImmutableOpenMap.of(), ImmutableOpenMap.of())) .build(); - Index index = new Index(SecurityLifecycleService.SECURITY_INDEX_NAME, UUID.randomUUID().toString()); + + if (withAlias) { + metaData = SecurityTestUtils.addAliasToMetaData(metaData, securityIndexName); + } + + Index index = new Index(securityIndexName, UUID.randomUUID().toString()); ShardRouting shardRouting = ShardRouting.newUnassigned(new ShardId(index, 0), true, EXISTING_STORE_INSTANCE, new UnassignedInfo(Reason.INDEX_CREATED, "")); IndexShardRoutingTable table = new IndexShardRoutingTable.Builder(new ShardId(index, 0)) @@ -266,10 +276,12 @@ public class NativeRolesStoreTests extends ESTestCase { .build()) .build(); - return ClusterState.builder(new ClusterName(NativeRolesStoreTests.class.getName())) + ClusterState clusterState = ClusterState.builder(new ClusterName(NativeRolesStoreTests.class.getName())) .metaData(metaData) .routingTable(routingTable) .build(); + + return clusterState; } private ClusterState getEmptyClusterState() { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java b/plugin/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java index c4177d49332..f3c97bd6c73 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/test/SecurityTestUtils.java @@ -6,36 +6,29 @@ package org.elasticsearch.xpack.security.test; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.Version; -import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.UnassignedInfo; -import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.io.FileSystemUtils; import org.elasticsearch.common.io.Streams; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.security.SecurityLifecycleService; -import org.elasticsearch.xpack.security.authz.store.NativeRolesStoreTests; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; import java.util.UUID; import static org.elasticsearch.cluster.routing.RecoverySource.StoreRecoverySource.EXISTING_STORE_INSTANCE; +import static org.elasticsearch.xpack.security.SecurityLifecycleService.SECURITY_INDEX_NAME; public class SecurityTestUtils { @@ -72,30 +65,6 @@ public class SecurityTestUtils { return writeFile(folder, name, content.getBytes(StandardCharsets.UTF_8)); } - public static ClusterState getClusterStateWithSecurityIndex() { - Settings settings = Settings.builder() - .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT) - .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) - .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) - .build(); - MetaData metaData = MetaData.builder() - .put(IndexMetaData.builder(SecurityLifecycleService.SECURITY_INDEX_NAME).settings(settings)) - .put(new IndexTemplateMetaData(SecurityLifecycleService.SECURITY_TEMPLATE_NAME, 0, 0, - Collections.singletonList(SecurityLifecycleService.SECURITY_INDEX_NAME), Settings.EMPTY, ImmutableOpenMap.of(), - ImmutableOpenMap.of(), ImmutableOpenMap.of())) - .build(); - RoutingTable routingTable = buildSecurityIndexRoutingTable(); - - return ClusterState.builder(new ClusterName(NativeRolesStoreTests.class.getName())) - .metaData(metaData) - .routingTable(routingTable) - .build(); - } - - public static RoutingTable buildSecurityIndexRoutingTable() { - return buildIndexRoutingTable(SecurityLifecycleService.SECURITY_INDEX_NAME); - } - public static RoutingTable buildIndexRoutingTable(String indexName) { Index index = new Index(indexName, UUID.randomUUID().toString()); ShardRouting shardRouting = ShardRouting.newUnassigned(new ShardId(index, 0), true, EXISTING_STORE_INSTANCE, @@ -108,4 +77,16 @@ public class SecurityTestUtils { .add(IndexRoutingTable.builder(index).addIndexShard(table).build()) .build(); } + + /** + * Adds the index alias {@code .security} to the underlying concrete index. + */ + public static MetaData addAliasToMetaData(MetaData metaData, String indexName) { + AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SECURITY_INDEX_NAME).build(); + MetaData.Builder metaDataBuilder = new MetaData.Builder(metaData); + IndexMetaData indexMetaData = metaData.index(indexName); + metaDataBuilder.put(IndexMetaData.builder(indexMetaData).putAlias(aliasMetaData)); + return metaDataBuilder.build(); + } + }