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 fba8c6ed2bd14..4fdf8907f5572 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
@@ -23,6 +23,8 @@
import org.elasticsearch.client.security.AuthenticateRequest;
import org.elasticsearch.client.security.AuthenticateResponse;
import org.elasticsearch.client.security.ChangePasswordRequest;
+import org.elasticsearch.client.security.ClearPrivilegesCacheRequest;
+import org.elasticsearch.client.security.ClearPrivilegesCacheResponse;
import org.elasticsearch.client.security.ClearRealmCacheRequest;
import org.elasticsearch.client.security.ClearRealmCacheResponse;
import org.elasticsearch.client.security.ClearRolesCacheRequest;
@@ -510,6 +512,38 @@ public Cancellable clearRolesCacheAsync(ClearRolesCacheRequest request, RequestO
ClearRolesCacheResponse::fromXContent, listener, emptySet());
}
+ /**
+ * Clears the privileges cache for a set of privileges.
+ * See
+ * the docs for more.
+ *
+ * @param request the request with the privileges for which the cache should be cleared.
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response from the clear privileges cache call
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public ClearPrivilegesCacheResponse clearPrivilegesCache(ClearPrivilegesCacheRequest request,
+ RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::clearPrivilegesCache, options,
+ ClearPrivilegesCacheResponse::fromXContent, emptySet());
+ }
+
+ /**
+ * Clears the privileges cache for a set of privileges asynchronously.
+ * See
+ * the docs for more.
+ *
+ * @param request the request with the privileges for which the cache should be cleared.
+ * @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
+ * @return cancellable that may be used to cancel the request
+ */
+ public Cancellable clearPrivilegesCacheAsync(ClearPrivilegesCacheRequest request, RequestOptions options,
+ ActionListener listener) {
+ return restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::clearPrivilegesCache, options,
+ ClearPrivilegesCacheResponse::fromXContent, listener, emptySet());
+ }
+
/**
* Synchronously retrieve the X.509 certificates that are used to encrypt communications in an Elasticsearch cluster.
* See
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 c88d1d180fcc8..55301aed30752 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
@@ -24,6 +24,7 @@
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.security.ChangePasswordRequest;
+import org.elasticsearch.client.security.ClearPrivilegesCacheRequest;
import org.elasticsearch.client.security.ClearRealmCacheRequest;
import org.elasticsearch.client.security.ClearRolesCacheRequest;
import org.elasticsearch.client.security.CreateApiKeyRequest;
@@ -183,6 +184,15 @@ static Request clearRolesCache(ClearRolesCacheRequest disableCacheRequest) {
return new Request(HttpPost.METHOD_NAME, endpoint);
}
+ static Request clearPrivilegesCache(ClearPrivilegesCacheRequest disableCacheRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPartAsIs("_security/privilege")
+ .addCommaSeparatedPathParts(disableCacheRequest.applications())
+ .addPathPart("_clear_cache")
+ .build();
+ return new Request(HttpPost.METHOD_NAME, endpoint);
+ }
+
static Request deleteRoleMapping(DeleteRoleMappingRequest deleteRoleMappingRequest) {
final String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_security/role_mapping")
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/ClearPrivilegesCacheRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/ClearPrivilegesCacheRequest.java
new file mode 100644
index 0000000000000..db6b2283e63b1
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/ClearPrivilegesCacheRequest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.Arrays;
+
+/**
+ * The request used to clear the cache for native application privileges stored in an index.
+ */
+public final class ClearPrivilegesCacheRequest implements Validatable {
+
+ private final String[] applications;
+
+ /**
+ * Sets the applications for which caches will be evicted. When not set all privileges will be evicted from the cache.
+ *
+ * @param applications The application names
+ */
+ public ClearPrivilegesCacheRequest(String... applications) {
+ this.applications = applications;
+ }
+
+ /**
+ * @return an array of application names that will have the cache evicted or null
if all
+ */
+ public String[] applications() {
+ return applications;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ClearPrivilegesCacheRequest that = (ClearPrivilegesCacheRequest) o;
+ return Arrays.equals(applications, that.applications);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(applications);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/security/ClearPrivilegesCacheResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/ClearPrivilegesCacheResponse.java
new file mode 100644
index 0000000000000..d6b62123b6595
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/security/ClearPrivilegesCacheResponse.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.NodesResponseHeader;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * The response object that will be returned when clearing the privileges cache
+ */
+public final class ClearPrivilegesCacheResponse extends SecurityNodesResponse {
+
+ @SuppressWarnings("unchecked")
+ private static final ConstructingObjectParser PARSER =
+ new ConstructingObjectParser<>("clear_privileges_cache_response", false,
+ args -> new ClearPrivilegesCacheResponse((List)args[0], (NodesResponseHeader) args[1], (String) args[2]));
+
+ static {
+ SecurityNodesResponse.declareCommonNodesResponseParsing(PARSER);
+ }
+
+ public ClearPrivilegesCacheResponse(List nodes, NodesResponseHeader header, String clusterName) {
+ super(nodes, header, clusterName);
+ }
+
+ public static ClearPrivilegesCacheResponse fromXContent(XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+}
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 c5ba7ba6011f3..5c1f454413c7c 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
@@ -30,6 +30,8 @@
import org.elasticsearch.client.security.AuthenticateResponse;
import org.elasticsearch.client.security.AuthenticateResponse.RealmInfo;
import org.elasticsearch.client.security.ChangePasswordRequest;
+import org.elasticsearch.client.security.ClearPrivilegesCacheRequest;
+import org.elasticsearch.client.security.ClearPrivilegesCacheResponse;
import org.elasticsearch.client.security.ClearRealmCacheRequest;
import org.elasticsearch.client.security.ClearRealmCacheResponse;
import org.elasticsearch.client.security.ClearRolesCacheRequest;
@@ -1003,6 +1005,52 @@ public void onFailure(Exception e) {
}
}
+ public void testClearPrivilegesCache() throws Exception {
+ RestHighLevelClient client = highLevelClient();
+ {
+ //tag::clear-privileges-cache-request
+ ClearPrivilegesCacheRequest request = new ClearPrivilegesCacheRequest("my_app"); // <1>
+ //end::clear-privileges-cache-request
+ //tag::clear-privileges-cache-execute
+ ClearPrivilegesCacheResponse response = client.security().clearPrivilegesCache(request, RequestOptions.DEFAULT);
+ //end::clear-privileges-cache-execute
+
+ assertNotNull(response);
+ assertThat(response.getNodes(), not(empty()));
+
+ //tag::clear-privileges-cache-response
+ List nodes = response.getNodes(); // <1>
+ //end::clear-privileges-cache-response
+ }
+
+ {
+ //tag::clear-privileges-cache-execute-listener
+ ClearPrivilegesCacheRequest request = new ClearPrivilegesCacheRequest("my_app");
+ ActionListener listener = new ActionListener<>() {
+ @Override
+ public void onResponse(ClearPrivilegesCacheResponse clearPrivilegesCacheResponse) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ //end::clear-privileges-cache-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::clear-privileges-cache-execute-async
+ client.security().clearPrivilegesCacheAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::clear-privileges-cache-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+ }
+
public void testGetSslCertificates() throws Exception {
RestHighLevelClient client = highLevelClient();
{
diff --git a/docs/java-rest/high-level/security/clear-privileges-cache.asciidoc b/docs/java-rest/high-level/security/clear-privileges-cache.asciidoc
new file mode 100644
index 0000000000000..2376c6a5bd88e
--- /dev/null
+++ b/docs/java-rest/high-level/security/clear-privileges-cache.asciidoc
@@ -0,0 +1,33 @@
+
+--
+:api: clear-privileges-cache
+:request: ClearPrivilegesCacheRequest
+:response: ClearPrivilegesCacheResponse
+--
+[role="xpack"]
+[id="{upid}-{api}"]
+=== Clear Privileges Cache API
+
+[id="{upid}-{api}-request"]
+==== Clear Privileges Cache Request
+
+A +{request}+ supports defining the name of applications that the cache should be cleared for.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> the name of the application(s) for which the cache should be cleared
+
+include::../execution.asciidoc[]
+
+[id="{upid}-{api}-response"]
+==== Clear Privileges Cache Response
+
+The returned +{response}+ allows to retrieve information about where the cache was cleared.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> the list of nodes that the cache was cleared on
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index fba4a96c78dd8..bf9ad52e35071 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -455,6 +455,7 @@ The Java High Level REST Client supports the following Security APIs:
* <<{upid}-get-roles>>
* <>
* <<{upid}-clear-roles-cache>>
+* <<{upid}-clear-privileges-cache>>
* <<{upid}-clear-realm-cache>>
* <<{upid}-authenticate>>
* <<{upid}-has-privileges>>
@@ -486,6 +487,7 @@ include::security/delete-privileges.asciidoc[]
include::security/get-builtin-privileges.asciidoc[]
include::security/get-privileges.asciidoc[]
include::security/clear-roles-cache.asciidoc[]
+include::security/clear-privileges-cache.asciidoc[]
include::security/clear-realm-cache.asciidoc[]
include::security/authenticate.asciidoc[]
include::security/has-privileges.asciidoc[]
diff --git a/x-pack/docs/en/rest-api/security.asciidoc b/x-pack/docs/en/rest-api/security.asciidoc
index 215ad2d1c25a9..5a81fc8d2c7bb 100644
--- a/x-pack/docs/en/rest-api/security.asciidoc
+++ b/x-pack/docs/en/rest-api/security.asciidoc
@@ -15,10 +15,11 @@ You can use the following APIs to perform security activities.
[[security-api-app-privileges]]
=== Application privileges
-You can use the following APIs to add, update, retrieve, and remove application
+You can use the following APIs to add, update, retrieve, and remove application
privileges:
-* <>
+* <>
+* <>
* <>
* <>
@@ -28,7 +29,7 @@ privileges:
You can use the following APIs to add, remove, update, and retrieve role mappings:
-* <>
+* <>
* <>
* <>
@@ -106,6 +107,7 @@ include::security/authenticate.asciidoc[]
include::security/change-password.asciidoc[]
include::security/clear-cache.asciidoc[]
include::security/clear-roles-cache.asciidoc[]
+include::security/clear-privileges-cache.asciidoc[]
include::security/create-api-keys.asciidoc[]
include::security/put-app-privileges.asciidoc[]
include::security/create-role-mappings.asciidoc[]
diff --git a/x-pack/docs/en/rest-api/security/clear-cache.asciidoc b/x-pack/docs/en/rest-api/security/clear-cache.asciidoc
index 2a1a227163da0..fcae76cb99779 100644
--- a/x-pack/docs/en/rest-api/security/clear-cache.asciidoc
+++ b/x-pack/docs/en/rest-api/security/clear-cache.asciidoc
@@ -25,8 +25,10 @@ There are realm settings that you can use to configure the user cache. For more
information, see
<>.
-To evict roles from the role cache, see the
+To evict roles from the role cache, see the
<>.
+To evict privileges from the privilege cache, see the
+<>.
[[security-api-clear-path-params]]
==== {api-path-parms-title}
diff --git a/x-pack/docs/en/rest-api/security/clear-privileges-cache.asciidoc b/x-pack/docs/en/rest-api/security/clear-privileges-cache.asciidoc
new file mode 100644
index 0000000000000..71dbeebcb3d4a
--- /dev/null
+++ b/x-pack/docs/en/rest-api/security/clear-privileges-cache.asciidoc
@@ -0,0 +1,43 @@
+[role="xpack"]
+[[security-api-clear-privilege-cache]]
+=== Clear privileges cache API
+++++
+Clear privileges cache
+++++
+
+Evicts privileges from the native application privilege cache.
+The cache is also automatically cleared for applications that have their privileges updated.
+
+[[security-api-clear-privilege-cache-request]]
+==== {api-request-title}
+
+`POST /_security/privilege//_clear_cache`
+
+[[security-api-clear-privilege-cache-prereqs]]
+==== {api-prereq-title}
+
+* To use this API, you must have at least the `manage_security` cluster
+privilege.
+
+[[security-api-clear-privilege-cache-desc]]
+==== {api-description-title}
+
+For more information about the native realm, see
+<> and <>.
+
+[[security-api-clear-privilege-cache-path-params]]
+==== {api-path-parms-title}
+
+`application`::
+ (string) The name of the application. If omitted, all entries are evicted from the cache.
+
+[[security-api-clear-privilege-cache-example]]
+==== {api-examples-title}
+
+The clear privileges cache API evicts privileges from the native application privilege cache.
+For example, to clear the cache for `myapp`:
+
+[source,console]
+--------------------------------------------------
+POST /_security/privilege/myapp/_clear_cache
+--------------------------------------------------
diff --git a/x-pack/docs/en/rest-api/security/delete-app-privileges.asciidoc b/x-pack/docs/en/rest-api/security/delete-app-privileges.asciidoc
index 0ff3ecc8b4aec..39ac1706c6dc2 100644
--- a/x-pack/docs/en/rest-api/security/delete-app-privileges.asciidoc
+++ b/x-pack/docs/en/rest-api/security/delete-app-privileges.asciidoc
@@ -10,7 +10,7 @@ Removes <>.
[[security-api-delete-privilege-request]]
==== {api-request-title}
-`DELETE /_security/privilege//`
+`DELETE /_security/privilege//`
[[security-api-delete-privilege-prereqs]]
==== {api-prereq-title}
@@ -34,16 +34,16 @@ To use this API, you must have either:
[[security-api-delete-privilege-example]]
==== {api-examples-title}
-The following example deletes the `read` application privilege from the
+The following example deletes the `read` application privilege from the
`myapp` application:
[source,console]
--------------------------------------------------
DELETE /_security/privilege/myapp/read
--------------------------------------------------
-// TEST[setup:app0102_privileges]
+// TEST[setup:app0102_privileges]
-If the role is successfully deleted, the request returns `{"found": true}`.
+If the privilege is successfully deleted, the request returns `{"found": true}`.
Otherwise, `found` is set to false.
[source,console-result]
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheAction.java
new file mode 100644
index 0000000000000..2fbe2e0639112
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheAction.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.security.action.privilege;
+
+import org.elasticsearch.action.ActionType;
+
+public class ClearPrivilegesCacheAction extends ActionType {
+
+ public static final ClearPrivilegesCacheAction INSTANCE = new ClearPrivilegesCacheAction();
+ public static final String NAME = "cluster:admin/xpack/security/privilege/cache/clear";
+
+ protected ClearPrivilegesCacheAction() {
+ super(NAME, ClearPrivilegesCacheResponse::new);
+ }
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheRequest.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheRequest.java
new file mode 100644
index 0000000000000..04acc372dfb56
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheRequest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.security.action.privilege;
+
+import org.elasticsearch.action.support.nodes.BaseNodesRequest;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.transport.TransportRequest;
+
+import java.io.IOException;
+
+public class ClearPrivilegesCacheRequest extends BaseNodesRequest {
+
+ private String[] applicationNames;
+ private boolean clearRolesCache = false;
+
+ public ClearPrivilegesCacheRequest() {
+ super((String[]) null);
+ }
+
+ public ClearPrivilegesCacheRequest(StreamInput in) throws IOException {
+ super(in);
+ applicationNames = in.readOptionalStringArray();
+ clearRolesCache = in.readBoolean();
+ }
+
+ public ClearPrivilegesCacheRequest applicationNames(String... applicationNames) {
+ this.applicationNames = applicationNames;
+ return this;
+ }
+
+ public ClearPrivilegesCacheRequest clearRolesCache(boolean clearRolesCache) {
+ this.clearRolesCache = clearRolesCache;
+ return this;
+ }
+
+ public String[] applicationNames() {
+ return applicationNames;
+ }
+
+ public boolean clearRolesCache() {
+ return clearRolesCache;
+ }
+
+ @Override
+ public void writeTo(StreamOutput out) throws IOException {
+ super.writeTo(out);
+ out.writeOptionalStringArray(applicationNames);
+ out.writeBoolean(clearRolesCache);
+ }
+
+ public static class Node extends TransportRequest {
+ private String[] applicationNames;
+ private boolean clearRolesCache;
+
+ public Node(StreamInput in) throws IOException {
+ super(in);
+ applicationNames = in.readOptionalStringArray();
+ clearRolesCache = in.readBoolean();
+ }
+
+ public Node(ClearPrivilegesCacheRequest request) {
+ this.applicationNames = request.applicationNames();
+ this.clearRolesCache = request.clearRolesCache;
+ }
+
+ public String[] getApplicationNames() {
+ return applicationNames;
+ }
+
+ public boolean clearRolesCache() {
+ return clearRolesCache;
+ }
+
+ @Override
+ public void writeTo(StreamOutput out) throws IOException {
+ super.writeTo(out);
+ out.writeOptionalStringArray(applicationNames);
+ out.writeBoolean(clearRolesCache);
+ }
+ }
+}
diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheResponse.java
new file mode 100644
index 0000000000000..85dcc3b94650f
--- /dev/null
+++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/privilege/ClearPrivilegesCacheResponse.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+package org.elasticsearch.xpack.core.security.action.privilege;
+
+import org.elasticsearch.action.FailedNodeException;
+import org.elasticsearch.action.support.nodes.BaseNodeResponse;
+import org.elasticsearch.action.support.nodes.BaseNodesResponse;
+import org.elasticsearch.cluster.ClusterName;
+import org.elasticsearch.cluster.node.DiscoveryNode;
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.xcontent.ToXContentFragment;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+
+import java.io.IOException;
+import java.util.List;
+
+public class ClearPrivilegesCacheResponse extends BaseNodesResponse
+ implements ToXContentFragment {
+
+ public ClearPrivilegesCacheResponse(StreamInput in) throws IOException {
+ super(in);
+ }
+
+ public ClearPrivilegesCacheResponse(ClusterName clusterName, List nodes, List failures) {
+ super(clusterName, nodes, failures);
+ }
+
+ @Override
+ protected List readNodesFrom(StreamInput in) throws IOException {
+ return in.readList(Node::new);
+ }
+
+ @Override
+ protected void writeNodesTo(StreamOutput out, List nodes) throws IOException {
+ out.writeList(nodes);
+ }
+
+ @Override
+ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+ builder.startObject("nodes");
+ for (Node node : getNodes()) {
+ builder.startObject(node.getNode().getId());
+ builder.field("name", node.getNode().getName());
+ builder.endObject();
+ }
+ builder.endObject();
+ return builder;
+ }
+
+ public static class Node extends BaseNodeResponse {
+ public Node(StreamInput in) throws IOException {
+ super(in);
+ }
+
+ public Node(DiscoveryNode node) {
+ super(node);
+ }
+ }
+}
diff --git a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
index 3b0f1b1228313..a272c506fa1ea 100644
--- a/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
+++ b/x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/Security.java
@@ -89,6 +89,7 @@
import org.elasticsearch.xpack.core.security.action.oidc.OpenIdConnectAuthenticateAction;
import org.elasticsearch.xpack.core.security.action.oidc.OpenIdConnectLogoutAction;
import org.elasticsearch.xpack.core.security.action.oidc.OpenIdConnectPrepareAuthenticationAction;
+import org.elasticsearch.xpack.core.security.action.privilege.ClearPrivilegesCacheAction;
import org.elasticsearch.xpack.core.security.action.privilege.DeletePrivilegesAction;
import org.elasticsearch.xpack.core.security.action.privilege.GetBuiltinPrivilegesAction;
import org.elasticsearch.xpack.core.security.action.privilege.GetPrivilegesAction;
@@ -153,6 +154,7 @@
import org.elasticsearch.xpack.security.action.oidc.TransportOpenIdConnectAuthenticateAction;
import org.elasticsearch.xpack.security.action.oidc.TransportOpenIdConnectLogoutAction;
import org.elasticsearch.xpack.security.action.oidc.TransportOpenIdConnectPrepareAuthenticationAction;
+import org.elasticsearch.xpack.security.action.privilege.TransportClearPrivilegesCacheAction;
import org.elasticsearch.xpack.security.action.privilege.TransportDeletePrivilegesAction;
import org.elasticsearch.xpack.security.action.privilege.TransportGetBuiltinPrivilegesAction;
import org.elasticsearch.xpack.security.action.privilege.TransportGetPrivilegesAction;
@@ -220,6 +222,7 @@
import org.elasticsearch.xpack.security.rest.action.oidc.RestOpenIdConnectAuthenticateAction;
import org.elasticsearch.xpack.security.rest.action.oidc.RestOpenIdConnectLogoutAction;
import org.elasticsearch.xpack.security.rest.action.oidc.RestOpenIdConnectPrepareAuthenticationAction;
+import org.elasticsearch.xpack.security.rest.action.privilege.RestClearPrivilegesCacheAction;
import org.elasticsearch.xpack.security.rest.action.privilege.RestDeletePrivilegesAction;
import org.elasticsearch.xpack.security.rest.action.privilege.RestGetBuiltinPrivilegesAction;
import org.elasticsearch.xpack.security.rest.action.privilege.RestGetPrivilegesAction;
@@ -430,6 +433,7 @@ Collection