Skip to content

Commit 2154a97

Browse files
Amend prepareIndexIfNeededThenExecute for token refresh (#41697)
This fixes a low level bug that manifests, in certain circumstances, by the failure of the refresh operation. Version 7.1 added a new `superseded_by` field to the `.security` index mapping. This field is used when indexing a refresh operation (a document update). Because the document update was not guarded by the obligatory `prepareIndexIfNeededThenExecute` the refresh operation would fail if it were the first operation when the cluster was upgraded from a version < 7.1 . This failure was catched (and fails reliably) in the backport #41673 .
1 parent 8e04f36 commit 2154a97

File tree

1 file changed

+16
-13
lines changed
  • x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc

1 file changed

+16
-13
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/TokenService.java

+16-13
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,12 @@ private void getUserTokenFromId(String userTokenId, Version tokenVersion, Action
347347
logger.warn("failed to get access token [{}] because index [{}] is not available", userTokenId, tokensIndex.aliasName());
348348
listener.onResponse(null);
349349
} else {
350+
final GetRequest getRequest = client.prepareGet(tokensIndex.aliasName(), SINGLE_MAPPING_NAME,
351+
getTokenDocumentId(userTokenId)).request();
352+
final Consumer<Exception> onFailure = ex -> listener.onFailure(traceLog("decode token", userTokenId, ex));
350353
tokensIndex.checkIndexVersionThenExecute(
351354
ex -> listener.onFailure(traceLog("prepare tokens index [" + tokensIndex.aliasName() +"]", userTokenId, ex)),
352-
() -> {
353-
final GetRequest getRequest = client.prepareGet(tokensIndex.aliasName(), SINGLE_MAPPING_NAME,
354-
getTokenDocumentId(userTokenId)).request();
355-
Consumer<Exception> onFailure = ex -> listener.onFailure(traceLog("decode token", userTokenId, ex));
356-
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest,
355+
() -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest,
357356
ActionListener.<GetResponse>wrap(response -> {
358357
if (response.isExists()) {
359358
Map<String, Object> accessTokenSource =
@@ -384,8 +383,8 @@ private void getUserTokenFromId(String userTokenId, Version tokenVersion, Action
384383
logger.error(new ParameterizedMessage("failed to get access token [{}]", userTokenId), e);
385384
listener.onFailure(e);
386385
}
387-
}), client::get);
388-
});
386+
}), client::get)
387+
);
389388
}
390389
}
391390

@@ -862,7 +861,9 @@ private void innerRefresh(String tokenDocId, Map<String, Object> source, long se
862861
.setRefreshPolicy(RefreshPolicy.IMMEDIATE)
863862
.setIfSeqNo(seqNo)
864863
.setIfPrimaryTerm(primaryTerm);
865-
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, updateRequest.request(),
864+
refreshedTokenIndex.prepareIndexIfNeededThenExecute(
865+
ex -> listener.onFailure(traceLog("prepare index [" + refreshedTokenIndex.aliasName() + "]", ex)),
866+
() -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, updateRequest.request(),
866867
ActionListener.<UpdateResponse>wrap(updateResponse -> {
867868
if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {
868869
logger.debug(() -> new ParameterizedMessage("updated the original token document to {}",
@@ -931,7 +932,7 @@ public void onFailure(Exception e) {
931932
} else {
932933
onFailure.accept(e);
933934
}
934-
}), client::update);
935+
}), client::update));
935936
}
936937
}
937938

@@ -1005,7 +1006,9 @@ private void getSupersedingTokenDocAsync(RefreshTokenStatus refreshTokenStatus,
10051006

10061007
private void getTokenDocAsync(String tokenDocId, SecurityIndexManager tokensIndex, ActionListener<GetResponse> listener) {
10071008
final GetRequest getRequest = client.prepareGet(tokensIndex.aliasName(), SINGLE_MAPPING_NAME, tokenDocId).request();
1008-
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest, listener, client::get);
1009+
tokensIndex.checkIndexVersionThenExecute(
1010+
ex -> listener.onFailure(traceLog("prepare tokens index [" + tokensIndex.aliasName() + "]", tokenDocId, ex)),
1011+
() -> executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest, listener, client::get));
10091012
}
10101013

10111014
private Version getTokenVersionCompatibility() {
@@ -1392,10 +1395,10 @@ private void checkIfTokenIsValid(UserToken userToken, ActionListener<UserToken>
13921395
logger.warn("failed to validate access token because the index [" + tokensIndex.aliasName() + "] doesn't exist");
13931396
listener.onResponse(null);
13941397
} else {
1398+
final GetRequest getRequest = client
1399+
.prepareGet(tokensIndex.aliasName(), SINGLE_MAPPING_NAME, getTokenDocumentId(userToken)).request();
1400+
Consumer<Exception> onFailure = ex -> listener.onFailure(traceLog("check token state", userToken.getId(), ex));
13951401
tokensIndex.checkIndexVersionThenExecute(listener::onFailure, () -> {
1396-
final GetRequest getRequest = client
1397-
.prepareGet(tokensIndex.aliasName(), SINGLE_MAPPING_NAME, getTokenDocumentId(userToken)).request();
1398-
Consumer<Exception> onFailure = ex -> listener.onFailure(traceLog("check token state", userToken.getId(), ex));
13991402
executeAsyncWithOrigin(client.threadPool().getThreadContext(), SECURITY_ORIGIN, getRequest,
14001403
ActionListener.<GetResponse>wrap(response -> {
14011404
if (response.isExists()) {

0 commit comments

Comments
 (0)