Security Tokens moved to a new separate index (#40742)

This commit introduces the `.security-tokens` and `.security-tokens-7`
alias-index pair. Because index snapshotting is at the index level granularity
(ie you cannot snapshot a subset of an index) snapshoting .`security` had
the undesirable effect of storing ephemeral security tokens. The changes
herein address this issue by moving tokens "seamlessly" (without user
intervention) to another index, so that a "Security Backup" (ie snapshot of
`.security`) would not be bloated by ephemeral data.
This commit is contained in:
Albert Zaharovits 2019-05-01 14:53:56 +03:00 committed by GitHub
parent bc333a5cbf
commit 990be1f806
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 2081 additions and 859 deletions

View File

@ -14,12 +14,15 @@ import java.util.Collections;
import java.util.Set; import java.util.Set;
public final class RestrictedIndicesNames { public final class RestrictedIndicesNames {
public static final String INTERNAL_SECURITY_INDEX_6 = ".security-6"; public static final String INTERNAL_SECURITY_MAIN_INDEX_6 = ".security-6";
public static final String INTERNAL_SECURITY_INDEX_7 = ".security-7"; public static final String INTERNAL_SECURITY_MAIN_INDEX_7 = ".security-7";
public static final String SECURITY_INDEX_NAME = ".security"; public static final String SECURITY_MAIN_ALIAS = ".security";
public static final Set<String> RESTRICTED_NAMES = Collections.unmodifiableSet( public static final String INTERNAL_SECURITY_TOKENS_INDEX_7 = ".security-tokens-7";
Sets.newHashSet(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX_6, INTERNAL_SECURITY_INDEX_7)); public static final String SECURITY_TOKENS_ALIAS = ".security-tokens";
public static final Set<String> RESTRICTED_NAMES = Collections.unmodifiableSet(Sets.newHashSet(SECURITY_MAIN_ALIAS,
INTERNAL_SECURITY_MAIN_INDEX_6, INTERNAL_SECURITY_MAIN_INDEX_7, INTERNAL_SECURITY_TOKENS_INDEX_7, SECURITY_TOKENS_ALIAS));
public static final Automaton NAMES_AUTOMATON = Automatons.patterns(RESTRICTED_NAMES); public static final Automaton NAMES_AUTOMATON = Automatons.patterns(RESTRICTED_NAMES);

View File

@ -1,5 +1,5 @@
{ {
"index_patterns" : [ ".security-*" ], "index_patterns" : [ ".security-7" ],
"order" : 1000, "order" : 1000,
"settings" : { "settings" : {
"number_of_shards" : 1, "number_of_shards" : 1,

View File

@ -0,0 +1,96 @@
{
"index_patterns" : [ ".security-tokens-7" ],
"order" : 1000,
"settings" : {
"number_of_shards" : 1,
"number_of_replicas" : 0,
"auto_expand_replicas" : "0-1",
"index.priority": 1000,
"index.format": 7
},
"mappings" : {
"_doc" : {
"_meta": {
"security-version": "${security.template.version}"
},
"dynamic" : "strict",
"properties" : {
"doc_type" : {
"type" : "keyword"
},
"creation_time" : {
"type" : "date",
"format" : "epoch_millis"
},
"refresh_token" : {
"type" : "object",
"properties" : {
"token" : {
"type" : "keyword"
},
"refreshed" : {
"type" : "boolean"
},
"refresh_time": {
"type": "date",
"format": "epoch_millis"
},
"superseded_by": {
"type": "keyword"
},
"invalidated" : {
"type" : "boolean"
},
"client" : {
"type" : "object",
"properties" : {
"type" : {
"type" : "keyword"
},
"user" : {
"type" : "keyword"
},
"realm" : {
"type" : "keyword"
}
}
}
}
},
"access_token" : {
"type" : "object",
"properties" : {
"user_token" : {
"type" : "object",
"properties" : {
"id" : {
"type" : "keyword"
},
"expiration_time" : {
"type" : "date",
"format" : "epoch_millis"
},
"version" : {
"type" : "integer"
},
"metadata" : {
"type" : "object",
"dynamic" : false
},
"authentication" : {
"type" : "binary"
}
}
},
"invalidated" : {
"type" : "boolean"
},
"realm" : {
"type" : "keyword"
}
}
}
}
}
}
}

View File

@ -601,14 +601,14 @@ public class ReservedRolesStoreTests extends ESTestCase {
private void assertMonitoringOnRestrictedIndices(Role role) { private void assertMonitoringOnRestrictedIndices(Role role) {
final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
final MetaData metaData = new MetaData.Builder() final MetaData metaData = new MetaData.Builder()
.put(new IndexMetaData.Builder(internalSecurityIndex) .put(new IndexMetaData.Builder(internalSecurityIndex)
.settings(indexSettings) .settings(indexSettings)
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
.build(), true) .build(), true)
.build(); .build();
final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY); final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
@ -616,10 +616,10 @@ public class ReservedRolesStoreTests extends ESTestCase {
GetSettingsAction.NAME, IndicesShardStoresAction.NAME, UpgradeStatusAction.NAME, RecoveryAction.NAME); GetSettingsAction.NAME, IndicesShardStoresAction.NAME, UpgradeStatusAction.NAME, RecoveryAction.NAME);
for (final String indexMonitoringActionName : indexMonitoringActionNamesList) { for (final String indexMonitoringActionName : indexMonitoringActionNamesList) {
final Map<String, IndexAccessControl> authzMap = role.indices().authorize(indexMonitoringActionName, final Map<String, IndexAccessControl> authzMap = role.indices().authorize(indexMonitoringActionName,
Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_INDEX_NAME), Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_MAIN_ALIAS),
metaData.getAliasAndIndexLookup(), fieldPermissionsCache); metaData.getAliasAndIndexLookup(), fieldPermissionsCache);
assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true)); assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true));
assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true)); assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).isGranted(), is(true));
} }
} }
@ -713,8 +713,8 @@ public class ReservedRolesStoreTests extends ESTestCase {
assertThat(superuserRole.cluster().check("internal:admin/foo", request), is(false)); assertThat(superuserRole.cluster().check("internal:admin/foo", request), is(false));
final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
final MetaData metaData = new MetaData.Builder() final MetaData metaData = new MetaData.Builder()
.put(new IndexMetaData.Builder("a1").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("a1").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
.put(new IndexMetaData.Builder("a2").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("a2").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
@ -731,7 +731,7 @@ public class ReservedRolesStoreTests extends ESTestCase {
.settings(indexSettings) .settings(indexSettings)
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
.build(), true) .build(), true)
.build(); .build();
@ -753,8 +753,8 @@ public class ReservedRolesStoreTests extends ESTestCase {
assertThat(authzMap.get("aaaaaa").isGranted(), is(true)); assertThat(authzMap.get("aaaaaa").isGranted(), is(true));
assertThat(authzMap.get("b").isGranted(), is(true)); assertThat(authzMap.get("b").isGranted(), is(true));
authzMap = superuserRole.indices().authorize(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME), authzMap = superuserRole.indices().authorize(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME),
Sets.newHashSet(RestrictedIndicesNames.SECURITY_INDEX_NAME), lookup, fieldPermissionsCache); Sets.newHashSet(RestrictedIndicesNames.SECURITY_MAIN_ALIAS), lookup, fieldPermissionsCache);
assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true)); assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).isGranted(), is(true));
assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true)); assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true));
assertTrue(superuserRole.indices().check(SearchAction.NAME)); assertTrue(superuserRole.indices().check(SearchAction.NAME));
assertFalse(superuserRole.indices().check("unknown")); assertFalse(superuserRole.indices().check("unknown"));
@ -762,7 +762,7 @@ public class ReservedRolesStoreTests extends ESTestCase {
assertThat(superuserRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(true)); assertThat(superuserRole.runAs().check(randomAlphaOfLengthBetween(1, 30)), is(true));
assertThat(superuserRole.indices().allowedIndicesMatcher(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME)) assertThat(superuserRole.indices().allowedIndicesMatcher(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME))
.test(RestrictedIndicesNames.SECURITY_INDEX_NAME), is(true)); .test(RestrictedIndicesNames.SECURITY_MAIN_ALIAS), is(true));
assertThat(superuserRole.indices().allowedIndicesMatcher(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME)) assertThat(superuserRole.indices().allowedIndicesMatcher(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME))
.test(internalSecurityIndex), is(true)); .test(internalSecurityIndex), is(true));
} }

View File

@ -258,9 +258,9 @@ import static java.util.Collections.singletonList;
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
import static org.elasticsearch.xpack.core.XPackSettings.API_KEY_SERVICE_ENABLED_SETTING; import static org.elasticsearch.xpack.core.XPackSettings.API_KEY_SERVICE_ENABLED_SETTING;
import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED; import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7;
public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin, public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin,
DiscoveryPlugin, MapperPlugin, ExtensiblePlugin { DiscoveryPlugin, MapperPlugin, ExtensiblePlugin {
@ -406,9 +406,10 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
components.add(auditTrailService); components.add(auditTrailService);
this.auditTrailService.set(auditTrailService); this.auditTrailService.set(auditTrailService);
securityIndex.set(SecurityIndexManager.buildSecurityIndexManager(client, clusterService)); securityIndex.set(SecurityIndexManager.buildSecurityMainIndexManager(client, clusterService));
final TokenService tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex.get(), clusterService); final TokenService tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex.get(),
SecurityIndexManager.buildSecurityTokensIndexManager(client, clusterService), clusterService);
this.tokenService.set(tokenService); this.tokenService.set(tokenService);
components.add(tokenService); components.add(tokenService);
@ -948,7 +949,7 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
public UnaryOperator<Map<String, IndexTemplateMetaData>> getIndexTemplateMetaDataUpgrader() { public UnaryOperator<Map<String, IndexTemplateMetaData>> getIndexTemplateMetaDataUpgrader() {
return templates -> { return templates -> {
// .security index is not managed by using templates anymore // .security index is not managed by using templates anymore
templates.remove(SECURITY_TEMPLATE_NAME); templates.remove(SECURITY_MAIN_TEMPLATE_7);
templates.remove("security_audit_log"); templates.remove("security_audit_log");
return templates; return templates;
}; };
@ -1015,9 +1016,9 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
@Override @Override
public void accept(DiscoveryNode node, ClusterState state) { public void accept(DiscoveryNode node, ClusterState state) {
if (state.getNodes().getMinNodeVersion().before(Version.V_7_0_0)) { if (state.getNodes().getMinNodeVersion().before(Version.V_7_0_0)) {
IndexMetaData indexMetaData = state.getMetaData().getIndices().get(SECURITY_INDEX_NAME); IndexMetaData indexMetaData = state.getMetaData().getIndices().get(SECURITY_MAIN_ALIAS);
if (indexMetaData != null && INDEX_FORMAT_SETTING.get(indexMetaData.getSettings()) < INTERNAL_INDEX_FORMAT) { if (indexMetaData != null && INDEX_FORMAT_SETTING.get(indexMetaData.getSettings()) < INTERNAL_MAIN_INDEX_FORMAT) {
throw new IllegalStateException("Security index is not on the current version [" + INTERNAL_INDEX_FORMAT + "] - " + throw new IllegalStateException("Security index is not on the current version [" + INTERNAL_MAIN_INDEX_FORMAT + "] - " +
"The Upgrade API must be run for 7.x nodes to join the cluster"); "The Upgrade API must be run for 7.x nodes to join the cluster");
} }
} }

View File

@ -98,7 +98,7 @@ import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING; import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING;
import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
public class ApiKeyService { public class ApiKeyService {
@ -207,7 +207,7 @@ public class ApiKeyService {
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("expiration_time"))); .should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("expiration_time")));
boolQuery.filter(expiredQuery); boolQuery.filter(expiredQuery);
final SearchRequest searchRequest = client.prepareSearch(SECURITY_INDEX_NAME) final SearchRequest searchRequest = client.prepareSearch(SECURITY_MAIN_ALIAS)
.setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings))
.setQuery(boolQuery) .setQuery(boolQuery)
.setVersion(false) .setVersion(false)
@ -286,7 +286,7 @@ public class ApiKeyService {
.endObject() .endObject()
.endObject(); .endObject();
final IndexRequest indexRequest = final IndexRequest indexRequest =
client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME) client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME)
.setSource(builder) .setSource(builder)
.setRefreshPolicy(request.getRefreshPolicy()) .setRefreshPolicy(request.getRefreshPolicy())
.request(); .request();
@ -319,7 +319,7 @@ public class ApiKeyService {
if (credentials != null) { if (credentials != null) {
final GetRequest getRequest = client final GetRequest getRequest = client
.prepareGet(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, credentials.getId()) .prepareGet(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, credentials.getId())
.setFetchSource(true) .setFetchSource(true)
.request(); .request();
executeAsyncWithOrigin(ctx, SECURITY_ORIGIN, getRequest, ActionListener.<GetResponse>wrap(response -> { executeAsyncWithOrigin(ctx, SECURITY_ORIGIN, getRequest, ActionListener.<GetResponse>wrap(response -> {
@ -727,7 +727,7 @@ public class ApiKeyService {
expiredQuery.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("expiration_time"))); expiredQuery.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("expiration_time")));
boolQuery.filter(expiredQuery); boolQuery.filter(expiredQuery);
} }
final SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) final SearchRequest request = client.prepareSearch(SECURITY_MAIN_ALIAS)
.setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings))
.setQuery(boolQuery) .setQuery(boolQuery)
.setVersion(false) .setVersion(false)
@ -801,7 +801,7 @@ public class ApiKeyService {
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
for (String apiKeyId : apiKeyIds) { for (String apiKeyId : apiKeyIds) {
UpdateRequest request = client UpdateRequest request = client
.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, apiKeyId) .prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, apiKeyId)
.setDoc(Collections.singletonMap("api_key_invalidated", true)) .setDoc(Collections.singletonMap("api_key_invalidated", true))
.request(); .request();
bulkRequestBuilder.add(request); bulkRequestBuilder.add(request);

View File

@ -22,7 +22,7 @@ import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.ScrollableHitSource; import org.elasticsearch.index.reindex.ScrollableHitSource;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.threadpool.ThreadPool.Names; import org.elasticsearch.threadpool.ThreadPool.Names;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
@ -51,7 +51,7 @@ public final class ExpiredApiKeysRemover extends AbstractRunnable {
@Override @Override
public void doRun() { public void doRun() {
DeleteByQueryRequest expiredDbq = new DeleteByQueryRequest(SecurityIndexManager.SECURITY_INDEX_NAME); DeleteByQueryRequest expiredDbq = new DeleteByQueryRequest(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
if (timeout != TimeValue.MINUS_ONE) { if (timeout != TimeValue.MINUS_ONE) {
expiredDbq.setTimeout(timeout); expiredDbq.setTimeout(timeout);
expiredDbq.getSearchRequest().source().timeout(timeout); expiredDbq.getSearchRequest().source().timeout(timeout);

View File

@ -26,6 +26,8 @@ import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import java.time.Instant; import java.time.Instant;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import static org.elasticsearch.action.support.TransportActions.isShardNotAvailableException; import static org.elasticsearch.action.support.TransportActions.isShardNotAvailableException;
@ -33,25 +35,44 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
/** /**
* Responsible for cleaning the invalidated and expired tokens from the security index. * Responsible for cleaning the invalidated and expired tokens from the security indices (`main` and `tokens`).
* The document gets deleted if it was created more than 24 hours which is the maximum * The document is deleted if it was created more than {@code #MAXIMUM_TOKEN_LIFETIME_HOURS} hours in the past.
* lifetime of a refresh token
*/ */
final class ExpiredTokenRemover extends AbstractRunnable { final class ExpiredTokenRemover extends AbstractRunnable {
private static final Logger logger = LogManager.getLogger(ExpiredTokenRemover.class); private static final Logger logger = LogManager.getLogger(ExpiredTokenRemover.class);
private final Client client; public static final long MAXIMUM_TOKEN_LIFETIME_HOURS = 24L;
private final AtomicBoolean inProgress = new AtomicBoolean(false);
private final TimeValue timeout;
ExpiredTokenRemover(Settings settings, Client client) { private final Client client;
private final SecurityIndexManager securityMainIndex;
private final SecurityIndexManager securityTokensIndex;
private final AtomicBoolean inProgress;
private final TimeValue timeout;
private boolean checkMainIndexForExpiredTokens;
ExpiredTokenRemover(Settings settings, Client client, SecurityIndexManager securityMainIndex,
SecurityIndexManager securityTokensIndex) {
this.client = client; this.client = client;
this.securityMainIndex = securityMainIndex;
this.securityTokensIndex = securityTokensIndex;
this.inProgress = new AtomicBoolean(false);
this.timeout = TokenService.DELETE_TIMEOUT.get(settings); this.timeout = TokenService.DELETE_TIMEOUT.get(settings);
this.checkMainIndexForExpiredTokens = true;
} }
@Override @Override
public void doRun() { public void doRun() {
DeleteByQueryRequest expiredDbq = new DeleteByQueryRequest(SecurityIndexManager.SECURITY_INDEX_NAME); final List<String> indicesWithTokens = new ArrayList<>();
if (securityTokensIndex.isAvailable()) {
indicesWithTokens.add(securityTokensIndex.aliasName());
}
if (securityMainIndex.isAvailable() && checkMainIndexForExpiredTokens) {
indicesWithTokens.add(securityMainIndex.aliasName());
}
if (indicesWithTokens.isEmpty()) {
return;
}
DeleteByQueryRequest expiredDbq = new DeleteByQueryRequest(indicesWithTokens.toArray(new String[0]));
if (timeout != TimeValue.MINUS_ONE) { if (timeout != TimeValue.MINUS_ONE) {
expiredDbq.setTimeout(timeout); expiredDbq.setTimeout(timeout);
expiredDbq.getSearchRequest().source().timeout(timeout); expiredDbq.getSearchRequest().source().timeout(timeout);
@ -59,12 +80,20 @@ final class ExpiredTokenRemover extends AbstractRunnable {
final Instant now = Instant.now(); final Instant now = Instant.now();
expiredDbq expiredDbq
.setQuery(QueryBuilders.boolQuery() .setQuery(QueryBuilders.boolQuery()
.filter(QueryBuilders.termsQuery("doc_type", "token")) .filter(QueryBuilders.termsQuery("doc_type", TokenService.TOKEN_DOC_TYPE))
.filter(QueryBuilders.rangeQuery("creation_time").lte(now.minus(24L, ChronoUnit.HOURS).toEpochMilli()))); .filter(QueryBuilders.rangeQuery("creation_time")
.lte(now.minus(MAXIMUM_TOKEN_LIFETIME_HOURS, ChronoUnit.HOURS).toEpochMilli())));
logger.trace(() -> new ParameterizedMessage("Removing old tokens: [{}]", Strings.toString(expiredDbq))); logger.trace(() -> new ParameterizedMessage("Removing old tokens: [{}]", Strings.toString(expiredDbq)));
executeAsyncWithOrigin(client, SECURITY_ORIGIN, DeleteByQueryAction.INSTANCE, expiredDbq, executeAsyncWithOrigin(client, SECURITY_ORIGIN, DeleteByQueryAction.INSTANCE, expiredDbq,
ActionListener.wrap(r -> { ActionListener.wrap(bulkResponse -> {
debugDbqResponse(r); debugDbqResponse(bulkResponse);
// tokens can still linger on the main index for their maximum lifetime after the tokens index has been created, because
// only after the tokens index has been created all nodes will store tokens there and not on the main security index
if (checkMainIndexForExpiredTokens && securityTokensIndex.indexExists()
&& securityTokensIndex.getCreationTime().isBefore(now.minus(MAXIMUM_TOKEN_LIFETIME_HOURS, ChronoUnit.HOURS))
&& bulkResponse.getBulkFailures().isEmpty() && bulkResponse.getSearchFailures().isEmpty()) {
checkMainIndexForExpiredTokens = false;
}
markComplete(); markComplete();
}, this::onFailure)); }, this::onFailure));
} }

View File

@ -66,7 +66,7 @@ import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING; import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING;
import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
/** /**
* NativeUsersStore is a store for users that reads from an Elasticsearch index. This store is responsible for fetching the full * NativeUsersStore is a store for users that reads from an Elasticsearch index. This store is responsible for fetching the full
@ -146,7 +146,7 @@ public class NativeUsersStore {
} }
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false); final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) { try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) {
SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) SearchRequest request = client.prepareSearch(SECURITY_MAIN_ALIAS)
.setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings))
.setQuery(query) .setQuery(query)
.setSize(1000) .setSize(1000)
@ -171,7 +171,7 @@ public class NativeUsersStore {
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareSearch(SECURITY_INDEX_NAME) client.prepareSearch(SECURITY_MAIN_ALIAS)
.setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), USER_DOC_TYPE)) .setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), USER_DOC_TYPE))
.setSize(0) .setSize(0)
.setTrackTotalHits(true) .setTrackTotalHits(true)
@ -205,7 +205,7 @@ public class NativeUsersStore {
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareGet(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, user)).request(), client.prepareGet(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, user)).request(),
new ActionListener<GetResponse>() { new ActionListener<GetResponse>() {
@Override @Override
public void onResponse(GetResponse response) { public void onResponse(GetResponse response) {
@ -245,7 +245,7 @@ public class NativeUsersStore {
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(docType, username)) client.prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(docType, username))
.setDoc(Requests.INDEX_CONTENT_TYPE, Fields.PASSWORD.getPreferredName(), .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.PASSWORD.getPreferredName(),
String.valueOf(request.passwordHash())) String.valueOf(request.passwordHash()))
.setRefreshPolicy(request.getRefreshPolicy()).request(), .setRefreshPolicy(request.getRefreshPolicy()).request(),
@ -283,7 +283,7 @@ public class NativeUsersStore {
private void createReservedUser(String username, char[] passwordHash, RefreshPolicy refresh, ActionListener<Void> listener) { private void createReservedUser(String username, char[] passwordHash, RefreshPolicy refresh, ActionListener<Void> listener) {
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(RESERVED_USER_TYPE, username)) client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(RESERVED_USER_TYPE, username))
.setSource(Fields.PASSWORD.getPreferredName(), String.valueOf(passwordHash), Fields.ENABLED.getPreferredName(), .setSource(Fields.PASSWORD.getPreferredName(), String.valueOf(passwordHash), Fields.ENABLED.getPreferredName(),
true, Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE) true, Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE)
.setRefreshPolicy(refresh).request(), .setRefreshPolicy(refresh).request(),
@ -323,7 +323,7 @@ public class NativeUsersStore {
// We must have an existing document // We must have an existing document
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, putUserRequest.username())) client.prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, putUserRequest.username()))
.setDoc(Requests.INDEX_CONTENT_TYPE, .setDoc(Requests.INDEX_CONTENT_TYPE,
Fields.USERNAME.getPreferredName(), putUserRequest.username(), Fields.USERNAME.getPreferredName(), putUserRequest.username(),
Fields.ROLES.getPreferredName(), putUserRequest.roles(), Fields.ROLES.getPreferredName(), putUserRequest.roles(),
@ -367,7 +367,7 @@ public class NativeUsersStore {
assert putUserRequest.passwordHash() != null; assert putUserRequest.passwordHash() != null;
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, putUserRequest.username())) client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, putUserRequest.username()))
.setSource(Fields.USERNAME.getPreferredName(), putUserRequest.username(), .setSource(Fields.USERNAME.getPreferredName(), putUserRequest.username(),
Fields.PASSWORD.getPreferredName(), String.valueOf(putUserRequest.passwordHash()), Fields.PASSWORD.getPreferredName(), String.valueOf(putUserRequest.passwordHash()),
Fields.ROLES.getPreferredName(), putUserRequest.roles(), Fields.ROLES.getPreferredName(), putUserRequest.roles(),
@ -410,7 +410,7 @@ public class NativeUsersStore {
final ActionListener<Void> listener) { final ActionListener<Void> listener) {
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, username)) client.prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, username))
.setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled)
.setRefreshPolicy(refreshPolicy) .setRefreshPolicy(refreshPolicy)
.request(), .request(),
@ -444,7 +444,7 @@ public class NativeUsersStore {
boolean clearCache, final ActionListener<Void> listener) { boolean clearCache, final ActionListener<Void> listener) {
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> { securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(RESERVED_USER_TYPE, username)) client.prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(RESERVED_USER_TYPE, username))
.setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled) .setDoc(Requests.INDEX_CONTENT_TYPE, Fields.ENABLED.getPreferredName(), enabled)
.setUpsert(XContentType.JSON, .setUpsert(XContentType.JSON,
Fields.PASSWORD.getPreferredName(), "", Fields.PASSWORD.getPreferredName(), "",
@ -479,7 +479,7 @@ public class NativeUsersStore {
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
DeleteRequest request = client DeleteRequest request = client
.prepareDelete(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, deleteUserRequest.username())) .prepareDelete(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(USER_DOC_TYPE, deleteUserRequest.username()))
.request(); .request();
request.setRefreshPolicy(deleteUserRequest.getRefreshPolicy()); request.setRefreshPolicy(deleteUserRequest.getRefreshPolicy());
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
@ -526,7 +526,7 @@ public class NativeUsersStore {
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareGet(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForUser(RESERVED_USER_TYPE, username)) client.prepareGet(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForUser(RESERVED_USER_TYPE, username))
.request(), .request(),
new ActionListener<GetResponse>() { new ActionListener<GetResponse>() {
@Override @Override
@ -571,7 +571,7 @@ public class NativeUsersStore {
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareSearch(SECURITY_INDEX_NAME) client.prepareSearch(SECURITY_MAIN_ALIAS)
.setTrackTotalHits(true) .setTrackTotalHits(true)
.setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE)) .setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE))
.setFetchSource(true).request(), .setFetchSource(true).request(),

View File

@ -35,6 +35,7 @@ import org.elasticsearch.xpack.core.security.action.rolemapping.PutRoleMappingRe
import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping; import org.elasticsearch.xpack.core.security.authc.support.mapper.ExpressionRoleMapping;
import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.ExpressionModel; import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.ExpressionModel;
import org.elasticsearch.xpack.core.security.client.SecurityClient; import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.security.authc.support.CachingRealm; import org.elasticsearch.xpack.security.authc.support.CachingRealm;
import org.elasticsearch.xpack.security.authc.support.UserRoleMapper; import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.support.SecurityIndexManager;
@ -60,13 +61,13 @@ import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING; import static org.elasticsearch.search.SearchService.DEFAULT_KEEPALIVE_SETTING;
import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN; import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isIndexDeleted;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.isMoveFromRedToNonRed;
/** /**
* This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch * This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch
* {@link SecurityIndexManager#SECURITY_INDEX_NAME index}. * {@link RestrictedIndicesNames#SECURITY_MAIN_ALIAS index}.
* <br> * <br>
* The store is responsible for all read and write operations as well as * The store is responsible for all read and write operations as well as
* {@link #resolveRoles(UserData, ActionListener) resolving roles}. * {@link #resolveRoles(UserData, ActionListener) resolving roles}.
@ -131,7 +132,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
final QueryBuilder query = QueryBuilders.termQuery(DOC_TYPE_FIELD, DOC_TYPE_ROLE_MAPPING); final QueryBuilder query = QueryBuilders.termQuery(DOC_TYPE_FIELD, DOC_TYPE_ROLE_MAPPING);
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false); final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) { try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) {
SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) SearchRequest request = client.prepareSearch(SECURITY_MAIN_ALIAS)
.setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings))
.setQuery(query) .setQuery(query)
.setSize(1000) .setSize(1000)
@ -143,7 +144,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
listener.onResponse(mappings.stream().filter(Objects::nonNull).collect(Collectors.toList())), listener.onResponse(mappings.stream().filter(Objects::nonNull).collect(Collectors.toList())),
ex -> { ex -> {
logger.error(new ParameterizedMessage("failed to load role mappings from index [{}] skipping all mappings.", logger.error(new ParameterizedMessage("failed to load role mappings from index [{}] skipping all mappings.",
SECURITY_INDEX_NAME), ex); SECURITY_MAIN_ALIAS), ex);
listener.onResponse(Collections.emptyList()); listener.onResponse(Collections.emptyList());
})), })),
doc -> buildMapping(getNameFromId(doc.getId()), doc.getSourceRef())); doc -> buildMapping(getNameFromId(doc.getId()), doc.getSourceRef()));
@ -202,7 +203,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
return; return;
} }
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForName(mapping.getName())) client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForName(mapping.getName()))
.setSource(xContentBuilder) .setSource(xContentBuilder)
.setRefreshPolicy(request.getRefreshPolicy()) .setRefreshPolicy(request.getRefreshPolicy())
.request(), .request(),
@ -231,7 +232,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareDelete(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForName(request.getName())) client.prepareDelete(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForName(request.getName()))
.setRefreshPolicy(request.getRefreshPolicy()) .setRefreshPolicy(request.getRefreshPolicy())
.request(), .request(),
new ActionListener<DeleteResponse>() { new ActionListener<DeleteResponse>() {
@ -286,7 +287,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
logger.info("The security index is not yet available - no role mappings can be loaded"); logger.info("The security index is not yet available - no role mappings can be loaded");
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("Security Index [{}] [exists: {}] [available: {}] [mapping up to date: {}]", logger.debug("Security Index [{}] [exists: {}] [available: {}] [mapping up to date: {}]",
SECURITY_INDEX_NAME, SECURITY_MAIN_ALIAS,
securityIndex.indexExists(), securityIndex.indexExists(),
securityIndex.isAvailable(), securityIndex.isAvailable(),
securityIndex.isMappingUpToDate() securityIndex.isMappingUpToDate()

View File

@ -65,7 +65,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.DOC_TYPE_VALUE; import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.DOC_TYPE_VALUE;
import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.Fields.APPLICATION; import static org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor.Fields.APPLICATION;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
/** /**
* {@code NativePrivilegeStore} is a store that reads/writes {@link ApplicationPrivilegeDescriptor} objects, * {@code NativePrivilegeStore} is a store that reads/writes {@link ApplicationPrivilegeDescriptor} objects,
@ -129,7 +129,7 @@ public class NativePrivilegeStore {
} }
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false); final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) { try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) {
SearchRequest request = client.prepareSearch(SECURITY_INDEX_NAME) SearchRequest request = client.prepareSearch(SECURITY_MAIN_ALIAS)
.setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings))
.setQuery(query) .setQuery(query)
.setSize(1000) .setSize(1000)
@ -201,7 +201,7 @@ public class NativePrivilegeStore {
} else { } else {
securityIndexManager.checkIndexVersionThenExecute(listener::onFailure, securityIndexManager.checkIndexVersionThenExecute(listener::onFailure,
() -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, () -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareGet(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, toDocId(application, name)) client.prepareGet(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, toDocId(application, name))
.request(), .request(),
new ActionListener<GetResponse>() { new ActionListener<GetResponse>() {
@Override @Override
@ -253,7 +253,7 @@ public class NativePrivilegeStore {
final String name = privilege.getName(); final String name = privilege.getName();
final XContentBuilder xContentBuilder = privilege.toXContent(jsonBuilder(), true); final XContentBuilder xContentBuilder = privilege.toXContent(jsonBuilder(), true);
ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, toDocId(privilege.getApplication(), name)) client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, toDocId(privilege.getApplication(), name))
.setSource(xContentBuilder) .setSource(xContentBuilder)
.setRefreshPolicy(refreshPolicy) .setRefreshPolicy(refreshPolicy)
.request(), listener, client::index); .request(), listener, client::index);
@ -284,7 +284,7 @@ public class NativePrivilegeStore {
}, listener::onFailure), names.size()); }, listener::onFailure), names.size());
for (String name : names) { for (String name : names) {
ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, ClientHelper.executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareDelete(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, toDocId(application, name)) client.prepareDelete(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, toDocId(application, name))
.setRefreshPolicy(refreshPolicy) .setRefreshPolicy(refreshPolicy)
.request(), groupListener, client::delete); .request(), groupListener, client::delete);
} }

View File

@ -70,7 +70,7 @@ import static org.elasticsearch.xpack.core.ClientHelper.SECURITY_ORIGIN;
import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin; import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
import static org.elasticsearch.xpack.core.security.SecurityField.setting; import static org.elasticsearch.xpack.core.security.SecurityField.setting;
import static org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ROLE_TYPE; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptor.ROLE_TYPE;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
/** /**
* NativeRolesStore is a {@code RolesStore} that, instead of reading from a * NativeRolesStore is a {@code RolesStore} that, instead of reading from a
@ -124,7 +124,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
QueryBuilder query = QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE); QueryBuilder query = QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE);
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false); final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) { try (ThreadContext.StoredContext ignore = client.threadPool().getThreadContext().stashWithOrigin(SECURITY_ORIGIN)) {
SearchRequest request = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) SearchRequest request = client.prepareSearch(SECURITY_MAIN_ALIAS)
.setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings)) .setScroll(DEFAULT_KEEPALIVE_SETTING.get(settings))
.setQuery(query) .setQuery(query)
.setSize(1000) .setSize(1000)
@ -142,7 +142,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
final String[] roleIds = names.stream().map(NativeRolesStore::getIdForRole).toArray(String[]::new); final String[] roleIds = names.stream().map(NativeRolesStore::getIdForRole).toArray(String[]::new);
MultiGetRequest multiGetRequest = client.prepareMultiGet().add(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, roleIds).request(); MultiGetRequest multiGetRequest = client.prepareMultiGet().add(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, roleIds).request();
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, multiGetRequest, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, multiGetRequest,
ActionListener.<MultiGetResponse>wrap(mGetResponse -> { ActionListener.<MultiGetResponse>wrap(mGetResponse -> {
final MultiGetItemResponse[] responses = mGetResponse.getResponses(); final MultiGetItemResponse[] responses = mGetResponse.getResponses();
@ -179,7 +179,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
} else { } else {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> { securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
DeleteRequest request = client DeleteRequest request = client
.prepareDelete(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForRole(deleteRoleRequest.name())).request(); .prepareDelete(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForRole(deleteRoleRequest.name())).request();
request.setRefreshPolicy(deleteRoleRequest.getRefreshPolicy()); request.setRefreshPolicy(deleteRoleRequest.getRefreshPolicy());
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
new ActionListener<DeleteResponse>() { new ActionListener<DeleteResponse>() {
@ -219,7 +219,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
listener.onFailure(e); listener.onFailure(e);
return; return;
} }
final IndexRequest indexRequest = client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForRole(role.getName())) final IndexRequest indexRequest = client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForRole(role.getName()))
.setSource(xContentBuilder) .setSource(xContentBuilder)
.setRefreshPolicy(request.getRefreshPolicy()) .setRefreshPolicy(request.getRefreshPolicy())
.request(); .request();
@ -253,11 +253,11 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareMultiSearch() client.prepareMultiSearch()
.add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) .add(client.prepareSearch(SECURITY_MAIN_ALIAS)
.setQuery(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .setQuery(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE))
.setTrackTotalHits(true) .setTrackTotalHits(true)
.setSize(0)) .setSize(0))
.add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) .add(client.prepareSearch(SECURITY_MAIN_ALIAS)
.setQuery(QueryBuilders.boolQuery() .setQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE))
.must(QueryBuilders.boolQuery() .must(QueryBuilders.boolQuery()
@ -268,7 +268,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
.setTrackTotalHits(true) .setTrackTotalHits(true)
.setSize(0) .setSize(0)
.setTerminateAfter(1)) .setTerminateAfter(1))
.add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) .add(client.prepareSearch(SECURITY_MAIN_ALIAS)
.setQuery(QueryBuilders.boolQuery() .setQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE)) .must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE))
.filter(existsQuery("indices.query"))) .filter(existsQuery("indices.query")))
@ -340,7 +340,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
private void executeGetRoleRequest(String role, ActionListener<GetResponse> listener) { private void executeGetRoleRequest(String role, ActionListener<GetResponse> listener) {
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
client.prepareGet(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, getIdForRole(role)).request(), client.prepareGet(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, getIdForRole(role)).request(),
listener, listener,
client::get)); client::get));
} }

View File

@ -53,6 +53,7 @@ import org.elasticsearch.xpack.core.template.TemplateUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -77,12 +78,13 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
*/ */
public class SecurityIndexManager implements ClusterStateListener { public class SecurityIndexManager implements ClusterStateListener {
public static final String INTERNAL_SECURITY_INDEX = RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7; public static final int INTERNAL_MAIN_INDEX_FORMAT = 6;
public static final int INTERNAL_INDEX_FORMAT = 6; public static final int INTERNAL_TOKENS_INDEX_FORMAT = 7;
public static final String SECURITY_MAIN_TEMPLATE_7 = "security-index-template-7";
public static final String SECURITY_TOKENS_TEMPLATE_7 = "security-tokens-index-template-7";
public static final String SECURITY_VERSION_STRING = "security-version"; public static final String SECURITY_VERSION_STRING = "security-version";
public static final String TEMPLATE_VERSION_PATTERN = Pattern.quote("${security.template.version}"); public static final String TEMPLATE_VERSION_PATTERN = Pattern.quote("${security.template.version}");
public static final String SECURITY_TEMPLATE_NAME = "security-index-template";
public static final String SECURITY_INDEX_NAME = ".security";
private static final Logger logger = LogManager.getLogger(SecurityIndexManager.class); private static final Logger logger = LogManager.getLogger(SecurityIndexManager.class);
private final String aliasName; private final String aliasName;
@ -95,13 +97,20 @@ public class SecurityIndexManager implements ClusterStateListener {
private volatile State indexState; private volatile State indexState;
public static SecurityIndexManager buildSecurityIndexManager(Client client, ClusterService clusterService) { public static SecurityIndexManager buildSecurityMainIndexManager(Client client, ClusterService clusterService) {
return new SecurityIndexManager(client, SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX, INTERNAL_INDEX_FORMAT, return new SecurityIndexManager(client, clusterService, RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
SecurityIndexManager::readSecurityTemplateAsBytes, clusterService); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7, INTERNAL_MAIN_INDEX_FORMAT,
() -> SecurityIndexManager.readTemplateAsBytes(SECURITY_MAIN_TEMPLATE_7));
} }
private SecurityIndexManager(Client client, String aliasName, String internalIndexName, int internalIndexFormat, public static SecurityIndexManager buildSecurityTokensIndexManager(Client client, ClusterService clusterService) {
Supplier<byte[]> mappingSourceSupplier, ClusterService clusterService) { return new SecurityIndexManager(client, clusterService, RestrictedIndicesNames.SECURITY_TOKENS_ALIAS,
RestrictedIndicesNames.INTERNAL_SECURITY_TOKENS_INDEX_7, INTERNAL_TOKENS_INDEX_FORMAT,
() -> SecurityIndexManager.readTemplateAsBytes(SECURITY_TOKENS_TEMPLATE_7));
}
private SecurityIndexManager(Client client, ClusterService clusterService, String aliasName, String internalIndexName,
int internalIndexFormat, Supplier<byte[]> mappingSourceSupplier) {
this(client, aliasName, internalIndexName, internalIndexFormat, mappingSourceSupplier, State.UNRECOVERED_STATE); this(client, aliasName, internalIndexName, internalIndexFormat, mappingSourceSupplier, State.UNRECOVERED_STATE);
clusterService.addListener(this); clusterService.addListener(this);
} }
@ -126,8 +135,16 @@ public class SecurityIndexManager implements ClusterStateListener {
return currentIndexState.mappingVersion == null || requiredVersion.test(currentIndexState.mappingVersion); return currentIndexState.mappingVersion == null || requiredVersion.test(currentIndexState.mappingVersion);
} }
public String aliasName() {
return aliasName;
}
public boolean indexExists() { public boolean indexExists() {
return this.indexState.indexExists; return this.indexState.indexExists();
}
public Instant getCreationTime() {
return this.indexState.creationTime;
} }
/** /**
@ -156,7 +173,7 @@ public class SecurityIndexManager implements ClusterStateListener {
throw new IllegalStateException("caller must make sure to use a frozen state and check indexAvailable"); throw new IllegalStateException("caller must make sure to use a frozen state and check indexAvailable");
} }
if (localState.indexExists) { if (localState.indexExists()) {
return new UnavailableShardsException(null, return new UnavailableShardsException(null,
"at least one primary shard for the index [" + localState.concreteIndexName + "] is unavailable"); "at least one primary shard for the index [" + localState.concreteIndexName + "] is unavailable");
} else { } else {
@ -183,17 +200,17 @@ public class SecurityIndexManager implements ClusterStateListener {
} }
final State previousState = indexState; final State previousState = indexState;
final IndexMetaData indexMetaData = resolveConcreteIndex(aliasName, event.state().metaData()); final IndexMetaData indexMetaData = resolveConcreteIndex(aliasName, event.state().metaData());
final boolean indexExists = indexMetaData != null; final Instant creationTime = indexMetaData != null ? Instant.ofEpochMilli(indexMetaData.getCreationDate()) : null;
final boolean isIndexUpToDate = indexExists == false || final boolean isIndexUpToDate = indexMetaData == null ||
INDEX_FORMAT_SETTING.get(indexMetaData.getSettings()).intValue() == internalIndexFormat; INDEX_FORMAT_SETTING.get(indexMetaData.getSettings()).intValue() == internalIndexFormat;
final boolean indexAvailable = checkIndexAvailable(event.state()); final boolean indexAvailable = checkIndexAvailable(event.state());
final boolean mappingIsUpToDate = indexExists == false || checkIndexMappingUpToDate(event.state()); final boolean mappingIsUpToDate = indexMetaData == null || checkIndexMappingUpToDate(event.state());
final Version mappingVersion = oldestIndexMappingVersion(event.state()); final Version mappingVersion = oldestIndexMappingVersion(event.state());
final ClusterHealthStatus indexStatus = indexMetaData == null ? null : final ClusterHealthStatus indexStatus = indexMetaData == null ? null :
new ClusterIndexHealth(indexMetaData, event.state().getRoutingTable().index(indexMetaData.getIndex())).getStatus(); new ClusterIndexHealth(indexMetaData, event.state().getRoutingTable().index(indexMetaData.getIndex())).getStatus();
final String concreteIndexName = indexMetaData == null ? internalIndexName : indexMetaData.getIndex().getName(); final String concreteIndexName = indexMetaData == null ? internalIndexName : indexMetaData.getIndex().getName();
final State newState = new State(indexExists, isIndexUpToDate, indexAvailable, mappingIsUpToDate, mappingVersion, concreteIndexName, final State newState = new State(creationTime, isIndexUpToDate, indexAvailable, mappingIsUpToDate, mappingVersion,
indexStatus); concreteIndexName, indexStatus);
this.indexState = newState; this.indexState = newState;
if (newState.equals(previousState) == false) { if (newState.equals(previousState) == false) {
@ -304,7 +321,7 @@ public class SecurityIndexManager implements ClusterStateListener {
*/ */
public void checkIndexVersionThenExecute(final Consumer<Exception> consumer, final Runnable andThen) { public void checkIndexVersionThenExecute(final Consumer<Exception> consumer, final Runnable andThen) {
final State indexState = this.indexState; // use a local copy so all checks execute against the same state! final State indexState = this.indexState; // use a local copy so all checks execute against the same state!
if (indexState.indexExists && indexState.isIndexUpToDate == false) { if (indexState.indexExists() && indexState.isIndexUpToDate == false) {
consumer.accept(new IllegalStateException( consumer.accept(new IllegalStateException(
"Index [" + indexState.concreteIndexName + "] is not on the current version. Security features relying on the index" "Index [" + indexState.concreteIndexName + "] is not on the current version. Security features relying on the index"
+ " will not be available until the upgrade API is run on the index")); + " will not be available until the upgrade API is run on the index"));
@ -324,11 +341,11 @@ public class SecurityIndexManager implements ClusterStateListener {
consumer.accept(new ElasticsearchStatusException( consumer.accept(new ElasticsearchStatusException(
"Cluster state has not been recovered yet, cannot write to the [" + indexState.concreteIndexName + "] index", "Cluster state has not been recovered yet, cannot write to the [" + indexState.concreteIndexName + "] index",
RestStatus.SERVICE_UNAVAILABLE)); RestStatus.SERVICE_UNAVAILABLE));
} else if (indexState.indexExists && indexState.isIndexUpToDate == false) { } else if (indexState.indexExists() && indexState.isIndexUpToDate == false) {
consumer.accept(new IllegalStateException( consumer.accept(new IllegalStateException(
"Index [" + indexState.concreteIndexName + "] is not on the current version." "Index [" + indexState.concreteIndexName + "] is not on the current version."
+ "Security features relying on the index will not be available until the upgrade API is run on the index")); + "Security features relying on the index will not be available until the upgrade API is run on the index"));
} else if (indexState.indexExists == false) { } else if (indexState.indexExists() == false) {
assert indexState.concreteIndexName != null; assert indexState.concreteIndexName != null;
logger.info("security index does not exist. Creating [{}] with alias [{}]", indexState.concreteIndexName, this.aliasName); logger.info("security index does not exist. Creating [{}] with alias [{}]", indexState.concreteIndexName, this.aliasName);
final byte[] mappingSource = mappingSourceSupplier.get(); final byte[] mappingSource = mappingSourceSupplier.get();
@ -396,8 +413,8 @@ public class SecurityIndexManager implements ClusterStateListener {
return previousState.indexStatus != null && currentState.indexStatus == null; return previousState.indexStatus != null && currentState.indexStatus == null;
} }
private static byte[] readSecurityTemplateAsBytes() { private static byte[] readTemplateAsBytes(String templateName) {
return TemplateUtils.loadTemplate("/" + SECURITY_TEMPLATE_NAME + ".json", Version.CURRENT.toString(), return TemplateUtils.loadTemplate("/" + templateName + ".json", Version.CURRENT.toString(),
SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8); SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
} }
@ -423,8 +440,8 @@ public class SecurityIndexManager implements ClusterStateListener {
* State of the security index. * State of the security index.
*/ */
public static class State { public static class State {
public static final State UNRECOVERED_STATE = new State(false, false, false, false, null, null, null); public static final State UNRECOVERED_STATE = new State(null, false, false, false, null, null, null);
public final boolean indexExists; public final Instant creationTime;
public final boolean isIndexUpToDate; public final boolean isIndexUpToDate;
public final boolean indexAvailable; public final boolean indexAvailable;
public final boolean mappingUpToDate; public final boolean mappingUpToDate;
@ -432,9 +449,9 @@ public class SecurityIndexManager implements ClusterStateListener {
public final String concreteIndexName; public final String concreteIndexName;
public final ClusterHealthStatus indexStatus; public final ClusterHealthStatus indexStatus;
public State(boolean indexExists, boolean isIndexUpToDate, boolean indexAvailable, public State(Instant creationTime, boolean isIndexUpToDate, boolean indexAvailable,
boolean mappingUpToDate, Version mappingVersion, String concreteIndexName, ClusterHealthStatus indexStatus) { boolean mappingUpToDate, Version mappingVersion, String concreteIndexName, ClusterHealthStatus indexStatus) {
this.indexExists = indexExists; this.creationTime = creationTime;
this.isIndexUpToDate = isIndexUpToDate; this.isIndexUpToDate = isIndexUpToDate;
this.indexAvailable = indexAvailable; this.indexAvailable = indexAvailable;
this.mappingUpToDate = mappingUpToDate; this.mappingUpToDate = mappingUpToDate;
@ -448,7 +465,7 @@ public class SecurityIndexManager implements ClusterStateListener {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
State state = (State) o; State state = (State) o;
return indexExists == state.indexExists && return Objects.equals(creationTime, state.creationTime) &&
isIndexUpToDate == state.isIndexUpToDate && isIndexUpToDate == state.isIndexUpToDate &&
indexAvailable == state.indexAvailable && indexAvailable == state.indexAvailable &&
mappingUpToDate == state.mappingUpToDate && mappingUpToDate == state.mappingUpToDate &&
@ -457,9 +474,13 @@ public class SecurityIndexManager implements ClusterStateListener {
indexStatus == state.indexStatus; indexStatus == state.indexStatus;
} }
public boolean indexExists() {
return creationTime != null;
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(indexExists, isIndexUpToDate, indexAvailable, mappingUpToDate, mappingVersion, concreteIndexName, return Objects.hash(creationTime, isIndexUpToDate, indexAvailable, mappingUpToDate, mappingVersion, concreteIndexName,
indexStatus); indexStatus);
} }
} }

View File

@ -13,8 +13,8 @@ import org.elasticsearch.xpack.core.security.action.role.GetRolesResponse;
import org.elasticsearch.xpack.core.security.action.role.PutRoleResponse; import org.elasticsearch.xpack.core.security.action.role.PutRoleResponse;
import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult; import org.elasticsearch.xpack.core.security.authz.store.RoleRetrievalResult;
import org.elasticsearch.xpack.core.security.client.SecurityClient; import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -56,7 +56,7 @@ public class ClearRolesCacheTests extends NativeRealmIntegTestCase {
logger.debug("--> created role [{}]", role); logger.debug("--> created role [{}]", role);
} }
ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME); ensureGreen(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
final Set<String> rolesSet = new HashSet<>(Arrays.asList(roles)); final Set<String> rolesSet = new HashSet<>(Arrays.asList(roles));
// warm up the caches on every node // warm up the caches on every node

View File

@ -59,7 +59,7 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase {
@Override @Override
public Set<String> excludeTemplates() { public Set<String> excludeTemplates() {
Set<String> templates = Sets.newHashSet(super.excludeTemplates()); Set<String> templates = Sets.newHashSet(super.excludeTemplates());
templates.add(SecurityIndexManager.SECURITY_TEMPLATE_NAME); // don't remove the security index template templates.add(SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7); // don't remove the security index template
return templates; return templates;
} }

View File

@ -67,7 +67,7 @@ import static org.elasticsearch.test.SecuritySettingsSourceField.TEST_PASSWORD_S
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.core.IsCollectionContaining.hasItem; import static org.hamcrest.core.IsCollectionContaining.hasItem;
@ -491,7 +491,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().startObject(); XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().startObject();
assertTrue("security index mapping not sufficient to read:\n" + assertTrue("security index mapping not sufficient to read:\n" +
Strings.toString(clusterState.toXContent(builder, ToXContent.EMPTY_PARAMS).endObject()), Strings.toString(clusterState.toXContent(builder, ToXContent.EMPTY_PARAMS).endObject()),
SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_MAIN_ALIAS, clusterState, logger,
Version.CURRENT.minimumIndexCompatibilityVersion()::onOrBefore)); Version.CURRENT.minimumIndexCompatibilityVersion()::onOrBefore));
Index securityIndex = resolveSecurityIndex(clusterState.metaData()); Index securityIndex = resolveSecurityIndex(clusterState.metaData());
if (securityIndex != null) { if (securityIndex != null) {
@ -509,7 +509,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER, UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER,
SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING))); SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING)));
GetIndexRequest getIndexRequest = new GetIndexRequest(); GetIndexRequest getIndexRequest = new GetIndexRequest();
getIndexRequest.indices(SECURITY_INDEX_NAME); getIndexRequest.indices(SECURITY_MAIN_ALIAS);
getIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen()); getIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
GetIndexResponse getIndexResponse = client.admin().indices().getIndex(getIndexRequest).actionGet(); GetIndexResponse getIndexResponse = client.admin().indices().getIndex(getIndexRequest).actionGet();
if (getIndexResponse.getIndices().length > 0) { if (getIndexResponse.getIndices().length > 0) {
@ -520,7 +520,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
} }
private static Index resolveSecurityIndex(MetaData metaData) { private static Index resolveSecurityIndex(MetaData metaData) {
final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(SECURITY_INDEX_NAME); final AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(SECURITY_MAIN_ALIAS);
if (aliasOrIndex != null) { if (aliasOrIndex != null) {
return aliasOrIndex.getIndices().get(0).getIndex(); return aliasOrIndex.getIndices().get(0).getIndex();
} }

View File

@ -68,8 +68,8 @@ import java.util.stream.Collectors;
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING; import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
import static org.elasticsearch.discovery.DiscoveryModule.ZEN2_DISCOVERY_TYPE; import static org.elasticsearch.discovery.DiscoveryModule.ZEN2_DISCOVERY_TYPE;
import static org.elasticsearch.discovery.DiscoveryModule.ZEN_DISCOVERY_TYPE; import static org.elasticsearch.discovery.DiscoveryModule.ZEN_DISCOVERY_TYPE;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -310,8 +310,8 @@ public class SecurityTests extends ESTestCase {
BiConsumer<DiscoveryNode, ClusterState> joinValidator = security.getJoinValidator(); BiConsumer<DiscoveryNode, ClusterState> joinValidator = security.getJoinValidator();
assertNotNull(joinValidator); assertNotNull(joinValidator);
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT); DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME) IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_MAIN_ALIAS)
.settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_INDEX_FORMAT - 1)) .settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_MAIN_INDEX_FORMAT - 1))
.numberOfShards(1).numberOfReplicas(0) .numberOfShards(1).numberOfReplicas(0)
.build(); .build();
DiscoveryNode existingOtherNode = new DiscoveryNode("bar", buildNewFakeTransportAddress(), Version.V_6_1_0); DiscoveryNode existingOtherNode = new DiscoveryNode("bar", buildNewFakeTransportAddress(), Version.V_6_1_0);
@ -330,8 +330,8 @@ public class SecurityTests extends ESTestCase {
BiConsumer<DiscoveryNode, ClusterState> joinValidator = security.getJoinValidator(); BiConsumer<DiscoveryNode, ClusterState> joinValidator = security.getJoinValidator();
assertNotNull(joinValidator); assertNotNull(joinValidator);
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT); DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
int indexFormat = randomBoolean() ? INTERNAL_INDEX_FORMAT : INTERNAL_INDEX_FORMAT - 1; int indexFormat = randomBoolean() ? INTERNAL_MAIN_INDEX_FORMAT : INTERNAL_MAIN_INDEX_FORMAT - 1;
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME) IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_MAIN_ALIAS)
.settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), indexFormat)) .settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), indexFormat))
.numberOfShards(1).numberOfReplicas(0) .numberOfShards(1).numberOfReplicas(0)
.build(); .build();
@ -349,8 +349,8 @@ public class SecurityTests extends ESTestCase {
assertNotNull(joinValidator); assertNotNull(joinValidator);
Version version = randomBoolean() ? Version.CURRENT : Version.V_6_1_0; Version version = randomBoolean() ? Version.CURRENT : Version.V_6_1_0;
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT); DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME) IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_MAIN_ALIAS)
.settings(settings(version).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_INDEX_FORMAT)) .settings(settings(version).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_MAIN_INDEX_FORMAT))
.numberOfShards(1).numberOfReplicas(0) .numberOfShards(1).numberOfReplicas(0)
.build(); .build();
DiscoveryNode existingOtherNode = new DiscoveryNode("bar", buildNewFakeTransportAddress(), version); DiscoveryNode existingOtherNode = new DiscoveryNode("bar", buildNewFakeTransportAddress(), version);

View File

@ -167,7 +167,7 @@ public class TransportOpenIdConnectLogoutActionTests extends OpenIdConnectTestCa
when(securityIndex.isAvailable()).thenReturn(true); when(securityIndex.isAvailable()).thenReturn(true);
final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, clusterService); tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, securityIndex, clusterService);
final TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null, final TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null,
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet()); TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());

View File

@ -195,10 +195,13 @@ public class TransportSamlInvalidateSessionActionTests extends SamlTestCase {
}).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class)); }).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class));
when(securityIndex.isAvailable()).thenReturn(true); when(securityIndex.isAvailable()).thenReturn(true);
when(securityIndex.indexExists()).thenReturn(true); when(securityIndex.indexExists()).thenReturn(true);
when(securityIndex.isIndexUpToDate()).thenReturn(true);
when(securityIndex.getCreationTime()).thenReturn(Clock.systemUTC().instant());
when(securityIndex.aliasName()).thenReturn(".security");
when(securityIndex.freeze()).thenReturn(securityIndex); when(securityIndex.freeze()).thenReturn(securityIndex);
final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, clusterService); tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, securityIndex, clusterService);
final TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null, final TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null,
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet()); TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
@ -308,7 +311,8 @@ public class TransportSamlInvalidateSessionActionTests extends SamlTestCase {
assertThat(filter1.get(1), instanceOf(TermQueryBuilder.class)); assertThat(filter1.get(1), instanceOf(TermQueryBuilder.class));
assertThat(((TermQueryBuilder) filter1.get(1)).fieldName(), equalTo("refresh_token.token")); assertThat(((TermQueryBuilder) filter1.get(1)).fieldName(), equalTo("refresh_token.token"));
assertThat(((TermQueryBuilder) filter1.get(1)).value(), equalTo(tokenToInvalidate1.v2())); assertThat(((TermQueryBuilder) filter1.get(1)).value(),
equalTo(TokenService.unpackVersionAndPayload(tokenToInvalidate1.v2()).v2()));
assertThat(bulkRequests.size(), equalTo(4)); // 4 updates (refresh-token + access-token) assertThat(bulkRequests.size(), equalTo(4)); // 4 updates (refresh-token + access-token)
// Invalidate refresh token 1 // Invalidate refresh token 1

View File

@ -203,7 +203,7 @@ public class TransportSamlLogoutActionTests extends SamlTestCase {
when(securityIndex.isAvailable()).thenReturn(true); when(securityIndex.isAvailable()).thenReturn(true);
final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); final ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, clusterService); tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, securityIndex, clusterService);
final TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null, final TransportService transportService = new TransportService(Settings.EMPTY, mock(Transport.class), null,
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet()); TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());

View File

@ -147,7 +147,8 @@ public class TransportCreateTokenActionTests extends ESTestCase {
} }
public void testClientCredentialsCreatesWithoutRefreshToken() throws Exception { public void testClientCredentialsCreatesWithoutRefreshToken() throws Exception {
final TokenService tokenService = new TokenService(SETTINGS, Clock.systemUTC(), client, securityIndex, clusterService); final TokenService tokenService = new TokenService(SETTINGS, Clock.systemUTC(), client, securityIndex, securityIndex,
clusterService);
Authentication authentication = new Authentication(new User("joe"), new Authentication.RealmRef("realm", "type", "node"), null); Authentication authentication = new Authentication(new User("joe"), new Authentication.RealmRef("realm", "type", "node"), null);
authentication.writeToContext(threadPool.getThreadContext()); authentication.writeToContext(threadPool.getThreadContext());
@ -171,7 +172,8 @@ public class TransportCreateTokenActionTests extends ESTestCase {
} }
public void testPasswordGrantTypeCreatesWithRefreshToken() throws Exception { public void testPasswordGrantTypeCreatesWithRefreshToken() throws Exception {
final TokenService tokenService = new TokenService(SETTINGS, Clock.systemUTC(), client, securityIndex, clusterService); final TokenService tokenService = new TokenService(SETTINGS, Clock.systemUTC(), client, securityIndex, securityIndex,
clusterService);
Authentication authentication = new Authentication(new User("joe"), new Authentication.RealmRef("realm", "type", "node"), null); Authentication authentication = new Authentication(new User("joe"), new Authentication.RealmRef("realm", "type", "node"), null);
authentication.writeToContext(threadPool.getThreadContext()); authentication.writeToContext(threadPool.getThreadContext());

View File

@ -34,7 +34,6 @@ import org.elasticsearch.xpack.core.security.action.InvalidateApiKeyResponse;
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.core.security.authz.RoleDescriptor; import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.core.security.client.SecurityClient; import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.elasticsearch.xpack.security.transport.filter.IPFilter; import org.elasticsearch.xpack.security.transport.filter.IPFilter;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -53,7 +52,7 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME; import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -336,7 +335,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
Instant dayBefore = created.minus(1L, ChronoUnit.DAYS); Instant dayBefore = created.minus(1L, ChronoUnit.DAYS);
assertTrue(Instant.now().isAfter(dayBefore)); assertTrue(Instant.now().isAfter(dayBefore));
UpdateResponse expirationDateUpdatedResponse = client UpdateResponse expirationDateUpdatedResponse = client
.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, createdApiKeys.get(0).getId()) .prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, createdApiKeys.get(0).getId())
.setDoc("expiration_time", dayBefore.toEpochMilli()) .setDoc("expiration_time", dayBefore.toEpochMilli())
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
.get(); .get();
@ -346,7 +345,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
// hack doc to modify the expiration time to the week before // hack doc to modify the expiration time to the week before
Instant weekBefore = created.minus(8L, ChronoUnit.DAYS); Instant weekBefore = created.minus(8L, ChronoUnit.DAYS);
assertTrue(Instant.now().isAfter(weekBefore)); assertTrue(Instant.now().isAfter(weekBefore));
expirationDateUpdatedResponse = client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, createdApiKeys.get(1).getId()) expirationDateUpdatedResponse = client.prepareUpdate(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, createdApiKeys.get(1).getId())
.setDoc("expiration_time", weekBefore.toEpochMilli()) .setDoc("expiration_time", weekBefore.toEpochMilli())
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
.get(); .get();
@ -390,8 +389,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
private void refreshSecurityIndex() throws Exception { private void refreshSecurityIndex() throws Exception {
assertBusy(() -> { assertBusy(() -> {
final RefreshResponse refreshResponse = client().admin().indices().prepareRefresh(SecurityIndexManager.SECURITY_INDEX_NAME) final RefreshResponse refreshResponse = client().admin().indices().prepareRefresh(SECURITY_MAIN_ALIAS).get();
.get();
assertThat(refreshResponse.getFailedShards(), is(0)); assertThat(refreshResponse.getFailedShards(), is(0));
}); });
} }

View File

@ -154,7 +154,7 @@ public class AuthenticationServiceTests extends ESTestCase {
@SuppressForbidden(reason = "Allow accessing localhost") @SuppressForbidden(reason = "Allow accessing localhost")
public void init() throws Exception { public void init() throws Exception {
concreteSecurityIndexName = randomFrom( concreteSecurityIndexName = randomFrom(
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
token = mock(AuthenticationToken.class); token = mock(AuthenticationToken.class);
when(token.principal()).thenReturn(randomAlphaOfLength(5)); when(token.principal()).thenReturn(randomAlphaOfLength(5));
@ -220,7 +220,7 @@ public class AuthenticationServiceTests extends ESTestCase {
}).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class)); }).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class));
ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool); ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool);
apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), client, securityIndex, clusterService, threadPool); apiKeyService = new ApiKeyService(settings, Clock.systemUTC(), client, securityIndex, clusterService, threadPool);
tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, clusterService); tokenService = new TokenService(settings, Clock.systemUTC(), client, securityIndex, securityIndex, clusterService);
service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()), service = new AuthenticationService(settings, realms, auditTrail, new DefaultAuthenticationFailureHandler(Collections.emptyMap()),
threadPool, new AnonymousUser(settings), tokenService, apiKeyService); threadPool, new AnonymousUser(settings), tokenService, apiKeyService);
} }
@ -1394,6 +1394,6 @@ public class AuthenticationServiceTests extends ESTestCase {
} }
private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) { private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) {
return new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, indexStatus); return new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, indexStatus);
} }
} }

View File

@ -36,7 +36,7 @@ import org.elasticsearch.xpack.core.security.action.user.AuthenticateResponse;
import org.elasticsearch.xpack.core.security.authc.TokenMetaData; import org.elasticsearch.xpack.core.security.authc.TokenMetaData;
import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken;
import org.elasticsearch.xpack.core.security.client.SecurityClient; import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -55,7 +55,6 @@ import java.util.stream.Collectors;
import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME; import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@TestLogging("org.elasticsearch.xpack.security.authz.store.FileRolesStore:DEBUG") @TestLogging("org.elasticsearch.xpack.security.authz.store.FileRolesStore:DEBUG")
@ -161,7 +160,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
assertThat(invalidateResponse.getResult().getErrors().size(), equalTo(0)); assertThat(invalidateResponse.getResult().getErrors().size(), equalTo(0));
AtomicReference<String> docId = new AtomicReference<>(); AtomicReference<String> docId = new AtomicReference<>();
assertBusy(() -> { assertBusy(() -> {
SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) SearchResponse searchResponse = client.prepareSearch(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS)
.setSource(SearchSourceBuilder.searchSource() .setSource(SearchSourceBuilder.searchSource()
.query(QueryBuilders.termQuery("doc_type", "token"))) .query(QueryBuilders.termQuery("doc_type", "token")))
.setSize(1) .setSize(1)
@ -174,7 +173,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
// hack doc to modify the creation time to the day before // hack doc to modify the creation time to the day before
Instant yesterday = created.minus(36L, ChronoUnit.HOURS); Instant yesterday = created.minus(36L, ChronoUnit.HOURS);
assertTrue(Instant.now().isAfter(yesterday)); assertTrue(Instant.now().isAfter(yesterday));
client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, docId.get()) client.prepareUpdate(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS, SINGLE_MAPPING_NAME, docId.get())
.setDoc("creation_time", yesterday.toEpochMilli()) .setDoc("creation_time", yesterday.toEpochMilli())
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
.get(); .get();
@ -192,8 +191,8 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
assertEquals("token malformed", e.getMessage()); assertEquals("token malformed", e.getMessage());
} }
} }
client.admin().indices().prepareRefresh(SecurityIndexManager.SECURITY_INDEX_NAME).get(); client.admin().indices().prepareRefresh(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS).get();
SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) SearchResponse searchResponse = client.prepareSearch(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS)
.setSource(SearchSourceBuilder.searchSource() .setSource(SearchSourceBuilder.searchSource()
.query(QueryBuilders.termQuery("doc_type", "token"))) .query(QueryBuilders.termQuery("doc_type", "token")))
.setTerminateAfter(1) .setTerminateAfter(1)
@ -358,10 +357,10 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
// We now have two documents, the original(now refreshed) token doc and the new one with the new access doc // We now have two documents, the original(now refreshed) token doc and the new one with the new access doc
AtomicReference<String> docId = new AtomicReference<>(); AtomicReference<String> docId = new AtomicReference<>();
assertBusy(() -> { assertBusy(() -> {
SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME) SearchResponse searchResponse = client.prepareSearch(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS)
.setSource(SearchSourceBuilder.searchSource() .setSource(SearchSourceBuilder.searchSource()
.query(QueryBuilders.boolQuery() .query(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("doc_type", "token")) .must(QueryBuilders.termQuery("doc_type", TokenService.TOKEN_DOC_TYPE))
.must(QueryBuilders.termQuery("refresh_token.refreshed", "true")))) .must(QueryBuilders.termQuery("refresh_token.refreshed", "true"))))
.setSize(1) .setSize(1)
.setTerminateAfter(1) .setTerminateAfter(1)
@ -374,7 +373,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
Instant refreshed = Instant.now(); Instant refreshed = Instant.now();
Instant aWhileAgo = refreshed.minus(50L, ChronoUnit.SECONDS); Instant aWhileAgo = refreshed.minus(50L, ChronoUnit.SECONDS);
assertTrue(Instant.now().isAfter(aWhileAgo)); assertTrue(Instant.now().isAfter(aWhileAgo));
UpdateResponse updateResponse = client.prepareUpdate(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, docId.get()) UpdateResponse updateResponse = client.prepareUpdate(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS, SINGLE_MAPPING_NAME, docId.get())
.setDoc("refresh_token", Collections.singletonMap("refresh_time", aWhileAgo.toEpochMilli())) .setDoc("refresh_token", Collections.singletonMap("refresh_time", aWhileAgo.toEpochMilli()))
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
.setFetchSource("refresh_token", Strings.EMPTY_STRING) .setFetchSource("refresh_token", Strings.EMPTY_STRING)

View File

@ -21,6 +21,9 @@ import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.action.update.UpdateAction; import org.elasticsearch.action.update.UpdateAction;
import org.elasticsearch.action.update.UpdateRequestBuilder; import org.elasticsearch.action.update.UpdateRequestBuilder;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.UUIDs; import org.elasticsearch.common.UUIDs;
@ -51,6 +54,7 @@ import org.elasticsearch.xpack.core.security.authc.support.TokensInvalidationRes
import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.core.watcher.watch.ClockMock; import org.elasticsearch.xpack.core.watcher.watch.ClockMock;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -74,6 +78,7 @@ import javax.crypto.SecretKey;
import static java.time.Clock.systemUTC; import static java.time.Clock.systemUTC;
import static org.elasticsearch.repositories.ESBlobStoreTestCase.randomBytes; import static org.elasticsearch.repositories.ESBlobStoreTestCase.randomBytes;
import static org.elasticsearch.test.ClusterServiceUtils.setState;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
@ -92,8 +97,10 @@ public class TokenServiceTests extends ESTestCase {
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build(); .put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
private Client client; private Client client;
private SecurityIndexManager securityIndex; private SecurityIndexManager securityMainIndex;
private SecurityIndexManager securityTokensIndex;
private ClusterService clusterService; private ClusterService clusterService;
private DiscoveryNode oldNode;
private Settings tokenServiceEnabledSettings = Settings.builder() private Settings tokenServiceEnabledSettings = Settings.builder()
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build(); .put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
@ -121,20 +128,21 @@ public class TokenServiceTests extends ESTestCase {
}).when(client).execute(eq(IndexAction.INSTANCE), any(IndexRequest.class), any(ActionListener.class)); }).when(client).execute(eq(IndexAction.INSTANCE), any(IndexRequest.class), any(ActionListener.class));
// setup lifecycle service // setup lifecycle service
securityIndex = mock(SecurityIndexManager.class); this.securityMainIndex = mockSecurityManager();
doAnswer(invocationOnMock -> { this.securityTokensIndex = mockSecurityManager();
Runnable runnable = (Runnable) invocationOnMock.getArguments()[1];
runnable.run();
return null;
}).when(securityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
doAnswer(invocationOnMock -> {
Runnable runnable = (Runnable) invocationOnMock.getArguments()[1];
runnable.run();
return null;
}).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class));
when(securityIndex.indexExists()).thenReturn(true);
when(securityIndex.isAvailable()).thenReturn(true);
this.clusterService = ClusterServiceUtils.createClusterService(threadPool); this.clusterService = ClusterServiceUtils.createClusterService(threadPool);
// version 7.1 was an "inflection" point in the Token Service development (access_tokens as UUIDS, multiple concurrent refreshes,
// tokens docs on a separate index), let's test the TokenService works in a mixed cluster with nodes with versions prior to these
// developments
if (randomBoolean()) {
oldNode = addAnotherDataNodeWithVersion(this.clusterService, randomFrom(Version.V_6_7_0, Version.V_7_0_0));
}
}
@After
public void tearDown() throws Exception {
super.tearDown();
clusterService.close();
} }
@BeforeClass @BeforeClass
@ -151,7 +159,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testAttachAndGetToken() throws Exception { public void testAttachAndGetToken() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -172,8 +181,8 @@ public class TokenServiceTests extends ESTestCase {
try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) { try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
// verify a second separate token service with its own salt can also verify // verify a second separate token service with its own salt can also verify
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
, clusterService); securityTokensIndex, clusterService);
anotherService.refreshMetaData(tokenService.getTokenMetaData()); anotherService.refreshMetaData(tokenService.getTokenMetaData());
PlainActionFuture<UserToken> future = new PlainActionFuture<>(); PlainActionFuture<UserToken> future = new PlainActionFuture<>();
anotherService.getAndValidateToken(requestContext, future); anotherService.getAndValidateToken(requestContext, future);
@ -183,7 +192,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testInvalidAuthorizationHeader() throws Exception { public void testInvalidAuthorizationHeader() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
ThreadContext requestContext = new ThreadContext(Settings.EMPTY); ThreadContext requestContext = new ThreadContext(Settings.EMPTY);
String token = randomFrom("", " "); String token = randomFrom("", " ");
String authScheme = randomFrom("Bearer ", "BEARER ", "bearer ", "Basic "); String authScheme = randomFrom("Bearer ", "BEARER ", "bearer ", "Basic ");
@ -198,7 +208,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testRotateKey() throws Exception { public void testRotateKey() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -251,12 +262,14 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testKeyExchange() throws Exception { public void testKeyExchange() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
int numRotations = randomIntBetween(1, 5); int numRotations = randomIntBetween(1, 5);
for (int i = 0; i < numRotations; i++) { for (int i = 0; i < numRotations; i++) {
rotateKeys(tokenService); rotateKeys(tokenService);
} }
TokenService otherTokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService otherTokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
otherTokenService.refreshMetaData(tokenService.getTokenMetaData()); otherTokenService.refreshMetaData(tokenService.getTokenMetaData());
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
@ -272,7 +285,7 @@ public class TokenServiceTests extends ESTestCase {
PlainActionFuture<UserToken> future = new PlainActionFuture<>(); PlainActionFuture<UserToken> future = new PlainActionFuture<>();
otherTokenService.getAndValidateToken(requestContext, future); otherTokenService.getAndValidateToken(requestContext, future);
UserToken serialized = future.get(); UserToken serialized = future.get();
assertAuthentication(authentication, serialized.getAuthentication()); assertEquals(authentication, serialized.getAuthentication());
} }
rotateKeys(tokenService); rotateKeys(tokenService);
@ -288,7 +301,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testPruneKeys() throws Exception { public void testPruneKeys() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -350,7 +364,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testPassphraseWorks() throws Exception { public void testPassphraseWorks() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -371,8 +386,8 @@ public class TokenServiceTests extends ESTestCase {
try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) { try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
// verify a second separate token service with its own passphrase cannot verify // verify a second separate token service with its own passphrase cannot verify
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
clusterService); securityTokensIndex, clusterService);
PlainActionFuture<UserToken> future = new PlainActionFuture<>(); PlainActionFuture<UserToken> future = new PlainActionFuture<>();
anotherService.getAndValidateToken(requestContext, future); anotherService.getAndValidateToken(requestContext, future);
assertNull(future.get()); assertNull(future.get());
@ -380,7 +395,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testGetTokenWhenKeyCacheHasExpired() throws Exception { public void testGetTokenWhenKeyCacheHasExpired() throws Exception {
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
@ -393,9 +409,9 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testInvalidatedToken() throws Exception { public void testInvalidatedToken() throws Exception {
when(securityIndex.indexExists()).thenReturn(true); when(securityMainIndex.indexExists()).thenReturn(true);
TokenService tokenService = TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -449,7 +465,8 @@ public class TokenServiceTests extends ESTestCase {
public void testTokenExpiry() throws Exception { public void testTokenExpiry() throws Exception {
ClockMock clock = ClockMock.frozen(); ClockMock clock = ClockMock.frozen();
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, clock, client, securityIndex, clusterService); TokenService tokenService = new TokenService(tokenServiceEnabledSettings, clock, client, securityMainIndex, securityTokensIndex,
clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -502,7 +519,7 @@ public class TokenServiceTests extends ESTestCase {
TokenService tokenService = new TokenService(Settings.builder() TokenService tokenService = new TokenService(Settings.builder()
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), false) .put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), false)
.build(), .build(),
Clock.systemUTC(), client, securityIndex, clusterService); Clock.systemUTC(), client, securityMainIndex, securityTokensIndex, clusterService);
IllegalStateException e = expectThrows(IllegalStateException.class, IllegalStateException e = expectThrows(IllegalStateException.class,
() -> tokenService.createOAuth2Tokens(null, null, null, true, null)); () -> tokenService.createOAuth2Tokens(null, null, null, true, null));
assertEquals("tokens are not enabled", e.getMessage()); assertEquals("tokens are not enabled", e.getMessage());
@ -545,7 +562,8 @@ public class TokenServiceTests extends ESTestCase {
final int numBytes = randomIntBetween(1, TokenService.MINIMUM_BYTES + 32); final int numBytes = randomIntBetween(1, TokenService.MINIMUM_BYTES + 32);
final byte[] randomBytes = new byte[numBytes]; final byte[] randomBytes = new byte[numBytes];
random().nextBytes(randomBytes); random().nextBytes(randomBytes);
TokenService tokenService = new TokenService(Settings.EMPTY, systemUTC(), client, securityIndex, clusterService); TokenService tokenService = new TokenService(Settings.EMPTY, systemUTC(), client, securityMainIndex, securityTokensIndex,
clusterService);
ThreadContext requestContext = new ThreadContext(Settings.EMPTY); ThreadContext requestContext = new ThreadContext(Settings.EMPTY);
requestContext.putHeader("Authorization", "Bearer " + Base64.getEncoder().encodeToString(randomBytes)); requestContext.putHeader("Authorization", "Bearer " + Base64.getEncoder().encodeToString(randomBytes));
@ -558,8 +576,8 @@ public class TokenServiceTests extends ESTestCase {
} }
public void testIndexNotAvailable() throws Exception { public void testIndexNotAvailable() throws Exception {
TokenService tokenService = TokenService tokenService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService); securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>(); PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture); tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
@ -576,34 +594,44 @@ public class TokenServiceTests extends ESTestCase {
return Void.TYPE; return Void.TYPE;
}).when(client).get(any(GetRequest.class), any(ActionListener.class)); }).when(client).get(any(GetRequest.class), any(ActionListener.class));
final SecurityIndexManager tokensIndex;
if (oldNode != null) {
tokensIndex = securityMainIndex;
when(securityTokensIndex.isAvailable()).thenReturn(false);
when(securityTokensIndex.indexExists()).thenReturn(false);
} else {
tokensIndex = securityTokensIndex;
when(securityMainIndex.isAvailable()).thenReturn(false);
when(securityMainIndex.indexExists()).thenReturn(false);
}
try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) { try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
PlainActionFuture<UserToken> future = new PlainActionFuture<>(); PlainActionFuture<UserToken> future = new PlainActionFuture<>();
tokenService.getAndValidateToken(requestContext, future); tokenService.getAndValidateToken(requestContext, future);
assertNull(future.get()); assertNull(future.get());
when(securityIndex.isAvailable()).thenReturn(false); when(tokensIndex.isAvailable()).thenReturn(false);
when(securityIndex.indexExists()).thenReturn(true); when(tokensIndex.indexExists()).thenReturn(true);
future = new PlainActionFuture<>(); future = new PlainActionFuture<>();
tokenService.getAndValidateToken(requestContext, future); tokenService.getAndValidateToken(requestContext, future);
assertNull(future.get()); assertNull(future.get());
when(securityIndex.indexExists()).thenReturn(false); when(tokensIndex.indexExists()).thenReturn(false);
future = new PlainActionFuture<>(); future = new PlainActionFuture<>();
tokenService.getAndValidateToken(requestContext, future); tokenService.getAndValidateToken(requestContext, future);
assertNull(future.get()); assertNull(future.get());
when(securityIndex.isAvailable()).thenReturn(true); when(tokensIndex.isAvailable()).thenReturn(true);
when(securityIndex.indexExists()).thenReturn(true); when(tokensIndex.indexExists()).thenReturn(true);
mockGetTokenFromId(token, false); mockGetTokenFromId(token, false);
future = new PlainActionFuture<>(); future = new PlainActionFuture<>();
tokenService.getAndValidateToken(requestContext, future); tokenService.getAndValidateToken(requestContext, future);
assertEquals(token.getAuthentication(), future.get().getAuthentication()); assertEquals(future.get().getAuthentication(), token.getAuthentication());
} }
} }
public void testGetAuthenticationWorksWithExpiredUserToken() throws Exception { public void testGetAuthenticationWorksWithExpiredUserToken() throws Exception {
TokenService tokenService = TokenService tokenService = new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), client, securityMainIndex,
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), client, securityIndex, clusterService); securityTokensIndex, clusterService);
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null); Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
UserToken expired = new UserToken(authentication, Instant.now().minus(3L, ChronoUnit.DAYS)); UserToken expired = new UserToken(authentication, Instant.now().minus(3L, ChronoUnit.DAYS));
mockGetTokenFromId(expired, false); mockGetTokenFromId(expired, false);
@ -672,4 +700,33 @@ public class TokenServiceTests extends ESTestCase {
} }
} }
private SecurityIndexManager mockSecurityManager() {
SecurityIndexManager mockSecurityIndex = mock(SecurityIndexManager.class);
doAnswer(invocationOnMock -> {
Runnable runnable = (Runnable) invocationOnMock.getArguments()[1];
runnable.run();
return null;
}).when(mockSecurityIndex).prepareIndexIfNeededThenExecute(any(Consumer.class), any(Runnable.class));
doAnswer(invocationOnMock -> {
Runnable runnable = (Runnable) invocationOnMock.getArguments()[1];
runnable.run();
return null;
}).when(mockSecurityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class));
when(mockSecurityIndex.indexExists()).thenReturn(true);
when(mockSecurityIndex.isAvailable()).thenReturn(true);
return mockSecurityIndex;
}
private DiscoveryNode addAnotherDataNodeWithVersion(ClusterService clusterService, Version version) {
final ClusterState currentState = clusterService.state();
final DiscoveryNodes.Builder discoBuilder = DiscoveryNodes.builder(currentState.getNodes());
final DiscoveryNode anotherDataNode = new DiscoveryNode("another_data_node#" + version, buildNewFakeTransportAddress(),
Collections.emptyMap(), Collections.singleton(DiscoveryNode.Role.DATA), version);
discoBuilder.add(anotherDataNode);
final ClusterState.Builder newStateBuilder = ClusterState.builder(currentState);
newStateBuilder.nodes(discoBuilder);
setState(clusterService, newStateBuilder.build());
return anotherDataNode;
}
} }

View File

@ -15,7 +15,7 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.test.NativeRealmIntegTestCase; import org.elasticsearch.test.NativeRealmIntegTestCase;
import org.elasticsearch.common.CharArrays; import org.elasticsearch.common.CharArrays;
import org.elasticsearch.xpack.core.security.client.SecurityClient; import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -85,7 +85,7 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase {
addedUsers.add(uname); addedUsers.add(uname);
} }
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME); ensureGreen(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
MockTerminal t = new MockTerminal(); MockTerminal t = new MockTerminal();
String username = nodeClientUsername(); String username = nodeClientUsername();
@ -136,7 +136,7 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase {
addedRoles.add(rname); addedRoles.add(rname);
} }
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME); ensureGreen(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
MockTerminal t = new MockTerminal(); MockTerminal t = new MockTerminal();
String username = nodeClientUsername(); String username = nodeClientUsername();

View File

@ -45,13 +45,13 @@ import org.elasticsearch.xpack.core.security.authz.RoleDescriptor;
import org.elasticsearch.xpack.core.security.authz.permission.Role; import org.elasticsearch.xpack.core.security.authz.permission.Role;
import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore;
import org.elasticsearch.xpack.core.security.client.SecurityClient; import org.elasticsearch.xpack.core.security.client.SecurityClient;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.core.security.user.AnonymousUser; import org.elasticsearch.xpack.core.security.user.AnonymousUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.ElasticUser;
import org.elasticsearch.xpack.core.security.user.KibanaUser; import org.elasticsearch.xpack.core.security.user.KibanaUser;
import org.elasticsearch.xpack.core.security.user.SystemUser; import org.elasticsearch.xpack.core.security.user.SystemUser;
import org.elasticsearch.xpack.core.security.user.User; import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore; import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
@ -67,8 +67,8 @@ import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDI
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout;
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
@ -146,7 +146,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
logger.error("--> creating user"); logger.error("--> creating user");
c.preparePutUser("joe", "s3kirt".toCharArray(), hasher, "role1", "user").get(); c.preparePutUser("joe", "s3kirt".toCharArray(), hasher, "role1", "user").get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
logger.info("--> retrieving user"); logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers("joe").get(); GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers()); assertTrue("user should exist", resp.hasUsers());
@ -201,7 +201,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
.metadata(metadata) .metadata(metadata)
.get(); .get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
logger.info("--> retrieving role"); logger.info("--> retrieving role");
GetRolesResponse resp = c.prepareGetRoles().names("test_role").get(); GetRolesResponse resp = c.prepareGetRoles().names("test_role").get();
assertTrue("role should exist", resp.hasRoles()); assertTrue("role should exist", resp.hasRoles());
@ -252,7 +252,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
logger.error("--> creating user"); logger.error("--> creating user");
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
logger.info("--> retrieving user"); logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers("joe").get(); GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers()); assertTrue("user should exist", resp.hasUsers());
@ -273,7 +273,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
logger.error("--> creating user"); logger.error("--> creating user");
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get(); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
logger.info("--> retrieving user"); logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers("joe").get(); GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers()); assertTrue("user should exist", resp.hasUsers());
@ -309,7 +309,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, c.preparePutUser("joe", "s3krit".toCharArray(), hasher,
SecuritySettingsSource.TEST_ROLE).get(); SecuritySettingsSource.TEST_ROLE).get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
logger.info("--> retrieving user"); logger.info("--> retrieving user");
GetUsersResponse resp = c.prepareGetUsers("joe").get(); GetUsersResponse resp = c.prepareGetUsers("joe").get();
assertTrue("user should exist", resp.hasUsers()); assertTrue("user should exist", resp.hasUsers());
@ -347,7 +347,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
logger.error("--> creating user"); logger.error("--> creating user");
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
if (authenticate) { if (authenticate) {
final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray())); final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray()));
@ -396,7 +396,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
logger.error("--> creating user"); logger.error("--> creating user");
securityClient().preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role", "snapshot_user").get(); securityClient().preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role", "snapshot_user").get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
logger.info("--> creating repository"); logger.info("--> creating repository");
assertAcked(client().admin().cluster() assertAcked(client().admin().cluster()
.preparePutRepository("test-repo") .preparePutRepository("test-repo")
@ -410,10 +410,10 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
.prepareCreateSnapshot("test-repo", "test-snap-1") .prepareCreateSnapshot("test-repo", "test-snap-1")
.setWaitForCompletion(true) .setWaitForCompletion(true)
.setIncludeGlobalState(false) .setIncludeGlobalState(false)
.setIndices(SECURITY_INDEX_NAME) .setIndices(SECURITY_MAIN_ALIAS)
.get().getSnapshotInfo(); .get().getSnapshotInfo();
assertThat(snapshotInfo.state(), is(SnapshotState.SUCCESS)); assertThat(snapshotInfo.state(), is(SnapshotState.SUCCESS));
assertThat(snapshotInfo.indices(), contains(SecurityIndexManager.INTERNAL_SECURITY_INDEX)); assertThat(snapshotInfo.indices(), contains(INTERNAL_SECURITY_MAIN_INDEX_7));
deleteSecurityIndex(); deleteSecurityIndex();
// the realm cache should clear itself but we don't wish to race it // the realm cache should clear itself but we don't wish to race it
securityClient().prepareClearRealmCache().get(); securityClient().prepareClearRealmCache().get();
@ -430,7 +430,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
RestoreSnapshotResponse response = client().admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap-1") RestoreSnapshotResponse response = client().admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap-1")
.setWaitForCompletion(true).setIncludeAliases(true).get(); .setWaitForCompletion(true).setIncludeAliases(true).get();
assertThat(response.status(), equalTo(RestStatus.OK)); assertThat(response.status(), equalTo(RestStatus.OK));
assertThat(response.getRestoreInfo().indices(), contains(SecurityIndexManager.INTERNAL_SECURITY_INDEX)); assertThat(response.getRestoreInfo().indices(), contains(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7));
// the realm cache should clear itself but we don't wish to race it // the realm cache should clear itself but we don't wish to race it
securityClient().prepareClearRealmCache().get(); securityClient().prepareClearRealmCache().get();
// users and roles are retrievable // users and roles are retrievable
@ -460,7 +460,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
.get(); .get();
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get(); c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get();
logger.error("--> waiting for .security index"); logger.error("--> waiting for .security index");
ensureGreen(SECURITY_INDEX_NAME); ensureGreen(SECURITY_MAIN_ALIAS);
final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray())); final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray()));
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster() ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster()
@ -591,12 +591,12 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
.get(); .get();
} }
IndicesStatsResponse response = client().admin().indices().prepareStats("foo", SECURITY_INDEX_NAME).get(); IndicesStatsResponse response = client().admin().indices().prepareStats("foo", SECURITY_MAIN_ALIAS).get();
assertThat(response.getFailedShards(), is(0)); assertThat(response.getFailedShards(), is(0));
assertThat(response.getIndices().size(), is(2)); assertThat(response.getIndices().size(), is(2));
assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX), notNullValue()); assertThat(response.getIndices().get(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7), notNullValue());
assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX).getIndex(), assertThat(response.getIndices().get(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7).getIndex(),
is(INTERNAL_SECURITY_INDEX)); is(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7));
} }
public void testOperationsOnReservedUsers() throws Exception { public void testOperationsOnReservedUsers() throws Exception {

View File

@ -15,6 +15,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -23,10 +24,10 @@ import static org.mockito.Mockito.when;
public class NativeRealmTests extends ESTestCase { public class NativeRealmTests extends ESTestCase {
private final String concreteSecurityIndexName = randomFrom( private final String concreteSecurityIndexName = randomFrom(
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) { private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) {
return new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, indexStatus); return new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, indexStatus);
} }
public void testCacheClearOnIndexHealthChange() { public void testCacheClearOnIndexHealthChange() {

View File

@ -27,6 +27,7 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult; import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
import org.elasticsearch.xpack.core.security.authc.support.Hasher; import org.elasticsearch.xpack.core.security.authc.support.Hasher;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.core.security.user.APMSystemUser; import org.elasticsearch.xpack.core.security.user.APMSystemUser;
import org.elasticsearch.xpack.core.security.user.BeatsSystemUser; import org.elasticsearch.xpack.core.security.user.BeatsSystemUser;
import org.elasticsearch.xpack.core.security.user.ElasticUser; import org.elasticsearch.xpack.core.security.user.ElasticUser;
@ -111,7 +112,7 @@ public class NativeUsersStoreTests extends ESTestCase {
values.put(PASSWORD_FIELD, BLANK_PASSWORD); values.put(PASSWORD_FIELD, BLANK_PASSWORD);
final GetResult result = new GetResult( final GetResult result = new GetResult(
SecurityIndexManager.SECURITY_INDEX_NAME, RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
MapperService.SINGLE_MAPPING_NAME, MapperService.SINGLE_MAPPING_NAME,
NativeUsersStore.getIdForUser(NativeUsersStore.RESERVED_USER_TYPE, randomAlphaOfLength(12)), NativeUsersStore.getIdForUser(NativeUsersStore.RESERVED_USER_TYPE, randomAlphaOfLength(12)),
0, 1, 1L, 0, 1, 1L,
@ -180,7 +181,7 @@ public class NativeUsersStoreTests extends ESTestCase {
nativeUsersStore.verifyPassword(username, password, future); nativeUsersStore.verifyPassword(username, password, future);
final GetResult getResult = new GetResult( final GetResult getResult = new GetResult(
SecurityIndexManager.SECURITY_INDEX_NAME, RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
MapperService.SINGLE_MAPPING_NAME, MapperService.SINGLE_MAPPING_NAME,
NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username), NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username),
UNASSIGNED_SEQ_NO, 0, 1L, UNASSIGNED_SEQ_NO, 0, 1L,
@ -222,7 +223,7 @@ public class NativeUsersStoreTests extends ESTestCase {
values.put(User.Fields.TYPE.getPreferredName(), NativeUsersStore.USER_DOC_TYPE); values.put(User.Fields.TYPE.getPreferredName(), NativeUsersStore.USER_DOC_TYPE);
final BytesReference source = BytesReference.bytes(jsonBuilder().map(values)); final BytesReference source = BytesReference.bytes(jsonBuilder().map(values));
final GetResult getResult = new GetResult( final GetResult getResult = new GetResult(
SecurityIndexManager.SECURITY_INDEX_NAME, RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
MapperService.SINGLE_MAPPING_NAME, MapperService.SINGLE_MAPPING_NAME,
NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username), NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username),
0, 1, 1L, 0, 1, 1L,
@ -230,7 +231,6 @@ public class NativeUsersStoreTests extends ESTestCase {
source, source,
Collections.emptyMap()); Collections.emptyMap());
actionRespond(GetRequest.class, new GetResponse(getResult)); actionRespond(GetRequest.class, new GetResponse(getResult));
} }

View File

@ -37,6 +37,7 @@ import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -53,7 +54,7 @@ import static org.mockito.Mockito.when;
public class NativeRoleMappingStoreTests extends ESTestCase { public class NativeRoleMappingStoreTests extends ESTestCase {
private final String concreteSecurityIndexName = randomFrom( private final String concreteSecurityIndexName = randomFrom(
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
public void testResolveRoles() throws Exception { public void testResolveRoles() throws Exception {
// Does match DN // Does match DN
@ -137,7 +138,7 @@ public class NativeRoleMappingStoreTests extends ESTestCase {
} }
private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) { private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) {
return new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, indexStatus); return new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, indexStatus);
} }
public void testCacheClearOnIndexHealthChange() { public void testCacheClearOnIndexHealthChange() {
@ -182,13 +183,13 @@ public class NativeRoleMappingStoreTests extends ESTestCase {
final NativeRoleMappingStore store = buildRoleMappingStoreForInvalidationTesting(numInvalidation); final NativeRoleMappingStore store = buildRoleMappingStoreForInvalidationTesting(numInvalidation);
store.onSecurityIndexStateChange( store.onSecurityIndexStateChange(
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null), new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null),
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null)); new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null));
assertEquals(1, numInvalidation.get()); assertEquals(1, numInvalidation.get());
store.onSecurityIndexStateChange( store.onSecurityIndexStateChange(
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null), new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null),
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null)); new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null));
assertEquals(2, numInvalidation.get()); assertEquals(2, numInvalidation.get());
} }

View File

@ -156,8 +156,8 @@ import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationExce
import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException;
import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationExceptionRunAs; import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationExceptionRunAs;
import static org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME; import static org.elasticsearch.xpack.security.audit.logfile.LoggingAuditTrail.PRINCIPAL_ROLES_FIELD_NAME;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.endsWith;
@ -864,8 +864,8 @@ public class AuthorizationServiceTests extends ESTestCase {
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.builder() when(state.metaData()).thenReturn(MetaData.builder()
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX) .put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
@ -874,31 +874,33 @@ public class AuthorizationServiceTests extends ESTestCase {
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
List<Tuple<String, TransportRequest>> requests = new ArrayList<>(); List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
new DeleteRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id")));
requests.add( requests.add(
new Tuple<>(BulkAction.NAME + "[s]", new DeleteRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id"))); new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id")));
requests.add(new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id"))); requests.add(
requests.add(new Tuple<>(BulkAction.NAME + "[s]", new IndexRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new Tuple<>(BulkAction.NAME + "[s]", new IndexRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(TermVectorsAction.NAME, requests.add(new Tuple<>(TermVectorsAction.NAME,
new TermVectorsRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "type", "id"))); new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "type", "id")));
requests.add(new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id"))); requests.add(new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id")));
requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest() requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest()
.addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_INDEX)))); .addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(UpdateSettingsAction.NAME, requests.add(new Tuple<>(UpdateSettingsAction.NAME,
new UpdateSettingsRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new UpdateSettingsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
// cannot execute monitor operations // cannot execute monitor operations
requests.add(new Tuple<>(IndicesStatsAction.NAME, requests.add(new Tuple<>(IndicesStatsAction.NAME,
new IndicesStatsRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new IndicesStatsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add( requests.add(new Tuple<>(RecoveryAction.NAME,
new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new RecoveryRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(IndicesSegmentsAction.NAME, requests.add(new Tuple<>(IndicesSegmentsAction.NAME,
new IndicesSegmentsRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new IndicesSegmentsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(GetSettingsAction.NAME, requests.add(new Tuple<>(GetSettingsAction.NAME,
new GetSettingsRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new GetSettingsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(IndicesShardStoresAction.NAME, requests.add(new Tuple<>(IndicesShardStoresAction.NAME,
new IndicesShardStoresRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new IndicesShardStoresRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(UpgradeStatusAction.NAME, requests.add(new Tuple<>(UpgradeStatusAction.NAME,
new UpgradeStatusRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new UpgradeStatusRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
for (Tuple<String, TransportRequest> requestTuple : requests) { for (Tuple<String, TransportRequest> requestTuple : requests) {
String action = requestTuple.v1(); String action = requestTuple.v1();
@ -912,13 +914,13 @@ public class AuthorizationServiceTests extends ESTestCase {
} }
// we should allow waiting for the health of the index or any index if the user has this permission // we should allow waiting for the health of the index or any index if the user has this permission
ClusterHealthRequest request = new ClusterHealthRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)); ClusterHealthRequest request = new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7));
authorize(authentication, ClusterHealthAction.NAME, request); authorize(authentication, ClusterHealthAction.NAME, request);
verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(ClusterHealthAction.NAME), eq(request), verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(ClusterHealthAction.NAME), eq(request),
authzInfoRoles(new String[]{role.getName()})); authzInfoRoles(new String[]{role.getName()}));
// multiple indices // multiple indices
request = new ClusterHealthRequest(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX, "foo", "bar"); request = new ClusterHealthRequest(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7, "foo", "bar");
authorize(authentication, ClusterHealthAction.NAME, request); authorize(authentication, ClusterHealthAction.NAME, request);
verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(ClusterHealthAction.NAME), eq(request), verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(ClusterHealthAction.NAME), eq(request),
authzInfoRoles(new String[]{role.getName()})); authzInfoRoles(new String[]{role.getName()}));
@ -940,8 +942,8 @@ public class AuthorizationServiceTests extends ESTestCase {
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.builder() when(state.metaData()).thenReturn(MetaData.builder()
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX) .put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
@ -949,12 +951,12 @@ public class AuthorizationServiceTests extends ESTestCase {
.build()); .build());
List<Tuple<String, ? extends TransportRequest>> requests = new ArrayList<>(); List<Tuple<String, ? extends TransportRequest>> requests = new ArrayList<>();
requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SECURITY_MAIN_ALIAS)));
requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SECURITY_MAIN_ALIAS)));
requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SECURITY_MAIN_ALIAS)));
requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SECURITY_MAIN_ALIAS)));
requests.add(new Tuple<>(IndicesShardStoresAction.NAME, new IndicesShardStoresRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(IndicesShardStoresAction.NAME, new IndicesShardStoresRequest().indices(SECURITY_MAIN_ALIAS)));
requests.add(new Tuple<>(UpgradeStatusAction.NAME, new UpgradeStatusRequest().indices(SECURITY_INDEX_NAME))); requests.add(new Tuple<>(UpgradeStatusAction.NAME, new UpgradeStatusRequest().indices(SECURITY_MAIN_ALIAS)));
for (final Tuple<String, ? extends TransportRequest> requestTuple : requests) { for (final Tuple<String, ? extends TransportRequest> requestTuple : requests) {
final String action = requestTuple.v1(); final String action = requestTuple.v1();
@ -984,8 +986,8 @@ public class AuthorizationServiceTests extends ESTestCase {
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.builder() when(state.metaData()).thenReturn(MetaData.builder()
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX) .put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
@ -994,25 +996,28 @@ public class AuthorizationServiceTests extends ESTestCase {
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext); final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
List<Tuple<String, TransportRequest>> requests = new ArrayList<>(); List<Tuple<String, TransportRequest>> requests = new ArrayList<>();
requests.add(new Tuple<>(DeleteAction.NAME, new DeleteRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id")));
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
createBulkShardRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), DeleteRequest::new)));
requests.add(new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id")));
requests.add(new Tuple<>(IndexAction.NAME, new IndexRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX))));
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
createBulkShardRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), IndexRequest::new)));
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX))));
requests.add(new Tuple<>(TermVectorsAction.NAME,
new TermVectorsRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "type", "id")));
requests.add(new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "type", "id")));
requests.add(new Tuple<>(TermVectorsAction.NAME,
new TermVectorsRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "type", "id")));
requests.add(new Tuple<>(IndicesAliasesAction.NAME,
new IndicesAliasesRequest().addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_INDEX))));
requests.add( requests.add(
new Tuple<>(ClusterHealthAction.NAME, new ClusterHealthRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX)))); new Tuple<>(DeleteAction.NAME, new DeleteRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id")));
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
createBulkShardRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), DeleteRequest::new)));
requests.add(
new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id")));
requests.add(new Tuple<>(IndexAction.NAME, new IndexRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(BulkAction.NAME + "[s]",
createBulkShardRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), IndexRequest::new)));
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(TermVectorsAction.NAME,
new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "type", "id")));
requests.add(
new Tuple<>(GetAction.NAME, new GetRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "type", "id")));
requests.add(new Tuple<>(TermVectorsAction.NAME,
new TermVectorsRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "type", "id")));
requests.add(new Tuple<>(IndicesAliasesAction.NAME, new IndicesAliasesRequest()
.addAliasAction(AliasActions.add().alias("security_alias").index(INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(ClusterHealthAction.NAME, requests.add(new Tuple<>(ClusterHealthAction.NAME,
new ClusterHealthRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "foo", "bar"))); new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
requests.add(new Tuple<>(ClusterHealthAction.NAME,
new ClusterHealthRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "foo", "bar")));
for (final Tuple<String, TransportRequest> requestTuple : requests) { for (final Tuple<String, TransportRequest> requestTuple : requests) {
final String action = requestTuple.v1(); final String action = requestTuple.v1();
@ -1033,8 +1038,8 @@ public class AuthorizationServiceTests extends ESTestCase {
ClusterState state = mock(ClusterState.class); ClusterState state = mock(ClusterState.class);
when(clusterService.state()).thenReturn(state); when(clusterService.state()).thenReturn(state);
when(state.metaData()).thenReturn(MetaData.builder() when(state.metaData()).thenReturn(MetaData.builder()
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX) .put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build()) .settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
@ -1046,7 +1051,7 @@ public class AuthorizationServiceTests extends ESTestCase {
SearchRequest request = new SearchRequest("_all"); SearchRequest request = new SearchRequest("_all");
authorize(authentication, action, request); authorize(authentication, action, request);
verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), authzInfoRoles(superuser.roles())); verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(action), eq(request), authzInfoRoles(superuser.roles()));
assertThat(request.indices(), arrayContainingInAnyOrder(INTERNAL_SECURITY_INDEX, SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContainingInAnyOrder(INTERNAL_SECURITY_MAIN_INDEX_7, SECURITY_MAIN_ALIAS));
} }
public void testCompositeActionsAreImmediatelyRejected() { public void testCompositeActionsAreImmediatelyRejected() {

View File

@ -24,7 +24,6 @@ import org.elasticsearch.xpack.core.security.authz.privilege.IndexPrivilege;
import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -47,8 +46,8 @@ public class AuthorizedIndicesTests extends ESTestCase {
RoleDescriptor bRole = new RoleDescriptor("b", null, RoleDescriptor bRole = new RoleDescriptor("b", null,
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("READ").build() }, null); new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("READ").build() }, null);
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
MetaData metaData = MetaData.builder() MetaData metaData = MetaData.builder()
.put(new IndexMetaData.Builder("a1").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("a1").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
.put(new IndexMetaData.Builder("a2").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("a2").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
@ -65,7 +64,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
.settings(indexSettings) .settings(indexSettings)
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
.build(), true) .build(), true)
.build(); .build();
final PlainActionFuture<Role> future = new PlainActionFuture<>(); final PlainActionFuture<Role> future = new PlainActionFuture<>();
@ -78,7 +77,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
assertFalse(list.contains("bbbbb")); assertFalse(list.contains("bbbbb"));
assertFalse(list.contains("ba")); assertFalse(list.contains("ba"));
assertThat(list, not(contains(internalSecurityIndex))); assertThat(list, not(contains(internalSecurityIndex)));
assertThat(list, not(contains(RestrictedIndicesNames.SECURITY_INDEX_NAME))); assertThat(list, not(contains(RestrictedIndicesNames.SECURITY_MAIN_ALIAS)));
} }
public void testAuthorizedIndicesUserWithSomeRolesEmptyMetaData() { public void testAuthorizedIndicesUserWithSomeRolesEmptyMetaData() {
@ -101,8 +100,8 @@ public class AuthorizedIndicesTests extends ESTestCase {
.cluster(ClusterPrivilege.ALL) .cluster(ClusterPrivilege.ALL)
.build(); .build();
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
MetaData metaData = MetaData.builder() MetaData metaData = MetaData.builder()
.put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
.put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
@ -111,7 +110,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
.settings(indexSettings) .settings(indexSettings)
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
.build(), true) .build(), true)
.build(); .build();
@ -119,7 +118,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup()); RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup());
assertThat(authorizedIndices, containsInAnyOrder("an-index", "another-index")); assertThat(authorizedIndices, containsInAnyOrder("an-index", "another-index"));
assertThat(authorizedIndices, not(contains(internalSecurityIndex))); assertThat(authorizedIndices, not(contains(internalSecurityIndex)));
assertThat(authorizedIndices, not(contains(RestrictedIndicesNames.SECURITY_INDEX_NAME))); assertThat(authorizedIndices, not(contains(RestrictedIndicesNames.SECURITY_MAIN_ALIAS)));
} }
public void testSecurityIndicesAreNotRemovedFromUnrestrictedRole() { public void testSecurityIndicesAreNotRemovedFromUnrestrictedRole() {
@ -128,8 +127,8 @@ public class AuthorizedIndicesTests extends ESTestCase {
.cluster(ClusterPrivilege.ALL) .cluster(ClusterPrivilege.ALL)
.build(); .build();
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
MetaData metaData = MetaData.builder() MetaData metaData = MetaData.builder()
.put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("an-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
.put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true) .put(new IndexMetaData.Builder("another-index").settings(indexSettings).numberOfShards(1).numberOfReplicas(0).build(), true)
@ -137,18 +136,18 @@ public class AuthorizedIndicesTests extends ESTestCase {
.settings(indexSettings) .settings(indexSettings)
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
.build(), true) .build(), true)
.build(); .build();
List<String> authorizedIndices = List<String> authorizedIndices =
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup()); RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup());
assertThat(authorizedIndices, containsInAnyOrder( assertThat(authorizedIndices, containsInAnyOrder(
"an-index", "another-index", SecurityIndexManager.SECURITY_INDEX_NAME, internalSecurityIndex)); "an-index", "another-index", RestrictedIndicesNames.SECURITY_MAIN_ALIAS, internalSecurityIndex));
List<String> authorizedIndicesSuperUser = List<String> authorizedIndicesSuperUser =
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup()); RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup());
assertThat(authorizedIndicesSuperUser, containsInAnyOrder( assertThat(authorizedIndicesSuperUser, containsInAnyOrder(
"an-index", "another-index", SecurityIndexManager.SECURITY_INDEX_NAME, internalSecurityIndex)); "an-index", "another-index", RestrictedIndicesNames.SECURITY_MAIN_ALIAS, internalSecurityIndex));
} }
} }

View File

@ -64,7 +64,6 @@ import org.elasticsearch.xpack.core.security.user.User;
import org.elasticsearch.xpack.core.security.user.XPackSecurityUser; import org.elasticsearch.xpack.core.security.user.XPackSecurityUser;
import org.elasticsearch.xpack.core.security.user.XPackUser; import org.elasticsearch.xpack.core.security.user.XPackUser;
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore; import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.elasticsearch.xpack.security.test.SecurityTestUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
@ -79,7 +78,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
@ -119,7 +118,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
indexNameExpressionResolver = new IndexNameExpressionResolver(); indexNameExpressionResolver = new IndexNameExpressionResolver();
final boolean withAlias = randomBoolean(); final boolean withAlias = randomBoolean();
final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); final String securityIndexName = SECURITY_MAIN_ALIAS + (withAlias ? "-" + randomAlphaOfLength(5) : "");
MetaData metaData = MetaData.builder() MetaData metaData = MetaData.builder()
.put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar")) .put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar"))
.putAlias(AliasMetaData.builder("foounauthorized")).settings(settings)) .putAlias(AliasMetaData.builder("foounauthorized")).settings(settings))
@ -1222,14 +1221,14 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
{ {
final List<String> authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, SearchAction.NAME); final List<String> authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal(); List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, hasItem(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(indices, hasItem(SECURITY_MAIN_ALIAS));
} }
{ {
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest(); IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest();
aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_INDEX_NAME)); aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias").index(SECURITY_MAIN_ALIAS));
final List<String> authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, IndicesAliasesAction.NAME); final List<String> authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal();
assertThat(indices, hasItem(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(indices, hasItem(SECURITY_MAIN_ALIAS));
} }
} }
@ -1237,7 +1236,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
SearchRequest request = new SearchRequest(); SearchRequest request = new SearchRequest();
final List<String> authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME); final List<String> authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal(); List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME))); assertThat(indices, not(hasItem(SECURITY_MAIN_ALIAS)));
} }
public void testNonXPackUserAccessingSecurityIndex() { public void testNonXPackUserAccessingSecurityIndex() {
@ -1249,7 +1248,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
SearchRequest request = new SearchRequest(); SearchRequest request = new SearchRequest();
final List<String> authorizedIndices = buildAuthorizedIndices(allAccessUser, SearchAction.NAME); final List<String> authorizedIndices = buildAuthorizedIndices(allAccessUser, SearchAction.NAME);
List<String> indices = resolveIndices(request, authorizedIndices).getLocal(); List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME))); assertThat(indices, not(hasItem(SECURITY_MAIN_ALIAS)));
} }
{ {
@ -1257,7 +1256,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias1").index("*")); aliasesRequest.addAliasAction(AliasActions.add().alias("security_alias1").index("*"));
final List<String> authorizedIndices = buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME); final List<String> authorizedIndices = buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME);
List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal(); List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal();
assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME))); assertThat(indices, not(hasItem(SECURITY_MAIN_ALIAS)));
} }
} }

View File

@ -22,8 +22,8 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Locale; import java.util.Locale;
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7;
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; import static org.elasticsearch.xpack.core.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
@ -56,7 +56,7 @@ public class SnapshotUserRoleIntegTests extends NativeRealmIntegTestCase {
final String snapshotUserToken = basicAuthHeaderValue(user, new SecureString(password)); final String snapshotUserToken = basicAuthHeaderValue(user, new SecureString(password));
client = client().filterWithHeader(Collections.singletonMap("Authorization", snapshotUserToken)); client = client().filterWithHeader(Collections.singletonMap("Authorization", snapshotUserToken));
securityClient().preparePutUser(user, password, Hasher.BCRYPT, "snapshot_user").get(); securityClient().preparePutUser(user, password, Hasher.BCRYPT, "snapshot_user").get();
ensureGreen(INTERNAL_SECURITY_INDEX_7); ensureGreen(INTERNAL_SECURITY_MAIN_INDEX_7);
} }
public void testSnapshotUserRoleCanSnapshotAndSeeAllIndices() { public void testSnapshotUserRoleCanSnapshotAndSeeAllIndices() {
@ -67,17 +67,17 @@ public class SnapshotUserRoleIntegTests extends NativeRealmIntegTestCase {
assertThat(getRepositoriesResponse.repositories().get(0).name(), is("repo")); assertThat(getRepositoriesResponse.repositories().get(0).name(), is("repo"));
// view all indices, including restricted ones // view all indices, including restricted ones
final GetIndexResponse getIndexResponse = client.admin().indices().prepareGetIndex().setIndices(randomFrom("_all", "*")).get(); final GetIndexResponse getIndexResponse = client.admin().indices().prepareGetIndex().setIndices(randomFrom("_all", "*")).get();
assertThat(Arrays.asList(getIndexResponse.indices()), containsInAnyOrder(INTERNAL_SECURITY_INDEX_7, ordinaryIndex)); assertThat(Arrays.asList(getIndexResponse.indices()), containsInAnyOrder(INTERNAL_SECURITY_MAIN_INDEX_7, ordinaryIndex));
// create snapshot that includes restricted indices // create snapshot that includes restricted indices
final CreateSnapshotResponse snapshotResponse = client.admin().cluster().prepareCreateSnapshot("repo", "snap") final CreateSnapshotResponse snapshotResponse = client.admin().cluster().prepareCreateSnapshot("repo", "snap")
.setIndices(randomFrom("_all", "*")).setWaitForCompletion(true).get(); .setIndices(randomFrom("_all", "*")).setWaitForCompletion(true).get();
assertThat(snapshotResponse.getSnapshotInfo().state(), is(SnapshotState.SUCCESS)); assertThat(snapshotResponse.getSnapshotInfo().state(), is(SnapshotState.SUCCESS));
assertThat(snapshotResponse.getSnapshotInfo().indices(), containsInAnyOrder(INTERNAL_SECURITY_INDEX_7, ordinaryIndex)); assertThat(snapshotResponse.getSnapshotInfo().indices(), containsInAnyOrder(INTERNAL_SECURITY_MAIN_INDEX_7, ordinaryIndex));
// view snapshots for repo // view snapshots for repo
final GetSnapshotsResponse getSnapshotResponse = client.admin().cluster().prepareGetSnapshots("repo").get(); final GetSnapshotsResponse getSnapshotResponse = client.admin().cluster().prepareGetSnapshots("repo").get();
assertThat(getSnapshotResponse.getSnapshots().size(), is(1)); assertThat(getSnapshotResponse.getSnapshots().size(), is(1));
assertThat(getSnapshotResponse.getSnapshots().get(0).snapshotId().getName(), is("snap")); assertThat(getSnapshotResponse.getSnapshots().get(0).snapshotId().getName(), is("snap"));
assertThat(getSnapshotResponse.getSnapshots().get(0).indices(), containsInAnyOrder(INTERNAL_SECURITY_INDEX_7, ordinaryIndex)); assertThat(getSnapshotResponse.getSnapshots().get(0).indices(), containsInAnyOrder(INTERNAL_SECURITY_MAIN_INDEX_7, ordinaryIndex));
} }
public void testSnapshotUserRoleIsReserved() { public void testSnapshotUserRoleIsReserved() {
@ -112,7 +112,7 @@ public class SnapshotUserRoleIntegTests extends NativeRealmIntegTestCase {
() -> client.admin().cluster().prepareDeleteSnapshot("repo", randomAlphaOfLength(4).toLowerCase(Locale.ROOT)).get(), () -> client.admin().cluster().prepareDeleteSnapshot("repo", randomAlphaOfLength(4).toLowerCase(Locale.ROOT)).get(),
"cluster:admin/snapshot/delete", "snapshot_user"); "cluster:admin/snapshot/delete", "snapshot_user");
// try destructive/revealing actions on all indices // try destructive/revealing actions on all indices
for (final String indexToTest : Arrays.asList(INTERNAL_SECURITY_INDEX_7, SECURITY_INDEX_NAME, ordinaryIndex)) { for (final String indexToTest : Arrays.asList(INTERNAL_SECURITY_MAIN_INDEX_7, SECURITY_MAIN_ALIAS, ordinaryIndex)) {
assertThrowsAuthorizationException(() -> client.prepareSearch(indexToTest).get(), "indices:data/read/search", "snapshot_user"); assertThrowsAuthorizationException(() -> client.prepareSearch(indexToTest).get(), "indices:data/read/search", "snapshot_user");
assertThrowsAuthorizationException(() -> client.prepareGet(indexToTest, "doc", "1").get(), "indices:data/read/get", assertThrowsAuthorizationException(() -> client.prepareGet(indexToTest, "doc", "1").get(), "indices:data/read/get",
"snapshot_user"); "snapshot_user");

View File

@ -293,14 +293,14 @@ public class IndicesPermissionTests extends ESTestCase {
public void testSecurityIndicesPermissions() { public void testSecurityIndicesPermissions() {
final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build(); final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
final MetaData metaData = new MetaData.Builder() final MetaData metaData = new MetaData.Builder()
.put(new IndexMetaData.Builder(internalSecurityIndex) .put(new IndexMetaData.Builder(internalSecurityIndex)
.settings(indexSettings) .settings(indexSettings)
.numberOfShards(1) .numberOfShards(1)
.numberOfReplicas(0) .numberOfReplicas(0)
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build()) .putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
.build(), true) .build(), true)
.build(); .build();
FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY); FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
@ -309,18 +309,18 @@ public class IndicesPermissionTests extends ESTestCase {
// allow_restricted_indices: false // allow_restricted_indices: false
IndicesPermission.Group group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, false, "*"); IndicesPermission.Group group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, false, "*");
Map<String, IndicesAccessControl.IndexAccessControl> authzMap = new IndicesPermission(group).authorize(SearchAction.NAME, Map<String, IndicesAccessControl.IndexAccessControl> authzMap = new IndicesPermission(group).authorize(SearchAction.NAME,
Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_INDEX_NAME), lookup, Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_MAIN_ALIAS), lookup,
fieldPermissionsCache); fieldPermissionsCache);
assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(false)); assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(false));
assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(false)); assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).isGranted(), is(false));
// allow_restricted_indices: true // allow_restricted_indices: true
group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, true, "*"); group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, true, "*");
authzMap = new IndicesPermission(group).authorize(SearchAction.NAME, authzMap = new IndicesPermission(group).authorize(SearchAction.NAME,
Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_INDEX_NAME), lookup, Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_MAIN_ALIAS), lookup,
fieldPermissionsCache); fieldPermissionsCache);
assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true)); assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true));
assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true)); assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).isGranted(), is(true));
} }
private static FieldPermissionsDefinition fieldPermissionDef(String[] granted, String[] denied) { private static FieldPermissionsDefinition fieldPermissionDef(String[] granted, String[] denied) {

View File

@ -57,6 +57,7 @@ import org.elasticsearch.xpack.security.authc.ApiKeyService.ApiKeyRoleDescriptor
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import java.io.IOException; import java.io.IOException;
import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -98,7 +99,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
private final FieldPermissionsCache cache = new FieldPermissionsCache(Settings.EMPTY); private final FieldPermissionsCache cache = new FieldPermissionsCache(Settings.EMPTY);
private final String concreteSecurityIndexName = randomFrom( private final String concreteSecurityIndexName = randomFrom(
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7); RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6, RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
public void testRolesWhenDlsFlsUnlicensed() throws IOException { public void testRolesWhenDlsFlsUnlicensed() throws IOException {
XPackLicenseState licenseState = mock(XPackLicenseState.class); XPackLicenseState licenseState = mock(XPackLicenseState.class);
@ -762,7 +763,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
} }
private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) { private SecurityIndexManager.State dummyState(ClusterHealthStatus indexStatus) {
return new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, indexStatus); return new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, indexStatus);
} }
public void testCacheClearOnIndexHealthChange() { public void testCacheClearOnIndexHealthChange() {
@ -837,13 +838,13 @@ public class CompositeRolesStoreTests extends ESTestCase {
}; };
compositeRolesStore.onSecurityIndexStateChange( compositeRolesStore.onSecurityIndexStateChange(
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null), new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null),
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null)); new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null));
assertEquals(1, numInvalidation.get()); assertEquals(1, numInvalidation.get());
compositeRolesStore.onSecurityIndexStateChange( compositeRolesStore.onSecurityIndexStateChange(
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null), new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null),
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null)); new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null));
assertEquals(2, numInvalidation.get()); assertEquals(2, numInvalidation.get());
} }

View File

@ -39,6 +39,7 @@ import org.elasticsearch.test.client.NoOpClient;
import org.elasticsearch.test.junit.annotations.TestLogging; import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.xpack.core.security.action.role.ClearRolesCacheRequest; import org.elasticsearch.xpack.core.security.action.role.ClearRolesCacheRequest;
import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor; import org.elasticsearch.xpack.core.security.authz.privilege.ApplicationPrivilegeDescriptor;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.security.support.SecurityIndexManager; import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
@ -125,7 +126,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(requests, iterableWithSize(1)); assertThat(requests, iterableWithSize(1));
assertThat(requests.get(0), instanceOf(GetRequest.class)); assertThat(requests.get(0), instanceOf(GetRequest.class));
GetRequest request = (GetRequest) requests.get(0); GetRequest request = (GetRequest) requests.get(0);
assertThat(request.index(), equalTo(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.index(), equalTo(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME)); assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME));
assertThat(request.id(), equalTo("application-privilege_myapp:admin")); assertThat(request.id(), equalTo("application-privilege_myapp:admin"));
@ -143,7 +144,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(requests, iterableWithSize(1)); assertThat(requests, iterableWithSize(1));
assertThat(requests.get(0), instanceOf(GetRequest.class)); assertThat(requests.get(0), instanceOf(GetRequest.class));
GetRequest request = (GetRequest) requests.get(0); GetRequest request = (GetRequest) requests.get(0);
assertThat(request.index(), equalTo(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.index(), equalTo(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME)); assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME));
assertThat(request.id(), equalTo("application-privilege_myapp:admin")); assertThat(request.id(), equalTo("application-privilege_myapp:admin"));
@ -166,7 +167,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(requests, iterableWithSize(1)); assertThat(requests, iterableWithSize(1));
assertThat(requests.get(0), instanceOf(SearchRequest.class)); assertThat(requests.get(0), instanceOf(SearchRequest.class));
SearchRequest request = (SearchRequest) requests.get(0); SearchRequest request = (SearchRequest) requests.get(0);
assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContaining(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
final String query = Strings.toString(request.source().query()); final String query = Strings.toString(request.source().query());
assertThat(query, containsString("{\"terms\":{\"application\":[\"myapp\",\"yourapp\"]")); assertThat(query, containsString("{\"terms\":{\"application\":[\"myapp\",\"yourapp\"]"));
@ -187,7 +188,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(requests, iterableWithSize(1)); assertThat(requests, iterableWithSize(1));
assertThat(requests.get(0), instanceOf(SearchRequest.class)); assertThat(requests.get(0), instanceOf(SearchRequest.class));
SearchRequest request = (SearchRequest) requests.get(0); SearchRequest request = (SearchRequest) requests.get(0);
assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContaining(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
final String query = Strings.toString(request.source().query()); final String query = Strings.toString(request.source().query());
assertThat(query, containsString("{\"bool\":{\"filter\":[{\"terms\":{\"application\":[\"yourapp\"]")); assertThat(query, containsString("{\"bool\":{\"filter\":[{\"terms\":{\"application\":[\"yourapp\"]"));
@ -207,7 +208,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(requests, iterableWithSize(1)); assertThat(requests, iterableWithSize(1));
assertThat(requests.get(0), instanceOf(SearchRequest.class)); assertThat(requests.get(0), instanceOf(SearchRequest.class));
SearchRequest request = (SearchRequest) requests.get(0); SearchRequest request = (SearchRequest) requests.get(0);
assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContaining(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
final String query = Strings.toString(request.source().query()); final String query = Strings.toString(request.source().query());
assertThat(query, containsString("{\"exists\":{\"field\":\"application\"")); assertThat(query, containsString("{\"exists\":{\"field\":\"application\""));
@ -232,7 +233,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(requests, iterableWithSize(1)); assertThat(requests, iterableWithSize(1));
assertThat(requests.get(0), instanceOf(SearchRequest.class)); assertThat(requests.get(0), instanceOf(SearchRequest.class));
SearchRequest request = (SearchRequest) requests.get(0); SearchRequest request = (SearchRequest) requests.get(0);
assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContaining(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
final String query = Strings.toString(request.source().query()); final String query = Strings.toString(request.source().query());
assertThat(query, containsString("{\"term\":{\"type\":{\"value\":\"application-privilege\"")); assertThat(query, containsString("{\"term\":{\"type\":{\"value\":\"application-privilege\""));
@ -268,7 +269,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
for (int i = 0; i < putPrivileges.size(); i++) { for (int i = 0; i < putPrivileges.size(); i++) {
ApplicationPrivilegeDescriptor privilege = putPrivileges.get(i); ApplicationPrivilegeDescriptor privilege = putPrivileges.get(i);
IndexRequest request = indexRequests.get(i); IndexRequest request = indexRequests.get(i);
assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContaining(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME)); assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME));
assertThat(request.id(), equalTo( assertThat(request.id(), equalTo(
"application-privilege_" + privilege.getApplication() + ":" + privilege.getName() "application-privilege_" + privilege.getApplication() + ":" + privilege.getName()
@ -277,7 +278,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
assertThat(request.source(), equalTo(BytesReference.bytes(builder))); assertThat(request.source(), equalTo(BytesReference.bytes(builder)));
final boolean created = privilege.getName().equals("user") == false; final boolean created = privilege.getName().equals("user") == false;
indexListener.onResponse(new IndexResponse( indexListener.onResponse(new IndexResponse(
new ShardId(SecurityIndexManager.SECURITY_INDEX_NAME, uuid, i), new ShardId(RestrictedIndicesNames.SECURITY_MAIN_ALIAS, uuid, i),
request.type(), request.id(), 1, 1, 1, created request.type(), request.id(), 1, 1, 1, created
)); ));
} }
@ -313,12 +314,12 @@ public class NativePrivilegeStoreTests extends ESTestCase {
for (int i = 0; i < privilegeNames.size(); i++) { for (int i = 0; i < privilegeNames.size(); i++) {
String name = privilegeNames.get(i); String name = privilegeNames.get(i);
DeleteRequest request = deletes.get(i); DeleteRequest request = deletes.get(i);
assertThat(request.indices(), arrayContaining(SecurityIndexManager.SECURITY_INDEX_NAME)); assertThat(request.indices(), arrayContaining(RestrictedIndicesNames.SECURITY_MAIN_ALIAS));
assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME)); assertThat(request.type(), equalTo(MapperService.SINGLE_MAPPING_NAME));
assertThat(request.id(), equalTo("application-privilege_app1:" + name)); assertThat(request.id(), equalTo("application-privilege_app1:" + name));
final boolean found = name.equals("p2") == false; final boolean found = name.equals("p2") == false;
deleteListener.onResponse(new DeleteResponse( deleteListener.onResponse(new DeleteResponse(
new ShardId(SecurityIndexManager.SECURITY_INDEX_NAME, uuid, i), new ShardId(RestrictedIndicesNames.SECURITY_MAIN_ALIAS, uuid, i),
request.type(), request.id(), 1, 1, 1, found request.type(), request.id(), 1, 1, 1, found
)); ));
} }

View File

@ -56,7 +56,7 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -187,7 +187,7 @@ public class NativeRolesStoreTests extends ESTestCase {
final ClusterService clusterService = mock(ClusterService.class); final ClusterService clusterService = mock(ClusterService.class);
final XPackLicenseState licenseState = mock(XPackLicenseState.class); final XPackLicenseState licenseState = mock(XPackLicenseState.class);
final AtomicBoolean methodCalled = new AtomicBoolean(false); final AtomicBoolean methodCalled = new AtomicBoolean(false);
final SecurityIndexManager securityIndex = SecurityIndexManager.buildSecurityIndexManager(client, clusterService); final SecurityIndexManager securityIndex = SecurityIndexManager.buildSecurityMainIndexManager(client, clusterService);
final NativeRolesStore rolesStore = new NativeRolesStore(Settings.EMPTY, client, licenseState, securityIndex) { final NativeRolesStore rolesStore = new NativeRolesStore(Settings.EMPTY, client, licenseState, securityIndex) {
@Override @Override
void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) { void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) {
@ -247,7 +247,7 @@ public class NativeRolesStoreTests extends ESTestCase {
private ClusterState getClusterStateWithSecurityIndex() { private ClusterState getClusterStateWithSecurityIndex() {
final boolean withAlias = randomBoolean(); final boolean withAlias = randomBoolean();
final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); final String securityIndexName = SECURITY_MAIN_ALIAS + (withAlias ? "-" + randomAlphaOfLength(5) : "");
Settings settings = Settings.builder() Settings settings = Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT) .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
@ -256,7 +256,7 @@ public class NativeRolesStoreTests extends ESTestCase {
.build(); .build();
MetaData metaData = MetaData.builder() MetaData metaData = MetaData.builder()
.put(IndexMetaData.builder(securityIndexName).settings(settings)) .put(IndexMetaData.builder(securityIndexName).settings(settings))
.put(new IndexTemplateMetaData(SecurityIndexManager.SECURITY_TEMPLATE_NAME, 0, 0, .put(new IndexTemplateMetaData(SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7, 0, 0,
Collections.singletonList(securityIndexName), Settings.EMPTY, ImmutableOpenMap.of(), Collections.singletonList(securityIndexName), Settings.EMPTY, ImmutableOpenMap.of(),
ImmutableOpenMap.of())) ImmutableOpenMap.of()))
.build(); .build();

View File

@ -29,6 +29,7 @@ import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.block.ClusterBlocks;
import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData;
@ -52,12 +53,12 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.security.test.SecurityTestUtils; import org.elasticsearch.xpack.security.test.SecurityTestUtils;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.core.template.TemplateUtils; import org.elasticsearch.xpack.core.template.TemplateUtils;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.junit.Before; import org.junit.Before;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.TEMPLATE_VERSION_PATTERN; import static org.elasticsearch.xpack.security.support.SecurityIndexManager.TEMPLATE_VERSION_PATTERN;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
@ -71,7 +72,6 @@ public class SecurityIndexManagerTests extends ESTestCase {
private static final ClusterName CLUSTER_NAME = new ClusterName("security-index-manager-tests"); private static final ClusterName CLUSTER_NAME = new ClusterName("security-index-manager-tests");
private static final ClusterState EMPTY_CLUSTER_STATE = new ClusterState.Builder(CLUSTER_NAME).build(); private static final ClusterState EMPTY_CLUSTER_STATE = new ClusterState.Builder(CLUSTER_NAME).build();
private static final String INDEX_NAME = ".security";
private static final String TEMPLATE_NAME = "SecurityIndexManagerTests-template"; private static final String TEMPLATE_NAME = "SecurityIndexManagerTests-template";
private SecurityIndexManager manager; private SecurityIndexManager manager;
private Map<Action<?>, Map<ActionRequest, ActionListener<?>>> actions; private Map<Action<?>, Map<ActionRequest, ActionListener<?>>> actions;
@ -96,13 +96,14 @@ public class SecurityIndexManagerTests extends ESTestCase {
actions.put(action, map); actions.put(action, map);
} }
}; };
manager = SecurityIndexManager.buildSecurityIndexManager(client, clusterService); manager = SecurityIndexManager.buildSecurityMainIndexManager(client, clusterService);
} }
public void testIndexWithUpToDateMappingAndTemplate() throws IOException { public void testIndexWithUpToDateMappingAndTemplate() throws IOException {
assertInitialState(); assertInitialState();
final ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME); final ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME);
markShardsAvailable(clusterStateBuilder); markShardsAvailable(clusterStateBuilder);
manager.clusterChanged(event(clusterStateBuilder)); manager.clusterChanged(event(clusterStateBuilder));
@ -114,8 +115,9 @@ public class SecurityIndexManagerTests extends ESTestCase {
public void testIndexWithoutPrimaryShards() throws IOException { public void testIndexWithoutPrimaryShards() throws IOException {
assertInitialState(); assertInitialState();
final ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME); final ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
Index index = new Index(INDEX_NAME, UUID.randomUUID().toString()); RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME);
Index index = new Index(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7, UUID.randomUUID().toString());
ShardRouting shardRouting = ShardRouting.newUnassigned(new ShardId(index, 0), true, ShardRouting shardRouting = ShardRouting.newUnassigned(new ShardId(index, 0), true,
RecoverySource.ExistingStoreRecoverySource.INSTANCE, new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, "")); RecoverySource.ExistingStoreRecoverySource.INSTANCE, new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, ""));
String nodeId = ESTestCase.randomAlphaOfLength(8); String nodeId = ESTestCase.randomAlphaOfLength(8);
@ -147,7 +149,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
manager.addIndexStateListener(listener); manager.addIndexStateListener(listener);
// index doesn't exist and now exists // index doesn't exist and now exists
final ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME); final ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME);
markShardsAvailable(clusterStateBuilder); markShardsAvailable(clusterStateBuilder);
manager.clusterChanged(event(clusterStateBuilder)); manager.clusterChanged(event(clusterStateBuilder));
@ -171,7 +174,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
previousState.set(null); previousState.set(null);
currentState.set(null); currentState.set(null);
ClusterState previousClusterState = clusterStateBuilder.build(); ClusterState previousClusterState = clusterStateBuilder.build();
Index prevIndex = previousClusterState.getRoutingTable().index(INDEX_NAME).getIndex(); Index prevIndex = previousClusterState.getRoutingTable().index(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7).getIndex();
clusterStateBuilder.routingTable(RoutingTable.builder() clusterStateBuilder.routingTable(RoutingTable.builder()
.add(IndexRoutingTable.builder(prevIndex) .add(IndexRoutingTable.builder(prevIndex)
.addIndexShard(new IndexShardRoutingTable.Builder(new ShardId(prevIndex, 0)) .addIndexShard(new IndexShardRoutingTable.Builder(new ShardId(prevIndex, 0))
@ -231,8 +234,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
prepareException.set(null); prepareException.set(null);
prepareRunnableCalled.set(false); prepareRunnableCalled.set(false);
// state recovered with index // state recovered with index
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME, ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
SecurityIndexManager.INTERNAL_INDEX_FORMAT); RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
markShardsAvailable(clusterStateBuilder); markShardsAvailable(clusterStateBuilder);
manager.clusterChanged(event(clusterStateBuilder)); manager.clusterChanged(event(clusterStateBuilder));
manager.prepareIndexIfNeededThenExecute(ex -> { manager.prepareIndexIfNeededThenExecute(ex -> {
@ -255,8 +258,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
assertThat(manager.isStateRecovered(), is(false)); assertThat(manager.isStateRecovered(), is(false));
assertThat(listenerCalled.get(), is(false)); assertThat(listenerCalled.get(), is(false));
// state recovered with index // state recovered with index
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME, ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
SecurityIndexManager.INTERNAL_INDEX_FORMAT); RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
markShardsAvailable(clusterStateBuilder); markShardsAvailable(clusterStateBuilder);
manager.clusterChanged(event(clusterStateBuilder)); manager.clusterChanged(event(clusterStateBuilder));
assertThat(manager.isStateRecovered(), is(true)); assertThat(manager.isStateRecovered(), is(true));
@ -278,8 +281,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
assertTrue(manager.isIndexUpToDate()); assertTrue(manager.isIndexUpToDate());
// index doesn't exist and now exists with wrong format // index doesn't exist and now exists with wrong format
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME, ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
SecurityIndexManager.INTERNAL_INDEX_FORMAT - 1); RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT - 1);
markShardsAvailable(clusterStateBuilder); markShardsAvailable(clusterStateBuilder);
manager.clusterChanged(event(clusterStateBuilder)); manager.clusterChanged(event(clusterStateBuilder));
assertTrue(listenerCalled.get()); assertTrue(listenerCalled.get());
@ -295,7 +298,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
listenerCalled.set(false); listenerCalled.set(false);
// index doesn't exist and now exists with correct format // index doesn't exist and now exists with correct format
clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_INDEX_FORMAT); clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
markShardsAvailable(clusterStateBuilder); markShardsAvailable(clusterStateBuilder);
manager.clusterChanged(event(clusterStateBuilder)); manager.clusterChanged(event(clusterStateBuilder));
assertTrue(listenerCalled.get()); assertTrue(listenerCalled.get());
@ -317,18 +321,19 @@ public class SecurityIndexManagerTests extends ESTestCase {
assertThat(manager.isStateRecovered(), Matchers.equalTo(true)); assertThat(manager.isStateRecovered(), Matchers.equalTo(true));
} }
public static ClusterState.Builder createClusterState(String indexName, String templateName) throws IOException { public static ClusterState.Builder createClusterState(String indexName, String aliasName, String templateName) throws IOException {
return createClusterState(indexName, templateName, templateName, SecurityIndexManager.INTERNAL_INDEX_FORMAT); return createClusterState(indexName, aliasName, templateName, templateName, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
} }
public static ClusterState.Builder createClusterState(String indexName, String templateName, int format) throws IOException { public static ClusterState.Builder createClusterState(String indexName, String aliasName, String templateName, int format)
return createClusterState(indexName, templateName, templateName, format);
}
private static ClusterState.Builder createClusterState(String indexName, String templateName, String buildMappingFrom, int format)
throws IOException { throws IOException {
return createClusterState(indexName, aliasName, templateName, templateName, format);
}
private static ClusterState.Builder createClusterState(String indexName, String aliasName, String templateName, String buildMappingFrom,
int format) throws IOException {
IndexTemplateMetaData.Builder templateBuilder = getIndexTemplateMetaData(templateName); IndexTemplateMetaData.Builder templateBuilder = getIndexTemplateMetaData(templateName);
IndexMetaData.Builder indexMeta = getIndexMetadata(indexName, buildMappingFrom, format); IndexMetaData.Builder indexMeta = getIndexMetadata(indexName, aliasName, buildMappingFrom, format);
MetaData.Builder metaDataBuilder = new MetaData.Builder(); MetaData.Builder metaDataBuilder = new MetaData.Builder();
metaDataBuilder.put(templateBuilder); metaDataBuilder.put(templateBuilder);
@ -338,7 +343,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
} }
private void markShardsAvailable(ClusterState.Builder clusterStateBuilder) { private void markShardsAvailable(ClusterState.Builder clusterStateBuilder) {
clusterStateBuilder.routingTable(SecurityTestUtils.buildIndexRoutingTable(INDEX_NAME)); clusterStateBuilder.routingTable(SecurityTestUtils.buildIndexRoutingTable(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7));
} }
private static ClusterState state() { private static ClusterState state() {
@ -349,7 +354,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
.build(); .build();
} }
private static IndexMetaData.Builder getIndexMetadata(String indexName, String templateName, int format) throws IOException { private static IndexMetaData.Builder getIndexMetadata(String indexName, String aliasName, String templateName, int format)
throws IOException {
IndexMetaData.Builder indexMetaData = IndexMetaData.builder(indexName); IndexMetaData.Builder indexMetaData = IndexMetaData.builder(indexName);
indexMetaData.settings(Settings.builder() indexMetaData.settings(Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT) .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
@ -357,7 +363,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.INDEX_FORMAT_SETTING.getKey(), format) .put(IndexMetaData.INDEX_FORMAT_SETTING.getKey(), format)
.build()); .build());
indexMetaData.putAlias(AliasMetaData.builder(aliasName).build());
final Map<String, String> mappings = getTemplateMappings(templateName); final Map<String, String> mappings = getTemplateMappings(templateName);
for (Map.Entry<String, String> entry : mappings.entrySet()) { for (Map.Entry<String, String> entry : mappings.entrySet()) {
indexMetaData.putMapping(entry.getKey(), entry.getValue()); indexMetaData.putMapping(entry.getKey(), entry.getValue());
@ -389,7 +395,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
} }
public void testMappingVersionMatching() throws IOException { public void testMappingVersionMatching() throws IOException {
String templateString = "/" + SECURITY_TEMPLATE_NAME + ".json"; String templateString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString);
manager.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); manager.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
assertTrue(manager.checkMappingVersion(Version.CURRENT.minimumIndexCompatibilityVersion()::before)); assertTrue(manager.checkMappingVersion(Version.CURRENT.minimumIndexCompatibilityVersion()::before));
@ -397,17 +403,19 @@ public class SecurityIndexManagerTests extends ESTestCase {
} }
public void testMissingVersionMappingThrowsError() throws IOException { public void testMissingVersionMappingThrowsError() throws IOException {
String templateString = "/missing-version-" + SECURITY_TEMPLATE_NAME + ".json"; String templateString = "/missing-version-security-index-template.json";
ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString); ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString);
final ClusterState clusterState = clusterStateBuilder.build(); final ClusterState clusterState = clusterStateBuilder.build();
IllegalStateException exception = expectThrows(IllegalStateException.class, IllegalStateException exception = expectThrows(IllegalStateException.class,
() -> SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals)); () -> SecurityIndexManager.checkIndexMappingVersionMatches(RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
assertEquals("Cannot read security-version string in index " + SECURITY_INDEX_NAME, exception.getMessage()); clusterState, logger, Version.CURRENT::equals));
assertEquals("Cannot read security-version string in index " + RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
exception.getMessage());
} }
public void testIndexTemplateIsIdentifiedAsUpToDate() throws IOException { public void testIndexTemplateIsIdentifiedAsUpToDate() throws IOException {
ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate( ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate(
"/" + SECURITY_TEMPLATE_NAME + ".json" "/" + SECURITY_MAIN_TEMPLATE_7 + ".json"
); );
manager.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); manager.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
// No upgrade actions run // No upgrade actions run
@ -415,20 +423,20 @@ public class SecurityIndexManagerTests extends ESTestCase {
} }
public void testIndexTemplateVersionMatching() throws Exception { public void testIndexTemplateVersionMatching() throws Exception {
String templateString = "/" + SECURITY_TEMPLATE_NAME + ".json"; String templateString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate(templateString); ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate(templateString);
final ClusterState clusterState = clusterStateBuilder.build(); final ClusterState clusterState = clusterStateBuilder.build();
assertTrue(SecurityIndexManager.checkTemplateExistsAndVersionMatches( assertTrue(SecurityIndexManager.checkTemplateExistsAndVersionMatches(
SecurityIndexManager.SECURITY_TEMPLATE_NAME, clusterState, logger, SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7, clusterState, logger,
Version.V_6_0_0::before)); Version.V_6_0_0::before));
assertFalse(SecurityIndexManager.checkTemplateExistsAndVersionMatches( assertFalse(SecurityIndexManager.checkTemplateExistsAndVersionMatches(
SecurityIndexManager.SECURITY_TEMPLATE_NAME, clusterState, logger, SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7, clusterState, logger,
Version.V_6_0_0::after)); Version.V_6_0_0::after));
} }
public void testUpToDateMappingsAreIdentifiedAsUpToDate() throws IOException { public void testUpToDateMappingsAreIdentifiedAsUpToDate() throws IOException {
String securityTemplateString = "/" + SECURITY_TEMPLATE_NAME + ".json"; String securityTemplateString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(securityTemplateString); ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(securityTemplateString);
manager.clusterChanged(new ClusterChangedEvent("test-event", manager.clusterChanged(new ClusterChangedEvent("test-event",
clusterStateBuilder.build(), EMPTY_CLUSTER_STATE)); clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
@ -438,8 +446,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
public void testMissingIndexIsIdentifiedAsUpToDate() throws IOException { public void testMissingIndexIsIdentifiedAsUpToDate() throws IOException {
final ClusterName clusterName = new ClusterName("test-cluster"); final ClusterName clusterName = new ClusterName("test-cluster");
final ClusterState.Builder clusterStateBuilder = ClusterState.builder(clusterName); final ClusterState.Builder clusterStateBuilder = ClusterState.builder(clusterName);
String mappingString = "/" + SECURITY_TEMPLATE_NAME + ".json"; String mappingString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
IndexTemplateMetaData.Builder templateMeta = getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, mappingString); IndexTemplateMetaData.Builder templateMeta = getIndexTemplateMetaData(SECURITY_MAIN_TEMPLATE_7, mappingString);
MetaData.Builder builder = new MetaData.Builder(clusterStateBuilder.build().getMetaData()); MetaData.Builder builder = new MetaData.Builder(clusterStateBuilder.build().getMetaData());
builder.put(templateMeta); builder.put(templateMeta);
clusterStateBuilder.metaData(builder); clusterStateBuilder.metaData(builder);
@ -450,24 +458,24 @@ public class SecurityIndexManagerTests extends ESTestCase {
private ClusterState.Builder createClusterStateWithTemplate(String securityTemplateString) throws IOException { private ClusterState.Builder createClusterStateWithTemplate(String securityTemplateString) throws IOException {
// add the correct mapping no matter what the template // add the correct mapping no matter what the template
ClusterState clusterState = createClusterStateWithIndex("/" + SECURITY_TEMPLATE_NAME + ".json").build(); ClusterState clusterState = createClusterStateWithIndex("/" + SECURITY_MAIN_TEMPLATE_7 + ".json").build();
final MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterState.metaData()); final MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterState.metaData());
metaDataBuilder.put(getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityTemplateString)); metaDataBuilder.put(getIndexTemplateMetaData(SECURITY_MAIN_TEMPLATE_7, securityTemplateString));
return ClusterState.builder(clusterState).metaData(metaDataBuilder); return ClusterState.builder(clusterState).metaData(metaDataBuilder);
} }
private ClusterState.Builder createClusterStateWithMapping(String securityTemplateString) throws IOException { private ClusterState.Builder createClusterStateWithMapping(String securityTemplateString) throws IOException {
final ClusterState clusterState = createClusterStateWithIndex(securityTemplateString).build(); final ClusterState clusterState = createClusterStateWithIndex(securityTemplateString).build();
final String indexName = clusterState.metaData().getAliasAndIndexLookup() final String indexName = clusterState.metaData().getAliasAndIndexLookup()
.get(SECURITY_INDEX_NAME).getIndices().get(0).getIndex().getName(); .get(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).getIndices().get(0).getIndex().getName();
return ClusterState.builder(clusterState).routingTable(SecurityTestUtils.buildIndexRoutingTable(indexName)); return ClusterState.builder(clusterState).routingTable(SecurityTestUtils.buildIndexRoutingTable(indexName));
} }
private ClusterState.Builder createClusterStateWithMappingAndTemplate(String securityTemplateString) throws IOException { private ClusterState.Builder createClusterStateWithMappingAndTemplate(String securityTemplateString) throws IOException {
ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(securityTemplateString); ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(securityTemplateString);
MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterStateBuilder.build().metaData()); MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterStateBuilder.build().metaData());
String securityMappingString = "/" + SECURITY_TEMPLATE_NAME + ".json"; String securityMappingString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
IndexTemplateMetaData.Builder securityTemplateMeta = getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityMappingString); IndexTemplateMetaData.Builder securityTemplateMeta = getIndexTemplateMetaData(SECURITY_MAIN_TEMPLATE_7, securityMappingString);
metaDataBuilder.put(securityTemplateMeta); metaDataBuilder.put(securityTemplateMeta);
return clusterStateBuilder.metaData(metaDataBuilder); return clusterStateBuilder.metaData(metaDataBuilder);
} }
@ -493,7 +501,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
private ClusterState.Builder createClusterStateWithIndex(String securityTemplate) throws IOException { private ClusterState.Builder createClusterStateWithIndex(String securityTemplate) throws IOException {
final MetaData.Builder metaDataBuilder = new MetaData.Builder(); final MetaData.Builder metaDataBuilder = new MetaData.Builder();
final boolean withAlias = randomBoolean(); final boolean withAlias = randomBoolean();
final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : ""); final String securityIndexName = RestrictedIndicesNames.SECURITY_MAIN_ALIAS
+ (withAlias ? "-" + randomAlphaOfLength(5) : "");
metaDataBuilder.put(createIndexMetadata(securityIndexName, securityTemplate)); metaDataBuilder.put(createIndexMetadata(securityIndexName, securityTemplate));
ClusterState.Builder clusterStateBuilder = ClusterState.builder(state()); ClusterState.Builder clusterStateBuilder = ClusterState.builder(state());

View File

@ -35,7 +35,7 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE; import static java.nio.file.StandardOpenOption.WRITE;
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME; import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
public class SecurityTestUtils { public class SecurityTestUtils {
@ -83,7 +83,7 @@ public class SecurityTestUtils {
* Adds the index alias {@code .security} to the underlying concrete index. * Adds the index alias {@code .security} to the underlying concrete index.
*/ */
public static MetaData addAliasToMetaData(MetaData metaData, String indexName) { public static MetaData addAliasToMetaData(MetaData metaData, String indexName) {
AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SECURITY_INDEX_NAME).build(); AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SECURITY_MAIN_ALIAS).build();
MetaData.Builder metaDataBuilder = new MetaData.Builder(metaData); MetaData.Builder metaDataBuilder = new MetaData.Builder(metaData);
IndexMetaData indexMetaData = metaData.index(indexName); IndexMetaData indexMetaData = metaData.index(indexName);
metaDataBuilder.put(IndexMetaData.builder(indexMetaData).putAlias(aliasMetaData)); metaDataBuilder.put(IndexMetaData.builder(indexMetaData).putAlias(aliasMetaData));

View File

@ -14,7 +14,6 @@ import org.elasticsearch.xpack.core.security.index.IndexAuditTrailField;
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames; import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
import org.elasticsearch.xpack.core.security.user.XPackUser; import org.elasticsearch.xpack.core.security.user.XPackUser;
import org.elasticsearch.xpack.security.audit.index.IndexNameResolver; import org.elasticsearch.xpack.security.audit.index.IndexNameResolver;
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -32,8 +31,6 @@ public class XPackUserTests extends ESTestCase {
public void testXPackUserCannotAccessRestrictedIndices() { public void testXPackUserCannotAccessRestrictedIndices() {
final String action = randomFrom(GetAction.NAME, SearchAction.NAME, IndexAction.NAME); final String action = randomFrom(GetAction.NAME, SearchAction.NAME, IndexAction.NAME);
final Predicate<String> predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action); final Predicate<String> predicate = XPackUser.ROLE.indices().allowedIndicesMatcher(action);
assertThat(predicate.test(SecurityIndexManager.SECURITY_INDEX_NAME), Matchers.is(false));
assertThat(predicate.test(SecurityIndexManager.INTERNAL_SECURITY_INDEX), Matchers.is(false));
for (String index : RestrictedIndicesNames.RESTRICTED_NAMES) { for (String index : RestrictedIndicesNames.RESTRICTED_NAMES) {
assertThat(predicate.test(index), Matchers.is(false)); assertThat(predicate.test(index), Matchers.is(false));
} }

View File

@ -0,0 +1,161 @@
---
setup:
- skip:
features: headers
- do:
cluster.health:
wait_for_status: yellow
- do:
security.put_role:
name: "all_access"
body: >
{
"cluster": [ "all" ],
"indices": [
{ "names": ["*"], "privileges": ["all"] }
]
}
- do:
security.put_user:
username: "test_user"
body: >
{
"password" : "x-pack-test-password",
"roles" : [ "all_access" ],
"full_name" : "user with all possible privileges (but not superuser)"
}
---
teardown:
- do:
security.delete_user:
username: "test_user"
ignore: 404
- do:
security.delete_role:
name: "all_access"
ignore: 404
---
"Test get security tokens index metadata":
- do:
security.get_token:
body:
grant_type: "password"
username: "test_user"
password: "x-pack-test-password"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- match: { expires_in: 1200 }
- is_false: scope
- do:
catch: forbidden
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
indices.get:
index: ".security-tokens"
- do:
catch: forbidden
headers:
Authorization: Bearer ${token}
indices.get:
index: ".security-tokens"
- do:
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
indices.get:
index: ".secu*rity*tokens"
- length: { $body: 0 }
- do:
headers:
Authorization: Bearer ${token}
indices.get:
index: ".secu*rity*tokens"
- length: { $body: 0 }
---
"Test get security document":
- do:
security.get_token:
body:
grant_type: "password"
username: "test_user"
password: "x-pack-test-password"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- match: { expires_in: 1200 }
- is_false: scope
- do:
catch: forbidden
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
get:
index: ".security-tokens"
id: token_${token}
- do:
catch: forbidden
headers:
Authorization: Bearer ${token}
get:
index: ".security-tokens"
id: token_${token}
---
"Test search security tokens index":
- do:
security.get_token:
body:
grant_type: "password"
username: "test_user"
password: "x-pack-test-password"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- match: { expires_in: 1200 }
- is_false: scope
- do:
catch: forbidden
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
search:
rest_total_hits_as_int: true
index: ".security-tokens"
- do:
catch: forbidden
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: ".security-tokens"
- do:
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
search:
rest_total_hits_as_int: true
index: ".secu*rity*tokens"
- match: { hits.total: 0 }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: ".secu*rity*tokens"
- match: { hits.total: 0 }

View File

@ -0,0 +1,161 @@
---
setup:
- skip:
features: headers
- do:
cluster.health:
wait_for_status: yellow
- do:
security.put_role:
name: "all_access"
body: >
{
"cluster": [ "all" ],
"indices": [
{ "names": ["*"], "privileges": ["all"] }
]
}
- do:
security.put_user:
username: "test_user"
body: >
{
"password" : "x-pack-test-password",
"roles" : [ "all_access" ],
"full_name" : "user with all possible privileges (but not superuser)"
}
---
teardown:
- do:
security.delete_user:
username: "test_user"
ignore: 404
- do:
security.delete_role:
name: "all_access"
ignore: 404
---
"Test get security tokens index metadata":
- do:
security.get_token:
body:
grant_type: "password"
username: "test_user"
password: "x-pack-test-password"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- match: { expires_in: 1200 }
- is_false: scope
- do:
catch: forbidden
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
indices.get:
index: ".security-tokens-7"
- do:
catch: forbidden
headers:
Authorization: Bearer ${token}
indices.get:
index: ".security-tokens-7"
- do:
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
indices.get:
index: ".secu*rity*tokens-7"
- length: { $body: 0 }
- do:
headers:
Authorization: Bearer ${token}
indices.get:
index: ".secu*rity*tokens-7"
- length: { $body: 0 }
---
"Test get security document":
- do:
security.get_token:
body:
grant_type: "password"
username: "test_user"
password: "x-pack-test-password"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- match: { expires_in: 1200 }
- is_false: scope
- do:
catch: forbidden
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
get:
index: ".security-tokens-7"
id: token_${token}
- do:
catch: forbidden
headers:
Authorization: Bearer ${token}
get:
index: ".security-tokens-7"
id: token_${token}
---
"Test search security tokens index":
- do:
security.get_token:
body:
grant_type: "password"
username: "test_user"
password: "x-pack-test-password"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- match: { expires_in: 1200 }
- is_false: scope
- do:
catch: forbidden
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
search:
rest_total_hits_as_int: true
index: ".security-tokens-7"
- do:
catch: forbidden
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: ".security-tokens-7"
- do:
headers: { Authorization: "Basic dGVzdF91c2VyOngtcGFjay10ZXN0LXBhc3N3b3Jk" } # test_user
search:
rest_total_hits_as_int: true
index: ".secu*rity*tokens-7"
- match: { hits.total: 0 }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: ".secu*rity*tokens-7"
- match: { hits.total: 0 }

View File

@ -119,6 +119,8 @@ for (Version version : bwcVersions.wireCompatible) {
setting 'xpack.security.enabled', 'true' setting 'xpack.security.enabled', 'true'
setting 'xpack.security.transport.ssl.enabled', 'true' setting 'xpack.security.transport.ssl.enabled', 'true'
setting 'xpack.security.authc.token.enabled', 'true' setting 'xpack.security.authc.token.enabled', 'true'
setting 'xpack.security.authc.token.timeout', '60m'
setting 'logger.org.elasticsearch.xpack.security.authc.TokenService', 'trace'
setting 'xpack.security.audit.enabled', 'true' setting 'xpack.security.audit.enabled', 'true'
if (project.inFipsJvm) { if (project.inFipsJvm) {
setting 'xpack.security.transport.ssl.key', 'testnode.pem' setting 'xpack.security.transport.ssl.key', 'testnode.pem'
@ -184,6 +186,8 @@ for (Version version : bwcVersions.wireCompatible) {
setting 'xpack.license.self_generated.type', 'trial' setting 'xpack.license.self_generated.type', 'trial'
setting 'xpack.security.enabled', 'true' setting 'xpack.security.enabled', 'true'
setting 'xpack.security.transport.ssl.enabled', 'true' setting 'xpack.security.transport.ssl.enabled', 'true'
setting 'xpack.security.authc.token.timeout', '60m'
setting 'logger.org.elasticsearch.xpack.security.authc.TokenService', 'trace'
if (project.inFipsJvm) { if (project.inFipsJvm) {
setting 'xpack.security.transport.ssl.key', 'testnode.pem' setting 'xpack.security.transport.ssl.key', 'testnode.pem'
setting 'xpack.security.transport.ssl.certificate', 'testnode.crt' setting 'xpack.security.transport.ssl.certificate', 'testnode.crt'

View File

@ -16,9 +16,14 @@ import org.elasticsearch.client.RestClient;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.test.rest.yaml.ObjectPath; import org.elasticsearch.test.rest.yaml.ObjectPath;
import org.junit.After;
import org.junit.Before;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -27,7 +32,33 @@ import static org.hamcrest.Matchers.equalTo;
public class TokenBackwardsCompatibilityIT extends AbstractUpgradeTestCase { public class TokenBackwardsCompatibilityIT extends AbstractUpgradeTestCase {
public void testGeneratingTokenInOldCluster() throws Exception { private Collection<RestClient> twoClients = null;
@Before
private void collectClientsByVersion() throws IOException {
Map<Version, RestClient> clientsByVersion = getRestClientByVersion();
if (clientsByVersion.size() == 2) {
// usual case, clients have different versions
twoClients = clientsByVersion.values();
} else {
assert clientsByVersion.size() == 1 : "A rolling upgrade has a maximum of two distinct node versions, found: "
+ clientsByVersion.keySet();
// tests assumes exactly two clients to simplify some logic
twoClients = new ArrayList<>();
twoClients.add(clientsByVersion.values().iterator().next());
twoClients.add(clientsByVersion.values().iterator().next());
}
}
@After
private void closeClientsByVersion() throws IOException {
for (RestClient client : twoClients) {
client.close();
}
twoClients = null;
}
public void testGeneratingTokensInOldCluster() throws Exception {
assumeTrue("this test should only run against the old cluster", CLUSTER_TYPE == ClusterType.OLD); assumeTrue("this test should only run against the old cluster", CLUSTER_TYPE == ClusterType.OLD);
{ {
Version minimumIndexCompatibilityVersion = Version.CURRENT.minimumIndexCompatibilityVersion(); Version minimumIndexCompatibilityVersion = Version.CURRENT.minimumIndexCompatibilityVersion();
@ -48,188 +79,363 @@ public class TokenBackwardsCompatibilityIT extends AbstractUpgradeTestCase {
client().performRequest(createTemplate); client().performRequest(createTemplate);
} }
} }
// Creates two access and refresh tokens and stores them in the token_backwards_compatibility_it index to be used for tests in the
// mixed/upgraded clusters
Map<String, Object> responseMap = createTokens(client(), "test_user", "x-pack-test-password");
String accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
// Create a couple of tokens and store them in the token_backwards_compatibility_it index to be used for tests in the mixed/upgraded storeTokens(client(), 1, accessToken, refreshToken);
// clusters
Request createTokenRequest = new Request("POST", "/_security/oauth2/token");
createTokenRequest.setJsonEntity(
"{\n" +
" \"username\": \"test_user\",\n" +
" \"password\": \"x-pack-test-password\",\n" +
" \"grant_type\": \"password\"\n" +
"}");
Response response = client().performRequest(createTokenRequest);
assertOK(response);
Map<String, Object> responseMap = entityAsMap(response);
String token = (String) responseMap.get("access_token");
assertNotNull(token);
assertTokenWorks(token);
// In this test either all or none tests or on a specific version: responseMap = createTokens(client(), "test_user", "x-pack-test-password");
Request indexRequest1 = new Request("PUT", "token_backwards_compatibility_it/_doc/old_cluster_token1"); accessToken = (String) responseMap.get("access_token");
indexRequest1.setJsonEntity( assertNotNull(accessToken);
"{\n" + assertAccessTokenWorks(accessToken);
" \"token\": \"" + token + "\"\n" + refreshToken = (String) responseMap.get("refresh_token");
"}"); assertNotNull(refreshToken);
Response indexResponse1 = client().performRequest(indexRequest1);
assertOK(indexResponse1); storeTokens(client(), 2, accessToken, refreshToken);
Request createSecondTokenRequest = new Request("POST", "/_security/oauth2/token");
createSecondTokenRequest.setEntity(createTokenRequest.getEntity());
response = client().performRequest(createSecondTokenRequest);
responseMap = entityAsMap(response);
token = (String) responseMap.get("access_token");
assertNotNull(token);
assertTokenWorks(token);
Request indexRequest2 = new Request("PUT", "token_backwards_compatibility_it/_doc/old_cluster_token2");
indexRequest2.setJsonEntity(
"{\n" +
" \"token\": \"" + token + "\"\n" +
"}");
Response indexResponse2 = client().performRequest(indexRequest2);
assertOK(indexResponse2);
} }
public void testTokenWorksInMixedCluster() throws Exception { public void testRefreshingTokensInOldCluster() throws Exception {
assumeTrue("this test should only run against the old cluster", CLUSTER_TYPE == ClusterType.OLD);
{
Version minimumIndexCompatibilityVersion = Version.CURRENT.minimumIndexCompatibilityVersion();
assertThat("this branch is not needed if we aren't compatible with 6.0",
minimumIndexCompatibilityVersion.onOrBefore(Version.V_6_0_0), equalTo(true));
if (minimumIndexCompatibilityVersion.before(Version.V_7_0_0)) {
XContentBuilder template = jsonBuilder();
template.startObject();
{
template.field("index_patterns", "*");
template.startObject("settings");
template.field("number_of_shards", 5);
template.endObject();
}
template.endObject();
Request createTemplate = new Request("PUT", "/_template/template");
createTemplate.setJsonEntity(Strings.toString(template));
client().performRequest(createTemplate);
}
}
// Creates access and refresh tokens and uses the refresh token. The new resulting tokens are used in different phases
Map<String, Object> responseMap = createTokens(client(), "test_user", "x-pack-test-password");
String accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
storeTokens(client(), 3, accessToken, refreshToken);
// refresh the token just created. The old token is invalid (tested further) and the new refresh token is tested in the upgraded
// cluster
Map<String, Object> refreshResponseMap = refreshToken(client(), refreshToken);
String refreshedAccessToken = (String) refreshResponseMap.get("access_token");
String refreshedRefreshToken = (String) refreshResponseMap.get("refresh_token");
assertNotNull(refreshedAccessToken);
assertNotNull(refreshedRefreshToken);
assertAccessTokenWorks(refreshedAccessToken);
// assert previous access token still works
assertAccessTokenWorks(accessToken);
storeTokens(client(), 4, refreshedAccessToken, refreshedRefreshToken);
}
public void testInvalidatingTokensInOldCluster() throws Exception {
assumeTrue("this test should only run against the old cluster", CLUSTER_TYPE == ClusterType.OLD);
{
Version minimumIndexCompatibilityVersion = Version.CURRENT.minimumIndexCompatibilityVersion();
assertThat("this branch is not needed if we aren't compatible with 6.0",
minimumIndexCompatibilityVersion.onOrBefore(Version.V_6_0_0), equalTo(true));
if (minimumIndexCompatibilityVersion.before(Version.V_7_0_0)) {
XContentBuilder template = jsonBuilder();
template.startObject();
{
template.field("index_patterns", "*");
template.startObject("settings");
template.field("number_of_shards", 5);
template.endObject();
}
template.endObject();
Request createTemplate = new Request("PUT", "/_template/template");
createTemplate.setJsonEntity(Strings.toString(template));
client().performRequest(createTemplate);
}
}
// Creates access and refresh tokens and tries to use the access tokens several times
Map<String, Object> responseMap = createTokens(client(), "test_user", "x-pack-test-password");
String accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
storeTokens(client(), 5, accessToken, refreshToken);
// invalidate access token
invalidateAccessToken(client(), accessToken);
assertAccessTokenDoesNotWork(accessToken);
// invalidate refresh token
invalidateRefreshToken(client(), refreshToken);
assertRefreshTokenInvalidated(refreshToken);
}
public void testAccessTokensWorkInMixedCluster() throws Exception {
// Verify that an old token continues to work during all stages of the rolling upgrade // Verify that an old token continues to work during all stages of the rolling upgrade
assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED); assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED);
Request getRequest = new Request("GET", "token_backwards_compatibility_it/_doc/old_cluster_token1"); for (int tokenIdx : Arrays.asList(1, 3, 4)) { // 2 is invalidated in another mixed-cluster test, 5 is invalidated in the old cluster
Response getResponse = client().performRequest(getRequest); Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
assertOK(getResponse); assertAccessTokenWorks((String) source.get("token"));
Map<String, Object> source = (Map<String, Object>) entityAsMap(getResponse).get("_source"); }
assertTokenWorks((String) source.get("token"));
} }
public void testInvalidatingTokenInMixedCluster() throws Exception { public void testTokensStayInvalidatedInMixedCluster() throws Exception {
// Verify that we can invalidate a token in a mixed cluster // Verify that an old, invalidated token remains invalidated during all stages of the rolling upgrade
assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED); assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED);
Request getRequest = new Request("GET", "token_backwards_compatibility_it/_doc/old_cluster_token2"); Map<String, Object> source = retrieveStoredTokens(client(), 5);
Response getResponse = client().performRequest(getRequest); assertAccessTokenDoesNotWork((String) source.get("token"));
assertOK(getResponse); assertRefreshTokenInvalidated((String) source.get("refresh_token"));
Map<String, Object> source = (Map<String, Object>) entityAsMap(getResponse).get("_source"); }
String token = (String) source.get("token");
public void testGeneratingTokensInMixedCluster() throws Exception {
assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED);
// Creates two access and refresh tokens and stores them in the token_backwards_compatibility_it index to be used for tests in the
// mixed/upgraded clusters
int generatedTokenIdxDuringMixed = 10;
for (RestClient client : twoClients) {
Map<String, Object> responseMap = createTokens(client, "test_user", "x-pack-test-password");
String accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
storeTokens(client(), generatedTokenIdxDuringMixed++, accessToken, refreshToken);
responseMap = createTokens(client, "test_user", "x-pack-test-password");
accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
storeTokens(client(), generatedTokenIdxDuringMixed++, accessToken, refreshToken);
}
}
public void testRefreshingTokensInMixedCluster() throws Exception {
// verify new nodes can refresh tokens created by old nodes and vice versa
assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED);
for (RestClient client1 : twoClients) {
Map<String, Object> responseMap = createTokens(client1, "test_user", "x-pack-test-password");
String accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
for (RestClient client2 : twoClients) {
responseMap = refreshToken(client2, refreshToken);
accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
}
}
}
public void testInvalidatingTokensInMixedCluster() throws Exception {
// Verify that we can invalidate an access and refresh token in a mixed cluster
assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED);
Map<String, Object> source = retrieveStoredTokens(client(), 2);
String accessToken = (String) source.get("token");
String refreshToken = (String) source.get("refresh_token");
// The token might be already invalidated by running testInvalidatingTokenInMixedCluster in a previous stage // The token might be already invalidated by running testInvalidatingTokenInMixedCluster in a previous stage
// we don't try to assert it works before invalidating. This case is handled by testTokenWorksInMixedCluster // we don't try to assert it works before invalidating. This case is handled by testTokenWorksInMixedCluster
Request invalidateRequest = new Request("DELETE", "/_security/oauth2/token"); invalidateAccessToken(client(), accessToken);
invalidateRequest.setJsonEntity("{\"token\": \"" + token + "\"}"); assertAccessTokenDoesNotWork(accessToken);
invalidateRequest.addParameter("error_trace", "true"); // invalidate refresh token
client().performRequest(invalidateRequest); invalidateRefreshToken(client(), refreshToken);
assertTokenDoesNotWork(token); assertRefreshTokenInvalidated(refreshToken);
} }
public void testMixedClusterWithUpgradedMaster() throws Exception { public void testTokensStayInvalidatedInUpgradedCluster() throws Exception {
assumeTrue("this test should only run against the mixed cluster", CLUSTER_TYPE == ClusterType.MIXED);
assumeTrue("the master must be on the latest version before we can write", isMasterOnLatestVersion());
// create token and refresh on version that supports it
Request createTokenRequest = new Request("POST", "/_security/oauth2/token");
createTokenRequest.setJsonEntity(
"{\n" +
" \"username\": \"test_user\",\n" +
" \"password\": \"x-pack-test-password\",\n" +
" \"grant_type\": \"password\"\n" +
"}");
try (RestClient client = getRestClientForCurrentVersionNodesOnly()) {
Response response = client.performRequest(createTokenRequest);
Map<String, Object> responseMap = entityAsMap(response);
String accessToken = (String) responseMap.get("access_token");
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(accessToken);
assertNotNull(refreshToken);
assertTokenWorks(accessToken);
Request tokenRefreshRequest = new Request("POST", "/_security/oauth2/token");
tokenRefreshRequest.setJsonEntity(
"{\n" +
" \"refresh_token\": \"" + refreshToken + "\",\n" +
" \"grant_type\": \"refresh_token\"\n" +
"}");
response = client.performRequest(tokenRefreshRequest);
responseMap = entityAsMap(response);
String updatedAccessToken = (String) responseMap.get("access_token");
String updatedRefreshToken = (String) responseMap.get("refresh_token");
assertNotNull(updatedAccessToken);
assertNotNull(updatedRefreshToken);
assertTokenWorks(updatedAccessToken);
assertTokenWorks(accessToken);
assertNotEquals(accessToken, updatedAccessToken);
assertNotEquals(refreshToken, updatedRefreshToken);
// Invalidate the new access token and ensure that it no longer works
Request invalidateTokenRequest = new Request("DELETE", "/_security/oauth2/token");
invalidateTokenRequest.setJsonEntity(
"{\n" +
" \"token\": \"" + updatedAccessToken + "\"\n" +
"}");
Response invalidateTokenResponse = client.performRequest(invalidateTokenRequest);
assertOK(invalidateTokenResponse);
assertTokenDoesNotWork(updatedAccessToken);
}
}
public void testUpgradedCluster() throws Exception {
assumeTrue("this test should only run against the upgraded cluster", CLUSTER_TYPE == ClusterType.UPGRADED); assumeTrue("this test should only run against the upgraded cluster", CLUSTER_TYPE == ClusterType.UPGRADED);
// Use an old token to authenticate, then invalidate it and verify that it can no longer be used for (int tokenIdx : Arrays.asList(2, 5)) {
Request getRequest = new Request("GET", "token_backwards_compatibility_it/_doc/old_cluster_token1"); Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
Response getResponse = client().performRequest(getRequest); assertAccessTokenDoesNotWork((String) source.get("token"));
assertOK(getResponse); assertRefreshTokenInvalidated((String) source.get("refresh_token"));
Map<String, Object> source = (Map<String, Object>) entityAsMap(getResponse).get("_source"); }
final String token = (String) source.get("token");
Request invalidateRequest = new Request("DELETE", "/_security/oauth2/token");
invalidateRequest.setJsonEntity("{\"token\": \"" + token + "\"}");
invalidateRequest.addParameter("error_trace", "true");
Response invalidationResponse = client().performRequest(invalidateRequest);
assertOK(invalidationResponse);
assertTokenDoesNotWork(token);
} }
private void assertTokenWorks(String token) throws IOException { public void testAccessTokensWorkInUpgradedCluster() throws Exception {
assumeTrue("this test should only run against the upgraded cluster", CLUSTER_TYPE == ClusterType.UPGRADED);
for (int tokenIdx : Arrays.asList(3, 4, 10, 12)) {
Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
assertAccessTokenWorks((String) source.get("token"));
}
}
public void testGeneratingTokensInUpgradedCluster() throws Exception {
assumeTrue("this test should only run against the upgraded cluster", CLUSTER_TYPE == ClusterType.UPGRADED);
Map<String, Object> responseMap = createTokens(client(), "test_user", "x-pack-test-password");
String accessToken = (String) responseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) responseMap.get("refresh_token");
assertNotNull(refreshToken);
}
public void testRefreshingTokensInUpgradedCluster() throws Exception {
assumeTrue("this test should only run against the upgraded cluster", CLUSTER_TYPE == ClusterType.UPGRADED);
for (int tokenIdx : Arrays.asList(4, 10, 12)) {
Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
Map<String, Object> refreshedResponseMap = refreshToken(client(), (String) source.get("refresh_token"));
String accessToken = (String) refreshedResponseMap.get("access_token");
assertNotNull(accessToken);
assertAccessTokenWorks(accessToken);
String refreshToken = (String) refreshedResponseMap.get("refresh_token");
assertNotNull(refreshToken);
}
}
public void testInvalidatingTokensInUpgradedCluster() throws Exception {
assumeTrue("this test should only run against the upgraded cluster", CLUSTER_TYPE == ClusterType.UPGRADED);
for (int tokenIdx : Arrays.asList(1, 11, 13)) {
Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
String accessToken = (String) source.get("token");
String refreshToken = (String) source.get("refresh_token");
// invalidate access token
invalidateAccessToken(client(), accessToken);
assertAccessTokenDoesNotWork(accessToken);
// invalidate refresh token
invalidateRefreshToken(client(), refreshToken);
assertRefreshTokenInvalidated(refreshToken);
}
}
private void assertAccessTokenWorks(String token) throws IOException {
for (RestClient client : twoClients) {
Request request = new Request("GET", "/_security/_authenticate"); Request request = new Request("GET", "/_security/_authenticate");
RequestOptions.Builder options = request.getOptions().toBuilder(); RequestOptions.Builder options = request.getOptions().toBuilder();
options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token); options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
request.setOptions(options); request.setOptions(options);
Response authenticateResponse = client().performRequest(request); Response authenticateResponse = client.performRequest(request);
assertOK(authenticateResponse); assertOK(authenticateResponse);
assertEquals("test_user", entityAsMap(authenticateResponse).get("username")); assertEquals("test_user", entityAsMap(authenticateResponse).get("username"));
} }
}
private void assertTokenDoesNotWork(String token) { private void assertAccessTokenDoesNotWork(String token) throws IOException {
for (RestClient client : twoClients) {
Request request = new Request("GET", "/_security/_authenticate"); Request request = new Request("GET", "/_security/_authenticate");
RequestOptions.Builder options = request.getOptions().toBuilder(); RequestOptions.Builder options = request.getOptions().toBuilder();
options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token); options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
request.setOptions(options); request.setOptions(options);
ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(request)); ResponseException e = expectThrows(ResponseException.class, () -> client.performRequest(request));
assertEquals(401, e.getResponse().getStatusLine().getStatusCode()); assertEquals(401, e.getResponse().getStatusLine().getStatusCode());
Response response = e.getResponse(); Response response = e.getResponse();
assertEquals("Bearer realm=\"security\", error=\"invalid_token\", error_description=\"The access token expired\"", assertEquals("Bearer realm=\"security\", error=\"invalid_token\", error_description=\"The access token expired\"",
response.getHeader("WWW-Authenticate")); response.getHeader("WWW-Authenticate"));
} }
private boolean isMasterOnLatestVersion() throws Exception {
Response response = client().performRequest(new Request("GET", "_cluster/state"));
assertOK(response);
final String masterNodeId = ObjectPath.createFromResponse(response).evaluate("master_node");
response = client().performRequest(new Request("GET", "_nodes"));
assertOK(response);
ObjectPath objectPath = ObjectPath.createFromResponse(response);
logger.info("Master node is on version: " + objectPath.evaluate("nodes." + masterNodeId + ".version"));
return Version.CURRENT.equals(Version.fromString(objectPath.evaluate("nodes." + masterNodeId + ".version")));
} }
private RestClient getRestClientForCurrentVersionNodesOnly() throws IOException { private void assertRefreshTokenInvalidated(String refreshToken) throws IOException {
for (RestClient client : twoClients) {
Request refreshTokenRequest = new Request("POST", "/_security/oauth2/token");
refreshTokenRequest.setJsonEntity(
"{\n" +
" \"refresh_token\": \"" + refreshToken + "\",\n" +
" \"grant_type\": \"refresh_token\"\n" +
"}");
ResponseException e = expectThrows(ResponseException.class, () -> client.performRequest(refreshTokenRequest));
assertEquals(400, e.getResponse().getStatusLine().getStatusCode());
Response response = e.getResponse();
Map<String, Object> responseMap = entityAsMap(response);
assertEquals("invalid_grant", responseMap.get("error"));
assertEquals("token has been invalidated", responseMap.get("error_description"));
}
}
private Map<Version, RestClient> getRestClientByVersion() throws IOException {
Response response = client().performRequest(new Request("GET", "_nodes")); Response response = client().performRequest(new Request("GET", "_nodes"));
assertOK(response); assertOK(response);
ObjectPath objectPath = ObjectPath.createFromResponse(response); ObjectPath objectPath = ObjectPath.createFromResponse(response);
Map<String, Object> nodesAsMap = objectPath.evaluate("nodes"); Map<String, Object> nodesAsMap = objectPath.evaluate("nodes");
List<HttpHost> hosts = new ArrayList<>(); Map<Version, List<HttpHost>> hostsByVersion = new HashMap<>();
for (Map.Entry<String, Object> entry : nodesAsMap.entrySet()) { for (Map.Entry<String, Object> entry : nodesAsMap.entrySet()) {
Map<String, Object> nodeDetails = (Map<String, Object>) entry.getValue(); Map<String, Object> nodeDetails = (Map<String, Object>) entry.getValue();
Version version = Version.fromString((String) nodeDetails.get("version")); Version version = Version.fromString((String) nodeDetails.get("version"));
if (Version.CURRENT.equals(version)) {
Map<String, Object> httpInfo = (Map<String, Object>) nodeDetails.get("http"); Map<String, Object> httpInfo = (Map<String, Object>) nodeDetails.get("http");
hosts.add(HttpHost.create((String) httpInfo.get("publish_address"))); hostsByVersion.computeIfAbsent(version, k -> new ArrayList<>()).add(HttpHost.create((String) httpInfo.get("publish_address")));
} }
Map<Version, RestClient> clientsByVersion = new HashMap<>();
for (Map.Entry<Version, List<HttpHost>> entry : hostsByVersion.entrySet()) {
clientsByVersion.put(entry.getKey(), buildClient(restClientSettings(), entry.getValue().toArray(new HttpHost[0])));
}
return clientsByVersion;
} }
return buildClient(restClientSettings(), hosts.toArray(new HttpHost[0])); private Map<String, Object> createTokens(RestClient client, String username, String password) throws IOException {
final Request createTokenRequest = new Request("POST", "/_security/oauth2/token");
createTokenRequest.setJsonEntity(
"{\n" +
" \"username\": \"" + username + "\",\n" +
" \"password\": \"" + password + "\",\n" +
" \"grant_type\": \"password\"\n" +
"}");
Response response = client().performRequest(createTokenRequest);
assertOK(response);
return entityAsMap(response);
}
private void storeTokens(RestClient client, int idx, String accessToken, String refreshToken) throws IOException {
final Request indexRequest = new Request("PUT", "token_backwards_compatibility_it/_doc/old_cluster_token" + idx);
indexRequest.setJsonEntity(
"{\n" +
" \"token\": \"" + accessToken + "\",\n" +
" \"refresh_token\": \"" + refreshToken + "\"\n" +
"}");
Response indexResponse1 = client.performRequest(indexRequest);
assertOK(indexResponse1);
}
private Map<String, Object> retrieveStoredTokens(RestClient client, int tokenIdx) throws IOException {
Request getRequest = new Request("GET", "token_backwards_compatibility_it/_doc/old_cluster_token" + tokenIdx);
Response getResponse = client().performRequest(getRequest);
assertOK(getResponse);
return (Map<String, Object>) entityAsMap(getResponse).get("_source");
}
private Map<String, Object> refreshToken(RestClient client, String refreshToken) throws IOException {
final Request refreshTokenRequest = new Request("POST", "/_security/oauth2/token");
refreshTokenRequest.setJsonEntity(
"{\n" +
" \"refresh_token\": \"" + refreshToken + "\",\n" +
" \"grant_type\": \"refresh_token\"\n" +
"}");
Response refreshResponse = client.performRequest(refreshTokenRequest);
assertOK(refreshResponse);
return entityAsMap(refreshResponse);
}
private void invalidateAccessToken(RestClient client, String accessToken) throws IOException {
Request invalidateRequest = new Request("DELETE", "/_security/oauth2/token");
invalidateRequest.setJsonEntity("{\"token\": \"" + accessToken + "\"}");
invalidateRequest.addParameter("error_trace", "true");
Response invalidateResponse = client.performRequest(invalidateRequest);
assertOK(invalidateResponse);
}
private void invalidateRefreshToken(RestClient client, String refreshToken) throws IOException {
Request invalidateRequest = new Request("DELETE", "/_security/oauth2/token");
invalidateRequest.setJsonEntity("{\"refresh_token\": \"" + refreshToken + "\"}");
invalidateRequest.addParameter("error_trace", "true");
Response invalidateResponse = client.performRequest(invalidateRequest);
assertOK(invalidateResponse);
} }
} }

View File

@ -3,14 +3,17 @@
- skip: - skip:
features: headers features: headers
- do:
cluster.health:
wait_for_status: yellow
- do: - do:
get: get:
index: token_index index: token_index
type: doc
id: "6" id: "6"
- match: { _index: token_index } - match: { _index: token_index }
- match: { _type: doc } - match: { _type: _doc }
- match: { _id: "6" } - match: { _id: "6" }
- is_true: _source.token - is_true: _source.token
- set: { _source.token : token } - set: { _source.token : token }
@ -24,6 +27,59 @@
- match: { roles.0: "superuser" } - match: { roles.0: "superuser" }
- match: { full_name: "Token User" } - match: { full_name: "Token User" }
# call three times because the client rotates the nodes
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }
---
"Get the indexed refreshed access token and use if to authenticate":
- skip:
features: headers
- do:
get:
index: token_index
id: "7"
- match: { _index: token_index }
- match: { _type: _doc }
- match: { _id: "7" }
- is_true: _source.token
- set: { _source.token : token }
- do:
headers:
Authorization: Bearer ${token}
security.authenticate: {}
- match: { username: "token_user" }
- match: { roles.0: "superuser" }
- match: { full_name: "Token User" }
- do: - do:
headers: headers:
Authorization: Bearer ${token} Authorization: Bearer ${token}
@ -31,7 +87,7 @@
rest_total_hits_as_int: true rest_total_hits_as_int: true
index: token_index index: token_index
- match: { hits.total: 6 } - match: { hits.total: 8 }
- do: - do:
headers: headers:
@ -40,7 +96,7 @@
rest_total_hits_as_int: true rest_total_hits_as_int: true
index: token_index index: token_index
- match: { hits.total: 6 } - match: { hits.total: 8 }
- do: - do:
headers: headers:
@ -49,5 +105,79 @@
rest_total_hits_as_int: true rest_total_hits_as_int: true
index: token_index index: token_index
- match: { hits.total: 6 } - match: { hits.total: 8 }
---
"Get the indexed refresh token and use it to get another access token and authenticate":
- skip:
features: headers
- do:
get:
index: token_index
id: "8"
- match: { _index: token_index }
- match: { _type: _doc }
- match: { _id: "8" }
- is_true: _source.token
- set: { _source.token : refresh_token }
- do:
security.get_token:
body:
grant_type: "refresh_token"
refresh_token: "${refresh_token}"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- is_true: refresh_token
- set: { refresh_token: refresh_token }
- match: { expires_in: 3600 }
- is_false: scope
- do:
headers:
Authorization: Bearer ${token}
security.authenticate: {}
- match: { username: "token_user" }
- match: { roles.0: "superuser" }
- match: { full_name: "Token User" }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }
# overwrite the used refresh token with the new one
- do:
headers:
Authorization: Bearer ${token}
index:
index: token_index
id: "8"
body: { "token" : "${refresh_token}"}

View File

@ -27,7 +27,9 @@
- match: { type: "Bearer" } - match: { type: "Bearer" }
- is_true: access_token - is_true: access_token
- set: { access_token: token } - set: { access_token: token }
- match: { expires_in: 1200 } - is_true: refresh_token
- set: { refresh_token: refresh_token }
- match: { expires_in: 3600 }
- is_false: scope - is_false: scope
- do: - do:
@ -54,15 +56,15 @@
bulk: bulk:
refresh: true refresh: true
body: body:
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "1"}}' - '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "1"}}'
- '{"f1": "v1_old", "f2": 0}' - '{"f1": "v1_old", "f2": 0}'
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "2"}}' - '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "2"}}'
- '{"f1": "v2_old", "f2": 1}' - '{"f1": "v2_old", "f2": 1}'
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "3"}}' - '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "3"}}'
- '{"f1": "v3_old", "f2": 2}' - '{"f1": "v3_old", "f2": 2}'
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "4"}}' - '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "4"}}'
- '{"f1": "v4_old", "f2": 3}' - '{"f1": "v4_old", "f2": 3}'
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "5"}}' - '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "5"}}'
- '{"f1": "v5_old", "f2": 4}' - '{"f1": "v5_old", "f2": 4}'
- do: - do:
@ -81,6 +83,48 @@
Authorization: Bearer ${token} Authorization: Bearer ${token}
index: index:
index: token_index index: token_index
type: doc
id: "6" id: "6"
body: { "token" : "${token}"} body: { "token" : "${token}"}
# refresh token and store it as well
- do:
security.get_token:
body:
grant_type: "refresh_token"
refresh_token: "${refresh_token}"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: refreshed_access_token }
- is_true: refresh_token
- set: { refresh_token: refreshed_refresh_token }
- match: { expires_in: 3600 }
- is_false: scope
# test refresh token (use it)
- do:
headers:
Authorization: Bearer ${refreshed_access_token}
security.authenticate: {}
- match: { username: "token_user" }
- match: { roles.0: "superuser" }
- match: { full_name: "Token User" }
# store the new refreshed access token
- do:
headers:
Authorization: Bearer ${refreshed_access_token}
index:
index: token_index
id: "7"
body: { "token" : "${refreshed_access_token}"}
# store the refresh token
- do:
headers:
Authorization: Bearer ${refreshed_access_token}
index:
index: token_index
id: "8"
body: { "token" : "${refreshed_refresh_token}"}

View File

@ -2,14 +2,18 @@
"Get the indexed token and use if to authenticate": "Get the indexed token and use if to authenticate":
- skip: - skip:
features: headers features: headers
- do:
cluster.health:
wait_for_status: yellow
- do: - do:
get: get:
index: token_index index: token_index
type: doc
id: "6" id: "6"
- match: { _index: token_index } - match: { _index: token_index }
- match: { _type: doc } - match: { _type: _doc }
- match: { _id: "6" } - match: { _id: "6" }
- is_true: _source.token - is_true: _source.token
- set: { _source.token : token } - set: { _source.token : token }
@ -30,7 +34,7 @@
rest_total_hits_as_int: true rest_total_hits_as_int: true
index: token_index index: token_index
- match: { hits.total: 6 } - match: { hits.total: 8 }
# counter example that we are really checking this # counter example that we are really checking this
- do: - do:
@ -40,3 +44,51 @@
search: search:
rest_total_hits_as_int: true rest_total_hits_as_int: true
index: token_index index: token_index
---
"Get the indexed refresh token and use if to get another access token and authenticate":
- skip:
features: headers
- do:
get:
index: token_index
id: "8"
- match: { _index: token_index }
- match: { _type: _doc }
- match: { _id: "8" }
- is_true: _source.token
- set: { _source.token : refresh_token }
- do:
security.get_token:
body:
grant_type: "refresh_token"
refresh_token: "${refresh_token}"
- match: { type: "Bearer" }
- is_true: access_token
- set: { access_token: token }
- is_true: refresh_token
- set: { refresh_token: refresh_token }
- match: { expires_in: 3600 }
- is_false: scope
- do:
headers:
Authorization: Bearer ${token}
security.authenticate: {}
- match: { username: "token_user" }
- match: { roles.0: "superuser" }
- match: { full_name: "Token User" }
- do:
headers:
Authorization: Bearer ${token}
search:
rest_total_hits_as_int: true
index: token_index
- match: { hits.total: 8 }

View File

@ -199,7 +199,7 @@ public abstract class AbstractAdLdapRealmTestCase extends SecurityIntegTestCase
@Override @Override
public Set<String> excludeTemplates() { public Set<String> excludeTemplates() {
Set<String> templates = Sets.newHashSet(super.excludeTemplates()); Set<String> templates = Sets.newHashSet(super.excludeTemplates());
templates.add(SecurityIndexManager.SECURITY_TEMPLATE_NAME); // don't remove the security index template templates.add(SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7); // don't remove the security index template
return templates; return templates;
} }