Skip to content

Commit 8b56b7c

Browse files
committed
HLRC: add enable and disable user API support (#33481)
This change adds support for enable and disable user APIs to the high level rest client. There is a common request base class for both requests with specific requests that simplify the use of these APIs. The response for these APIs is simply an empty object so a new response class has been created for cases where we expect an empty response to be returned. Finally, the put user documentation has been moved to the proper location that is not within an x-pack sub directory and the document tags no longer contain x-pack. See #29827
1 parent 7a0872d commit 8b56b7c

File tree

13 files changed

+535
-28
lines changed

13 files changed

+535
-28
lines changed

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
package org.elasticsearch.client;
2121

2222
import org.elasticsearch.action.ActionListener;
23+
import org.elasticsearch.client.security.DisableUserRequest;
24+
import org.elasticsearch.client.security.EnableUserRequest;
2325
import org.elasticsearch.client.security.PutUserRequest;
2426
import org.elasticsearch.client.security.PutUserResponse;
27+
import org.elasticsearch.client.security.EmptyResponse;
2528

2629
import java.io.IOException;
2730

@@ -66,4 +69,60 @@ public void putUserAsync(PutUserRequest request, RequestOptions options, ActionL
6669
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putUser, options,
6770
PutUserResponse::fromXContent, listener, emptySet());
6871
}
72+
73+
/**
74+
* Enable a native realm or built-in user synchronously.
75+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html">
76+
* the docs</a> for more.
77+
* @param request the request with the user to enable
78+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
79+
* @return the response from the enable user call
80+
* @throws IOException in case there is a problem sending the request or parsing back the response
81+
*/
82+
public EmptyResponse enableUser(EnableUserRequest request, RequestOptions options) throws IOException {
83+
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::enableUser, options,
84+
EmptyResponse::fromXContent, emptySet());
85+
}
86+
87+
/**
88+
* Enable a native realm or built-in user asynchronously.
89+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html">
90+
* the docs</a> for more.
91+
* @param request the request with the user to enable
92+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
93+
* @param listener the listener to be notified upon request completion
94+
*/
95+
public void enableUserAsync(EnableUserRequest request, RequestOptions options,
96+
ActionListener<EmptyResponse> listener) {
97+
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::enableUser, options,
98+
EmptyResponse::fromXContent, listener, emptySet());
99+
}
100+
101+
/**
102+
* Disable a native realm or built-in user synchronously.
103+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-disable-user.html">
104+
* the docs</a> for more.
105+
* @param request the request with the user to disable
106+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
107+
* @return the response from the enable user call
108+
* @throws IOException in case there is a problem sending the request or parsing back the response
109+
*/
110+
public EmptyResponse disableUser(DisableUserRequest request, RequestOptions options) throws IOException {
111+
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::disableUser, options,
112+
EmptyResponse::fromXContent, emptySet());
113+
}
114+
115+
/**
116+
* Disable a native realm or built-in user asynchronously.
117+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-disable-user.html">
118+
* the docs</a> for more.
119+
* @param request the request with the user to disable
120+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
121+
* @param listener the listener to be notified upon request completion
122+
*/
123+
public void disableUserAsync(DisableUserRequest request, RequestOptions options,
124+
ActionListener<EmptyResponse> listener) {
125+
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::disableUser, options,
126+
EmptyResponse::fromXContent, listener, emptySet());
127+
}
69128
}

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,17 @@
2020
package org.elasticsearch.client;
2121

2222
import org.apache.http.client.methods.HttpPut;
23+
import org.elasticsearch.client.security.DisableUserRequest;
24+
import org.elasticsearch.client.security.EnableUserRequest;
2325
import org.elasticsearch.client.security.PutUserRequest;
26+
import org.elasticsearch.client.security.SetUserEnabledRequest;
2427

2528
import java.io.IOException;
2629

2730
import static org.elasticsearch.client.RequestConverters.REQUEST_BODY_CONTENT_TYPE;
2831
import static org.elasticsearch.client.RequestConverters.createEntity;
2932

30-
public final class SecurityRequestConverters {
33+
final class SecurityRequestConverters {
3134

3235
private SecurityRequestConverters() {}
3336

@@ -42,4 +45,24 @@ static Request putUser(PutUserRequest putUserRequest) throws IOException {
4245
params.withRefreshPolicy(putUserRequest.getRefreshPolicy());
4346
return request;
4447
}
48+
49+
static Request enableUser(EnableUserRequest enableUserRequest) {
50+
return setUserEnabled(enableUserRequest);
51+
}
52+
53+
static Request disableUser(DisableUserRequest disableUserRequest) {
54+
return setUserEnabled(disableUserRequest);
55+
}
56+
57+
private static Request setUserEnabled(SetUserEnabledRequest setUserEnabledRequest) {
58+
String endpoint = new RequestConverters.EndpointBuilder()
59+
.addPathPartAsIs("_xpack/security/user")
60+
.addPathPart(setUserEnabledRequest.getUsername())
61+
.addPathPart(setUserEnabledRequest.isEnabled() ? "_enable" : "_disable")
62+
.build();
63+
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
64+
RequestConverters.Params params = new RequestConverters.Params(request);
65+
params.withRefreshPolicy(setUserEnabledRequest.getRefreshPolicy());
66+
return request;
67+
}
4568
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
/**
23+
* Request object to disable a native realm or built-in user.
24+
*/
25+
public final class DisableUserRequest extends SetUserEnabledRequest {
26+
27+
public DisableUserRequest(String username, RefreshPolicy refreshPolicy) {
28+
super(false, username, refreshPolicy);
29+
}
30+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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.common.xcontent.ObjectParser;
23+
import org.elasticsearch.common.xcontent.XContentParser;
24+
25+
import java.io.IOException;
26+
27+
/**
28+
* Response for a request which simply returns an empty object.
29+
*/
30+
public final class EmptyResponse {
31+
32+
private static final ObjectParser<EmptyResponse, Void> PARSER = new ObjectParser<>("empty_response", false, EmptyResponse::new);
33+
34+
public static EmptyResponse fromXContent(XContentParser parser) throws IOException {
35+
return PARSER.parse(parser, null);
36+
}
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
/**
23+
* Request object to enable a native realm or built-in user.
24+
*/
25+
public final class EnableUserRequest extends SetUserEnabledRequest {
26+
27+
public EnableUserRequest(String username, RefreshPolicy refreshPolicy) {
28+
super(true, username, refreshPolicy);
29+
}
30+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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.Validatable;
23+
24+
import java.util.Objects;
25+
26+
/**
27+
* Abstract request object to enable or disable a built-in or native user.
28+
*/
29+
public abstract class SetUserEnabledRequest implements Validatable {
30+
31+
private final boolean enabled;
32+
private final String username;
33+
private final RefreshPolicy refreshPolicy;
34+
35+
SetUserEnabledRequest(boolean enabled, String username, RefreshPolicy refreshPolicy) {
36+
this.enabled = enabled;
37+
this.username = Objects.requireNonNull(username, "username is required");
38+
this.refreshPolicy = refreshPolicy == null ? RefreshPolicy.getDefault() : refreshPolicy;
39+
}
40+
41+
public boolean isEnabled() {
42+
return enabled;
43+
}
44+
45+
public String getUsername() {
46+
return username;
47+
}
48+
49+
public RefreshPolicy getRefreshPolicy() {
50+
return refreshPolicy;
51+
}
52+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityRequestConvertersTests.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package org.elasticsearch.client;
2121

2222
import org.apache.http.client.methods.HttpPut;
23+
import org.elasticsearch.client.security.DisableUserRequest;
24+
import org.elasticsearch.client.security.EnableUserRequest;
2325
import org.elasticsearch.client.security.PutUserRequest;
2426
import org.elasticsearch.client.security.RefreshPolicy;
2527
import org.elasticsearch.test.ESTestCase;
@@ -53,12 +55,7 @@ public void testPutUser() throws IOException {
5355
}
5456

5557
final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
56-
final Map<String, String> expectedParams;
57-
if (refreshPolicy != RefreshPolicy.NONE) {
58-
expectedParams = Collections.singletonMap("refresh", refreshPolicy.getValue());
59-
} else {
60-
expectedParams = Collections.emptyMap();
61-
}
58+
final Map<String, String> expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);
6259

6360
PutUserRequest putUserRequest = new PutUserRequest(username, password, roles, fullName, email, enabled, metadata, refreshPolicy);
6461
Request request = SecurityRequestConverters.putUser(putUserRequest);
@@ -67,4 +64,36 @@ public void testPutUser() throws IOException {
6764
assertEquals(expectedParams, request.getParameters());
6865
assertToXContentBody(putUserRequest, request.getEntity());
6966
}
67+
68+
public void testEnableUser() {
69+
final String username = randomAlphaOfLengthBetween(1, 12);
70+
final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
71+
final Map<String, String> expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);
72+
EnableUserRequest enableUserRequest = new EnableUserRequest(username, refreshPolicy);
73+
Request request = SecurityRequestConverters.enableUser(enableUserRequest);
74+
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
75+
assertEquals("/_xpack/security/user/" + username + "/_enable", request.getEndpoint());
76+
assertEquals(expectedParams, request.getParameters());
77+
assertNull(request.getEntity());
78+
}
79+
80+
public void testDisableUser() {
81+
final String username = randomAlphaOfLengthBetween(1, 12);
82+
final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
83+
final Map<String, String> expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);
84+
DisableUserRequest disableUserRequest = new DisableUserRequest(username, refreshPolicy);
85+
Request request = SecurityRequestConverters.disableUser(disableUserRequest);
86+
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
87+
assertEquals("/_xpack/security/user/" + username + "/_disable", request.getEndpoint());
88+
assertEquals(expectedParams, request.getParameters());
89+
assertNull(request.getEntity());
90+
}
91+
92+
private static Map<String, String> getExpectedParamsFromRefreshPolicy(RefreshPolicy refreshPolicy) {
93+
if (refreshPolicy != RefreshPolicy.NONE) {
94+
return Collections.singletonMap("refresh", refreshPolicy.getValue());
95+
} else {
96+
return Collections.emptyMap();
97+
}
98+
}
7099
}

0 commit comments

Comments
 (0)