Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLRC: add enable and disable user API support #33481

Merged
merged 3 commits into from
Sep 7, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
package org.elasticsearch.client;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.security.DisableUserRequest;
import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.PutUserResponse;
import org.elasticsearch.client.security.EmptyResponse;

import java.io.IOException;

Expand Down Expand Up @@ -66,4 +69,60 @@ public void putUserAsync(PutUserRequest request, RequestOptions options, ActionL
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::putUser, options,
PutUserResponse::fromXContent, listener, emptySet());
}

/**
* Enable a native realm or built-in user synchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html">
* the docs</a> for more.
* @param request the request with the user to enable
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response from the enable user call
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public EmptyResponse enableUser(EnableUserRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::enableUser, options,
EmptyResponse::fromXContent, emptySet());
}

/**
* Enable a native realm or built-in user asynchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-enable-user.html">
* the docs</a> for more.
* @param request the request with the user to enable
* @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 enableUserAsync(EnableUserRequest request, RequestOptions options,
ActionListener<EmptyResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::enableUser, options,
EmptyResponse::fromXContent, listener, emptySet());
}

/**
* Disable a native realm or built-in user synchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-disable-user.html">
* the docs</a> for more.
* @param request the request with the user to disable
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response from the enable user call
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public EmptyResponse disableUser(DisableUserRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, SecurityRequestConverters::disableUser, options,
EmptyResponse::fromXContent, emptySet());
}

/**
* Disable a native realm or built-in user asynchronously.
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-disable-user.html">
* the docs</a> for more.
* @param request the request with the user to disable
* @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 disableUserAsync(DisableUserRequest request, RequestOptions options,
ActionListener<EmptyResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, SecurityRequestConverters::disableUser, options,
EmptyResponse::fromXContent, listener, emptySet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@
package org.elasticsearch.client;

import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.security.DisableUserRequest;
import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.SetUserEnabledRequest;

import java.io.IOException;

import static org.elasticsearch.client.RequestConverters.REQUEST_BODY_CONTENT_TYPE;
import static org.elasticsearch.client.RequestConverters.createEntity;

public final class SecurityRequestConverters {
final class SecurityRequestConverters {

private SecurityRequestConverters() {}

Expand All @@ -42,4 +45,24 @@ static Request putUser(PutUserRequest putUserRequest) throws IOException {
params.withRefreshPolicy(putUserRequest.getRefreshPolicy());
return request;
}

static Request enableUser(EnableUserRequest enableUserRequest) {
return setUserEnabled(enableUserRequest);
}

static Request disableUser(DisableUserRequest disableUserRequest) {
return setUserEnabled(disableUserRequest);
}

private static Request setUserEnabled(SetUserEnabledRequest setUserEnabledRequest) {
String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_xpack/security/user")
.addPathPart(setUserEnabledRequest.getUsername())
.addPathPart(setUserEnabledRequest.isEnabled() ? "_enable" : "_disable")
.build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params(request);
params.withRefreshPolicy(setUserEnabledRequest.getRefreshPolicy());
return request;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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;

/**
* Request object to disable a native realm or built-in user.
*/
public final class DisableUserRequest extends SetUserEnabledRequest {

public DisableUserRequest(String username, RefreshPolicy refreshPolicy) {
super(false, username, refreshPolicy);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;

import java.io.IOException;

/**
* Response for a request which simply returns an empty object.
*/
public final class EmptyResponse {

private static final ObjectParser<EmptyResponse, Void> PARSER = new ObjectParser<>("empty_response", false, EmptyResponse::new);

public static EmptyResponse fromXContent(XContentParser parser) throws IOException {
return PARSER.parse(parser, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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;

/**
* Request object to enable a native realm or built-in user.
*/
public final class EnableUserRequest extends SetUserEnabledRequest {

public EnableUserRequest(String username, RefreshPolicy refreshPolicy) {
super(true, username, refreshPolicy);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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;

/**
* Abstract request object to enable or disable a built-in or native user.
*/
public abstract class SetUserEnabledRequest implements Validatable {

private final boolean enabled;
private final String username;
private final RefreshPolicy refreshPolicy;

SetUserEnabledRequest(boolean enabled, String username, RefreshPolicy refreshPolicy) {
this.enabled = enabled;
this.username = Objects.requireNonNull(username, "username is required");
this.refreshPolicy = refreshPolicy == null ? RefreshPolicy.getDefault() : refreshPolicy;
}

public boolean isEnabled() {
return enabled;
}

public String getUsername() {
return username;
}

public RefreshPolicy getRefreshPolicy() {
return refreshPolicy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package org.elasticsearch.client;

import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.security.DisableUserRequest;
import org.elasticsearch.client.security.EnableUserRequest;
import org.elasticsearch.client.security.PutUserRequest;
import org.elasticsearch.client.security.RefreshPolicy;
import org.elasticsearch.test.ESTestCase;
Expand Down Expand Up @@ -53,12 +55,7 @@ public void testPutUser() throws IOException {
}

final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
final Map<String, String> expectedParams;
if (refreshPolicy != RefreshPolicy.NONE) {
expectedParams = Collections.singletonMap("refresh", refreshPolicy.getValue());
} else {
expectedParams = Collections.emptyMap();
}
final Map<String, String> expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);

PutUserRequest putUserRequest = new PutUserRequest(username, password, roles, fullName, email, enabled, metadata, refreshPolicy);
Request request = SecurityRequestConverters.putUser(putUserRequest);
Expand All @@ -67,4 +64,36 @@ public void testPutUser() throws IOException {
assertEquals(expectedParams, request.getParameters());
assertToXContentBody(putUserRequest, request.getEntity());
}

public void testEnableUser() {
final String username = randomAlphaOfLengthBetween(1, 12);
final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
final Map<String, String> expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);
EnableUserRequest enableUserRequest = new EnableUserRequest(username, refreshPolicy);
Request request = SecurityRequestConverters.enableUser(enableUserRequest);
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
assertEquals("/_xpack/security/user/" + username + "/_enable", request.getEndpoint());
assertEquals(expectedParams, request.getParameters());
assertNull(request.getEntity());
}

public void testDisableUser() {
final String username = randomAlphaOfLengthBetween(1, 12);
final RefreshPolicy refreshPolicy = randomFrom(RefreshPolicy.values());
final Map<String, String> expectedParams = getExpectedParamsFromRefreshPolicy(refreshPolicy);
DisableUserRequest disableUserRequest = new DisableUserRequest(username, refreshPolicy);
Request request = SecurityRequestConverters.disableUser(disableUserRequest);
assertEquals(HttpPut.METHOD_NAME, request.getMethod());
assertEquals("/_xpack/security/user/" + username + "/_disable", request.getEndpoint());
assertEquals(expectedParams, request.getParameters());
assertNull(request.getEntity());
}

private static Map<String, String> getExpectedParamsFromRefreshPolicy(RefreshPolicy refreshPolicy) {
if (refreshPolicy != RefreshPolicy.NONE) {
return Collections.singletonMap("refresh", refreshPolicy.getValue());
} else {
return Collections.emptyMap();
}
}
}
Loading