diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/apikey/GetApiKeyRequestTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/apikey/GetApiKeyRequestTests.java index 87b64a419a25f..9e99ac6f1d4ff 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/apikey/GetApiKeyRequestTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/security/action/apikey/GetApiKeyRequestTests.java @@ -93,6 +93,8 @@ public void writeTo(StreamOutput out) throws IOException { String[][] inputs = new String[][] { { randomNullOrEmptyString(), "user", "api-kid", "api-kname", "false", "true" }, { "realm", randomNullOrEmptyString(), "api-kid", "api-kname", "false", "true" }, + { randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), "api-kname", "false", "true" }, + { randomNullOrEmptyString(), randomNullOrEmptyString(), "api-kid", randomNullOrEmptyString(), "false", "true" }, { "realm", "user", "api-kid", randomNullOrEmptyString(), "false", "false" }, { randomNullOrEmptyString(), randomNullOrEmptyString(), "api-kid", "api-kname", "false", "false" }, { "realm", randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), "true", "false" }, @@ -106,6 +108,8 @@ public void writeTo(StreamOutput out) throws IOException { "username or realm name must not be specified when the api key id or api key name is specified", "only one of [api key id, api key name] can be specified", "active_only must not be [true] when the api key id or api key name is specified" }, + { "active_only must not be [true] when the api key id or api key name is specified" }, + { "active_only must not be [true] when the api key id or api key name is specified" }, { "username or realm name must not be specified when the api key id or api key name is specified" }, { "only one of [api key id, api key name] can be specified" }, { "neither username nor realm-name may be specified when retrieving owned API keys" }, diff --git a/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/apikey/ApiKeyRestIT.java b/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/apikey/ApiKeyRestIT.java index 4bb5a39bb410d..7fe4611eb8b66 100644 --- a/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/apikey/ApiKeyRestIT.java +++ b/x-pack/plugin/security/qa/security-trial/src/javaRestTest/java/org/elasticsearch/xpack/security/apikey/ApiKeyRestIT.java @@ -1431,14 +1431,7 @@ public void testGetActiveOnlyApiKeys() throws Exception { final EncodedApiKey apiKey2 = createApiKey("key-2", Collections.emptyMap(), TimeValue.timeValueNanos(1)); { - final Map parameters = new HashMap<>(); - parameters.put("active_only", "true"); - if (randomBoolean()) { - parameters.put("username", MANAGE_OWN_API_KEY_USER); - } - - final GetApiKeyResponse response = getApiKeysWithRequestParams(parameters); - + final GetApiKeyResponse response = getApiKeysWithRequestParams(Map.of("active_only", "true")); assertResponseContainsApiKeyIds(response, apiKey0.id, apiKey1.id); } { @@ -1446,25 +1439,14 @@ public void testGetActiveOnlyApiKeys() throws Exception { if (randomBoolean()) { parameters.put("active_only", "false"); } - if (randomBoolean()) { - parameters.put("username", MANAGE_OWN_API_KEY_USER); - } - final GetApiKeyResponse response = getApiKeysWithRequestParams(parameters); - assertResponseContainsApiKeyIds(response, apiKey0.id, apiKey1.id, apiKey2.id); } getSecurityClient().invalidateApiKeys(apiKey0.id); - { - final Map parameters = new HashMap<>(); - parameters.put("active_only", "true"); - if (randomBoolean()) { - parameters.put("username", MANAGE_OWN_API_KEY_USER); - } - - final GetApiKeyResponse response = getApiKeysWithRequestParams(parameters); + { + final GetApiKeyResponse response = getApiKeysWithRequestParams(Map.of("active_only", "true")); assertResponseContainsApiKeyIds(response, apiKey1.id); } { @@ -1472,24 +1454,69 @@ public void testGetActiveOnlyApiKeys() throws Exception { if (randomBoolean()) { parameters.put("active_only", "false"); } - if (randomBoolean()) { - parameters.put("username", MANAGE_OWN_API_KEY_USER); - } - final GetApiKeyResponse response = getApiKeysWithRequestParams(parameters); - assertResponseContainsApiKeyIds(response, apiKey0.id, apiKey1.id, apiKey2.id); } getSecurityClient().invalidateApiKeys(apiKey1.id); - // Active-only returns empty when no keys found + { final GetApiKeyResponse response = getApiKeysWithRequestParams(Map.of("active_only", "true")); - assertThat(response.getApiKeyInfos(), emptyArray()); } } + public void testGetActiveOnlyApiKeysWithMultipleUsers() throws Exception { + final String manageOwnApiKeyUserApiKeyId = createApiKey("key-0", Collections.emptyMap()).id; + + final var createApiKeyRequest = new Request("POST", "_security/api_key"); + createApiKeyRequest.setJsonEntity(XContentTestUtils.convertToXContent(Map.of("name", "key-1"), XContentType.JSON).utf8ToString()); + setUserForRequest(createApiKeyRequest, MANAGE_API_KEY_USER, END_USER_PASSWORD); + final String manageApiKeyUserApiKeyId = assertOKAndCreateObjectPath(client().performRequest(createApiKeyRequest)).evaluate("id"); + + // Two active API keys + assertResponseContainsApiKeyIds( + getApiKeysWithRequestParams(Map.of("active_only", Boolean.toString(randomBoolean()))), + manageOwnApiKeyUserApiKeyId, + manageApiKeyUserApiKeyId + ); + assertResponseContainsApiKeyIds( + getApiKeysWithRequestParams(Map.of("active_only", Boolean.toString(randomBoolean()), "username", MANAGE_API_KEY_USER)), + manageApiKeyUserApiKeyId + ); + assertResponseContainsApiKeyIds( + getApiKeysWithRequestParams(Map.of("active_only", Boolean.toString(randomBoolean()), "username", MANAGE_OWN_API_KEY_USER)), + manageOwnApiKeyUserApiKeyId + ); + + // One active API key + invalidateApiKeysForUser(MANAGE_OWN_API_KEY_USER); + + assertResponseContainsApiKeyIds(getApiKeysWithRequestParams(Map.of("active_only", "true")), manageApiKeyUserApiKeyId); + assertResponseContainsApiKeyIds( + getApiKeysWithRequestParams(Map.of("active_only", "true", "username", MANAGE_API_KEY_USER)), + manageApiKeyUserApiKeyId + ); + assertThat( + getApiKeysWithRequestParams(Map.of("active_only", "true", "username", MANAGE_OWN_API_KEY_USER)).getApiKeyInfos(), + emptyArray() + ); + + // No more active API keys + invalidateApiKeysForUser(MANAGE_API_KEY_USER); + + assertThat( + getApiKeysWithRequestParams(Map.of("active_only", "true", "username", randomFrom(MANAGE_API_KEY_USER, MANAGE_OWN_API_KEY_USER))) + .getApiKeyInfos(), + emptyArray() + ); + assertResponseContainsApiKeyIds( + getApiKeysWithRequestParams(Map.of("active_only", "false")), + manageOwnApiKeyUserApiKeyId, + manageApiKeyUserApiKeyId + ); + } + private static GetApiKeyResponse getApiKeysWithRequestParams(Map requestParams) throws IOException { final var request = new Request(HttpGet.METHOD_NAME, "/_security/api_key/"); request.addParameters(requestParams); @@ -1513,7 +1540,6 @@ private Response performRequestWithManageOwnApiKeyUser(Request request) throws I return client().performRequest(request); } - @SuppressWarnings("unchecked") private void fetchAndAssertApiKeyContainsWorkflows(String apiKeyId, String roleName, String... expectedWorkflows) throws IOException { Response getApiKeyResponse = fetchApiKey(apiKeyId); List actualWorkflows = assertOKAndCreateObjectPath(getApiKeyResponse).evaluate( @@ -1522,7 +1548,6 @@ private void fetchAndAssertApiKeyContainsWorkflows(String apiKeyId, String roleN assertThat(actualWorkflows, containsInAnyOrder(expectedWorkflows)); } - @SuppressWarnings("unchecked") private void fetchAndAssertApiKeyDoesNotContainWorkflows(String apiKeyId, String roleName) throws IOException { Response getApiKeyResponse = fetchApiKey(apiKeyId); Map restriction = assertOKAndCreateObjectPath(getApiKeyResponse).evaluate(