Skip to content

Commit 5e953dc

Browse files
authored
Fix NPE on disabled API key auth cache (#120483)
Currently, when `xpack.security.authc.api_key.cache.ttl` is set to `0d` API key creation (and invalidation) fail with NPEs. This PR adds null checks to fix this.
1 parent 7322015 commit 5e953dc

File tree

3 files changed

+60
-5
lines changed

3 files changed

+60
-5
lines changed

docs/changelog/120483.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 120483
2+
summary: Fix NPE on disabled API auth key cache
3+
area: Authentication
4+
type: bug
5+
issues: []

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,19 @@ public void invalidate(Collection<String> keys) {
266266
if (apiKeyDocCache != null) {
267267
apiKeyDocCache.invalidate(keys);
268268
}
269-
keys.forEach(apiKeyAuthCache::invalidate);
269+
if (apiKeyAuthCache != null) {
270+
keys.forEach(apiKeyAuthCache::invalidate);
271+
}
270272
}
271273

272274
@Override
273275
public void invalidateAll() {
274276
if (apiKeyDocCache != null) {
275277
apiKeyDocCache.invalidateAll();
276278
}
277-
apiKeyAuthCache.invalidateAll();
279+
if (apiKeyAuthCache != null) {
280+
apiKeyAuthCache.invalidateAll();
281+
}
278282
}
279283
});
280284
cacheInvalidatorRegistry.registerCacheInvalidator("api_key_doc", new CacheInvalidatorRegistry.CacheInvalidator() {
@@ -589,9 +593,11 @@ private void createApiKeyAndIndexIt(
589593
+ "])";
590594
assert indexResponse.getResult() == DocWriteResponse.Result.CREATED
591595
: "Index response was [" + indexResponse.getResult() + "]";
592-
final ListenableFuture<CachedApiKeyHashResult> listenableFuture = new ListenableFuture<>();
593-
listenableFuture.onResponse(new CachedApiKeyHashResult(true, apiKey));
594-
apiKeyAuthCache.put(request.getId(), listenableFuture);
596+
if (apiKeyAuthCache != null) {
597+
final ListenableFuture<CachedApiKeyHashResult> listenableFuture = new ListenableFuture<>();
598+
listenableFuture.onResponse(new CachedApiKeyHashResult(true, apiKey));
599+
apiKeyAuthCache.put(request.getId(), listenableFuture);
600+
}
595601
listener.onResponse(new CreateApiKeyResponse(request.getName(), request.getId(), apiKey, expiration));
596602
}, listener::onFailure))
597603
)

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyServiceTests.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,6 +2367,50 @@ public void testWillInvalidateAuthCacheWhenDocNotFound() {
23672367
assertNull(service.getApiKeyAuthCache().get(docId));
23682368
}
23692369

2370+
public void testCanCreateApiKeyWithAuthCacheDisabled() {
2371+
final ApiKeyService service = createApiKeyService(
2372+
Settings.builder()
2373+
.put(XPackSettings.API_KEY_SERVICE_ENABLED_SETTING.getKey(), true)
2374+
.put("xpack.security.authc.api_key.cache.ttl", "0s")
2375+
.build()
2376+
);
2377+
final Authentication authentication = AuthenticationTestHelper.builder()
2378+
.user(new User(randomAlphaOfLengthBetween(8, 16), "superuser"))
2379+
.realmRef(new RealmRef(randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8)))
2380+
.build(false);
2381+
final CreateApiKeyRequest createApiKeyRequest = new CreateApiKeyRequest(randomAlphaOfLengthBetween(3, 8), null, null);
2382+
when(client.prepareIndex(anyString())).thenReturn(new IndexRequestBuilder(client));
2383+
when(client.prepareBulk()).thenReturn(new BulkRequestBuilder(client));
2384+
when(client.threadPool()).thenReturn(threadPool);
2385+
doAnswer(inv -> {
2386+
final Object[] args = inv.getArguments();
2387+
@SuppressWarnings("unchecked")
2388+
final ActionListener<BulkResponse> listener = (ActionListener<BulkResponse>) args[2];
2389+
final IndexResponse indexResponse = new IndexResponse(
2390+
new ShardId(INTERNAL_SECURITY_MAIN_INDEX_7, randomAlphaOfLength(22), randomIntBetween(0, 1)),
2391+
createApiKeyRequest.getId(),
2392+
randomLongBetween(1, 99),
2393+
randomLongBetween(1, 99),
2394+
randomIntBetween(1, 99),
2395+
true
2396+
);
2397+
listener.onResponse(
2398+
new BulkResponse(
2399+
new BulkItemResponse[] { BulkItemResponse.success(randomInt(), DocWriteRequest.OpType.INDEX, indexResponse) },
2400+
randomLongBetween(0, 100)
2401+
)
2402+
);
2403+
return null;
2404+
}).when(client).execute(eq(TransportBulkAction.TYPE), any(BulkRequest.class), any());
2405+
2406+
assertThat(service.getFromCache(createApiKeyRequest.getId()), is(nullValue()));
2407+
final PlainActionFuture<CreateApiKeyResponse> listener = new PlainActionFuture<>();
2408+
service.createApiKey(authentication, createApiKeyRequest, Set.of(), listener);
2409+
final CreateApiKeyResponse createApiKeyResponse = listener.actionGet();
2410+
assertThat(createApiKeyResponse.getId(), equalTo(createApiKeyRequest.getId()));
2411+
assertThat(service.getFromCache(createApiKeyResponse.getId()), is(nullValue()));
2412+
}
2413+
23702414
public void testGetCreatorRealm() {
23712415
final User user = AuthenticationTests.randomUser();
23722416

0 commit comments

Comments
 (0)