diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
index 50c1f8bd828..1d773a9d7ee 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java
@@ -20,6 +20,8 @@
package org.elasticsearch.client;
import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.client.security.DeleteRoleRequest;
+import org.elasticsearch.client.security.DeleteRoleResponse;
import org.elasticsearch.client.security.PutRoleMappingRequest;
import org.elasticsearch.client.security.PutRoleMappingResponse;
import org.elasticsearch.client.security.DisableUserRequest;
@@ -36,6 +38,7 @@ import org.elasticsearch.client.security.DeleteRoleMappingResponse;
import java.io.IOException;
import static java.util.Collections.emptySet;
+import static java.util.Collections.singleton;
/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the Security APIs.
@@ -252,4 +255,31 @@ public final class SecurityClient {
DeleteRoleMappingResponse::fromXContent, listener, emptySet());
}
+ /**
+ * Removes role from the native realm.
+ * See
+ * the docs for more.
+ * @param request the request with the role to delete
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response from the delete role call
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public DeleteRoleResponse deleteRole(DeleteRoleRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::deleteRole, options,
+ DeleteRoleResponse::fromXContent, singleton(404));
+ }
+
+ /**
+ * Removes role from the native realm.
+ * See
+ * the docs for more.
+ * @param request the request with the role to delete
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener the listener to be notified upon request completion
+ */
+ public void deleteRoleAsync(DeleteRoleRequest request, RequestOptions options, ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deleteRole, options,
+ DeleteRoleResponse::fromXContent, listener, singleton(404));
+ }
+
}
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 d64389d3948..a8a975d28ad 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
@@ -22,11 +22,12 @@ package org.elasticsearch.client;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
+import org.elasticsearch.client.security.DeleteRoleMappingRequest;
+import org.elasticsearch.client.security.DeleteRoleRequest;
import org.elasticsearch.client.security.PutRoleMappingRequest;
import org.elasticsearch.client.security.DisableUserRequest;
import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.ChangePasswordRequest;
-import org.elasticsearch.client.security.DeleteRoleMappingRequest;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.SetUserEnabledRequest;
@@ -96,7 +97,7 @@ final class SecurityRequestConverters {
return request;
}
- static Request deleteRoleMapping(DeleteRoleMappingRequest deleteRoleMappingRequest) throws IOException {
+ static Request deleteRoleMapping(DeleteRoleMappingRequest deleteRoleMappingRequest) {
final String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_xpack/security/role_mapping")
.addPathPart(deleteRoleMappingRequest.getName())
@@ -107,4 +108,14 @@ final class SecurityRequestConverters {
return request;
}
+ static Request deleteRole(DeleteRoleRequest deleteRoleRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_xpack/security/role")
+ .addPathPart(deleteRoleRequest.getName())
+ .build();
+ Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
+ RequestConverters.Params params = new RequestConverters.Params(request);
+ params.withRefreshPolicy(deleteRoleRequest.getRefreshPolicy());
+ return request;
+ }
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/DeleteRoleRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/DeleteRoleRequest.java
new file mode 100644
index 00000000000..39c9a9b7afb
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/DeleteRoleRequest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client.security;
+
+import org.elasticsearch.client.Validatable;
+
+import java.util.Objects;
+
+/**
+ * A request delete a role from the security index
+ */
+public final class DeleteRoleRequest implements Validatable {
+
+ private final String name;
+ private final RefreshPolicy refreshPolicy;
+
+ public DeleteRoleRequest(String name) {
+ this(name, RefreshPolicy.IMMEDIATE);
+ }
+
+ public DeleteRoleRequest(String name, RefreshPolicy refreshPolicy) {
+ this.name = Objects.requireNonNull(name, "name is required");
+ this.refreshPolicy = Objects.requireNonNull(refreshPolicy, "refresh policy is required");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public RefreshPolicy getRefreshPolicy() {
+ return refreshPolicy;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/DeleteRoleResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/DeleteRoleResponse.java
new file mode 100644
index 00000000000..3db10bb9702
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/DeleteRoleResponse.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.client.security;
+
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+
+/**
+ * Response for a role being deleted from the native realm
+ */
+public final class DeleteRoleResponse {
+
+ private final boolean found;
+
+ public DeleteRoleResponse(boolean found) {
+ this.found = found;
+ }
+
+ public boolean isFound() {
+ return this.found;
+ }
+
+ private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("delete_role_response",
+ true, args -> new DeleteRoleResponse((boolean) args[0]));
+
+ static {
+ PARSER.declareBoolean(constructorArg(), new ParseField("found"));
+ }
+
+ public static DeleteRoleResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+}
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 1c4df942d8c..4267e238580 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
@@ -22,10 +22,11 @@ package org.elasticsearch.client;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
+import org.elasticsearch.client.security.DeleteRoleMappingRequest;
+import org.elasticsearch.client.security.DeleteRoleRequest;
import org.elasticsearch.client.security.DisableUserRequest;
import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.ChangePasswordRequest;
-import org.elasticsearch.client.security.DeleteRoleMappingRequest;
import org.elasticsearch.client.security.PutRoleMappingRequest;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.RefreshPolicy;
@@ -177,4 +178,15 @@ public class SecurityRequestConvertersTests extends ESTestCase {
assertNull(request.getEntity());
}
+ public void testDeleteRole() {
+ final String name = randomAlphaOfLengthBetween(1, 12);
+ final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
+ final Map expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);
+ DeleteRoleRequest deleteRoleRequest = new DeleteRoleRequest(name, refreshPolicy);
+ Request request = SecurityRequestConverters.deleteRole(deleteRoleRequest);
+ assertEquals(HttpDelete.METHOD_NAME, request.getMethod());
+ assertEquals("/_xpack/security/role/" + name, request.getEndpoint());
+ assertEquals(expectedParams, request.getParameters());
+ assertNull(request.getEntity());
+ }
}
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 4bc6f75de53..ac1b9b6753a 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
@@ -19,14 +19,20 @@
package org.elasticsearch.client.documentation;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
+import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.security.ChangePasswordRequest;
import org.elasticsearch.client.security.DeleteRoleMappingRequest;
import org.elasticsearch.client.security.DeleteRoleMappingResponse;
+import org.elasticsearch.client.security.DeleteRoleRequest;
+import org.elasticsearch.client.security.DeleteRoleResponse;
import org.elasticsearch.client.security.DisableUserRequest;
import org.elasticsearch.client.security.EmptyResponse;
import org.elasticsearch.client.security.EnableUserRequest;
@@ -36,18 +42,23 @@ import org.elasticsearch.client.security.PutRoleMappingResponse;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.PutUserResponse;
import org.elasticsearch.client.security.RefreshPolicy;
-import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression;
-import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression;
import org.elasticsearch.client.security.support.CertificateInfo;
+import org.elasticsearch.client.security.support.expressiondsl.RoleMapperExpression;
import org.elasticsearch.client.security.support.expressiondsl.expressions.AnyRoleMapperExpression;
+import org.elasticsearch.client.security.support.expressiondsl.fields.FieldRoleMapperExpression;
+import org.elasticsearch.common.Strings;
+import org.elasticsearch.common.xcontent.XContentBuilder;
import org.hamcrest.Matchers;
+import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+
public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
public void testPutUser() throws Exception {
@@ -417,4 +428,72 @@ public class SecurityDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
+ public void testDeleteRole() throws Exception {
+ RestHighLevelClient client = highLevelClient();
+ addRole("testrole");
+
+ {
+ // tag::delete-role-request
+ DeleteRoleRequest deleteRoleRequest = new DeleteRoleRequest(
+ "testrole"); // <1>
+ // end::delete-role-request
+
+ // tag::delete-role-execute
+ DeleteRoleResponse deleteRoleResponse = client.security().deleteRole(deleteRoleRequest, RequestOptions.DEFAULT);
+ // end::delete-role-execute
+
+ // tag::delete-role-response
+ boolean found = deleteRoleResponse.isFound(); // <1>
+ // end::delete-role-response
+ assertTrue(found);
+
+ // check if deleting the already deleted role again will give us a different response
+ deleteRoleResponse = client.security().deleteRole(deleteRoleRequest, RequestOptions.DEFAULT);
+ assertFalse(deleteRoleResponse.isFound());
+ }
+
+ {
+ DeleteRoleRequest deleteRoleRequest = new DeleteRoleRequest("testrole");
+
+ ActionListener listener;
+ //tag::delete-role-execute-listener
+ listener = new ActionListener() {
+ @Override
+ public void onResponse(DeleteRoleResponse deleteRoleResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ //end::delete-role-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ //tag::delete-role-execute-async
+ client.security().deleteRoleAsync(deleteRoleRequest, RequestOptions.DEFAULT, listener); // <1>
+ //end::delete-role-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
+ // TODO: move all calls to high-level REST client once APIs for adding new role exist
+ private void addRole(String roleName) throws IOException {
+ Request addRoleRequest = new Request(HttpPost.METHOD_NAME, "/_xpack/security/role/" + roleName);
+ try (XContentBuilder builder = jsonBuilder()) {
+ builder.startObject();
+ {
+ builder.array("cluster", "all");
+ }
+ builder.endObject();
+ addRoleRequest.setEntity(new NStringEntity(Strings.toString(builder), ContentType.APPLICATION_JSON));
+ }
+ client().performRequest(addRoleRequest);
+ }
+
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/security/DeleteRoleResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/DeleteRoleResponseTests.java
new file mode 100644
index 00000000000..a2c08fcf881
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/security/DeleteRoleResponseTests.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.client.security;
+
+import org.elasticsearch.common.bytes.BytesReference;
+import org.elasticsearch.common.xcontent.NamedXContentRegistry;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentFactory;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+
+public class DeleteRoleResponseTests extends ESTestCase {
+
+ public void testBasicParsing() throws IOException {
+ XContentType contentType = randomFrom(XContentType.values());
+ final boolean found = randomBoolean();
+ XContentBuilder builder = XContentFactory.contentBuilder(contentType).startObject()
+ .field("found", found).endObject();
+ BytesReference bytes = BytesReference.bytes(builder);
+
+ DeleteRoleResponse response = parse(builder.contentType(), bytes);
+ assertEquals(found, response.isFound());
+ }
+
+ public void testParsingWithMissingField() throws IOException {
+ XContentType contentType = randomFrom(XContentType.values());
+ XContentBuilder builder = XContentFactory.contentBuilder(contentType).startObject().endObject();
+ BytesReference bytes = BytesReference.bytes(builder);
+
+ expectThrows(IllegalArgumentException.class, () -> parse(builder.contentType(), bytes));
+ }
+
+ private DeleteRoleResponse parse(XContentType contentType, BytesReference bytes) throws IOException {
+ XContentParser parser = XContentFactory.xContent(contentType)
+ .createParser(NamedXContentRegistry.EMPTY, null, bytes.streamInput());
+ parser.nextToken();
+ return DeleteRoleResponse.fromXContent(parser);
+ }
+
+}
diff --git a/docs/java-rest/high-level/document/delete.asciidoc b/docs/java-rest/high-level/document/delete.asciidoc
index 1b32fca7042..12fede7af80 100644
--- a/docs/java-rest/high-level/document/delete.asciidoc
+++ b/docs/java-rest/high-level/document/delete.asciidoc
@@ -10,7 +10,7 @@
[id="{upid}-{api}-request"]
==== Delete Request
-A +{request}+ requires the following arguments:
+A +{request}+ has no arguments
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
diff --git a/docs/java-rest/high-level/security/delete-role.asciidoc b/docs/java-rest/high-level/security/delete-role.asciidoc
new file mode 100644
index 00000000000..0086b89bb68
--- /dev/null
+++ b/docs/java-rest/high-level/security/delete-role.asciidoc
@@ -0,0 +1,33 @@
+--
+:api: delete-role
+:request: DeleteRoleRequest
+:response: DeleteRoleResponse
+--
+
+[id="{upid}-{api}"]
+=== Delete Role API
+
+[id="{upid}-{api}-request"]
+==== Delete Role Request
+
+A +{request}+ has a single argument
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> role to delete
+
+include::../execution.asciidoc[]
+
+[id="{upid}-{api}-response"]
+==== Delete Response
+
+The returned +{response}+ allows to retrieve information about the executed
+ operation as follows:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> whether the given role was found
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 28ef96d5eae..6cde79a22e5 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -310,12 +310,16 @@ include::rollup/get_rollup_caps.asciidoc[]
== Security APIs
+:upid: {mainid}-security
+:doc-tests-file: {doc-tests}/SecurityDocumentationIT.java
+
The Java High Level REST Client supports the following Security APIs:
* <>
* <>
* <>
* <>
+* <>
* <>
* <>
* <>
@@ -324,6 +328,7 @@ include::security/put-user.asciidoc[]
include::security/enable-user.asciidoc[]
include::security/disable-user.asciidoc[]
include::security/change-password.asciidoc[]
+include::security/delete-role.asciidoc[]
include::security/get-certificates.asciidoc[]
include::security/put-role-mapping.asciidoc[]
include::security/delete-role-mapping.asciidoc[]