|
10 | 10 | import org.elasticsearch.ElasticsearchException; |
11 | 11 | import org.elasticsearch.Version; |
12 | 12 | import org.elasticsearch.action.ActionListener; |
| 13 | +import org.elasticsearch.action.DocWriteRequest; |
13 | 14 | import org.elasticsearch.action.bulk.BulkAction; |
| 15 | +import org.elasticsearch.action.bulk.BulkItemResponse; |
14 | 16 | import org.elasticsearch.action.bulk.BulkRequest; |
| 17 | +import org.elasticsearch.action.bulk.BulkResponse; |
15 | 18 | import org.elasticsearch.action.get.GetRequest; |
16 | 19 | import org.elasticsearch.action.index.IndexAction; |
17 | 20 | import org.elasticsearch.action.index.IndexRequest; |
18 | 21 | import org.elasticsearch.action.index.IndexRequestBuilder; |
| 22 | +import org.elasticsearch.action.index.IndexResponse; |
19 | 23 | import org.elasticsearch.action.support.PlainActionFuture; |
20 | 24 | import org.elasticsearch.client.Client; |
21 | 25 | import org.elasticsearch.common.bytes.BytesArray; |
22 | 26 | import org.elasticsearch.common.bytes.BytesReference; |
| 27 | +import org.elasticsearch.common.cache.Cache; |
23 | 28 | import org.elasticsearch.common.util.concurrent.ListenableFuture; |
24 | 29 | import org.elasticsearch.core.Tuple; |
25 | 30 | import org.elasticsearch.common.settings.SecureString; |
|
36 | 41 | import org.elasticsearch.common.xcontent.XContentType; |
37 | 42 | import org.elasticsearch.common.xcontent.json.JsonXContent; |
38 | 43 | import org.elasticsearch.index.get.GetResult; |
| 44 | +import org.elasticsearch.index.shard.ShardId; |
39 | 45 | import org.elasticsearch.license.XPackLicenseState; |
40 | 46 | import org.elasticsearch.test.ClusterServiceUtils; |
41 | 47 | import org.elasticsearch.test.ESTestCase; |
|
48 | 54 | import org.elasticsearch.xpack.core.security.SecurityContext; |
49 | 55 | import org.elasticsearch.xpack.core.security.action.ApiKeyTests; |
50 | 56 | import org.elasticsearch.xpack.core.security.action.CreateApiKeyRequest; |
| 57 | +import org.elasticsearch.xpack.core.security.action.CreateApiKeyResponse; |
51 | 58 | import org.elasticsearch.xpack.core.security.authc.Authentication; |
52 | 59 | import org.elasticsearch.xpack.core.security.authc.Authentication.AuthenticationType; |
53 | 60 | import org.elasticsearch.xpack.core.security.authc.Authentication.RealmRef; |
@@ -177,6 +184,40 @@ public void testCreateApiKeyUsesBulkIndexAction() { |
177 | 184 | service.createApiKey(authentication, createApiKeyRequest, Set.of(), new PlainActionFuture<>()); |
178 | 185 | } |
179 | 186 |
|
| 187 | + public void testCreateApiKeyWillCacheOnCreation() { |
| 188 | + final Settings settings = Settings.builder().put(XPackSettings.API_KEY_SERVICE_ENABLED_SETTING.getKey(), true).build(); |
| 189 | + final ApiKeyService service = createApiKeyService(settings); |
| 190 | + final Authentication authentication = new Authentication( |
| 191 | + new User(randomAlphaOfLengthBetween(8, 16), "superuser"), |
| 192 | + new RealmRef(randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8), randomAlphaOfLengthBetween(3, 8)), |
| 193 | + null); |
| 194 | + final CreateApiKeyRequest createApiKeyRequest = new CreateApiKeyRequest(randomAlphaOfLengthBetween(3, 8), null, null); |
| 195 | + when(client.prepareIndex(anyString())).thenReturn(new IndexRequestBuilder(client, IndexAction.INSTANCE)); |
| 196 | + when(client.threadPool()).thenReturn(threadPool); |
| 197 | + doAnswer(inv -> { |
| 198 | + final Object[] args = inv.getArguments(); |
| 199 | + @SuppressWarnings("unchecked") |
| 200 | + final ActionListener<BulkResponse> listener = (ActionListener<BulkResponse>) args[2]; |
| 201 | + final IndexResponse indexResponse = new IndexResponse( |
| 202 | + new ShardId(INTERNAL_SECURITY_MAIN_INDEX_7, randomAlphaOfLength(22), randomIntBetween(0, 1)), |
| 203 | + createApiKeyRequest.getId(), randomLongBetween(1, 99), randomLongBetween(1, 99), randomIntBetween(1, 99), true); |
| 204 | + listener.onResponse(new BulkResponse(new BulkItemResponse[]{ |
| 205 | + new BulkItemResponse(randomInt(), DocWriteRequest.OpType.INDEX, indexResponse) |
| 206 | + }, randomLongBetween(0, 100))); |
| 207 | + return null; |
| 208 | + }).when(client).execute(eq(BulkAction.INSTANCE), any(BulkRequest.class), any()); |
| 209 | + |
| 210 | + final Cache<String, ListenableFuture<CachedApiKeyHashResult>> apiKeyAuthCache = service.getApiKeyAuthCache(); |
| 211 | + assertNull(apiKeyAuthCache.get(createApiKeyRequest.getId())); |
| 212 | + final PlainActionFuture<CreateApiKeyResponse> listener = new PlainActionFuture<>(); |
| 213 | + service.createApiKey(authentication, createApiKeyRequest, Set.of(), listener); |
| 214 | + final CreateApiKeyResponse createApiKeyResponse = listener.actionGet(); |
| 215 | + assertThat(createApiKeyResponse.getId(), equalTo(createApiKeyRequest.getId())); |
| 216 | + final CachedApiKeyHashResult cachedApiKeyHashResult = service.getFromCache(createApiKeyResponse.getId()); |
| 217 | + assertThat(cachedApiKeyHashResult.success, is(true)); |
| 218 | + cachedApiKeyHashResult.verify(createApiKeyResponse.getKey()); |
| 219 | + } |
| 220 | + |
180 | 221 | public void testGetCredentialsFromThreadContext() { |
181 | 222 | ThreadContext threadContext = threadPool.getThreadContext(); |
182 | 223 | assertNull(ApiKeyService.getCredentialsFromHeader(threadContext)); |
|
0 commit comments