Skip to content

Commit 149ca9c

Browse files
committed
HLRC: Implement get-user-privileges API (#36292)
This adds the _security/user/_privileges API to the High Level Rest Client. This also makes some changes to the Java model for the Role APIs in order to better accommodate the GetPrivileges API
1 parent 0f64235 commit 149ca9c

File tree

15 files changed

+958
-149
lines changed

15 files changed

+958
-149
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/SecurityClient.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
import org.elasticsearch.client.security.GetRolesResponse;
4949
import org.elasticsearch.client.security.GetSslCertificatesRequest;
5050
import org.elasticsearch.client.security.GetSslCertificatesResponse;
51+
import org.elasticsearch.client.security.GetUserPrivilegesRequest;
52+
import org.elasticsearch.client.security.GetUserPrivilegesResponse;
5153
import org.elasticsearch.client.security.GetUsersRequest;
5254
import org.elasticsearch.client.security.GetUsersResponse;
5355
import org.elasticsearch.client.security.HasPrivilegesRequest;
@@ -340,6 +342,25 @@ public void hasPrivilegesAsync(HasPrivilegesRequest request, RequestOptions opti
340342
HasPrivilegesResponse::fromXContent, listener, emptySet());
341343
}
342344

345+
/**
346+
* Retrieve the set of effective privileges held by the current user.
347+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
348+
*/
349+
public GetUserPrivilegesResponse getUserPrivileges(RequestOptions options) throws IOException {
350+
return restHighLevelClient.performRequestAndParseEntity(GetUserPrivilegesRequest.INSTANCE, GetUserPrivilegesRequest::getRequest,
351+
options, GetUserPrivilegesResponse::fromXContent, emptySet());
352+
}
353+
354+
/**
355+
* Asynchronously retrieve the set of effective privileges held by the current user.
356+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
357+
* @param listener the listener to be notified upon request completion
358+
*/
359+
public void getUserPrivilegesAsync(RequestOptions options, ActionListener<GetUserPrivilegesResponse> listener) {
360+
restHighLevelClient.performRequestAsyncAndParseEntity(GetUserPrivilegesRequest.INSTANCE, GetUserPrivilegesRequest::getRequest,
361+
options, GetUserPrivilegesResponse::fromXContent, listener, emptySet());
362+
}
363+
343364
/**
344365
* Clears the cache in one or more realms.
345366
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-clear-cache.html">
@@ -726,5 +747,4 @@ public void deletePrivilegesAsync(DeletePrivilegesRequest request, RequestOption
726747
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::deletePrivileges, options,
727748
DeletePrivilegesResponse::fromXContent, listener, singleton(404));
728749
}
729-
730750
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.security;
21+
22+
import org.apache.http.client.methods.HttpGet;
23+
import org.elasticsearch.client.Request;
24+
import org.elasticsearch.client.RequestOptions;
25+
import org.elasticsearch.client.Validatable;
26+
27+
/**
28+
* A request object for the {@link org.elasticsearch.client.SecurityClient#getUserPrivileges(RequestOptions)} API.
29+
* This request takes no parameters, and has a singleton {@link #INSTANCE}.
30+
*/
31+
public class GetUserPrivilegesRequest implements Validatable {
32+
33+
public static final GetUserPrivilegesRequest INSTANCE = new GetUserPrivilegesRequest();
34+
35+
private GetUserPrivilegesRequest() {
36+
}
37+
38+
public Request getRequest() {
39+
return new Request(HttpGet.METHOD_NAME, "/_security/user/_privileges");
40+
}
41+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.security;
21+
22+
import org.elasticsearch.client.RequestOptions;
23+
import org.elasticsearch.client.security.user.privileges.ApplicationResourcePrivileges;
24+
import org.elasticsearch.client.security.user.privileges.GlobalPrivileges;
25+
import org.elasticsearch.client.security.user.privileges.UserIndicesPrivileges;
26+
import org.elasticsearch.common.ParseField;
27+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
28+
import org.elasticsearch.common.xcontent.XContentParser;
29+
30+
import java.io.IOException;
31+
import java.util.Collection;
32+
import java.util.Collections;
33+
import java.util.LinkedHashSet;
34+
import java.util.Objects;
35+
import java.util.Set;
36+
37+
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
38+
39+
/**
40+
* The response for the {@link org.elasticsearch.client.SecurityClient#getUserPrivileges(RequestOptions)} API.
41+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-get-user-privileges.html">the API docs</a>
42+
*/
43+
public class GetUserPrivilegesResponse {
44+
45+
private static final ConstructingObjectParser<GetUserPrivilegesResponse, Void> PARSER = new ConstructingObjectParser<>(
46+
"get_user_privileges_response", true, GetUserPrivilegesResponse::buildResponseFromParserArgs);
47+
48+
@SuppressWarnings("unchecked")
49+
private static GetUserPrivilegesResponse buildResponseFromParserArgs(Object[] args) {
50+
return new GetUserPrivilegesResponse(
51+
(Collection<String>) args[0],
52+
(Collection<GlobalPrivileges>) args[1],
53+
(Collection<UserIndicesPrivileges>) args[2],
54+
(Collection<ApplicationResourcePrivileges>) args[3],
55+
(Collection<String>) args[4]
56+
);
57+
}
58+
59+
static {
60+
PARSER.declareStringArray(constructorArg(), new ParseField("cluster"));
61+
PARSER.declareObjectArray(constructorArg(), (parser, ignore) -> GlobalPrivileges.fromXContent(parser),
62+
new ParseField("global"));
63+
PARSER.declareObjectArray(constructorArg(), (parser, ignore) -> UserIndicesPrivileges.fromXContent(parser),
64+
new ParseField("indices"));
65+
PARSER.declareObjectArray(constructorArg(), (parser, ignore) -> ApplicationResourcePrivileges.fromXContent(parser),
66+
new ParseField("applications"));
67+
PARSER.declareStringArray(constructorArg(), new ParseField("run_as"));
68+
}
69+
70+
public static GetUserPrivilegesResponse fromXContent(XContentParser parser) throws IOException {
71+
return PARSER.parse(parser, null);
72+
}
73+
74+
private Set<String> clusterPrivileges;
75+
private Set<GlobalPrivileges> globalPrivileges;
76+
private Set<UserIndicesPrivileges> indicesPrivileges;
77+
private Set<ApplicationResourcePrivileges> applicationPrivileges;
78+
private Set<String> runAsPrivilege;
79+
80+
public GetUserPrivilegesResponse(Collection<String> clusterPrivileges, Collection<GlobalPrivileges> globalPrivileges,
81+
Collection<UserIndicesPrivileges> indicesPrivileges,
82+
Collection<ApplicationResourcePrivileges> applicationPrivileges, Collection<String> runAsPrivilege) {
83+
this.clusterPrivileges = Collections.unmodifiableSet(new LinkedHashSet<>(clusterPrivileges));
84+
this.globalPrivileges = Collections.unmodifiableSet(new LinkedHashSet<>(globalPrivileges));
85+
this.indicesPrivileges = Collections.unmodifiableSet(new LinkedHashSet<>(indicesPrivileges));
86+
this.applicationPrivileges = Collections.unmodifiableSet(new LinkedHashSet<>(applicationPrivileges));
87+
this.runAsPrivilege = Collections.unmodifiableSet(new LinkedHashSet<>(runAsPrivilege));
88+
}
89+
90+
public Set<String> getClusterPrivileges() {
91+
return clusterPrivileges;
92+
}
93+
94+
public Set<GlobalPrivileges> getGlobalPrivileges() {
95+
return globalPrivileges;
96+
}
97+
98+
public Set<UserIndicesPrivileges> getIndicesPrivileges() {
99+
return indicesPrivileges;
100+
}
101+
102+
public Set<ApplicationResourcePrivileges> getApplicationPrivileges() {
103+
return applicationPrivileges;
104+
}
105+
106+
public Set<String> getRunAsPrivilege() {
107+
return runAsPrivilege;
108+
}
109+
110+
@Override
111+
public String toString() {
112+
return "GetUserPrivilegesResponse{" +
113+
"clusterPrivileges=" + clusterPrivileges +
114+
", globalPrivileges=" + globalPrivileges +
115+
", indicesPrivileges=" + indicesPrivileges +
116+
", applicationPrivileges=" + applicationPrivileges +
117+
", runAsPrivilege=" + runAsPrivilege +
118+
'}';
119+
}
120+
121+
@Override
122+
public boolean equals(Object o) {
123+
if (this == o) {
124+
return true;
125+
}
126+
if (o == null || getClass() != o.getClass()) {
127+
return false;
128+
}
129+
final GetUserPrivilegesResponse that = (GetUserPrivilegesResponse) o;
130+
return Objects.equals(this.clusterPrivileges, that.clusterPrivileges) &&
131+
Objects.equals(this.globalPrivileges, that.globalPrivileges) &&
132+
Objects.equals(this.indicesPrivileges, that.indicesPrivileges) &&
133+
Objects.equals(this.applicationPrivileges, that.applicationPrivileges) &&
134+
Objects.equals(this.runAsPrivilege, that.runAsPrivilege);
135+
}
136+
137+
@Override
138+
public int hashCode() {
139+
return Objects.hash(clusterPrivileges, globalPrivileges, indicesPrivileges, applicationPrivileges, runAsPrivilege);
140+
}
141+
}

client/rest-high-level/src/main/java/org/elasticsearch/client/security/PutRoleRequest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ public boolean equals(Object obj) {
7474
@Override
7575
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
7676
builder.startObject();
77-
if (role.getApplicationResourcePrivileges() != null) {
78-
builder.field(Role.APPLICATIONS.getPreferredName(), role.getApplicationResourcePrivileges());
77+
if (role.getApplicationPrivileges() != null) {
78+
builder.field(Role.APPLICATIONS.getPreferredName(), role.getApplicationPrivileges());
7979
}
8080
if (role.getClusterPrivileges() != null) {
8181
builder.field(Role.CLUSTER.getPreferredName(), role.getClusterPrivileges());
8282
}
83-
if (role.getGlobalApplicationPrivileges() != null) {
84-
builder.field(Role.GLOBAL.getPreferredName(), role.getGlobalApplicationPrivileges());
83+
if (role.getGlobalPrivileges() != null) {
84+
builder.field(Role.GLOBAL.getPreferredName(), role.getGlobalPrivileges());
8585
}
8686
if (role.getIndicesPrivileges() != null) {
8787
builder.field(Role.INDICES.getPreferredName(), role.getIndicesPrivileges());

0 commit comments

Comments
 (0)