Enables security to work with index aliases (elastic/x-pack-elasticsearch#1496)

This commit enables security to work with an index named .security (as
it could before) OR an alias named .security that points to a concrete
index by a different name that has the security index.  This prepares
the ability to migrate from a 5.x to 6.x security index that allows
changing and re-indexing the underlying security index while maintaining
a .security alias that points to the underlying updated index.

relates elastic/x-pack-elasticsearch#1216

Original commit: elastic/x-pack-elasticsearch@9fee12e5a0
This commit is contained in:
Ali Beyad 2017-05-23 09:10:06 -04:00 committed by GitHub
parent 521b7a1940
commit ec175debd0
7 changed files with 138 additions and 100 deletions

View File

@ -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;

View File

@ -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<UpgradeState> migrateDataState =
new AtomicReference<>(UpgradeState.NOT_STARTED);
private final AtomicReference<UpgradeState> 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 <code>null</code> 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<Version> loadIndexMappingVersions(String indexName,
ClusterState clusterState, Logger logger) {
Set<Version> 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<IndexMetaData> 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 {

View File

@ -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,10 +445,13 @@ 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);
Index securityIndex = resolveSecurityIndex(clusterState.metaData());
if (securityIndex != null) {
IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(securityIndex);
if (indexRoutingTable != null) {
assertTrue(indexRoutingTable.allPrimaryShardsActive());
}
}
});
}
}
@ -456,10 +462,13 @@ 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);
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;
}
}

View File

@ -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<ActionListener> listeners;
private CopyOnWriteArrayList<ActionListener> 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(

View File

@ -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");

View File

@ -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() {

View File

@ -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();
}
}