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:
parent
bc333a5cbf
commit
990be1f806
|
@ -14,12 +14,15 @@ import java.util.Collections;
|
|||
import java.util.Set;
|
||||
|
||||
public final class RestrictedIndicesNames {
|
||||
public static final String INTERNAL_SECURITY_INDEX_6 = ".security-6";
|
||||
public static final String INTERNAL_SECURITY_INDEX_7 = ".security-7";
|
||||
public static final String SECURITY_INDEX_NAME = ".security";
|
||||
public static final String INTERNAL_SECURITY_MAIN_INDEX_6 = ".security-6";
|
||||
public static final String INTERNAL_SECURITY_MAIN_INDEX_7 = ".security-7";
|
||||
public static final String SECURITY_MAIN_ALIAS = ".security";
|
||||
|
||||
public static final Set<String> RESTRICTED_NAMES = Collections.unmodifiableSet(
|
||||
Sets.newHashSet(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX_6, INTERNAL_SECURITY_INDEX_7));
|
||||
public static final String INTERNAL_SECURITY_TOKENS_INDEX_7 = ".security-tokens-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);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"index_patterns" : [ ".security-*" ],
|
||||
"index_patterns" : [ ".security-7" ],
|
||||
"order" : 1000,
|
||||
"settings" : {
|
||||
"number_of_shards" : 1,
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -601,14 +601,14 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
|
||||
private void assertMonitoringOnRestrictedIndices(Role role) {
|
||||
final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7);
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
final MetaData metaData = new MetaData.Builder()
|
||||
.put(new IndexMetaData.Builder(internalSecurityIndex)
|
||||
.settings(indexSettings)
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build())
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
|
||||
.build(), true)
|
||||
.build();
|
||||
final FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
|
||||
|
@ -616,10 +616,10 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
GetSettingsAction.NAME, IndicesShardStoresAction.NAME, UpgradeStatusAction.NAME, RecoveryAction.NAME);
|
||||
for (final String indexMonitoringActionName : indexMonitoringActionNamesList) {
|
||||
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);
|
||||
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));
|
||||
|
||||
final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7);
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
final MetaData metaData = new MetaData.Builder()
|
||||
.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)
|
||||
|
@ -731,7 +731,7 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
.settings(indexSettings)
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build())
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
|
||||
.build(), true)
|
||||
.build();
|
||||
|
||||
|
@ -753,8 +753,8 @@ public class ReservedRolesStoreTests extends ESTestCase {
|
|||
assertThat(authzMap.get("aaaaaa").isGranted(), is(true));
|
||||
assertThat(authzMap.get("b").isGranted(), is(true));
|
||||
authzMap = superuserRole.indices().authorize(randomFrom(IndexAction.NAME, DeleteIndexAction.NAME, SearchAction.NAME),
|
||||
Sets.newHashSet(RestrictedIndicesNames.SECURITY_INDEX_NAME), lookup, fieldPermissionsCache);
|
||||
assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_INDEX_NAME).isGranted(), is(true));
|
||||
Sets.newHashSet(RestrictedIndicesNames.SECURITY_MAIN_ALIAS), lookup, fieldPermissionsCache);
|
||||
assertThat(authzMap.get(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).isGranted(), is(true));
|
||||
assertThat(authzMap.get(internalSecurityIndex).isGranted(), is(true));
|
||||
assertTrue(superuserRole.indices().check(SearchAction.NAME));
|
||||
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.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))
|
||||
.test(internalSecurityIndex), is(true));
|
||||
}
|
||||
|
|
|
@ -258,9 +258,9 @@ import static java.util.Collections.singletonList;
|
|||
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.HTTP_SSL_ENABLED;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7;
|
||||
|
||||
public class Security extends Plugin implements ActionPlugin, IngestPlugin, NetworkPlugin, ClusterPlugin,
|
||||
DiscoveryPlugin, MapperPlugin, ExtensiblePlugin {
|
||||
|
@ -406,9 +406,10 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
|
|||
components.add(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);
|
||||
components.add(tokenService);
|
||||
|
||||
|
@ -948,7 +949,7 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
|
|||
public UnaryOperator<Map<String, IndexTemplateMetaData>> getIndexTemplateMetaDataUpgrader() {
|
||||
return templates -> {
|
||||
// .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");
|
||||
return templates;
|
||||
};
|
||||
|
@ -1015,9 +1016,9 @@ public class Security extends Plugin implements ActionPlugin, IngestPlugin, Netw
|
|||
@Override
|
||||
public void accept(DiscoveryNode node, ClusterState state) {
|
||||
if (state.getNodes().getMinNodeVersion().before(Version.V_7_0_0)) {
|
||||
IndexMetaData indexMetaData = state.getMetaData().getIndices().get(SECURITY_INDEX_NAME);
|
||||
if (indexMetaData != null && INDEX_FORMAT_SETTING.get(indexMetaData.getSettings()) < INTERNAL_INDEX_FORMAT) {
|
||||
throw new IllegalStateException("Security index is not on the current version [" + INTERNAL_INDEX_FORMAT + "] - " +
|
||||
IndexMetaData indexMetaData = state.getMetaData().getIndices().get(SECURITY_MAIN_ALIAS);
|
||||
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_MAIN_INDEX_FORMAT + "] - " +
|
||||
"The Upgrade API must be run for 7.x nodes to join the cluster");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.xpack.core.ClientHelper.SECURITY_ORIGIN;
|
||||
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 {
|
||||
|
||||
|
@ -207,7 +207,7 @@ public class ApiKeyService {
|
|||
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("expiration_time")));
|
||||
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))
|
||||
.setQuery(boolQuery)
|
||||
.setVersion(false)
|
||||
|
@ -286,7 +286,7 @@ public class ApiKeyService {
|
|||
.endObject()
|
||||
.endObject();
|
||||
final IndexRequest indexRequest =
|
||||
client.prepareIndex(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME)
|
||||
client.prepareIndex(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME)
|
||||
.setSource(builder)
|
||||
.setRefreshPolicy(request.getRefreshPolicy())
|
||||
.request();
|
||||
|
@ -319,7 +319,7 @@ public class ApiKeyService {
|
|||
|
||||
if (credentials != null) {
|
||||
final GetRequest getRequest = client
|
||||
.prepareGet(SECURITY_INDEX_NAME, SINGLE_MAPPING_NAME, credentials.getId())
|
||||
.prepareGet(SECURITY_MAIN_ALIAS, SINGLE_MAPPING_NAME, credentials.getId())
|
||||
.setFetchSource(true)
|
||||
.request();
|
||||
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")));
|
||||
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))
|
||||
.setQuery(boolQuery)
|
||||
.setVersion(false)
|
||||
|
@ -801,7 +801,7 @@ public class ApiKeyService {
|
|||
BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();
|
||||
for (String apiKeyId : apiKeyIds) {
|
||||
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))
|
||||
.request();
|
||||
bulkRequestBuilder.add(request);
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
|||
import org.elasticsearch.index.reindex.ScrollableHitSource;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
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.Instant;
|
||||
|
@ -51,7 +51,7 @@ public final class ExpiredApiKeysRemover extends AbstractRunnable {
|
|||
|
||||
@Override
|
||||
public void doRun() {
|
||||
DeleteByQueryRequest expiredDbq = new DeleteByQueryRequest(SecurityIndexManager.SECURITY_INDEX_NAME);
|
||||
DeleteByQueryRequest expiredDbq = new DeleteByQueryRequest(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
|
||||
if (timeout != TimeValue.MINUS_ONE) {
|
||||
expiredDbq.setTimeout(timeout);
|
||||
expiredDbq.getSearchRequest().source().timeout(timeout);
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
|||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Responsible for cleaning the invalidated and expired tokens from the security index.
|
||||
* The document gets deleted if it was created more than 24 hours which is the maximum
|
||||
* lifetime of a refresh token
|
||||
* Responsible for cleaning the invalidated and expired tokens from the security indices (`main` and `tokens`).
|
||||
* The document is deleted if it was created more than {@code #MAXIMUM_TOKEN_LIFETIME_HOURS} hours in the past.
|
||||
*/
|
||||
final class ExpiredTokenRemover extends AbstractRunnable {
|
||||
private static final Logger logger = LogManager.getLogger(ExpiredTokenRemover.class);
|
||||
|
||||
private final Client client;
|
||||
private final AtomicBoolean inProgress = new AtomicBoolean(false);
|
||||
private final TimeValue timeout;
|
||||
public static final long MAXIMUM_TOKEN_LIFETIME_HOURS = 24L;
|
||||
|
||||
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.securityMainIndex = securityMainIndex;
|
||||
this.securityTokensIndex = securityTokensIndex;
|
||||
this.inProgress = new AtomicBoolean(false);
|
||||
this.timeout = TokenService.DELETE_TIMEOUT.get(settings);
|
||||
this.checkMainIndexForExpiredTokens = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
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) {
|
||||
expiredDbq.setTimeout(timeout);
|
||||
expiredDbq.getSearchRequest().source().timeout(timeout);
|
||||
|
@ -59,12 +80,20 @@ final class ExpiredTokenRemover extends AbstractRunnable {
|
|||
final Instant now = Instant.now();
|
||||
expiredDbq
|
||||
.setQuery(QueryBuilders.boolQuery()
|
||||
.filter(QueryBuilders.termsQuery("doc_type", "token"))
|
||||
.filter(QueryBuilders.rangeQuery("creation_time").lte(now.minus(24L, ChronoUnit.HOURS).toEpochMilli())));
|
||||
.filter(QueryBuilders.termsQuery("doc_type", TokenService.TOKEN_DOC_TYPE))
|
||||
.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)));
|
||||
executeAsyncWithOrigin(client, SECURITY_ORIGIN, DeleteByQueryAction.INSTANCE, expiredDbq,
|
||||
ActionListener.wrap(r -> {
|
||||
debugDbqResponse(r);
|
||||
ActionListener.wrap(bulkResponse -> {
|
||||
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();
|
||||
}, this::onFailure));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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.xpack.core.ClientHelper.SECURITY_ORIGIN;
|
||||
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
|
||||
|
@ -146,7 +146,7 @@ public class NativeUsersStore {
|
|||
}
|
||||
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
|
||||
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))
|
||||
.setQuery(query)
|
||||
.setSize(1000)
|
||||
|
@ -171,7 +171,7 @@ public class NativeUsersStore {
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
|
||||
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))
|
||||
.setSize(0)
|
||||
.setTrackTotalHits(true)
|
||||
|
@ -205,7 +205,7 @@ public class NativeUsersStore {
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
|
||||
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>() {
|
||||
@Override
|
||||
public void onResponse(GetResponse response) {
|
||||
|
@ -245,7 +245,7 @@ public class NativeUsersStore {
|
|||
|
||||
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
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(),
|
||||
String.valueOf(request.passwordHash()))
|
||||
.setRefreshPolicy(request.getRefreshPolicy()).request(),
|
||||
|
@ -283,7 +283,7 @@ public class NativeUsersStore {
|
|||
private void createReservedUser(String username, char[] passwordHash, RefreshPolicy refresh, ActionListener<Void> listener) {
|
||||
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
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(),
|
||||
true, Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE)
|
||||
.setRefreshPolicy(refresh).request(),
|
||||
|
@ -323,7 +323,7 @@ public class NativeUsersStore {
|
|||
// We must have an existing document
|
||||
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
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,
|
||||
Fields.USERNAME.getPreferredName(), putUserRequest.username(),
|
||||
Fields.ROLES.getPreferredName(), putUserRequest.roles(),
|
||||
|
@ -367,7 +367,7 @@ public class NativeUsersStore {
|
|||
assert putUserRequest.passwordHash() != null;
|
||||
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
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(),
|
||||
Fields.PASSWORD.getPreferredName(), String.valueOf(putUserRequest.passwordHash()),
|
||||
Fields.ROLES.getPreferredName(), putUserRequest.roles(),
|
||||
|
@ -410,7 +410,7 @@ public class NativeUsersStore {
|
|||
final ActionListener<Void> listener) {
|
||||
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
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)
|
||||
.setRefreshPolicy(refreshPolicy)
|
||||
.request(),
|
||||
|
@ -444,7 +444,7 @@ public class NativeUsersStore {
|
|||
boolean clearCache, final ActionListener<Void> listener) {
|
||||
securityIndex.prepareIndexIfNeededThenExecute(listener::onFailure, () -> {
|
||||
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)
|
||||
.setUpsert(XContentType.JSON,
|
||||
Fields.PASSWORD.getPreferredName(), "",
|
||||
|
@ -479,7 +479,7 @@ public class NativeUsersStore {
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
|
||||
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.setRefreshPolicy(deleteUserRequest.getRefreshPolicy());
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
|
||||
|
@ -526,7 +526,7 @@ public class NativeUsersStore {
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
|
||||
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(),
|
||||
new ActionListener<GetResponse>() {
|
||||
@Override
|
||||
|
@ -571,7 +571,7 @@ public class NativeUsersStore {
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareSearch(SECURITY_INDEX_NAME)
|
||||
client.prepareSearch(SECURITY_MAIN_ALIAS)
|
||||
.setTrackTotalHits(true)
|
||||
.setQuery(QueryBuilders.termQuery(Fields.TYPE.getPreferredName(), RESERVED_USER_TYPE))
|
||||
.setFetchSource(true).request(),
|
||||
|
|
|
@ -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.expressiondsl.ExpressionModel;
|
||||
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.UserRoleMapper;
|
||||
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.xpack.core.ClientHelper.SECURITY_ORIGIN;
|
||||
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.isMoveFromRedToNonRed;
|
||||
|
||||
/**
|
||||
* This store reads + writes {@link ExpressionRoleMapping role mappings} in an Elasticsearch
|
||||
* {@link SecurityIndexManager#SECURITY_INDEX_NAME index}.
|
||||
* {@link RestrictedIndicesNames#SECURITY_MAIN_ALIAS index}.
|
||||
* <br>
|
||||
* The store is responsible for all read and write operations as well as
|
||||
* {@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 Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
|
||||
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))
|
||||
.setQuery(query)
|
||||
.setSize(1000)
|
||||
|
@ -143,7 +144,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
|
|||
listener.onResponse(mappings.stream().filter(Objects::nonNull).collect(Collectors.toList())),
|
||||
ex -> {
|
||||
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());
|
||||
})),
|
||||
doc -> buildMapping(getNameFromId(doc.getId()), doc.getSourceRef()));
|
||||
|
@ -202,7 +203,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
|
|||
return;
|
||||
}
|
||||
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)
|
||||
.setRefreshPolicy(request.getRefreshPolicy())
|
||||
.request(),
|
||||
|
@ -231,7 +232,7 @@ public class NativeRoleMappingStore implements UserRoleMapper {
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
|
||||
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())
|
||||
.request(),
|
||||
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");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Security Index [{}] [exists: {}] [available: {}] [mapping up to date: {}]",
|
||||
SECURITY_INDEX_NAME,
|
||||
SECURITY_MAIN_ALIAS,
|
||||
securityIndex.indexExists(),
|
||||
securityIndex.isAvailable(),
|
||||
securityIndex.isMappingUpToDate()
|
||||
|
|
|
@ -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.security.authz.privilege.ApplicationPrivilegeDescriptor.DOC_TYPE_VALUE;
|
||||
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,
|
||||
|
@ -129,7 +129,7 @@ public class NativePrivilegeStore {
|
|||
}
|
||||
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
|
||||
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))
|
||||
.setQuery(query)
|
||||
.setSize(1000)
|
||||
|
@ -201,7 +201,7 @@ public class NativePrivilegeStore {
|
|||
} else {
|
||||
securityIndexManager.checkIndexVersionThenExecute(listener::onFailure,
|
||||
() -> 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(),
|
||||
new ActionListener<GetResponse>() {
|
||||
@Override
|
||||
|
@ -253,7 +253,7 @@ public class NativePrivilegeStore {
|
|||
final String name = privilege.getName();
|
||||
final XContentBuilder xContentBuilder = privilege.toXContent(jsonBuilder(), true);
|
||||
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)
|
||||
.setRefreshPolicy(refreshPolicy)
|
||||
.request(), listener, client::index);
|
||||
|
@ -284,7 +284,7 @@ public class NativePrivilegeStore {
|
|||
}, listener::onFailure), names.size());
|
||||
for (String name : names) {
|
||||
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)
|
||||
.request(), groupListener, client::delete);
|
||||
}
|
||||
|
|
|
@ -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.security.SecurityField.setting;
|
||||
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
|
||||
|
@ -124,7 +124,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
QueryBuilder query = QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE);
|
||||
final Supplier<ThreadContext.StoredContext> supplier = client.threadPool().getThreadContext().newRestorableContext(false);
|
||||
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))
|
||||
.setQuery(query)
|
||||
.setSize(1000)
|
||||
|
@ -142,7 +142,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
|
||||
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,
|
||||
ActionListener.<MultiGetResponse>wrap(mGetResponse -> {
|
||||
final MultiGetItemResponse[] responses = mGetResponse.getResponses();
|
||||
|
@ -179,7 +179,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
} else {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
|
||||
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());
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, request,
|
||||
new ActionListener<DeleteResponse>() {
|
||||
|
@ -219,7 +219,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
listener.onFailure(e);
|
||||
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)
|
||||
.setRefreshPolicy(request.getRefreshPolicy())
|
||||
.request();
|
||||
|
@ -253,11 +253,11 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
|
||||
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN,
|
||||
client.prepareMultiSearch()
|
||||
.add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
.add(client.prepareSearch(SECURITY_MAIN_ALIAS)
|
||||
.setQuery(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE))
|
||||
.setTrackTotalHits(true)
|
||||
.setSize(0))
|
||||
.add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
.add(client.prepareSearch(SECURITY_MAIN_ALIAS)
|
||||
.setQuery(QueryBuilders.boolQuery()
|
||||
.must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE))
|
||||
.must(QueryBuilders.boolQuery()
|
||||
|
@ -268,7 +268,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
.setTrackTotalHits(true)
|
||||
.setSize(0)
|
||||
.setTerminateAfter(1))
|
||||
.add(client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
.add(client.prepareSearch(SECURITY_MAIN_ALIAS)
|
||||
.setQuery(QueryBuilders.boolQuery()
|
||||
.must(QueryBuilders.termQuery(RoleDescriptor.Fields.TYPE.getPreferredName(), ROLE_TYPE))
|
||||
.filter(existsQuery("indices.query")))
|
||||
|
@ -340,7 +340,7 @@ public class NativeRolesStore implements BiConsumer<Set<String>, ActionListener<
|
|||
private void executeGetRoleRequest(String role, ActionListener<GetResponse> listener) {
|
||||
securityIndex.checkIndexVersionThenExecute(listener::onFailure, () ->
|
||||
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,
|
||||
client::get));
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ import org.elasticsearch.xpack.core.template.TemplateUtils;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -77,12 +78,13 @@ import static org.elasticsearch.xpack.core.ClientHelper.executeAsyncWithOrigin;
|
|||
*/
|
||||
public class SecurityIndexManager implements ClusterStateListener {
|
||||
|
||||
public static final String INTERNAL_SECURITY_INDEX = RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7;
|
||||
public static final int INTERNAL_INDEX_FORMAT = 6;
|
||||
public static final int INTERNAL_MAIN_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 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 final String aliasName;
|
||||
|
@ -95,19 +97,26 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
|
||||
private volatile State indexState;
|
||||
|
||||
public static SecurityIndexManager buildSecurityIndexManager(Client client, ClusterService clusterService) {
|
||||
return new SecurityIndexManager(client, SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX, INTERNAL_INDEX_FORMAT,
|
||||
SecurityIndexManager::readSecurityTemplateAsBytes, clusterService);
|
||||
public static SecurityIndexManager buildSecurityMainIndexManager(Client client, ClusterService clusterService) {
|
||||
return new SecurityIndexManager(client, clusterService, RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
|
||||
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,
|
||||
Supplier<byte[]> mappingSourceSupplier, ClusterService clusterService) {
|
||||
public static SecurityIndexManager buildSecurityTokensIndexManager(Client client, 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);
|
||||
clusterService.addListener(this);
|
||||
}
|
||||
|
||||
private SecurityIndexManager(Client client, String aliasName, String internalIndexName, int internalIndexFormat,
|
||||
Supplier<byte[]> mappingSourceSupplier, State indexState) {
|
||||
Supplier<byte[]> mappingSourceSupplier, State indexState) {
|
||||
this.aliasName = aliasName;
|
||||
this.internalIndexName = internalIndexName;
|
||||
this.internalIndexFormat = internalIndexFormat;
|
||||
|
@ -126,8 +135,16 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
return currentIndexState.mappingVersion == null || requiredVersion.test(currentIndexState.mappingVersion);
|
||||
}
|
||||
|
||||
public String aliasName() {
|
||||
return aliasName;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
if (localState.indexExists) {
|
||||
if (localState.indexExists()) {
|
||||
return new UnavailableShardsException(null,
|
||||
"at least one primary shard for the index [" + localState.concreteIndexName + "] is unavailable");
|
||||
} else {
|
||||
|
@ -183,17 +200,17 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
}
|
||||
final State previousState = indexState;
|
||||
final IndexMetaData indexMetaData = resolveConcreteIndex(aliasName, event.state().metaData());
|
||||
final boolean indexExists = indexMetaData != null;
|
||||
final boolean isIndexUpToDate = indexExists == false ||
|
||||
final Instant creationTime = indexMetaData != null ? Instant.ofEpochMilli(indexMetaData.getCreationDate()) : null;
|
||||
final boolean isIndexUpToDate = indexMetaData == null ||
|
||||
INDEX_FORMAT_SETTING.get(indexMetaData.getSettings()).intValue() == internalIndexFormat;
|
||||
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 ClusterHealthStatus indexStatus = indexMetaData == null ? null :
|
||||
new ClusterIndexHealth(indexMetaData, event.state().getRoutingTable().index(indexMetaData.getIndex())).getStatus();
|
||||
final String concreteIndexName = indexMetaData == null ? internalIndexName : indexMetaData.getIndex().getName();
|
||||
final State newState = new State(indexExists, isIndexUpToDate, indexAvailable, mappingIsUpToDate, mappingVersion, concreteIndexName,
|
||||
indexStatus);
|
||||
final State newState = new State(creationTime, isIndexUpToDate, indexAvailable, mappingIsUpToDate, mappingVersion,
|
||||
concreteIndexName, indexStatus);
|
||||
this.indexState = newState;
|
||||
|
||||
if (newState.equals(previousState) == false) {
|
||||
|
@ -304,7 +321,7 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
*/
|
||||
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!
|
||||
if (indexState.indexExists && indexState.isIndexUpToDate == false) {
|
||||
if (indexState.indexExists() && indexState.isIndexUpToDate == false) {
|
||||
consumer.accept(new IllegalStateException(
|
||||
"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"));
|
||||
|
@ -324,11 +341,11 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
consumer.accept(new ElasticsearchStatusException(
|
||||
"Cluster state has not been recovered yet, cannot write to the [" + indexState.concreteIndexName + "] index",
|
||||
RestStatus.SERVICE_UNAVAILABLE));
|
||||
} else if (indexState.indexExists && indexState.isIndexUpToDate == false) {
|
||||
} else if (indexState.indexExists() && indexState.isIndexUpToDate == false) {
|
||||
consumer.accept(new IllegalStateException(
|
||||
"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"));
|
||||
} else if (indexState.indexExists == false) {
|
||||
} else if (indexState.indexExists() == false) {
|
||||
assert indexState.concreteIndexName != null;
|
||||
logger.info("security index does not exist. Creating [{}] with alias [{}]", indexState.concreteIndexName, this.aliasName);
|
||||
final byte[] mappingSource = mappingSourceSupplier.get();
|
||||
|
@ -396,8 +413,8 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
return previousState.indexStatus != null && currentState.indexStatus == null;
|
||||
}
|
||||
|
||||
private static byte[] readSecurityTemplateAsBytes() {
|
||||
return TemplateUtils.loadTemplate("/" + SECURITY_TEMPLATE_NAME + ".json", Version.CURRENT.toString(),
|
||||
private static byte[] readTemplateAsBytes(String templateName) {
|
||||
return TemplateUtils.loadTemplate("/" + templateName + ".json", Version.CURRENT.toString(),
|
||||
SecurityIndexManager.TEMPLATE_VERSION_PATTERN).getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
|
@ -423,8 +440,8 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
* State of the security index.
|
||||
*/
|
||||
public static class State {
|
||||
public static final State UNRECOVERED_STATE = new State(false, false, false, false, null, null, null);
|
||||
public final boolean indexExists;
|
||||
public static final State UNRECOVERED_STATE = new State(null, false, false, false, null, null, null);
|
||||
public final Instant creationTime;
|
||||
public final boolean isIndexUpToDate;
|
||||
public final boolean indexAvailable;
|
||||
public final boolean mappingUpToDate;
|
||||
|
@ -432,9 +449,9 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
public final String concreteIndexName;
|
||||
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) {
|
||||
this.indexExists = indexExists;
|
||||
this.creationTime = creationTime;
|
||||
this.isIndexUpToDate = isIndexUpToDate;
|
||||
this.indexAvailable = indexAvailable;
|
||||
this.mappingUpToDate = mappingUpToDate;
|
||||
|
@ -448,7 +465,7 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
State state = (State) o;
|
||||
return indexExists == state.indexExists &&
|
||||
return Objects.equals(creationTime, state.creationTime) &&
|
||||
isIndexUpToDate == state.isIndexUpToDate &&
|
||||
indexAvailable == state.indexAvailable &&
|
||||
mappingUpToDate == state.mappingUpToDate &&
|
||||
|
@ -457,9 +474,13 @@ public class SecurityIndexManager implements ClusterStateListener {
|
|||
indexStatus == state.indexStatus;
|
||||
}
|
||||
|
||||
public boolean indexExists() {
|
||||
return creationTime != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(indexExists, isIndexUpToDate, indexAvailable, mappingUpToDate, mappingVersion, concreteIndexName,
|
||||
return Objects.hash(creationTime, isIndexUpToDate, indexAvailable, mappingUpToDate, mappingVersion, concreteIndexName,
|
||||
indexStatus);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.authz.store.RoleRetrievalResult;
|
||||
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.support.SecurityIndexManager;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
|
@ -56,7 +56,7 @@ public class ClearRolesCacheTests extends NativeRealmIntegTestCase {
|
|||
logger.debug("--> created role [{}]", role);
|
||||
}
|
||||
|
||||
ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME);
|
||||
ensureGreen(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
|
||||
|
||||
final Set<String> rolesSet = new HashSet<>(Arrays.asList(roles));
|
||||
// warm up the caches on every node
|
||||
|
|
|
@ -59,7 +59,7 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase {
|
|||
@Override
|
||||
public Set<String> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.assertNoTimeout;
|
||||
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.core.IsCollectionContaining.hasItem;
|
||||
|
||||
|
@ -491,7 +491,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
|
|||
XContentBuilder builder = JsonXContent.contentBuilder().prettyPrint().startObject();
|
||||
assertTrue("security index mapping not sufficient to read:\n" +
|
||||
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));
|
||||
Index securityIndex = resolveSecurityIndex(clusterState.metaData());
|
||||
if (securityIndex != null) {
|
||||
|
@ -509,7 +509,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
|
|||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER,
|
||||
SecuritySettingsSourceField.TEST_PASSWORD_SECURE_STRING)));
|
||||
GetIndexRequest getIndexRequest = new GetIndexRequest();
|
||||
getIndexRequest.indices(SECURITY_INDEX_NAME);
|
||||
getIndexRequest.indices(SECURITY_MAIN_ALIAS);
|
||||
getIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
|
||||
GetIndexResponse getIndexResponse = client.admin().indices().getIndex(getIndexRequest).actionGet();
|
||||
if (getIndexResponse.getIndices().length > 0) {
|
||||
|
@ -520,7 +520,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
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) {
|
||||
return aliasOrIndex.getIndices().get(0).getIndex();
|
||||
}
|
||||
|
|
|
@ -68,8 +68,8 @@ import java.util.stream.Collectors;
|
|||
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.ZEN_DISCOVERY_TYPE;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_INDEX_FORMAT;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -310,8 +310,8 @@ public class SecurityTests extends ESTestCase {
|
|||
BiConsumer<DiscoveryNode, ClusterState> joinValidator = security.getJoinValidator();
|
||||
assertNotNull(joinValidator);
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME)
|
||||
.settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_INDEX_FORMAT - 1))
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_MAIN_ALIAS)
|
||||
.settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_MAIN_INDEX_FORMAT - 1))
|
||||
.numberOfShards(1).numberOfReplicas(0)
|
||||
.build();
|
||||
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();
|
||||
assertNotNull(joinValidator);
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
int indexFormat = randomBoolean() ? INTERNAL_INDEX_FORMAT : INTERNAL_INDEX_FORMAT - 1;
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME)
|
||||
int indexFormat = randomBoolean() ? INTERNAL_MAIN_INDEX_FORMAT : INTERNAL_MAIN_INDEX_FORMAT - 1;
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_MAIN_ALIAS)
|
||||
.settings(settings(Version.V_6_1_0).put(INDEX_FORMAT_SETTING.getKey(), indexFormat))
|
||||
.numberOfShards(1).numberOfReplicas(0)
|
||||
.build();
|
||||
|
@ -349,8 +349,8 @@ public class SecurityTests extends ESTestCase {
|
|||
assertNotNull(joinValidator);
|
||||
Version version = randomBoolean() ? Version.CURRENT : Version.V_6_1_0;
|
||||
DiscoveryNode node = new DiscoveryNode("foo", buildNewFakeTransportAddress(), Version.CURRENT);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_INDEX_NAME)
|
||||
.settings(settings(version).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_INDEX_FORMAT))
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(SECURITY_MAIN_ALIAS)
|
||||
.settings(settings(version).put(INDEX_FORMAT_SETTING.getKey(), INTERNAL_MAIN_INDEX_FORMAT))
|
||||
.numberOfShards(1).numberOfReplicas(0)
|
||||
.build();
|
||||
DiscoveryNode existingOtherNode = new DiscoveryNode("bar", buildNewFakeTransportAddress(), version);
|
||||
|
|
|
@ -167,7 +167,7 @@ public class TransportOpenIdConnectLogoutActionTests extends OpenIdConnectTestCa
|
|||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
|
||||
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,
|
||||
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
|
||||
|
|
|
@ -195,10 +195,13 @@ public class TransportSamlInvalidateSessionActionTests extends SamlTestCase {
|
|||
}).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
when(securityIndex.isAvailable()).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);
|
||||
|
||||
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,
|
||||
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(((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)
|
||||
// Invalidate refresh token 1
|
||||
|
|
|
@ -203,7 +203,7 @@ public class TransportSamlLogoutActionTests extends SamlTestCase {
|
|||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
|
||||
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,
|
||||
TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> null, null, Collections.emptySet());
|
||||
|
|
|
@ -147,7 +147,8 @@ public class TransportCreateTokenActionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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.writeToContext(threadPool.getThreadContext());
|
||||
|
||||
|
@ -171,7 +172,8 @@ public class TransportCreateTokenActionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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.writeToContext(threadPool.getThreadContext());
|
||||
|
||||
|
|
|
@ -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.authz.RoleDescriptor;
|
||||
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.junit.After;
|
||||
import org.junit.Before;
|
||||
|
@ -53,7 +52,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
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.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
@ -336,7 +335,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
|
|||
Instant dayBefore = created.minus(1L, ChronoUnit.DAYS);
|
||||
assertTrue(Instant.now().isAfter(dayBefore));
|
||||
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())
|
||||
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
||||
.get();
|
||||
|
@ -346,7 +345,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
|
|||
// hack doc to modify the expiration time to the week before
|
||||
Instant weekBefore = created.minus(8L, ChronoUnit.DAYS);
|
||||
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())
|
||||
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
||||
.get();
|
||||
|
@ -390,8 +389,7 @@ public class ApiKeyIntegTests extends SecurityIntegTestCase {
|
|||
|
||||
private void refreshSecurityIndex() throws Exception {
|
||||
assertBusy(() -> {
|
||||
final RefreshResponse refreshResponse = client().admin().indices().prepareRefresh(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
.get();
|
||||
final RefreshResponse refreshResponse = client().admin().indices().prepareRefresh(SECURITY_MAIN_ALIAS).get();
|
||||
assertThat(refreshResponse.getFailedShards(), is(0));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
@SuppressForbidden(reason = "Allow accessing localhost")
|
||||
public void init() throws Exception {
|
||||
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);
|
||||
when(token.principal()).thenReturn(randomAlphaOfLength(5));
|
||||
|
@ -220,7 +220,7 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
}).when(securityIndex).checkIndexVersionThenExecute(any(Consumer.class), any(Runnable.class));
|
||||
ClusterService clusterService = ClusterServiceUtils.createClusterService(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()),
|
||||
threadPool, new AnonymousUser(settings), tokenService, apiKeyService);
|
||||
}
|
||||
|
@ -1394,6 +1394,6 @@ public class AuthenticationServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.support.UsernamePasswordToken;
|
||||
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.Before;
|
||||
|
||||
|
@ -55,7 +55,6 @@ import java.util.stream.Collectors;
|
|||
|
||||
import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME;
|
||||
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;
|
||||
|
||||
@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));
|
||||
AtomicReference<String> docId = new AtomicReference<>();
|
||||
assertBusy(() -> {
|
||||
SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
SearchResponse searchResponse = client.prepareSearch(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS)
|
||||
.setSource(SearchSourceBuilder.searchSource()
|
||||
.query(QueryBuilders.termQuery("doc_type", "token")))
|
||||
.setSize(1)
|
||||
|
@ -174,7 +173,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
// hack doc to modify the creation time to the day before
|
||||
Instant yesterday = created.minus(36L, ChronoUnit.HOURS);
|
||||
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())
|
||||
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
||||
.get();
|
||||
|
@ -192,8 +191,8 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
assertEquals("token malformed", e.getMessage());
|
||||
}
|
||||
}
|
||||
client.admin().indices().prepareRefresh(SecurityIndexManager.SECURITY_INDEX_NAME).get();
|
||||
SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
client.admin().indices().prepareRefresh(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS).get();
|
||||
SearchResponse searchResponse = client.prepareSearch(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS)
|
||||
.setSource(SearchSourceBuilder.searchSource()
|
||||
.query(QueryBuilders.termQuery("doc_type", "token")))
|
||||
.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
|
||||
AtomicReference<String> docId = new AtomicReference<>();
|
||||
assertBusy(() -> {
|
||||
SearchResponse searchResponse = client.prepareSearch(SecurityIndexManager.SECURITY_INDEX_NAME)
|
||||
SearchResponse searchResponse = client.prepareSearch(RestrictedIndicesNames.SECURITY_TOKENS_ALIAS)
|
||||
.setSource(SearchSourceBuilder.searchSource()
|
||||
.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"))))
|
||||
.setSize(1)
|
||||
.setTerminateAfter(1)
|
||||
|
@ -374,7 +373,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||
Instant refreshed = Instant.now();
|
||||
Instant aWhileAgo = refreshed.minus(50L, ChronoUnit.SECONDS);
|
||||
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()))
|
||||
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
||||
.setFetchSource("refresh_token", Strings.EMPTY_STRING)
|
||||
|
|
|
@ -21,6 +21,9 @@ import org.elasticsearch.action.support.PlainActionFuture;
|
|||
import org.elasticsearch.action.update.UpdateAction;
|
||||
import org.elasticsearch.action.update.UpdateRequestBuilder;
|
||||
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.common.Strings;
|
||||
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.watcher.watch.ClockMock;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
@ -74,6 +78,7 @@ import javax.crypto.SecretKey;
|
|||
|
||||
import static java.time.Clock.systemUTC;
|
||||
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.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
@ -92,8 +97,10 @@ public class TokenServiceTests extends ESTestCase {
|
|||
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true).build();
|
||||
|
||||
private Client client;
|
||||
private SecurityIndexManager securityIndex;
|
||||
private SecurityIndexManager securityMainIndex;
|
||||
private SecurityIndexManager securityTokensIndex;
|
||||
private ClusterService clusterService;
|
||||
private DiscoveryNode oldNode;
|
||||
private Settings tokenServiceEnabledSettings = Settings.builder()
|
||||
.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));
|
||||
|
||||
// setup lifecycle service
|
||||
securityIndex = mock(SecurityIndexManager.class);
|
||||
doAnswer(invocationOnMock -> {
|
||||
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.securityMainIndex = mockSecurityManager();
|
||||
this.securityTokensIndex = mockSecurityManager();
|
||||
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
|
||||
|
@ -151,7 +159,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -172,8 +181,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
|
||||
try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
||||
// verify a second separate token service with its own salt can also verify
|
||||
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex
|
||||
, clusterService);
|
||||
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
|
||||
securityTokensIndex, clusterService);
|
||||
anotherService.refreshMetaData(tokenService.getTokenMetaData());
|
||||
PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
||||
anotherService.getAndValidateToken(requestContext, future);
|
||||
|
@ -183,7 +192,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
String token = randomFrom("", " ");
|
||||
String authScheme = randomFrom("Bearer ", "BEARER ", "bearer ", "Basic ");
|
||||
|
@ -198,7 +208,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -251,12 +262,14 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
for (int i = 0; i < numRotations; i++) {
|
||||
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());
|
||||
Authentication authentication = new Authentication(new User("joe", "admin"), new RealmRef("native_realm", "native", "node1"), null);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
|
@ -272,7 +285,7 @@ public class TokenServiceTests extends ESTestCase {
|
|||
PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
||||
otherTokenService.getAndValidateToken(requestContext, future);
|
||||
UserToken serialized = future.get();
|
||||
assertAuthentication(authentication, serialized.getAuthentication());
|
||||
assertEquals(authentication, serialized.getAuthentication());
|
||||
}
|
||||
|
||||
rotateKeys(tokenService);
|
||||
|
@ -288,7 +301,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -350,7 +364,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -371,8 +386,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
|
||||
try (ThreadContext.StoredContext ignore = requestContext.newStoredContext(true)) {
|
||||
// verify a second separate token service with its own passphrase cannot verify
|
||||
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex,
|
||||
clusterService);
|
||||
TokenService anotherService = new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityMainIndex,
|
||||
securityTokensIndex, clusterService);
|
||||
PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
||||
anotherService.getAndValidateToken(requestContext, future);
|
||||
assertNull(future.get());
|
||||
|
@ -380,7 +395,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
|
@ -393,9 +409,9 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testInvalidatedToken() throws Exception {
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
TokenService tokenService =
|
||||
new TokenService(tokenServiceEnabledSettings, systemUTC(), client, securityIndex, clusterService);
|
||||
when(securityMainIndex.indexExists()).thenReturn(true);
|
||||
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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -449,7 +465,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
|
||||
public void testTokenExpiry() throws Exception {
|
||||
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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -502,7 +519,7 @@ public class TokenServiceTests extends ESTestCase {
|
|||
TokenService tokenService = new TokenService(Settings.builder()
|
||||
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), false)
|
||||
.build(),
|
||||
Clock.systemUTC(), client, securityIndex, clusterService);
|
||||
Clock.systemUTC(), client, securityMainIndex, securityTokensIndex, clusterService);
|
||||
IllegalStateException e = expectThrows(IllegalStateException.class,
|
||||
() -> tokenService.createOAuth2Tokens(null, null, null, true, null));
|
||||
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 byte[] randomBytes = new byte[numBytes];
|
||||
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);
|
||||
requestContext.putHeader("Authorization", "Bearer " + Base64.getEncoder().encodeToString(randomBytes));
|
||||
|
@ -558,8 +576,8 @@ public class TokenServiceTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testIndexNotAvailable() 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);
|
||||
PlainActionFuture<Tuple<UserToken, String>> tokenFuture = new PlainActionFuture<>();
|
||||
tokenService.createOAuth2Tokens(authentication, authentication, Collections.emptyMap(), true, tokenFuture);
|
||||
|
@ -576,34 +594,44 @@ public class TokenServiceTests extends ESTestCase {
|
|||
return Void.TYPE;
|
||||
}).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)) {
|
||||
PlainActionFuture<UserToken> future = new PlainActionFuture<>();
|
||||
tokenService.getAndValidateToken(requestContext, future);
|
||||
assertNull(future.get());
|
||||
|
||||
when(securityIndex.isAvailable()).thenReturn(false);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
when(tokensIndex.isAvailable()).thenReturn(false);
|
||||
when(tokensIndex.indexExists()).thenReturn(true);
|
||||
future = new PlainActionFuture<>();
|
||||
tokenService.getAndValidateToken(requestContext, future);
|
||||
assertNull(future.get());
|
||||
|
||||
when(securityIndex.indexExists()).thenReturn(false);
|
||||
when(tokensIndex.indexExists()).thenReturn(false);
|
||||
future = new PlainActionFuture<>();
|
||||
tokenService.getAndValidateToken(requestContext, future);
|
||||
assertNull(future.get());
|
||||
|
||||
when(securityIndex.isAvailable()).thenReturn(true);
|
||||
when(securityIndex.indexExists()).thenReturn(true);
|
||||
when(tokensIndex.isAvailable()).thenReturn(true);
|
||||
when(tokensIndex.indexExists()).thenReturn(true);
|
||||
mockGetTokenFromId(token, false);
|
||||
future = new PlainActionFuture<>();
|
||||
tokenService.getAndValidateToken(requestContext, future);
|
||||
assertEquals(token.getAuthentication(), future.get().getAuthentication());
|
||||
assertEquals(future.get().getAuthentication(), token.getAuthentication());
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetAuthenticationWorksWithExpiredUserToken() throws Exception {
|
||||
TokenService tokenService =
|
||||
new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), client, securityIndex, clusterService);
|
||||
TokenService tokenService = new TokenService(tokenServiceEnabledSettings, Clock.systemUTC(), client, securityMainIndex,
|
||||
securityTokensIndex, clusterService);
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.elasticsearch.env.Environment;
|
|||
import org.elasticsearch.test.NativeRealmIntegTestCase;
|
||||
import org.elasticsearch.common.CharArrays;
|
||||
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 java.nio.charset.StandardCharsets;
|
||||
|
@ -85,7 +85,7 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase {
|
|||
addedUsers.add(uname);
|
||||
}
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME);
|
||||
ensureGreen(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
|
||||
|
||||
MockTerminal t = new MockTerminal();
|
||||
String username = nodeClientUsername();
|
||||
|
@ -136,7 +136,7 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase {
|
|||
addedRoles.add(rname);
|
||||
}
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SecurityIndexManager.SECURITY_INDEX_NAME);
|
||||
ensureGreen(RestrictedIndicesNames.SECURITY_MAIN_ALIAS);
|
||||
|
||||
MockTerminal t = new MockTerminal();
|
||||
String username = nodeClientUsername();
|
||||
|
|
|
@ -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.store.ReservedRolesStore;
|
||||
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.ElasticUser;
|
||||
import org.elasticsearch.xpack.core.security.user.KibanaUser;
|
||||
import org.elasticsearch.xpack.core.security.user.SystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.User;
|
||||
import org.elasticsearch.xpack.security.authz.store.NativeRolesStore;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.junit.Before;
|
||||
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.assertNoTimeout;
|
||||
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.security.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
|
||||
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.containsString;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
|
@ -146,7 +146,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3kirt".toCharArray(), hasher, "role1", "user").get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
logger.info("--> retrieving user");
|
||||
GetUsersResponse resp = c.prepareGetUsers("joe").get();
|
||||
assertTrue("user should exist", resp.hasUsers());
|
||||
|
@ -201,7 +201,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
.metadata(metadata)
|
||||
.get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
logger.info("--> retrieving role");
|
||||
GetRolesResponse resp = c.prepareGetRoles().names("test_role").get();
|
||||
assertTrue("role should exist", resp.hasRoles());
|
||||
|
@ -252,7 +252,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
logger.info("--> retrieving user");
|
||||
GetUsersResponse resp = c.prepareGetUsers("joe").get();
|
||||
assertTrue("user should exist", resp.hasUsers());
|
||||
|
@ -273,7 +273,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, SecuritySettingsSource.TEST_ROLE).get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
logger.info("--> retrieving user");
|
||||
GetUsersResponse resp = c.prepareGetUsers("joe").get();
|
||||
assertTrue("user should exist", resp.hasUsers());
|
||||
|
@ -309,7 +309,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
c.preparePutUser("joe", "s3krit".toCharArray(), hasher,
|
||||
SecuritySettingsSource.TEST_ROLE).get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
logger.info("--> retrieving user");
|
||||
GetUsersResponse resp = c.prepareGetUsers("joe").get();
|
||||
assertTrue("user should exist", resp.hasUsers());
|
||||
|
@ -347,7 +347,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
logger.error("--> creating user");
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
|
||||
if (authenticate) {
|
||||
final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray()));
|
||||
|
@ -396,7 +396,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
logger.error("--> creating user");
|
||||
securityClient().preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role", "snapshot_user").get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
logger.info("--> creating repository");
|
||||
assertAcked(client().admin().cluster()
|
||||
.preparePutRepository("test-repo")
|
||||
|
@ -410,10 +410,10 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
.prepareCreateSnapshot("test-repo", "test-snap-1")
|
||||
.setWaitForCompletion(true)
|
||||
.setIncludeGlobalState(false)
|
||||
.setIndices(SECURITY_INDEX_NAME)
|
||||
.setIndices(SECURITY_MAIN_ALIAS)
|
||||
.get().getSnapshotInfo();
|
||||
assertThat(snapshotInfo.state(), is(SnapshotState.SUCCESS));
|
||||
assertThat(snapshotInfo.indices(), contains(SecurityIndexManager.INTERNAL_SECURITY_INDEX));
|
||||
assertThat(snapshotInfo.indices(), contains(INTERNAL_SECURITY_MAIN_INDEX_7));
|
||||
deleteSecurityIndex();
|
||||
// the realm cache should clear itself but we don't wish to race it
|
||||
securityClient().prepareClearRealmCache().get();
|
||||
|
@ -430,7 +430,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
RestoreSnapshotResponse response = client().admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap-1")
|
||||
.setWaitForCompletion(true).setIncludeAliases(true).get();
|
||||
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
|
||||
securityClient().prepareClearRealmCache().get();
|
||||
// users and roles are retrievable
|
||||
|
@ -460,7 +460,7 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
.get();
|
||||
c.preparePutUser("joe", "s3krit".toCharArray(), hasher, "test_role").get();
|
||||
logger.error("--> waiting for .security index");
|
||||
ensureGreen(SECURITY_INDEX_NAME);
|
||||
ensureGreen(SECURITY_MAIN_ALIAS);
|
||||
|
||||
final String token = basicAuthHeaderValue("joe", new SecureString("s3krit".toCharArray()));
|
||||
ClusterHealthResponse response = client().filterWithHeader(Collections.singletonMap("Authorization", token)).admin().cluster()
|
||||
|
@ -591,12 +591,12 @@ public class NativeRealmIntegTests extends NativeRealmIntegTestCase {
|
|||
.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.getIndices().size(), is(2));
|
||||
assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX), notNullValue());
|
||||
assertThat(response.getIndices().get(INTERNAL_SECURITY_INDEX).getIndex(),
|
||||
is(INTERNAL_SECURITY_INDEX));
|
||||
assertThat(response.getIndices().get(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7), notNullValue());
|
||||
assertThat(response.getIndices().get(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7).getIndex(),
|
||||
is(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7));
|
||||
}
|
||||
|
||||
public void testOperationsOnReservedUsers() throws Exception {
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.xpack.core.security.authc.RealmConfig;
|
|||
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
@ -23,10 +24,10 @@ import static org.mockito.Mockito.when;
|
|||
public class NativeRealmTests extends ESTestCase {
|
||||
|
||||
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) {
|
||||
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() {
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.elasticsearch.test.ESTestCase;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.core.security.authc.AuthenticationResult;
|
||||
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.BeatsSystemUser;
|
||||
import org.elasticsearch.xpack.core.security.user.ElasticUser;
|
||||
|
@ -111,7 +112,7 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
values.put(PASSWORD_FIELD, BLANK_PASSWORD);
|
||||
|
||||
final GetResult result = new GetResult(
|
||||
SecurityIndexManager.SECURITY_INDEX_NAME,
|
||||
RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
|
||||
MapperService.SINGLE_MAPPING_NAME,
|
||||
NativeUsersStore.getIdForUser(NativeUsersStore.RESERVED_USER_TYPE, randomAlphaOfLength(12)),
|
||||
0, 1, 1L,
|
||||
|
@ -180,7 +181,7 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
nativeUsersStore.verifyPassword(username, password, future);
|
||||
|
||||
final GetResult getResult = new GetResult(
|
||||
SecurityIndexManager.SECURITY_INDEX_NAME,
|
||||
RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
|
||||
MapperService.SINGLE_MAPPING_NAME,
|
||||
NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username),
|
||||
UNASSIGNED_SEQ_NO, 0, 1L,
|
||||
|
@ -222,7 +223,7 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
values.put(User.Fields.TYPE.getPreferredName(), NativeUsersStore.USER_DOC_TYPE);
|
||||
final BytesReference source = BytesReference.bytes(jsonBuilder().map(values));
|
||||
final GetResult getResult = new GetResult(
|
||||
SecurityIndexManager.SECURITY_INDEX_NAME,
|
||||
RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
|
||||
MapperService.SINGLE_MAPPING_NAME,
|
||||
NativeUsersStore.getIdForUser(NativeUsersStore.USER_DOC_TYPE, username),
|
||||
0, 1, 1L,
|
||||
|
@ -230,7 +231,6 @@ public class NativeUsersStoreTests extends ESTestCase {
|
|||
source,
|
||||
Collections.emptyMap());
|
||||
|
||||
|
||||
actionRespond(GetRequest.class, new GetResponse(getResult));
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.elasticsearch.xpack.security.authc.support.UserRoleMapper;
|
|||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -53,7 +54,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
public class NativeRoleMappingStoreTests extends ESTestCase {
|
||||
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 {
|
||||
// Does match DN
|
||||
|
@ -137,7 +138,7 @@ public class NativeRoleMappingStoreTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
@ -182,13 +183,13 @@ public class NativeRoleMappingStoreTests extends ESTestCase {
|
|||
final NativeRoleMappingStore store = buildRoleMappingStoreForInvalidationTesting(numInvalidation);
|
||||
|
||||
store.onSecurityIndexStateChange(
|
||||
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null));
|
||||
new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null));
|
||||
assertEquals(1, numInvalidation.get());
|
||||
|
||||
store.onSecurityIndexStateChange(
|
||||
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null));
|
||||
new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null));
|
||||
assertEquals(2, numInvalidation.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -156,8 +156,8 @@ import static org.elasticsearch.test.SecurityTestsUtils.assertAuthenticationExce
|
|||
import static org.elasticsearch.test.SecurityTestsUtils.assertThrowsAuthorizationException;
|
||||
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.support.SecurityIndexManager.INTERNAL_SECURITY_INDEX;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
|
||||
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
|
@ -864,8 +864,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(MetaData.builder()
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build())
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
|
@ -874,31 +874,33 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
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(
|
||||
new Tuple<>(BulkAction.NAME + "[s]", new DeleteRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id")));
|
||||
requests.add(new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX), "id")));
|
||||
requests.add(new Tuple<>(BulkAction.NAME + "[s]", new IndexRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX))));
|
||||
requests.add(new Tuple<>(SearchAction.NAME, new SearchRequest(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX))));
|
||||
new Tuple<>(UpdateAction.NAME, new UpdateRequest(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7), "id")));
|
||||
requests.add(
|
||||
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_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
|
||||
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), "id")));
|
||||
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), "id")));
|
||||
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,
|
||||
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
|
||||
requests.add(new Tuple<>(IndicesStatsAction.NAME,
|
||||
new IndicesStatsRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX))));
|
||||
requests.add(
|
||||
new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(randomFrom(SECURITY_INDEX_NAME, INTERNAL_SECURITY_INDEX))));
|
||||
new IndicesStatsRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
|
||||
requests.add(new Tuple<>(RecoveryAction.NAME,
|
||||
new RecoveryRequest().indices(randomFrom(SECURITY_MAIN_ALIAS, INTERNAL_SECURITY_MAIN_INDEX_7))));
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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) {
|
||||
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
|
||||
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);
|
||||
verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(ClusterHealthAction.NAME), eq(request),
|
||||
authzInfoRoles(new String[]{role.getName()}));
|
||||
|
||||
// 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);
|
||||
verify(auditTrail).accessGranted(eq(requestId), eq(authentication), eq(ClusterHealthAction.NAME), eq(request),
|
||||
authzInfoRoles(new String[]{role.getName()}));
|
||||
|
@ -940,8 +942,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(MetaData.builder()
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build())
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
|
@ -949,12 +951,12 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
.build());
|
||||
|
||||
List<Tuple<String, ? extends TransportRequest>> requests = new ArrayList<>();
|
||||
requests.add(new Tuple<>(IndicesStatsAction.NAME, new IndicesStatsRequest().indices(SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(RecoveryAction.NAME, new RecoveryRequest().indices(SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(IndicesShardStoresAction.NAME, new IndicesShardStoresRequest().indices(SECURITY_INDEX_NAME)));
|
||||
requests.add(new Tuple<>(UpgradeStatusAction.NAME, new UpgradeStatusRequest().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_MAIN_ALIAS)));
|
||||
requests.add(new Tuple<>(IndicesSegmentsAction.NAME, new IndicesSegmentsRequest().indices(SECURITY_MAIN_ALIAS)));
|
||||
requests.add(new Tuple<>(GetSettingsAction.NAME, new GetSettingsRequest().indices(SECURITY_MAIN_ALIAS)));
|
||||
requests.add(new Tuple<>(IndicesShardStoresAction.NAME, new IndicesShardStoresRequest().indices(SECURITY_MAIN_ALIAS)));
|
||||
requests.add(new Tuple<>(UpgradeStatusAction.NAME, new UpgradeStatusRequest().indices(SECURITY_MAIN_ALIAS)));
|
||||
|
||||
for (final Tuple<String, ? extends TransportRequest> requestTuple : requests) {
|
||||
final String action = requestTuple.v1();
|
||||
|
@ -984,8 +986,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(MetaData.builder()
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build())
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
|
@ -994,25 +996,28 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
final String requestId = AuditUtil.getOrGenerateRequestId(threadContext);
|
||||
|
||||
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(
|
||||
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,
|
||||
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) {
|
||||
final String action = requestTuple.v1();
|
||||
|
@ -1033,8 +1038,8 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
ClusterState state = mock(ClusterState.class);
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
when(state.metaData()).thenReturn(MetaData.builder()
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_INDEX)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_INDEX_NAME).build())
|
||||
.put(new IndexMetaData.Builder(INTERNAL_SECURITY_MAIN_INDEX_7)
|
||||
.putAlias(new AliasMetaData.Builder(SECURITY_MAIN_ALIAS).build())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT).build())
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
|
@ -1046,7 +1051,7 @@ public class AuthorizationServiceTests extends ESTestCase {
|
|||
SearchRequest request = new SearchRequest("_all");
|
||||
authorize(authentication, action, request);
|
||||
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() {
|
||||
|
|
|
@ -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.index.RestrictedIndicesNames;
|
||||
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -47,8 +46,8 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
RoleDescriptor bRole = new RoleDescriptor("b", null,
|
||||
new IndicesPrivileges[] { IndicesPrivileges.builder().indices("b").privileges("READ").build() }, null);
|
||||
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7);
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
MetaData metaData = MetaData.builder()
|
||||
.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)
|
||||
|
@ -65,7 +64,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
.settings(indexSettings)
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build())
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
|
||||
.build(), true)
|
||||
.build();
|
||||
final PlainActionFuture<Role> future = new PlainActionFuture<>();
|
||||
|
@ -78,7 +77,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
assertFalse(list.contains("bbbbb"));
|
||||
assertFalse(list.contains("ba"));
|
||||
assertThat(list, not(contains(internalSecurityIndex)));
|
||||
assertThat(list, not(contains(RestrictedIndicesNames.SECURITY_INDEX_NAME)));
|
||||
assertThat(list, not(contains(RestrictedIndicesNames.SECURITY_MAIN_ALIAS)));
|
||||
}
|
||||
|
||||
public void testAuthorizedIndicesUserWithSomeRolesEmptyMetaData() {
|
||||
|
@ -101,8 +100,8 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
.cluster(ClusterPrivilege.ALL)
|
||||
.build();
|
||||
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7);
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
MetaData metaData = MetaData.builder()
|
||||
.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)
|
||||
|
@ -111,7 +110,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
.settings(indexSettings)
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build())
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
|
||||
.build(), true)
|
||||
.build();
|
||||
|
||||
|
@ -119,7 +118,7 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup());
|
||||
assertThat(authorizedIndices, containsInAnyOrder("an-index", "another-index"));
|
||||
assertThat(authorizedIndices, not(contains(internalSecurityIndex)));
|
||||
assertThat(authorizedIndices, not(contains(RestrictedIndicesNames.SECURITY_INDEX_NAME)));
|
||||
assertThat(authorizedIndices, not(contains(RestrictedIndicesNames.SECURITY_MAIN_ALIAS)));
|
||||
}
|
||||
|
||||
public void testSecurityIndicesAreNotRemovedFromUnrestrictedRole() {
|
||||
|
@ -128,8 +127,8 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
.cluster(ClusterPrivilege.ALL)
|
||||
.build();
|
||||
Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7);
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
MetaData metaData = MetaData.builder()
|
||||
.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)
|
||||
|
@ -137,18 +136,18 @@ public class AuthorizedIndicesTests extends ESTestCase {
|
|||
.settings(indexSettings)
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build())
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
|
||||
.build(), true)
|
||||
.build();
|
||||
|
||||
List<String> authorizedIndices =
|
||||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup());
|
||||
assertThat(authorizedIndices, containsInAnyOrder(
|
||||
"an-index", "another-index", SecurityIndexManager.SECURITY_INDEX_NAME, internalSecurityIndex));
|
||||
"an-index", "another-index", RestrictedIndicesNames.SECURITY_MAIN_ALIAS, internalSecurityIndex));
|
||||
|
||||
List<String> authorizedIndicesSuperUser =
|
||||
RBACEngine.resolveAuthorizedIndicesFromRole(role, SearchAction.NAME, metaData.getAliasAndIndexLookup());
|
||||
assertThat(authorizedIndicesSuperUser, containsInAnyOrder(
|
||||
"an-index", "another-index", SecurityIndexManager.SECURITY_INDEX_NAME, internalSecurityIndex));
|
||||
"an-index", "another-index", RestrictedIndicesNames.SECURITY_MAIN_ALIAS, internalSecurityIndex));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.XPackUser;
|
||||
import org.elasticsearch.xpack.security.authz.store.CompositeRolesStore;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.elasticsearch.xpack.security.test.SecurityTestUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
@ -79,7 +78,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
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.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
|
@ -119,7 +118,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
|
|||
indexNameExpressionResolver = new IndexNameExpressionResolver();
|
||||
|
||||
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()
|
||||
.put(indexBuilder("foo").putAlias(AliasMetaData.builder("foofoobar"))
|
||||
.putAlias(AliasMetaData.builder("foounauthorized")).settings(settings))
|
||||
|
@ -1222,14 +1221,14 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
|
|||
{
|
||||
final List<String> authorizedIndices = buildAuthorizedIndices(XPackSecurityUser.INSTANCE, SearchAction.NAME);
|
||||
List<String> indices = resolveIndices(request, authorizedIndices).getLocal();
|
||||
assertThat(indices, hasItem(SecurityIndexManager.SECURITY_INDEX_NAME));
|
||||
assertThat(indices, hasItem(SECURITY_MAIN_ALIAS));
|
||||
}
|
||||
{
|
||||
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);
|
||||
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();
|
||||
final List<String> authorizedIndices = buildAuthorizedIndices(XPackUser.INSTANCE, SearchAction.NAME);
|
||||
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() {
|
||||
|
@ -1249,7 +1248,7 @@ public class IndicesAndAliasesResolverTests extends ESTestCase {
|
|||
SearchRequest request = new SearchRequest();
|
||||
final List<String> authorizedIndices = buildAuthorizedIndices(allAccessUser, SearchAction.NAME);
|
||||
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("*"));
|
||||
final List<String> authorizedIndices = buildAuthorizedIndices(allAccessUser, IndicesAliasesAction.NAME);
|
||||
List<String> indices = resolveIndices(aliasesRequest, authorizedIndices).getLocal();
|
||||
assertThat(indices, not(hasItem(SecurityIndexManager.SECURITY_INDEX_NAME)));
|
||||
assertThat(indices, not(hasItem(SECURITY_MAIN_ALIAS)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
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.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7;
|
||||
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
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));
|
||||
client = client().filterWithHeader(Collections.singletonMap("Authorization", snapshotUserToken));
|
||||
securityClient().preparePutUser(user, password, Hasher.BCRYPT, "snapshot_user").get();
|
||||
ensureGreen(INTERNAL_SECURITY_INDEX_7);
|
||||
ensureGreen(INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
}
|
||||
|
||||
public void testSnapshotUserRoleCanSnapshotAndSeeAllIndices() {
|
||||
|
@ -67,17 +67,17 @@ public class SnapshotUserRoleIntegTests extends NativeRealmIntegTestCase {
|
|||
assertThat(getRepositoriesResponse.repositories().get(0).name(), is("repo"));
|
||||
// view all indices, including restricted ones
|
||||
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
|
||||
final CreateSnapshotResponse snapshotResponse = client.admin().cluster().prepareCreateSnapshot("repo", "snap")
|
||||
.setIndices(randomFrom("_all", "*")).setWaitForCompletion(true).get();
|
||||
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
|
||||
final GetSnapshotsResponse getSnapshotResponse = client.admin().cluster().prepareGetSnapshots("repo").get();
|
||||
assertThat(getSnapshotResponse.getSnapshots().size(), is(1));
|
||||
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() {
|
||||
|
@ -112,7 +112,7 @@ public class SnapshotUserRoleIntegTests extends NativeRealmIntegTestCase {
|
|||
() -> client.admin().cluster().prepareDeleteSnapshot("repo", randomAlphaOfLength(4).toLowerCase(Locale.ROOT)).get(),
|
||||
"cluster:admin/snapshot/delete", "snapshot_user");
|
||||
// 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.prepareGet(indexToTest, "doc", "1").get(), "indices:data/read/get",
|
||||
"snapshot_user");
|
||||
|
|
|
@ -293,14 +293,14 @@ public class IndicesPermissionTests extends ESTestCase {
|
|||
|
||||
public void testSecurityIndicesPermissions() {
|
||||
final Settings indexSettings = Settings.builder().put("index.version.created", Version.CURRENT).build();
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_INDEX_7);
|
||||
final String internalSecurityIndex = randomFrom(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_6,
|
||||
RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7);
|
||||
final MetaData metaData = new MetaData.Builder()
|
||||
.put(new IndexMetaData.Builder(internalSecurityIndex)
|
||||
.settings(indexSettings)
|
||||
.numberOfShards(1)
|
||||
.numberOfReplicas(0)
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_INDEX_NAME).build())
|
||||
.putAlias(new AliasMetaData.Builder(RestrictedIndicesNames.SECURITY_MAIN_ALIAS).build())
|
||||
.build(), true)
|
||||
.build();
|
||||
FieldPermissionsCache fieldPermissionsCache = new FieldPermissionsCache(Settings.EMPTY);
|
||||
|
@ -309,18 +309,18 @@ public class IndicesPermissionTests extends ESTestCase {
|
|||
// allow_restricted_indices: false
|
||||
IndicesPermission.Group group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, false, "*");
|
||||
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);
|
||||
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
|
||||
group = new IndicesPermission.Group(IndexPrivilege.ALL, new FieldPermissions(), null, true, "*");
|
||||
authzMap = new IndicesPermission(group).authorize(SearchAction.NAME,
|
||||
Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_INDEX_NAME), lookup,
|
||||
Sets.newHashSet(internalSecurityIndex, RestrictedIndicesNames.SECURITY_MAIN_ALIAS), lookup,
|
||||
fieldPermissionsCache);
|
||||
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) {
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.elasticsearch.xpack.security.authc.ApiKeyService.ApiKeyRoleDescriptor
|
|||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -98,7 +99,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||
|
||||
private final FieldPermissionsCache cache = new FieldPermissionsCache(Settings.EMPTY);
|
||||
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 {
|
||||
XPackLicenseState licenseState = mock(XPackLicenseState.class);
|
||||
|
@ -762,7 +763,7 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
@ -837,13 +838,13 @@ public class CompositeRolesStoreTests extends ESTestCase {
|
|||
};
|
||||
|
||||
compositeRolesStore.onSecurityIndexStateChange(
|
||||
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null));
|
||||
new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null));
|
||||
assertEquals(1, numInvalidation.get());
|
||||
|
||||
compositeRolesStore.onSecurityIndexStateChange(
|
||||
new SecurityIndexManager.State(true, true, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(true, false, true, true, null, concreteSecurityIndexName, null));
|
||||
new SecurityIndexManager.State(Instant.now(), true, true, true, null, concreteSecurityIndexName, null),
|
||||
new SecurityIndexManager.State(Instant.now(), false, true, true, null, concreteSecurityIndexName, null));
|
||||
assertEquals(2, numInvalidation.get());
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.elasticsearch.test.client.NoOpClient;
|
|||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
import org.elasticsearch.xpack.core.security.action.role.ClearRolesCacheRequest;
|
||||
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.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
|
@ -125,7 +126,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(requests, iterableWithSize(1));
|
||||
assertThat(requests.get(0), instanceOf(GetRequest.class));
|
||||
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.id(), equalTo("application-privilege_myapp:admin"));
|
||||
|
||||
|
@ -143,7 +144,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(requests, iterableWithSize(1));
|
||||
assertThat(requests.get(0), instanceOf(GetRequest.class));
|
||||
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.id(), equalTo("application-privilege_myapp:admin"));
|
||||
|
||||
|
@ -166,7 +167,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(requests, iterableWithSize(1));
|
||||
assertThat(requests.get(0), instanceOf(SearchRequest.class));
|
||||
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());
|
||||
assertThat(query, containsString("{\"terms\":{\"application\":[\"myapp\",\"yourapp\"]"));
|
||||
|
@ -187,7 +188,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(requests, iterableWithSize(1));
|
||||
assertThat(requests.get(0), instanceOf(SearchRequest.class));
|
||||
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());
|
||||
assertThat(query, containsString("{\"bool\":{\"filter\":[{\"terms\":{\"application\":[\"yourapp\"]"));
|
||||
|
@ -207,7 +208,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(requests, iterableWithSize(1));
|
||||
assertThat(requests.get(0), instanceOf(SearchRequest.class));
|
||||
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());
|
||||
assertThat(query, containsString("{\"exists\":{\"field\":\"application\""));
|
||||
|
@ -232,7 +233,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(requests, iterableWithSize(1));
|
||||
assertThat(requests.get(0), instanceOf(SearchRequest.class));
|
||||
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());
|
||||
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++) {
|
||||
ApplicationPrivilegeDescriptor privilege = putPrivileges.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.id(), equalTo(
|
||||
"application-privilege_" + privilege.getApplication() + ":" + privilege.getName()
|
||||
|
@ -277,7 +278,7 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
assertThat(request.source(), equalTo(BytesReference.bytes(builder)));
|
||||
final boolean created = privilege.getName().equals("user") == false;
|
||||
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
|
||||
));
|
||||
}
|
||||
|
@ -313,12 +314,12 @@ public class NativePrivilegeStoreTests extends ESTestCase {
|
|||
for (int i = 0; i < privilegeNames.size(); i++) {
|
||||
String name = privilegeNames.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.id(), equalTo("application-privilege_app1:" + name));
|
||||
final boolean found = name.equals("p2") == false;
|
||||
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
|
||||
));
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
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.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -187,7 +187,7 @@ public class NativeRolesStoreTests extends ESTestCase {
|
|||
final ClusterService clusterService = mock(ClusterService.class);
|
||||
final XPackLicenseState licenseState = mock(XPackLicenseState.class);
|
||||
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) {
|
||||
@Override
|
||||
void innerPutRole(final PutRoleRequest request, final RoleDescriptor role, final ActionListener<Boolean> listener) {
|
||||
|
@ -247,7 +247,7 @@ public class NativeRolesStoreTests extends ESTestCase {
|
|||
|
||||
private ClusterState getClusterStateWithSecurityIndex() {
|
||||
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()
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
|
||||
|
@ -256,7 +256,7 @@ public class NativeRolesStoreTests extends ESTestCase {
|
|||
.build();
|
||||
MetaData metaData = MetaData.builder()
|
||||
.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(),
|
||||
ImmutableOpenMap.of()))
|
||||
.build();
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.elasticsearch.cluster.ClusterName;
|
|||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlocks;
|
||||
import org.elasticsearch.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
|
@ -52,12 +53,12 @@ import org.elasticsearch.rest.RestStatus;
|
|||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.security.test.SecurityTestUtils;
|
||||
import org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames;
|
||||
import org.elasticsearch.xpack.core.template.TemplateUtils;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_INDEX_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_TEMPLATE_NAME;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7;
|
||||
import static org.elasticsearch.xpack.security.support.SecurityIndexManager.TEMPLATE_VERSION_PATTERN;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
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 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 SecurityIndexManager manager;
|
||||
private Map<Action<?>, Map<ActionRequest, ActionListener<?>>> actions;
|
||||
|
@ -96,13 +96,14 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
actions.put(action, map);
|
||||
}
|
||||
};
|
||||
manager = SecurityIndexManager.buildSecurityIndexManager(client, clusterService);
|
||||
manager = SecurityIndexManager.buildSecurityMainIndexManager(client, clusterService);
|
||||
}
|
||||
|
||||
public void testIndexWithUpToDateMappingAndTemplate() throws IOException {
|
||||
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);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
|
||||
|
@ -114,8 +115,9 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
public void testIndexWithoutPrimaryShards() throws IOException {
|
||||
assertInitialState();
|
||||
|
||||
final ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME);
|
||||
Index index = new Index(INDEX_NAME, UUID.randomUUID().toString());
|
||||
final ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
|
||||
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,
|
||||
RecoverySource.ExistingStoreRecoverySource.INSTANCE, new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, ""));
|
||||
String nodeId = ESTestCase.randomAlphaOfLength(8);
|
||||
|
@ -147,7 +149,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
manager.addIndexStateListener(listener);
|
||||
|
||||
// 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);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
|
||||
|
@ -171,7 +174,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
previousState.set(null);
|
||||
currentState.set(null);
|
||||
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()
|
||||
.add(IndexRoutingTable.builder(prevIndex)
|
||||
.addIndexShard(new IndexShardRoutingTable.Builder(new ShardId(prevIndex, 0))
|
||||
|
@ -231,8 +234,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
prepareException.set(null);
|
||||
prepareRunnableCalled.set(false);
|
||||
// state recovered with index
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME,
|
||||
SecurityIndexManager.INTERNAL_INDEX_FORMAT);
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
|
||||
RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
|
||||
markShardsAvailable(clusterStateBuilder);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
manager.prepareIndexIfNeededThenExecute(ex -> {
|
||||
|
@ -255,8 +258,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
assertThat(manager.isStateRecovered(), is(false));
|
||||
assertThat(listenerCalled.get(), is(false));
|
||||
// state recovered with index
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME,
|
||||
SecurityIndexManager.INTERNAL_INDEX_FORMAT);
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
|
||||
RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
|
||||
markShardsAvailable(clusterStateBuilder);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
assertThat(manager.isStateRecovered(), is(true));
|
||||
|
@ -278,8 +281,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
assertTrue(manager.isIndexUpToDate());
|
||||
|
||||
// index doesn't exist and now exists with wrong format
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(INDEX_NAME, TEMPLATE_NAME,
|
||||
SecurityIndexManager.INTERNAL_INDEX_FORMAT - 1);
|
||||
ClusterState.Builder clusterStateBuilder = createClusterState(RestrictedIndicesNames.INTERNAL_SECURITY_MAIN_INDEX_7,
|
||||
RestrictedIndicesNames.SECURITY_MAIN_ALIAS, TEMPLATE_NAME, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT - 1);
|
||||
markShardsAvailable(clusterStateBuilder);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
assertTrue(listenerCalled.get());
|
||||
|
@ -295,7 +298,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
|
||||
listenerCalled.set(false);
|
||||
// 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);
|
||||
manager.clusterChanged(event(clusterStateBuilder));
|
||||
assertTrue(listenerCalled.get());
|
||||
|
@ -317,18 +321,19 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
assertThat(manager.isStateRecovered(), Matchers.equalTo(true));
|
||||
}
|
||||
|
||||
public static ClusterState.Builder createClusterState(String indexName, String templateName) throws IOException {
|
||||
return createClusterState(indexName, templateName, templateName, SecurityIndexManager.INTERNAL_INDEX_FORMAT);
|
||||
public static ClusterState.Builder createClusterState(String indexName, String aliasName, String templateName) throws IOException {
|
||||
return createClusterState(indexName, aliasName, templateName, templateName, SecurityIndexManager.INTERNAL_MAIN_INDEX_FORMAT);
|
||||
}
|
||||
|
||||
public static ClusterState.Builder createClusterState(String indexName, String templateName, int format) throws IOException {
|
||||
return createClusterState(indexName, templateName, templateName, format);
|
||||
}
|
||||
|
||||
private static ClusterState.Builder createClusterState(String indexName, String templateName, String buildMappingFrom, int format)
|
||||
public static ClusterState.Builder createClusterState(String indexName, String aliasName, String templateName, int format)
|
||||
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);
|
||||
IndexMetaData.Builder indexMeta = getIndexMetadata(indexName, buildMappingFrom, format);
|
||||
IndexMetaData.Builder indexMeta = getIndexMetadata(indexName, aliasName, buildMappingFrom, format);
|
||||
|
||||
MetaData.Builder metaDataBuilder = new MetaData.Builder();
|
||||
metaDataBuilder.put(templateBuilder);
|
||||
|
@ -338,7 +343,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
@ -349,7 +354,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
.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.settings(Settings.builder()
|
||||
.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.INDEX_FORMAT_SETTING.getKey(), format)
|
||||
.build());
|
||||
|
||||
indexMetaData.putAlias(AliasMetaData.builder(aliasName).build());
|
||||
final Map<String, String> mappings = getTemplateMappings(templateName);
|
||||
for (Map.Entry<String, String> entry : mappings.entrySet()) {
|
||||
indexMetaData.putMapping(entry.getKey(), entry.getValue());
|
||||
|
@ -389,7 +395,7 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testMappingVersionMatching() throws IOException {
|
||||
String templateString = "/" + SECURITY_TEMPLATE_NAME + ".json";
|
||||
String templateString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
|
||||
ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(templateString);
|
||||
manager.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
|
||||
assertTrue(manager.checkMappingVersion(Version.CURRENT.minimumIndexCompatibilityVersion()::before));
|
||||
|
@ -397,17 +403,19 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
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);
|
||||
final ClusterState clusterState = clusterStateBuilder.build();
|
||||
IllegalStateException exception = expectThrows(IllegalStateException.class,
|
||||
() -> SecurityIndexManager.checkIndexMappingVersionMatches(SECURITY_INDEX_NAME, clusterState, logger, Version.CURRENT::equals));
|
||||
assertEquals("Cannot read security-version string in index " + SECURITY_INDEX_NAME, exception.getMessage());
|
||||
() -> SecurityIndexManager.checkIndexMappingVersionMatches(RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
|
||||
clusterState, logger, Version.CURRENT::equals));
|
||||
assertEquals("Cannot read security-version string in index " + RestrictedIndicesNames.SECURITY_MAIN_ALIAS,
|
||||
exception.getMessage());
|
||||
}
|
||||
|
||||
public void testIndexTemplateIsIdentifiedAsUpToDate() throws IOException {
|
||||
ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate(
|
||||
"/" + SECURITY_TEMPLATE_NAME + ".json"
|
||||
"/" + SECURITY_MAIN_TEMPLATE_7 + ".json"
|
||||
);
|
||||
manager.clusterChanged(new ClusterChangedEvent("test-event", clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
|
||||
// No upgrade actions run
|
||||
|
@ -415,20 +423,20 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testIndexTemplateVersionMatching() throws Exception {
|
||||
String templateString = "/" + SECURITY_TEMPLATE_NAME + ".json";
|
||||
String templateString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
|
||||
ClusterState.Builder clusterStateBuilder = createClusterStateWithTemplate(templateString);
|
||||
final ClusterState clusterState = clusterStateBuilder.build();
|
||||
|
||||
assertTrue(SecurityIndexManager.checkTemplateExistsAndVersionMatches(
|
||||
SecurityIndexManager.SECURITY_TEMPLATE_NAME, clusterState, logger,
|
||||
SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7, clusterState, logger,
|
||||
Version.V_6_0_0::before));
|
||||
assertFalse(SecurityIndexManager.checkTemplateExistsAndVersionMatches(
|
||||
SecurityIndexManager.SECURITY_TEMPLATE_NAME, clusterState, logger,
|
||||
SecurityIndexManager.SECURITY_MAIN_TEMPLATE_7, clusterState, logger,
|
||||
Version.V_6_0_0::after));
|
||||
}
|
||||
|
||||
public void testUpToDateMappingsAreIdentifiedAsUpToDate() throws IOException {
|
||||
String securityTemplateString = "/" + SECURITY_TEMPLATE_NAME + ".json";
|
||||
String securityTemplateString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
|
||||
ClusterState.Builder clusterStateBuilder = createClusterStateWithMappingAndTemplate(securityTemplateString);
|
||||
manager.clusterChanged(new ClusterChangedEvent("test-event",
|
||||
clusterStateBuilder.build(), EMPTY_CLUSTER_STATE));
|
||||
|
@ -438,8 +446,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
public void testMissingIndexIsIdentifiedAsUpToDate() throws IOException {
|
||||
final ClusterName clusterName = new ClusterName("test-cluster");
|
||||
final ClusterState.Builder clusterStateBuilder = ClusterState.builder(clusterName);
|
||||
String mappingString = "/" + SECURITY_TEMPLATE_NAME + ".json";
|
||||
IndexTemplateMetaData.Builder templateMeta = getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, mappingString);
|
||||
String mappingString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
|
||||
IndexTemplateMetaData.Builder templateMeta = getIndexTemplateMetaData(SECURITY_MAIN_TEMPLATE_7, mappingString);
|
||||
MetaData.Builder builder = new MetaData.Builder(clusterStateBuilder.build().getMetaData());
|
||||
builder.put(templateMeta);
|
||||
clusterStateBuilder.metaData(builder);
|
||||
|
@ -450,24 +458,24 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
|
||||
private ClusterState.Builder createClusterStateWithTemplate(String securityTemplateString) throws IOException {
|
||||
// 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());
|
||||
metaDataBuilder.put(getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityTemplateString));
|
||||
metaDataBuilder.put(getIndexTemplateMetaData(SECURITY_MAIN_TEMPLATE_7, securityTemplateString));
|
||||
return ClusterState.builder(clusterState).metaData(metaDataBuilder);
|
||||
}
|
||||
|
||||
private ClusterState.Builder createClusterStateWithMapping(String securityTemplateString) throws IOException {
|
||||
final ClusterState clusterState = createClusterStateWithIndex(securityTemplateString).build();
|
||||
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));
|
||||
}
|
||||
|
||||
private ClusterState.Builder createClusterStateWithMappingAndTemplate(String securityTemplateString) throws IOException {
|
||||
ClusterState.Builder clusterStateBuilder = createClusterStateWithMapping(securityTemplateString);
|
||||
MetaData.Builder metaDataBuilder = new MetaData.Builder(clusterStateBuilder.build().metaData());
|
||||
String securityMappingString = "/" + SECURITY_TEMPLATE_NAME + ".json";
|
||||
IndexTemplateMetaData.Builder securityTemplateMeta = getIndexTemplateMetaData(SECURITY_TEMPLATE_NAME, securityMappingString);
|
||||
String securityMappingString = "/" + SECURITY_MAIN_TEMPLATE_7 + ".json";
|
||||
IndexTemplateMetaData.Builder securityTemplateMeta = getIndexTemplateMetaData(SECURITY_MAIN_TEMPLATE_7, securityMappingString);
|
||||
metaDataBuilder.put(securityTemplateMeta);
|
||||
return clusterStateBuilder.metaData(metaDataBuilder);
|
||||
}
|
||||
|
@ -493,7 +501,8 @@ public class SecurityIndexManagerTests extends ESTestCase {
|
|||
private ClusterState.Builder createClusterStateWithIndex(String securityTemplate) throws IOException {
|
||||
final MetaData.Builder metaDataBuilder = new MetaData.Builder();
|
||||
final boolean withAlias = randomBoolean();
|
||||
final String securityIndexName = SECURITY_INDEX_NAME + (withAlias ? "-" + randomAlphaOfLength(5) : "");
|
||||
final String securityIndexName = RestrictedIndicesNames.SECURITY_MAIN_ALIAS
|
||||
+ (withAlias ? "-" + randomAlphaOfLength(5) : "");
|
||||
metaDataBuilder.put(createIndexMetadata(securityIndexName, securityTemplate));
|
||||
|
||||
ClusterState.Builder clusterStateBuilder = ClusterState.builder(state());
|
||||
|
|
|
@ -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.TRUNCATE_EXISTING;
|
||||
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 {
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class SecurityTestUtils {
|
|||
* Adds the index alias {@code .security} to the underlying concrete index.
|
||||
*/
|
||||
public static MetaData addAliasToMetaData(MetaData metaData, String indexName) {
|
||||
AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SECURITY_INDEX_NAME).build();
|
||||
AliasMetaData aliasMetaData = AliasMetaData.newAliasMetaDataBuilder(SECURITY_MAIN_ALIAS).build();
|
||||
MetaData.Builder metaDataBuilder = new MetaData.Builder(metaData);
|
||||
IndexMetaData indexMetaData = metaData.index(indexName);
|
||||
metaDataBuilder.put(IndexMetaData.builder(indexMetaData).putAlias(aliasMetaData));
|
||||
|
|
|
@ -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.user.XPackUser;
|
||||
import org.elasticsearch.xpack.security.audit.index.IndexNameResolver;
|
||||
import org.elasticsearch.xpack.security.support.SecurityIndexManager;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
|
@ -32,8 +31,6 @@ public class XPackUserTests extends ESTestCase {
|
|||
public void testXPackUserCannotAccessRestrictedIndices() {
|
||||
final String action = randomFrom(GetAction.NAME, SearchAction.NAME, IndexAction.NAME);
|
||||
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) {
|
||||
assertThat(predicate.test(index), Matchers.is(false));
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
@ -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 }
|
||||
|
|
@ -119,6 +119,8 @@ for (Version version : bwcVersions.wireCompatible) {
|
|||
setting 'xpack.security.enabled', 'true'
|
||||
setting 'xpack.security.transport.ssl.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'
|
||||
if (project.inFipsJvm) {
|
||||
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.security.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) {
|
||||
setting 'xpack.security.transport.ssl.key', 'testnode.pem'
|
||||
setting 'xpack.security.transport.ssl.certificate', 'testnode.crt'
|
||||
|
|
|
@ -16,9 +16,14 @@ import org.elasticsearch.client.RestClient;
|
|||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.test.rest.yaml.ObjectPath;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -27,7 +32,33 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
|
||||
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);
|
||||
{
|
||||
Version minimumIndexCompatibilityVersion = Version.CURRENT.minimumIndexCompatibilityVersion();
|
||||
|
@ -48,188 +79,363 @@ public class TokenBackwardsCompatibilityIT extends AbstractUpgradeTestCase {
|
|||
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
|
||||
// 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);
|
||||
storeTokens(client(), 1, accessToken, refreshToken);
|
||||
|
||||
// In this test either all or none tests or on a specific version:
|
||||
Request indexRequest1 = new Request("PUT", "token_backwards_compatibility_it/_doc/old_cluster_token1");
|
||||
indexRequest1.setJsonEntity(
|
||||
"{\n" +
|
||||
" \"token\": \"" + token + "\"\n" +
|
||||
"}");
|
||||
Response indexResponse1 = client().performRequest(indexRequest1);
|
||||
assertOK(indexResponse1);
|
||||
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);
|
||||
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(), 2, accessToken, refreshToken);
|
||||
}
|
||||
|
||||
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
|
||||
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");
|
||||
Response getResponse = client().performRequest(getRequest);
|
||||
assertOK(getResponse);
|
||||
Map<String, Object> source = (Map<String, Object>) entityAsMap(getResponse).get("_source");
|
||||
assertTokenWorks((String) source.get("token"));
|
||||
}
|
||||
|
||||
public void testInvalidatingTokenInMixedCluster() throws Exception {
|
||||
// Verify that we can invalidate a token in a mixed cluster
|
||||
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");
|
||||
Response getResponse = client().performRequest(getRequest);
|
||||
assertOK(getResponse);
|
||||
Map<String, Object> source = (Map<String, Object>) entityAsMap(getResponse).get("_source");
|
||||
String token = (String) source.get("token");
|
||||
// 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
|
||||
Request invalidateRequest = new Request("DELETE", "/_security/oauth2/token");
|
||||
invalidateRequest.setJsonEntity("{\"token\": \"" + token + "\"}");
|
||||
invalidateRequest.addParameter("error_trace", "true");
|
||||
client().performRequest(invalidateRequest);
|
||||
assertTokenDoesNotWork(token);
|
||||
}
|
||||
|
||||
public void testMixedClusterWithUpgradedMaster() 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);
|
||||
for (int tokenIdx : Arrays.asList(1, 3, 4)) { // 2 is invalidated in another mixed-cluster test, 5 is invalidated in the old cluster
|
||||
Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
|
||||
assertAccessTokenWorks((String) source.get("token"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpgradedCluster() throws Exception {
|
||||
public void testTokensStayInvalidatedInMixedCluster() throws Exception {
|
||||
// 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);
|
||||
Map<String, Object> source = retrieveStoredTokens(client(), 5);
|
||||
assertAccessTokenDoesNotWork((String) source.get("token"));
|
||||
assertRefreshTokenInvalidated((String) source.get("refresh_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
|
||||
// we don't try to assert it works before invalidating. This case is handled by testTokenWorksInMixedCluster
|
||||
invalidateAccessToken(client(), accessToken);
|
||||
assertAccessTokenDoesNotWork(accessToken);
|
||||
// invalidate refresh token
|
||||
invalidateRefreshToken(client(), refreshToken);
|
||||
assertRefreshTokenInvalidated(refreshToken);
|
||||
}
|
||||
|
||||
public void testTokensStayInvalidatedInUpgradedCluster() throws Exception {
|
||||
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
|
||||
Request getRequest = new Request("GET", "token_backwards_compatibility_it/_doc/old_cluster_token1");
|
||||
Response getResponse = client().performRequest(getRequest);
|
||||
assertOK(getResponse);
|
||||
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);
|
||||
for (int tokenIdx : Arrays.asList(2, 5)) {
|
||||
Map<String, Object> source = retrieveStoredTokens(client(), tokenIdx);
|
||||
assertAccessTokenDoesNotWork((String) source.get("token"));
|
||||
assertRefreshTokenInvalidated((String) source.get("refresh_token"));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertTokenWorks(String token) throws IOException {
|
||||
Request request = new Request("GET", "/_security/_authenticate");
|
||||
RequestOptions.Builder options = request.getOptions().toBuilder();
|
||||
options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
|
||||
request.setOptions(options);
|
||||
Response authenticateResponse = client().performRequest(request);
|
||||
assertOK(authenticateResponse);
|
||||
assertEquals("test_user", entityAsMap(authenticateResponse).get("username"));
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertTokenDoesNotWork(String token) {
|
||||
Request request = new Request("GET", "/_security/_authenticate");
|
||||
RequestOptions.Builder options = request.getOptions().toBuilder();
|
||||
options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
|
||||
request.setOptions(options);
|
||||
ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest(request));
|
||||
assertEquals(401, e.getResponse().getStatusLine().getStatusCode());
|
||||
Response response = e.getResponse();
|
||||
assertEquals("Bearer realm=\"security\", error=\"invalid_token\", error_description=\"The access token expired\"",
|
||||
response.getHeader("WWW-Authenticate"));
|
||||
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);
|
||||
}
|
||||
|
||||
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")));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
private RestClient getRestClientForCurrentVersionNodesOnly() throws IOException {
|
||||
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");
|
||||
RequestOptions.Builder options = request.getOptions().toBuilder();
|
||||
options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
|
||||
request.setOptions(options);
|
||||
Response authenticateResponse = client.performRequest(request);
|
||||
assertOK(authenticateResponse);
|
||||
assertEquals("test_user", entityAsMap(authenticateResponse).get("username"));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertAccessTokenDoesNotWork(String token) throws IOException {
|
||||
for (RestClient client : twoClients) {
|
||||
Request request = new Request("GET", "/_security/_authenticate");
|
||||
RequestOptions.Builder options = request.getOptions().toBuilder();
|
||||
options.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
|
||||
request.setOptions(options);
|
||||
ResponseException e = expectThrows(ResponseException.class, () -> client.performRequest(request));
|
||||
assertEquals(401, e.getResponse().getStatusLine().getStatusCode());
|
||||
Response response = e.getResponse();
|
||||
assertEquals("Bearer realm=\"security\", error=\"invalid_token\", error_description=\"The access token expired\"",
|
||||
response.getHeader("WWW-Authenticate"));
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
assertOK(response);
|
||||
ObjectPath objectPath = ObjectPath.createFromResponse(response);
|
||||
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()) {
|
||||
Map<String, Object> nodeDetails = (Map<String, Object>) entry.getValue();
|
||||
Version version = Version.fromString((String) nodeDetails.get("version"));
|
||||
if (Version.CURRENT.equals(version)) {
|
||||
Map<String, Object> httpInfo = (Map<String, Object>) nodeDetails.get("http");
|
||||
hosts.add(HttpHost.create((String) httpInfo.get("publish_address")));
|
||||
}
|
||||
Map<String, Object> httpInfo = (Map<String, Object>) nodeDetails.get("http");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
get:
|
||||
index: token_index
|
||||
type: doc
|
||||
id: "6"
|
||||
|
||||
- match: { _index: token_index }
|
||||
- match: { _type: doc }
|
||||
- match: { _type: _doc }
|
||||
- match: { _id: "6" }
|
||||
- is_true: _source.token
|
||||
- set: { _source.token : token }
|
||||
|
@ -24,6 +27,59 @@
|
|||
- match: { roles.0: "superuser" }
|
||||
- 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:
|
||||
headers:
|
||||
Authorization: Bearer ${token}
|
||||
|
@ -31,7 +87,7 @@
|
|||
rest_total_hits_as_int: true
|
||||
index: token_index
|
||||
|
||||
- match: { hits.total: 6 }
|
||||
- match: { hits.total: 8 }
|
||||
|
||||
- do:
|
||||
headers:
|
||||
|
@ -40,7 +96,7 @@
|
|||
rest_total_hits_as_int: true
|
||||
index: token_index
|
||||
|
||||
- match: { hits.total: 6 }
|
||||
- match: { hits.total: 8 }
|
||||
|
||||
- do:
|
||||
headers:
|
||||
|
@ -49,5 +105,79 @@
|
|||
rest_total_hits_as_int: true
|
||||
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}"}
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
- match: { type: "Bearer" }
|
||||
- is_true: access_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
|
||||
|
||||
- do:
|
||||
|
@ -54,15 +56,15 @@
|
|||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "1"}}'
|
||||
- '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "1"}}'
|
||||
- '{"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}'
|
||||
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "3"}}'
|
||||
- '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "3"}}'
|
||||
- '{"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}'
|
||||
- '{"index": {"_index": "token_index", "_type": "doc", "_id" : "5"}}'
|
||||
- '{"index": {"_index": "token_index", "_type": "_doc", "_id" : "5"}}'
|
||||
- '{"f1": "v5_old", "f2": 4}'
|
||||
|
||||
- do:
|
||||
|
@ -81,6 +83,48 @@
|
|||
Authorization: Bearer ${token}
|
||||
index:
|
||||
index: token_index
|
||||
type: doc
|
||||
id: "6"
|
||||
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}"}
|
||||
|
|
|
@ -2,14 +2,18 @@
|
|||
"Get the indexed token and use if to authenticate":
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
get:
|
||||
index: token_index
|
||||
type: doc
|
||||
id: "6"
|
||||
|
||||
- match: { _index: token_index }
|
||||
- match: { _type: doc }
|
||||
- match: { _type: _doc }
|
||||
- match: { _id: "6" }
|
||||
- is_true: _source.token
|
||||
- set: { _source.token : token }
|
||||
|
@ -30,7 +34,7 @@
|
|||
rest_total_hits_as_int: true
|
||||
index: token_index
|
||||
|
||||
- match: { hits.total: 6 }
|
||||
- match: { hits.total: 8 }
|
||||
|
||||
# counter example that we are really checking this
|
||||
- do:
|
||||
|
@ -40,3 +44,51 @@
|
|||
search:
|
||||
rest_total_hits_as_int: true
|
||||
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 }
|
||||
|
|
|
@ -199,7 +199,7 @@ public abstract class AbstractAdLdapRealmTestCase extends SecurityIntegTestCase
|
|||
@Override
|
||||
public Set<String> 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue