mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-01 16:39:11 +00:00
Test: update TokenAuthIntegTests to modify document to test expiration
This change modifies how we test the deletion of expired documents to be in line with elastic/x-pack-elasticsearch#3468 and also adds debugging output in case the failures in CI continue. Relates elastic/x-pack-elasticsearch#2253 Original commit: elastic/x-pack-elasticsearch@979b5357f5
This commit is contained in:
parent
0a8e4da3bd
commit
858178602e
@ -6,7 +6,9 @@
|
|||||||
package org.elasticsearch.xpack.security.authc;
|
package org.elasticsearch.xpack.security.authc;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.bulk.BulkItemResponse;
|
||||||
import org.elasticsearch.action.search.SearchRequest;
|
import org.elasticsearch.action.search.SearchRequest;
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.common.logging.Loggers;
|
import org.elasticsearch.common.logging.Loggers;
|
||||||
@ -14,8 +16,10 @@ import org.elasticsearch.common.settings.Settings;
|
|||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
|
||||||
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
|
import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
||||||
import org.elasticsearch.index.reindex.DeleteByQueryAction;
|
import org.elasticsearch.index.reindex.DeleteByQueryAction;
|
||||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||||
|
import org.elasticsearch.index.reindex.ScrollableHitSource;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.threadpool.ThreadPool.Names;
|
import org.elasticsearch.threadpool.ThreadPool.Names;
|
||||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||||
@ -56,8 +60,10 @@ final class ExpiredTokenRemover extends AbstractRunnable {
|
|||||||
.filter(QueryBuilders.termQuery("doc_type", TokenService.DOC_TYPE))
|
.filter(QueryBuilders.termQuery("doc_type", TokenService.DOC_TYPE))
|
||||||
.filter(QueryBuilders.rangeQuery("expiration_time").lte(Instant.now().toEpochMilli())));
|
.filter(QueryBuilders.rangeQuery("expiration_time").lte(Instant.now().toEpochMilli())));
|
||||||
executeAsyncWithOrigin(client, SECURITY_ORIGIN, DeleteByQueryAction.INSTANCE, dbq,
|
executeAsyncWithOrigin(client, SECURITY_ORIGIN, DeleteByQueryAction.INSTANCE, dbq,
|
||||||
ActionListener.wrap(r -> markComplete(),
|
ActionListener.wrap(r -> {
|
||||||
e -> {
|
debugDbqResponse(r);
|
||||||
|
markComplete();
|
||||||
|
}, e -> {
|
||||||
if (isShardNotAvailableException(e) == false) {
|
if (isShardNotAvailableException(e) == false) {
|
||||||
logger.error("failed to delete expired tokens", e);
|
logger.error("failed to delete expired tokens", e);
|
||||||
}
|
}
|
||||||
@ -71,6 +77,21 @@ final class ExpiredTokenRemover extends AbstractRunnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void debugDbqResponse(BulkByScrollResponse response) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("delete by query of tokens finished with [{}] deletions, [{}] bulk failures, [{}] search failures",
|
||||||
|
response.getDeleted(), response.getBulkFailures().size(), response.getSearchFailures().size());
|
||||||
|
for (BulkItemResponse.Failure failure : response.getBulkFailures()) {
|
||||||
|
logger.debug(new ParameterizedMessage("deletion failed for index [{}], type [{}], id [{}]",
|
||||||
|
failure.getIndex(), failure.getType(), failure.getId()), failure.getCause());
|
||||||
|
}
|
||||||
|
for (ScrollableHitSource.SearchFailure failure : response.getSearchFailures()) {
|
||||||
|
logger.debug(new ParameterizedMessage("search failed for index [{}], shard [{}] on node [{}]",
|
||||||
|
failure.getIndex(), failure.getShardId(), failure.getNodeId()), failure.getReason());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean isExpirationInProgress() {
|
boolean isExpirationInProgress() {
|
||||||
return inProgress.get();
|
return inProgress.get();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import org.elasticsearch.ElasticsearchSecurityException;
|
|||||||
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
|
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
|
||||||
import org.elasticsearch.action.search.SearchResponse;
|
import org.elasticsearch.action.search.SearchResponse;
|
||||||
import org.elasticsearch.action.support.PlainActionFuture;
|
import org.elasticsearch.action.support.PlainActionFuture;
|
||||||
|
import org.elasticsearch.action.support.WriteRequest;
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
||||||
import org.elasticsearch.common.settings.SecureString;
|
import org.elasticsearch.common.settings.SecureString;
|
||||||
@ -18,6 +19,7 @@ import org.elasticsearch.index.query.QueryBuilders;
|
|||||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||||
import org.elasticsearch.test.SecuritySettingsSource;
|
import org.elasticsearch.test.SecuritySettingsSource;
|
||||||
|
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||||
import org.elasticsearch.xpack.XPackSettings;
|
import org.elasticsearch.xpack.XPackSettings;
|
||||||
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
import org.elasticsearch.xpack.security.SecurityLifecycleService;
|
||||||
import org.elasticsearch.xpack.security.action.token.CreateTokenResponse;
|
import org.elasticsearch.xpack.security.action.token.CreateTokenResponse;
|
||||||
@ -30,9 +32,11 @@ import org.junit.Before;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.greaterThan;
|
import static org.hamcrest.Matchers.greaterThan;
|
||||||
@ -43,8 +47,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||||||
public Settings nodeSettings(int nodeOrdinal) {
|
public Settings nodeSettings(int nodeOrdinal) {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(super.nodeSettings(nodeOrdinal))
|
.put(super.nodeSettings(nodeOrdinal))
|
||||||
// turn down token expiration interval and crank up the deletion interval
|
// crank up the deletion interval and set timeout for delete requests
|
||||||
.put(TokenService.TOKEN_EXPIRATION.getKey(), TimeValue.timeValueSeconds(1L))
|
|
||||||
.put(TokenService.DELETE_INTERVAL.getKey(), TimeValue.timeValueSeconds(1L))
|
.put(TokenService.DELETE_INTERVAL.getKey(), TimeValue.timeValueSeconds(1L))
|
||||||
.put(TokenService.DELETE_TIMEOUT.getKey(), TimeValue.timeValueSeconds(2L))
|
.put(TokenService.DELETE_TIMEOUT.getKey(), TimeValue.timeValueSeconds(2L))
|
||||||
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true)
|
.put(XPackSettings.TOKEN_SERVICE_ENABLED_SETTING.getKey(), true)
|
||||||
@ -117,6 +120,7 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestLogging("org.elasticsearch.xpack.security.authc:DEBUG")
|
||||||
public void testExpiredTokensDeletedAfterExpiration() throws Exception {
|
public void testExpiredTokensDeletedAfterExpiration() throws Exception {
|
||||||
final Client client = client().filterWithHeader(Collections.singletonMap("Authorization",
|
final Client client = client().filterWithHeader(Collections.singletonMap("Authorization",
|
||||||
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER,
|
UsernamePasswordToken.basicAuthHeaderValue(SecuritySettingsSource.TEST_SUPERUSER,
|
||||||
@ -132,15 +136,25 @@ public class TokenAuthIntegTests extends SecurityIntegTestCase {
|
|||||||
|
|
||||||
InvalidateTokenResponse invalidateResponse = securityClient.prepareInvalidateToken(response.getTokenString()).get();
|
InvalidateTokenResponse invalidateResponse = securityClient.prepareInvalidateToken(response.getTokenString()).get();
|
||||||
assertTrue(invalidateResponse.isCreated());
|
assertTrue(invalidateResponse.isCreated());
|
||||||
|
AtomicReference<String> docId = new AtomicReference<>();
|
||||||
assertBusy(() -> {
|
assertBusy(() -> {
|
||||||
SearchResponse searchResponse = client.prepareSearch(SecurityLifecycleService.SECURITY_INDEX_NAME)
|
SearchResponse searchResponse = client.prepareSearch(SecurityLifecycleService.SECURITY_INDEX_NAME)
|
||||||
.setSource(SearchSourceBuilder.searchSource().query(QueryBuilders.termQuery("doc_type", TokenService.DOC_TYPE)))
|
.setSource(SearchSourceBuilder.searchSource().query(QueryBuilders.termQuery("doc_type", TokenService.DOC_TYPE)))
|
||||||
.setSize(0)
|
.setSize(1)
|
||||||
.setTerminateAfter(1)
|
.setTerminateAfter(1)
|
||||||
.get();
|
.get();
|
||||||
assertThat(searchResponse.getHits().getTotalHits(), greaterThan(0L));
|
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
|
||||||
|
docId.set(searchResponse.getHits().getAt(0).getId());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// hack doc to modify the time to the day before
|
||||||
|
Instant dayBefore = created.minus(1L, ChronoUnit.DAYS);
|
||||||
|
assertTrue(Instant.now().isAfter(dayBefore));
|
||||||
|
client.prepareUpdate(SecurityLifecycleService.SECURITY_INDEX_NAME, "doc", docId.get())
|
||||||
|
.setDoc("expiration_time", dayBefore.toEpochMilli())
|
||||||
|
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
||||||
|
.get();
|
||||||
|
|
||||||
AtomicBoolean deleteTriggered = new AtomicBoolean(false);
|
AtomicBoolean deleteTriggered = new AtomicBoolean(false);
|
||||||
assertBusy(() -> {
|
assertBusy(() -> {
|
||||||
assertTrue(Instant.now().isAfter(created.plusSeconds(1L).plusMillis(500L)));
|
assertTrue(Instant.now().isAfter(created.plusSeconds(1L).plusMillis(500L)));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user