security: filter content of known requests with passwords (elastic/elasticsearch#4700)
This commit adds a mechanism for defining known sensitive values in rest bodies so that these can be filtered when auditing the request body. Original commit: elastic/x-pack-elasticsearch@d138a6bff7
This commit is contained in:
parent
d690c5f789
commit
9005e9fdb9
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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.security.rest;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Identifies an object that supplies a filter for the content of a {@link RestRequest}. This interface should be implemented by a
|
||||
* {@link org.elasticsearch.rest.RestHandler} that expects there will be sensitive content in the body of the request such as a password
|
||||
*/
|
||||
public interface RestRequestFilter {
|
||||
|
||||
/**
|
||||
* Wraps the RestRequest and returns a version that provides the filtered content
|
||||
*/
|
||||
default RestRequest getFilteredRequest(RestRequest restRequest) throws IOException {
|
||||
Set<String> fields = getFilteredFields();
|
||||
if (restRequest.hasContent() && fields.isEmpty() == false) {
|
||||
return new RestRequest(restRequest.getXContentRegistry(), restRequest.params(), restRequest.path()) {
|
||||
|
||||
private BytesReference filteredBytes = null;
|
||||
|
||||
@Override
|
||||
public Method method() {
|
||||
return restRequest.method();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uri() {
|
||||
return restRequest.uri();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasContent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BytesReference content() {
|
||||
if (filteredBytes == null) {
|
||||
BytesReference content = restRequest.content();
|
||||
Tuple<XContentType, Map<String, Object>> result = XContentHelper.convertToMap(content, true);
|
||||
Map<String, Object> transformedSource = XContentMapValues.filter(result.v2(), null,
|
||||
fields.toArray(Strings.EMPTY_ARRAY));
|
||||
try {
|
||||
XContentBuilder xContentBuilder = XContentBuilder.builder(result.v1().xContent()).map(transformedSource);
|
||||
filteredBytes = xContentBuilder.bytes();
|
||||
} catch (IOException e) {
|
||||
throw new ElasticsearchException("failed to parse request", e);
|
||||
}
|
||||
}
|
||||
return filteredBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String header(String name) {
|
||||
return restRequest.header(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<Entry<String, String>> headers() {
|
||||
return restRequest.headers();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return restRequest;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of fields that should be filtered. This can be a dot separated pattern to match sub objects and also supports wildcards
|
||||
*/
|
||||
Set<String> getFilteredFields();
|
||||
}
|
|
@ -25,6 +25,8 @@ import org.elasticsearch.xpack.security.authc.AuthenticationService;
|
|||
import org.elasticsearch.xpack.security.transport.ServerTransportFilter;
|
||||
import org.elasticsearch.xpack.ssl.SSLService;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.XPackSettings.HTTP_SSL_ENABLED;
|
||||
|
||||
public class SecurityRestFilter implements RestHandler {
|
||||
|
@ -58,7 +60,7 @@ public class SecurityRestFilter implements RestHandler {
|
|||
assert handler != null;
|
||||
ServerTransportFilter.extactClientCertificates(logger, threadContext, handler.engine(), nettyHttpRequest.getChannel());
|
||||
}
|
||||
service.authenticate(request, ActionListener.wrap(
|
||||
service.authenticate(maybeWrapRestRequest(request), ActionListener.wrap(
|
||||
authentication -> {
|
||||
RemoteHostHeader.process(request, threadContext);
|
||||
restHandler.handleRequest(request, channel, client);
|
||||
|
@ -75,4 +77,11 @@ public class SecurityRestFilter implements RestHandler {
|
|||
restHandler.handleRequest(request, channel, client);
|
||||
}
|
||||
}
|
||||
|
||||
RestRequest maybeWrapRestRequest(RestRequest restRequest) throws IOException {
|
||||
if (restHandler instanceof RestRequestFilter) {
|
||||
return ((RestRequestFilter)restHandler).getFilteredRequest(restRequest);
|
||||
}
|
||||
return restRequest;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,14 +18,17 @@ import org.elasticsearch.rest.action.RestBuilderListener;
|
|||
import org.elasticsearch.xpack.security.SecurityContext;
|
||||
import org.elasticsearch.xpack.security.action.user.ChangePasswordResponse;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.rest.RestRequestFilter;
|
||||
import org.elasticsearch.xpack.security.user.User;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
|
||||
public class RestChangePasswordAction extends BaseRestHandler {
|
||||
public class RestChangePasswordAction extends BaseRestHandler implements RestRequestFilter {
|
||||
|
||||
private final SecurityContext securityContext;
|
||||
|
||||
|
@ -62,4 +65,11 @@ public class RestChangePasswordAction extends BaseRestHandler {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static final Set<String> FILTERED_FIELDS = Collections.singleton("password");
|
||||
|
||||
@Override
|
||||
public Set<String> getFilteredFields() {
|
||||
return FILTERED_FIELDS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.xpack.security.rest.action.user;
|
|||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
|
@ -18,8 +19,11 @@ import org.elasticsearch.rest.action.RestBuilderListener;
|
|||
import org.elasticsearch.xpack.security.action.user.PutUserRequestBuilder;
|
||||
import org.elasticsearch.xpack.security.action.user.PutUserResponse;
|
||||
import org.elasticsearch.xpack.security.client.SecurityClient;
|
||||
import org.elasticsearch.xpack.security.rest.RestRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
|
@ -27,7 +31,8 @@ import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
|||
/**
|
||||
* Rest endpoint to add a User to the security index
|
||||
*/
|
||||
public class RestPutUserAction extends BaseRestHandler {
|
||||
public class RestPutUserAction extends BaseRestHandler implements RestRequestFilter {
|
||||
|
||||
public RestPutUserAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(POST, "/_xpack/security/user/{username}", this);
|
||||
|
@ -58,4 +63,11 @@ public class RestPutUserAction extends BaseRestHandler {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static final Set<String> FILTERED_FIELDS = Collections.unmodifiableSet(Sets.newHashSet("password", "passwordHash"));
|
||||
|
||||
@Override
|
||||
public Set<String> getFilteredFields() {
|
||||
return FILTERED_FIELDS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.xpack.watcher.rest.action;
|
|||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -17,6 +18,7 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.security.rest.RestRequestFilter;
|
||||
import org.elasticsearch.xpack.watcher.client.WatcherClient;
|
||||
import org.elasticsearch.xpack.watcher.execution.ActionExecutionMode;
|
||||
import org.elasticsearch.xpack.watcher.rest.WatcherRestHandler;
|
||||
|
@ -26,13 +28,16 @@ import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchReq
|
|||
import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
import static org.elasticsearch.xpack.watcher.rest.action.RestExecuteWatchAction.Field.IGNORE_CONDITION;
|
||||
import static org.elasticsearch.xpack.watcher.rest.action.RestExecuteWatchAction.Field.RECORD_EXECUTION;
|
||||
|
||||
public class RestExecuteWatchAction extends WatcherRestHandler {
|
||||
public class RestExecuteWatchAction extends WatcherRestHandler implements RestRequestFilter {
|
||||
|
||||
public RestExecuteWatchAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
|
||||
|
@ -132,6 +137,17 @@ public class RestExecuteWatchAction extends WatcherRestHandler {
|
|||
return builder.request();
|
||||
}
|
||||
|
||||
private static final Set<String> FILTERED_FIELDS = Collections.unmodifiableSet(
|
||||
Sets.newHashSet("watch.input.http.request.auth.basic.password",
|
||||
"watch.input.chain.inputs.*.http.request.auth.basic.password",
|
||||
"watch.actions.*.email.attachments.*.reporting.auth.basic.password",
|
||||
"watch.actions.*.webhook.auth.basic.password"));
|
||||
|
||||
@Override
|
||||
public Set<String> getFilteredFields() {
|
||||
return FILTERED_FIELDS;
|
||||
}
|
||||
|
||||
interface Field {
|
||||
ParseField ID = new ParseField("_id");
|
||||
ParseField WATCH_RECORD = new ParseField("watch_record");
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.xpack.watcher.rest.action;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
|
@ -13,19 +14,23 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.security.rest.RestRequestFilter;
|
||||
import org.elasticsearch.xpack.watcher.client.WatcherClient;
|
||||
import org.elasticsearch.xpack.watcher.rest.WatcherRestHandler;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchRequest;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
import static org.elasticsearch.rest.RestStatus.CREATED;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
|
||||
public class RestPutWatchAction extends WatcherRestHandler {
|
||||
public class RestPutWatchAction extends WatcherRestHandler implements RestRequestFilter {
|
||||
|
||||
public RestPutWatchAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
|
||||
|
@ -55,4 +60,12 @@ public class RestPutWatchAction extends WatcherRestHandler {
|
|||
});
|
||||
}
|
||||
|
||||
private static final Set<String> FILTERED_FIELDS = Collections.unmodifiableSet(
|
||||
Sets.newHashSet("input.http.request.auth.basic.password", "input.chain.inputs.*.http.request.auth.basic.password",
|
||||
"actions.*.email.attachments.*.reporting.auth.basic.password", "actions.*.webhook.auth.basic.password"));
|
||||
|
||||
@Override
|
||||
public Set<String> getFilteredFields() {
|
||||
return FILTERED_FIELDS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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.security.rest;
|
||||
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class RestRequestFilterTests extends ESTestCase {
|
||||
|
||||
public void testFilteringItemsInSubLevels() throws IOException {
|
||||
BytesReference content = new BytesArray("{\"root\": {\"second\": {\"third\": \"password\", \"foo\": \"bar\"}}}");
|
||||
RestRequestFilter filter = () -> Collections.singleton("root.second.third");
|
||||
FakeRestRequest restRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY).withContent(content).build();
|
||||
RestRequest filtered = filter.getFilteredRequest(restRequest);
|
||||
assertNotEquals(content, filtered.content());
|
||||
|
||||
Map<String, Object> map = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, filtered.content()).map();
|
||||
Map<String, Object> root = (Map<String, Object>) map.get("root");
|
||||
assertNotNull(root);
|
||||
Map<String, Object> second = (Map<String, Object>) root.get("second");
|
||||
assertNotNull(second);
|
||||
assertEquals("bar", second.get("foo"));
|
||||
assertNull(second.get("third"));
|
||||
}
|
||||
|
||||
public void testFilteringItemsInSubLevelsWithWildCard() throws IOException {
|
||||
BytesReference content = new BytesArray("{\"root\": {\"second\": {\"third\": \"password\", \"foo\": \"bar\"}}}");
|
||||
RestRequestFilter filter = () -> Collections.singleton("root.*.third");
|
||||
FakeRestRequest restRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY).withContent(content).build();
|
||||
RestRequest filtered = filter.getFilteredRequest(restRequest);
|
||||
assertNotEquals(content, filtered.content());
|
||||
|
||||
Map<String, Object> map = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, filtered.content()).map();
|
||||
Map<String, Object> root = (Map<String, Object>) map.get("root");
|
||||
assertNotNull(root);
|
||||
Map<String, Object> second = (Map<String, Object>) root.get("second");
|
||||
assertNotNull(second);
|
||||
assertEquals("bar", second.get("foo"));
|
||||
assertNull(second.get("third"));
|
||||
}
|
||||
|
||||
public void testFilteringItemsInSubLevelsWithLeadingWildCard() throws IOException {
|
||||
BytesReference content = new BytesArray("{\"root\": {\"second\": {\"third\": \"password\", \"foo\": \"bar\"}}}");
|
||||
RestRequestFilter filter = () -> Collections.singleton("*.third");
|
||||
FakeRestRequest restRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY).withContent(content).build();
|
||||
RestRequest filtered = filter.getFilteredRequest(restRequest);
|
||||
assertNotEquals(content, filtered.content());
|
||||
|
||||
Map<String, Object> map = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, filtered.content()).map();
|
||||
Map<String, Object> root = (Map<String, Object>) map.get("root");
|
||||
assertNotNull(root);
|
||||
Map<String, Object> second = (Map<String, Object>) root.get("second");
|
||||
assertNotNull(second);
|
||||
assertEquals("bar", second.get("foo"));
|
||||
assertNull(second.get("third"));
|
||||
}
|
||||
}
|
|
@ -5,10 +5,14 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.security.rest;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
|
@ -17,13 +21,19 @@ import org.elasticsearch.rest.RestHandler;
|
|||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.test.rest.FakeRestRequest;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication;
|
||||
import org.elasticsearch.xpack.security.authc.Authentication.RealmRef;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationService;
|
||||
import org.elasticsearch.xpack.security.user.XPackUser;
|
||||
import org.elasticsearch.xpack.ssl.SSLService;
|
||||
import org.junit.Before;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.xpack.security.support.Exceptions.authenticationError;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
|
@ -35,6 +45,7 @@ import static org.mockito.Mockito.verifyZeroInteractions;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class SecurityRestFilterTests extends ESTestCase {
|
||||
|
||||
private AuthenticationService authcService;
|
||||
private RestChannel channel;
|
||||
private SecurityRestFilter filter;
|
||||
|
@ -48,10 +59,8 @@ public class SecurityRestFilterTests extends ESTestCase {
|
|||
licenseState = mock(XPackLicenseState.class);
|
||||
when(licenseState.isAuthAllowed()).thenReturn(true);
|
||||
restHandler = mock(RestHandler.class);
|
||||
ThreadPool threadPool = mock(ThreadPool.class);
|
||||
when(threadPool.getThreadContext()).thenReturn(new ThreadContext(Settings.EMPTY));
|
||||
filter = new SecurityRestFilter(Settings.EMPTY, licenseState, mock(SSLService.class),
|
||||
threadPool.getThreadContext(), authcService, restHandler);
|
||||
new ThreadContext(Settings.EMPTY), authcService, restHandler);
|
||||
}
|
||||
|
||||
public void testProcess() throws Exception {
|
||||
|
@ -102,4 +111,52 @@ public class SecurityRestFilterTests extends ESTestCase {
|
|||
verifyZeroInteractions(channel);
|
||||
verifyZeroInteractions(authcService);
|
||||
}
|
||||
|
||||
public void testProcessFiltersBodyCorrectly() throws Exception {
|
||||
FakeRestRequest restRequest = new FakeRestRequest.Builder(NamedXContentRegistry.EMPTY)
|
||||
.withContent(new BytesArray("{\"password\": \"changeme\", \"foo\": \"bar\"}")).build();
|
||||
when(channel.request()).thenReturn(restRequest);
|
||||
SetOnce<RestRequest> handlerRequest = new SetOnce<>();
|
||||
restHandler = new FilteredRestHandler() {
|
||||
@Override
|
||||
public void handleRequest(RestRequest request, RestChannel channel, NodeClient client) throws Exception {
|
||||
handlerRequest.set(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getFilteredFields() {
|
||||
return Collections.singleton("password");
|
||||
}
|
||||
};
|
||||
SetOnce<RestRequest> authcServiceRequest = new SetOnce<>();
|
||||
doAnswer((i) -> {
|
||||
ActionListener callback =
|
||||
(ActionListener) i.getArguments()[1];
|
||||
authcServiceRequest.set((RestRequest)i.getArguments()[0]);
|
||||
callback.onResponse(new Authentication(XPackUser.INSTANCE, new RealmRef("test", "test", "t"), null));
|
||||
return Void.TYPE;
|
||||
}).when(authcService).authenticate(any(RestRequest.class), any(ActionListener.class));
|
||||
filter = new SecurityRestFilter(Settings.EMPTY, licenseState, mock(SSLService.class),
|
||||
new ThreadContext(Settings.EMPTY), authcService, restHandler);
|
||||
|
||||
filter.handleRequest(restRequest, channel, null);
|
||||
|
||||
assertEquals(restRequest, handlerRequest.get());
|
||||
assertEquals(restRequest.content(), handlerRequest.get().content());
|
||||
Map<String, Object> original = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, handlerRequest.get()
|
||||
.content()).map();
|
||||
assertEquals(2, original.size());
|
||||
assertEquals("changeme", original.get("password"));
|
||||
assertEquals("bar", original.get("foo"));
|
||||
|
||||
assertNotEquals(restRequest, authcServiceRequest.get());
|
||||
assertNotEquals(restRequest.content(), authcServiceRequest.get().content());
|
||||
|
||||
Map<String, Object> map = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, authcServiceRequest.get()
|
||||
.content()).map();
|
||||
assertEquals(1, map.size());
|
||||
assertEquals("bar", map.get("foo"));
|
||||
}
|
||||
|
||||
private interface FilteredRestHandler extends RestHandler, RestRequestFilter {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue