From 9cf24321fbbeabbb2f1e9afff2a7e4999455cce7 Mon Sep 17 00:00:00 2001 From: Yogesh Gaikwad <902768+bizybot@users.noreply.github.com> Date: Thu, 15 Aug 2019 21:51:40 +1000 Subject: [PATCH] HLRC: add support for retrieval/invalidation of owned API keys (#45474) This commit updates Rest client(get/invalidate API keys APIs) to support retrieval or invalidation of API keys owned by the currently authenticated user. Relates: #40031 --- .../client/SecurityRequestConverters.java | 2 +- .../client/security/GetApiKeyRequest.java | 42 ++++++++++++---- .../security/InvalidateApiKeyRequest.java | 43 ++++++++++++---- .../SecurityRequestConvertersTests.java | 9 ++-- .../SecurityDocumentationIT.java | 49 ++++++++++++++++--- .../security/GetApiKeyRequestTests.java | 34 ++++++++----- .../InvalidateApiKeyRequestTests.java | 34 ++++++++----- .../high-level/security/get-api-key.asciidoc | 8 +++ .../security/invalidate-api-key.asciidoc | 8 +++ 9 files changed, 176 insertions(+), 53 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java index 18ecc2cea281a..ebe125dbe25e6 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityRequestConverters.java @@ -294,7 +294,7 @@ static Request getApiKey(final GetApiKeyRequest getApiKeyRequest) throws IOExcep if (Strings.hasText(getApiKeyRequest.getRealmName())) { request.addParameter("realm_name", getApiKeyRequest.getRealmName()); } - + request.addParameter("owner", Boolean.toString(getApiKeyRequest.ownedByAuthenticatedUser())); return request; } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetApiKeyRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetApiKeyRequest.java index 6fa98ec549b07..9427489786387 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetApiKeyRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/GetApiKeyRequest.java @@ -36,13 +36,14 @@ public final class GetApiKeyRequest implements Validatable, ToXContentObject { private final String userName; private final String id; private final String name; + private final boolean ownedByAuthenticatedUser; // pkg scope for testing GetApiKeyRequest(@Nullable String realmName, @Nullable String userName, @Nullable String apiKeyId, - @Nullable String apiKeyName) { + @Nullable String apiKeyName, boolean ownedByAuthenticatedUser) { if (Strings.hasText(realmName) == false && Strings.hasText(userName) == false && Strings.hasText(apiKeyId) == false - && Strings.hasText(apiKeyName) == false) { - throwValidationError("One of [api key id, api key name, username, realm name] must be specified"); + && Strings.hasText(apiKeyName) == false && ownedByAuthenticatedUser == false) { + throwValidationError("One of [api key id, api key name, username, realm name] must be specified if [owner] flag is false"); } if (Strings.hasText(apiKeyId) || Strings.hasText(apiKeyName)) { if (Strings.hasText(realmName) || Strings.hasText(userName)) { @@ -50,6 +51,11 @@ public final class GetApiKeyRequest implements Validatable, ToXContentObject { "username or realm name must not be specified when the api key id or api key name is specified"); } } + if (ownedByAuthenticatedUser) { + if (Strings.hasText(realmName) || Strings.hasText(userName)) { + throwValidationError("neither username nor realm-name may be specified when retrieving owned API keys"); + } + } if (Strings.hasText(apiKeyId) && Strings.hasText(apiKeyName)) { throwValidationError("only one of [api key id, api key name] can be specified"); } @@ -57,6 +63,7 @@ public final class GetApiKeyRequest implements Validatable, ToXContentObject { this.userName = userName; this.id = apiKeyId; this.name = apiKeyName; + this.ownedByAuthenticatedUser = ownedByAuthenticatedUser; } private void throwValidationError(String message) { @@ -79,13 +86,17 @@ public String getName() { return name; } + public boolean ownedByAuthenticatedUser() { + return ownedByAuthenticatedUser; + } + /** * Creates get API key request for given realm name * @param realmName realm name * @return {@link GetApiKeyRequest} */ public static GetApiKeyRequest usingRealmName(String realmName) { - return new GetApiKeyRequest(realmName, null, null, null); + return new GetApiKeyRequest(realmName, null, null, null, false); } /** @@ -94,7 +105,7 @@ public static GetApiKeyRequest usingRealmName(String realmName) { * @return {@link GetApiKeyRequest} */ public static GetApiKeyRequest usingUserName(String userName) { - return new GetApiKeyRequest(null, userName, null, null); + return new GetApiKeyRequest(null, userName, null, null, false); } /** @@ -104,25 +115,36 @@ public static GetApiKeyRequest usingUserName(String userName) { * @return {@link GetApiKeyRequest} */ public static GetApiKeyRequest usingRealmAndUserName(String realmName, String userName) { - return new GetApiKeyRequest(realmName, userName, null, null); + return new GetApiKeyRequest(realmName, userName, null, null, false); } /** * Creates get API key request for given api key id * @param apiKeyId api key id + * @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current + * authenticated user else{@code false} * @return {@link GetApiKeyRequest} */ - public static GetApiKeyRequest usingApiKeyId(String apiKeyId) { - return new GetApiKeyRequest(null, null, apiKeyId, null); + public static GetApiKeyRequest usingApiKeyId(String apiKeyId, boolean ownedByAuthenticatedUser) { + return new GetApiKeyRequest(null, null, apiKeyId, null, ownedByAuthenticatedUser); } /** * Creates get API key request for given api key name * @param apiKeyName api key name + * @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current + * authenticated user else{@code false} * @return {@link GetApiKeyRequest} */ - public static GetApiKeyRequest usingApiKeyName(String apiKeyName) { - return new GetApiKeyRequest(null, null, null, apiKeyName); + public static GetApiKeyRequest usingApiKeyName(String apiKeyName, boolean ownedByAuthenticatedUser) { + return new GetApiKeyRequest(null, null, null, apiKeyName, ownedByAuthenticatedUser); + } + + /** + * Creates get api key request to retrieve api key information for the api keys owned by the current authenticated user. + */ + public static GetApiKeyRequest forOwnedApiKeys() { + return new GetApiKeyRequest(null, null, null, null, true); } @Override diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/InvalidateApiKeyRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/InvalidateApiKeyRequest.java index d3203354b7ab1..351294e36d38b 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/InvalidateApiKeyRequest.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/InvalidateApiKeyRequest.java @@ -36,13 +36,14 @@ public final class InvalidateApiKeyRequest implements Validatable, ToXContentObj private final String userName; private final String id; private final String name; + private final boolean ownedByAuthenticatedUser; // pkg scope for testing InvalidateApiKeyRequest(@Nullable String realmName, @Nullable String userName, @Nullable String apiKeyId, - @Nullable String apiKeyName) { + @Nullable String apiKeyName, boolean ownedByAuthenticatedUser) { if (Strings.hasText(realmName) == false && Strings.hasText(userName) == false && Strings.hasText(apiKeyId) == false - && Strings.hasText(apiKeyName) == false) { - throwValidationError("One of [api key id, api key name, username, realm name] must be specified"); + && Strings.hasText(apiKeyName) == false && ownedByAuthenticatedUser == false) { + throwValidationError("One of [api key id, api key name, username, realm name] must be specified if [owner] flag is false"); } if (Strings.hasText(apiKeyId) || Strings.hasText(apiKeyName)) { if (Strings.hasText(realmName) || Strings.hasText(userName)) { @@ -50,6 +51,11 @@ public final class InvalidateApiKeyRequest implements Validatable, ToXContentObj "username or realm name must not be specified when the api key id or api key name is specified"); } } + if (ownedByAuthenticatedUser) { + if (Strings.hasText(realmName) || Strings.hasText(userName)) { + throwValidationError("neither username nor realm-name may be specified when invalidating owned API keys"); + } + } if (Strings.hasText(apiKeyId) && Strings.hasText(apiKeyName)) { throwValidationError("only one of [api key id, api key name] can be specified"); } @@ -57,6 +63,7 @@ public final class InvalidateApiKeyRequest implements Validatable, ToXContentObj this.userName = userName; this.id = apiKeyId; this.name = apiKeyName; + this.ownedByAuthenticatedUser = ownedByAuthenticatedUser; } private void throwValidationError(String message) { @@ -79,13 +86,17 @@ public String getName() { return name; } + public boolean ownedByAuthenticatedUser() { + return ownedByAuthenticatedUser; + } + /** * Creates invalidate API key request for given realm name * @param realmName realm name * @return {@link InvalidateApiKeyRequest} */ public static InvalidateApiKeyRequest usingRealmName(String realmName) { - return new InvalidateApiKeyRequest(realmName, null, null, null); + return new InvalidateApiKeyRequest(realmName, null, null, null, false); } /** @@ -94,7 +105,7 @@ public static InvalidateApiKeyRequest usingRealmName(String realmName) { * @return {@link InvalidateApiKeyRequest} */ public static InvalidateApiKeyRequest usingUserName(String userName) { - return new InvalidateApiKeyRequest(null, userName, null, null); + return new InvalidateApiKeyRequest(null, userName, null, null, false); } /** @@ -104,25 +115,36 @@ public static InvalidateApiKeyRequest usingUserName(String userName) { * @return {@link InvalidateApiKeyRequest} */ public static InvalidateApiKeyRequest usingRealmAndUserName(String realmName, String userName) { - return new InvalidateApiKeyRequest(realmName, userName, null, null); + return new InvalidateApiKeyRequest(realmName, userName, null, null, false); } /** * Creates invalidate API key request for given api key id * @param apiKeyId api key id + * @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current authenticated user else + * {@code false} * @return {@link InvalidateApiKeyRequest} */ - public static InvalidateApiKeyRequest usingApiKeyId(String apiKeyId) { - return new InvalidateApiKeyRequest(null, null, apiKeyId, null); + public static InvalidateApiKeyRequest usingApiKeyId(String apiKeyId, boolean ownedByAuthenticatedUser) { + return new InvalidateApiKeyRequest(null, null, apiKeyId, null, ownedByAuthenticatedUser); } /** * Creates invalidate API key request for given api key name * @param apiKeyName api key name + * @param ownedByAuthenticatedUser set {@code true} if the request is only for the API keys owned by current authenticated user else + * {@code false} * @return {@link InvalidateApiKeyRequest} */ - public static InvalidateApiKeyRequest usingApiKeyName(String apiKeyName) { - return new InvalidateApiKeyRequest(null, null, null, apiKeyName); + public static InvalidateApiKeyRequest usingApiKeyName(String apiKeyName, boolean ownedByAuthenticatedUser) { + return new InvalidateApiKeyRequest(null, null, null, apiKeyName, ownedByAuthenticatedUser); + } + + /** + * Creates invalidate api key request to invalidate api keys owned by the current authenticated user. + */ + public static InvalidateApiKeyRequest forOwnedApiKeys() { + return new InvalidateApiKeyRequest(null, null, null, null, true); } @Override @@ -140,6 +162,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws if (name != null) { builder.field("name", name); } + builder.field("owner", ownedByAuthenticatedUser); return builder.endObject(); } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java index 4c99cb323969e..51f77cb972ff6 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java @@ -446,10 +446,11 @@ public void testGetApiKey() throws IOException { final Request request = SecurityRequestConverters.getApiKey(getApiKeyRequest); assertEquals(HttpGet.METHOD_NAME, request.getMethod()); assertEquals("/_security/api_key", request.getEndpoint()); - Map mapOfParameters = new HashMap<>(); - mapOfParameters.put("realm_name", realmName); - mapOfParameters.put("username", userName); - assertThat(request.getParameters(), equalTo(mapOfParameters)); + Map expectedMapOfParameters = new HashMap<>(); + expectedMapOfParameters.put("realm_name", realmName); + expectedMapOfParameters.put("username", userName); + expectedMapOfParameters.put("owner", Boolean.FALSE.toString()); + assertThat(request.getParameters(), equalTo(expectedMapOfParameters)); } public void testInvalidateApiKey() throws IOException { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java index 9bbc3b2ea9072..d4f782eaaee47 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java @@ -1917,7 +1917,7 @@ public void testGetApiKey() throws Exception { Instant.now().plusMillis(expiration.getMillis()), false, "test_user", "default_file"); { // tag::get-api-key-id-request - GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId()); + GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId(), false); // end::get-api-key-id-request // tag::get-api-key-execute @@ -1931,7 +1931,7 @@ public void testGetApiKey() throws Exception { { // tag::get-api-key-name-request - GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyName(createApiKeyResponse1.getName()); + GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyName(createApiKeyResponse1.getName(), false); // end::get-api-key-name-request GetApiKeyResponse getApiKeyResponse = client.security().getApiKey(getApiKeyRequest, RequestOptions.DEFAULT); @@ -1965,6 +1965,18 @@ public void testGetApiKey() throws Exception { verifyApiKey(getApiKeyResponse.getApiKeyInfos().get(0), expectedApiKeyInfo); } + { + // tag::get-api-keys-owned-by-authenticated-user-request + GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.forOwnedApiKeys(); + // end::get-api-keys-owned-by-authenticated-user-request + + GetApiKeyResponse getApiKeyResponse = client.security().getApiKey(getApiKeyRequest, RequestOptions.DEFAULT); + + assertThat(getApiKeyResponse.getApiKeyInfos(), is(notNullValue())); + assertThat(getApiKeyResponse.getApiKeyInfos().size(), is(1)); + verifyApiKey(getApiKeyResponse.getApiKeyInfos().get(0), expectedApiKeyInfo); + } + { // tag::get-user-realm-api-keys-request GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingRealmAndUserName("default_file", "test_user"); @@ -1980,7 +1992,7 @@ public void testGetApiKey() throws Exception { } { - GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId()); + GetApiKeyRequest getApiKeyRequest = GetApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId(), false); ActionListener listener; // tag::get-api-key-execute-listener @@ -2041,7 +2053,7 @@ public void testInvalidateApiKey() throws Exception { { // tag::invalidate-api-key-id-request - InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId()); + InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse1.getId(), false); // end::invalidate-api-key-id-request // tag::invalidate-api-key-execute @@ -2066,7 +2078,8 @@ public void testInvalidateApiKey() throws Exception { assertNotNull(createApiKeyResponse2.getKey()); // tag::invalidate-api-key-name-request - InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyName(createApiKeyResponse2.getName()); + InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyName(createApiKeyResponse2.getName(), + false); // end::invalidate-api-key-name-request InvalidateApiKeyResponse invalidateApiKeyResponse = client.security().invalidateApiKey(invalidateApiKeyRequest, @@ -2159,7 +2172,7 @@ public void testInvalidateApiKey() throws Exception { assertThat(createApiKeyResponse6.getName(), equalTo("k6")); assertNotNull(createApiKeyResponse6.getKey()); - InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse6.getId()); + InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.usingApiKeyId(createApiKeyResponse6.getId(), false); ActionListener listener; // tag::invalidate-api-key-execute-listener @@ -2195,5 +2208,29 @@ public void onFailure(Exception e) { assertThat(invalidatedApiKeyIds, containsInAnyOrder(expectedInvalidatedApiKeyIds.toArray(Strings.EMPTY_ARRAY))); assertThat(response.getPreviouslyInvalidatedApiKeys().size(), equalTo(0)); } + + { + createApiKeyRequest = new CreateApiKeyRequest("k7", roles, expiration, refreshPolicy); + CreateApiKeyResponse createApiKeyResponse7 = client.security().createApiKey(createApiKeyRequest, RequestOptions.DEFAULT); + assertThat(createApiKeyResponse7.getName(), equalTo("k7")); + assertNotNull(createApiKeyResponse7.getKey()); + + // tag::invalidate-api-keys-owned-by-authenticated-user-request + InvalidateApiKeyRequest invalidateApiKeyRequest = InvalidateApiKeyRequest.forOwnedApiKeys(); + // end::invalidate-api-keys-owned-by-authenticated-user-request + + InvalidateApiKeyResponse invalidateApiKeyResponse = client.security().invalidateApiKey(invalidateApiKeyRequest, + RequestOptions.DEFAULT); + + final List errors = invalidateApiKeyResponse.getErrors(); + final List invalidatedApiKeyIds = invalidateApiKeyResponse.getInvalidatedApiKeys(); + final List previouslyInvalidatedApiKeyIds = invalidateApiKeyResponse.getPreviouslyInvalidatedApiKeys(); + + assertTrue(errors.isEmpty()); + List expectedInvalidatedApiKeyIds = Arrays.asList(createApiKeyResponse7.getId()); + assertThat(invalidatedApiKeyIds, containsInAnyOrder(expectedInvalidatedApiKeyIds.toArray(Strings.EMPTY_ARRAY))); + assertThat(previouslyInvalidatedApiKeyIds.size(), equalTo(0)); + } + } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetApiKeyRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetApiKeyRequestTests.java index 79551e1e73e92..cbd05ae4c5ac3 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetApiKeyRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/GetApiKeyRequestTests.java @@ -30,10 +30,10 @@ public class GetApiKeyRequestTests extends ESTestCase { public void testRequestValidation() { - GetApiKeyRequest request = GetApiKeyRequest.usingApiKeyId(randomAlphaOfLength(5)); + GetApiKeyRequest request = GetApiKeyRequest.usingApiKeyId(randomAlphaOfLength(5), randomBoolean()); Optional ve = request.validate(); assertFalse(ve.isPresent()); - request = GetApiKeyRequest.usingApiKeyName(randomAlphaOfLength(5)); + request = GetApiKeyRequest.usingApiKeyName(randomAlphaOfLength(5), randomBoolean()); ve = request.validate(); assertFalse(ve.isPresent()); request = GetApiKeyRequest.usingRealmName(randomAlphaOfLength(5)); @@ -45,28 +45,40 @@ public void testRequestValidation() { request = GetApiKeyRequest.usingRealmAndUserName(randomAlphaOfLength(5), randomAlphaOfLength(7)); ve = request.validate(); assertFalse(ve.isPresent()); + request = GetApiKeyRequest.forOwnedApiKeys(); + ve = request.validate(); + assertFalse(ve.isPresent()); } public void testRequestValidationFailureScenarios() throws IOException { String[][] inputs = new String[][] { - { randomFrom(new String[] { null, "" }), randomFrom(new String[] { null, "" }), randomFrom(new String[] { null, "" }), - randomFrom(new String[] { null, "" }) }, - { randomFrom(new String[] { null, "" }), "user", "api-kid", "api-kname" }, - { "realm", randomFrom(new String[] { null, "" }), "api-kid", "api-kname" }, - { "realm", "user", "api-kid", randomFrom(new String[] { null, "" }) }, - { randomFrom(new String[] { null, "" }), randomFrom(new String[] { null, "" }), "api-kid", "api-kname" } }; - String[] expectedErrorMessages = new String[] { "One of [api key id, api key name, username, realm name] must be specified", + { randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), "false" }, + { randomNullOrEmptyString(), "user", "api-kid", "api-kname", "false" }, + { "realm", randomNullOrEmptyString(), "api-kid", "api-kname", "false" }, + { "realm", "user", "api-kid", randomNullOrEmptyString(), "false" }, + { randomNullOrEmptyString(), randomNullOrEmptyString(), "api-kid", "api-kname", "false" }, + { "realm", randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), "true"}, + { randomNullOrEmptyString(), "user", randomNullOrEmptyString(), randomNullOrEmptyString(), "true"} }; + String[] expectedErrorMessages = new String[] { + "One of [api key id, api key name, username, realm name] must be specified if [owner] flag is false", "username or realm name must not be specified 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", "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" }; + "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", + "neither username nor realm-name may be specified when retrieving owned API keys" }; for (int i = 0; i < inputs.length; i++) { final int caseNo = i; IllegalArgumentException ve = expectThrows(IllegalArgumentException.class, - () -> new GetApiKeyRequest(inputs[caseNo][0], inputs[caseNo][1], inputs[caseNo][2], inputs[caseNo][3])); + () -> new GetApiKeyRequest(inputs[caseNo][0], inputs[caseNo][1], inputs[caseNo][2], inputs[caseNo][3], + Boolean.valueOf(inputs[caseNo][4]))); assertNotNull(ve); assertThat(ve.getMessage(), equalTo(expectedErrorMessages[caseNo])); } } + + private static String randomNullOrEmptyString() { + return randomBoolean() ? "" : null; + } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/InvalidateApiKeyRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/InvalidateApiKeyRequestTests.java index 25ee4bb05bcc4..a29adb9ea382b 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/InvalidateApiKeyRequestTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/InvalidateApiKeyRequestTests.java @@ -31,10 +31,10 @@ public class InvalidateApiKeyRequestTests extends ESTestCase { public void testRequestValidation() { - InvalidateApiKeyRequest request = InvalidateApiKeyRequest.usingApiKeyId(randomAlphaOfLength(5)); + InvalidateApiKeyRequest request = InvalidateApiKeyRequest.usingApiKeyId(randomAlphaOfLength(5), randomBoolean()); Optional ve = request.validate(); assertThat(ve.isPresent(), is(false)); - request = InvalidateApiKeyRequest.usingApiKeyName(randomAlphaOfLength(5)); + request = InvalidateApiKeyRequest.usingApiKeyName(randomAlphaOfLength(5), randomBoolean()); ve = request.validate(); assertThat(ve.isPresent(), is(false)); request = InvalidateApiKeyRequest.usingRealmName(randomAlphaOfLength(5)); @@ -46,28 +46,40 @@ public void testRequestValidation() { request = InvalidateApiKeyRequest.usingRealmAndUserName(randomAlphaOfLength(5), randomAlphaOfLength(7)); ve = request.validate(); assertThat(ve.isPresent(), is(false)); + request = InvalidateApiKeyRequest.forOwnedApiKeys(); + ve = request.validate(); + assertFalse(ve.isPresent()); } public void testRequestValidationFailureScenarios() throws IOException { String[][] inputs = new String[][] { - { randomFrom(new String[] { null, "" }), randomFrom(new String[] { null, "" }), randomFrom(new String[] { null, "" }), - randomFrom(new String[] { null, "" }) }, - { randomFrom(new String[] { null, "" }), "user", "api-kid", "api-kname" }, - { "realm", randomFrom(new String[] { null, "" }), "api-kid", "api-kname" }, - { "realm", "user", "api-kid", randomFrom(new String[] { null, "" }) }, - { randomFrom(new String[] { null, "" }), randomFrom(new String[] { null, "" }), "api-kid", "api-kname" } }; - String[] expectedErrorMessages = new String[] { "One of [api key id, api key name, username, realm name] must be specified", + { randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), "false" }, + { randomNullOrEmptyString(), "user", "api-kid", "api-kname", "false" }, + { "realm", randomNullOrEmptyString(), "api-kid", "api-kname", "false" }, + { "realm", "user", "api-kid", randomNullOrEmptyString(), "false" }, + { randomNullOrEmptyString(), randomNullOrEmptyString(), "api-kid", "api-kname", "false" }, + { "realm", randomNullOrEmptyString(), randomNullOrEmptyString(), randomNullOrEmptyString(), "true" }, + { randomNullOrEmptyString(), "user", randomNullOrEmptyString(), randomNullOrEmptyString(), "true" } }; + String[] expectedErrorMessages = new String[] { + "One of [api key id, api key name, username, realm name] must be specified if [owner] flag is false", "username or realm name must not be specified 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", "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" }; + "only one of [api key id, api key name] can be specified", + "neither username nor realm-name may be specified when invalidating owned API keys", + "neither username nor realm-name may be specified when invalidating owned API keys" }; for (int i = 0; i < inputs.length; i++) { final int caseNo = i; IllegalArgumentException ve = expectThrows(IllegalArgumentException.class, - () -> new InvalidateApiKeyRequest(inputs[caseNo][0], inputs[caseNo][1], inputs[caseNo][2], inputs[caseNo][3])); + () -> new InvalidateApiKeyRequest(inputs[caseNo][0], inputs[caseNo][1], inputs[caseNo][2], inputs[caseNo][3], + Boolean.valueOf(inputs[caseNo][4]))); assertNotNull(ve); assertThat(ve.getMessage(), equalTo(expectedErrorMessages[caseNo])); } } + + private static String randomNullOrEmptyString() { + return randomBoolean() ? "" : null; + } } diff --git a/docs/java-rest/high-level/security/get-api-key.asciidoc b/docs/java-rest/high-level/security/get-api-key.asciidoc index bb98b527d22ba..911acd3e92ef5 100644 --- a/docs/java-rest/high-level/security/get-api-key.asciidoc +++ b/docs/java-rest/high-level/security/get-api-key.asciidoc @@ -21,6 +21,8 @@ The +{request}+ supports retrieving API key information for . All API keys for a specific user in a specific realm +. A specific key or all API keys owned by the current authenticated user + ===== Retrieve a specific API key by its id ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- @@ -51,6 +53,12 @@ include-tagged::{doc-tests-file}[get-user-api-keys-request] include-tagged::{doc-tests-file}[get-user-realm-api-keys-request] -------------------------------------------------- +===== Retrieve all API keys for the current authenticated user +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[get-api-keys-owned-by-authenticated-user-request] +-------------------------------------------------- + include::../execution.asciidoc[] [id="{upid}-{api}-response"] diff --git a/docs/java-rest/high-level/security/invalidate-api-key.asciidoc b/docs/java-rest/high-level/security/invalidate-api-key.asciidoc index 7f9c43b3165a8..b8a99f932d93e 100644 --- a/docs/java-rest/high-level/security/invalidate-api-key.asciidoc +++ b/docs/java-rest/high-level/security/invalidate-api-key.asciidoc @@ -21,6 +21,8 @@ The +{request}+ supports invalidating . All API keys for a specific user in a specific realm +. A specific key or all API keys owned by the current authenticated user + ===== Specific API key by API key id ["source","java",subs="attributes,callouts,macros"] -------------------------------------------------- @@ -51,6 +53,12 @@ include-tagged::{doc-tests-file}[invalidate-user-api-keys-request] include-tagged::{doc-tests-file}[invalidate-user-realm-api-keys-request] -------------------------------------------------- +===== Retrieve all API keys for the current authenticated user +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests-file}[invalidate-api-keys-owned-by-authenticated-user-request] +-------------------------------------------------- + include::../execution.asciidoc[] [id="{upid}-{api}-response"]