Merge remote-tracking branch 'origin/master' into json_strict_duplicate_checks

Original commit: elastic/x-pack-elasticsearch@601a663982
This commit is contained in:
Daniel Mitterdorfer 2016-12-12 12:36:38 +01:00
commit b7d2ef0160
20 changed files with 110 additions and 238 deletions

View File

@ -5,37 +5,34 @@
*/ */
package org.elasticsearch.xpack.graph.rest.action; package org.elasticsearch.xpack.graph.rest.action;
import static org.elasticsearch.rest.RestRequest.Method.GET; import org.elasticsearch.ElasticsearchParseException;
import static org.elasticsearch.rest.RestRequest.Method.POST; import org.elasticsearch.action.support.IndicesOptions;
import static org.elasticsearch.xpack.graph.action.GraphExploreAction.INSTANCE; import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.xpack.XPackClient;
import org.elasticsearch.xpack.graph.action.GraphExploreRequest;
import org.elasticsearch.xpack.graph.action.GraphExploreRequest.TermBoost;
import org.elasticsearch.xpack.graph.action.Hop;
import org.elasticsearch.xpack.graph.action.VertexRequest;
import org.elasticsearch.xpack.rest.XPackRestHandler;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import org.elasticsearch.ElasticsearchParseException; import static org.elasticsearch.rest.RestRequest.Method.GET;
import org.elasticsearch.action.support.IndicesOptions; import static org.elasticsearch.rest.RestRequest.Method.POST;
import org.elasticsearch.common.ParseField; import static org.elasticsearch.xpack.graph.action.GraphExploreAction.INSTANCE;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestActions;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.xpack.XPackClient;
import org.elasticsearch.xpack.graph.action.GraphExploreRequest;
import org.elasticsearch.xpack.graph.action.Hop;
import org.elasticsearch.xpack.graph.action.VertexRequest;
import org.elasticsearch.xpack.graph.action.GraphExploreRequest.TermBoost;
import org.elasticsearch.xpack.rest.XPackRestHandler;
/** /**
* @see GraphExploreRequest * @see GraphExploreRequest
@ -88,14 +85,13 @@ public class RestGraphAction extends XPackRestHandler {
if (request.hasParam(TIMEOUT_FIELD.getPreferredName())) { if (request.hasParam(TIMEOUT_FIELD.getPreferredName())) {
graphRequest.timeout(request.paramAsTime(TIMEOUT_FIELD.getPreferredName(), null)); graphRequest.timeout(request.paramAsTime(TIMEOUT_FIELD.getPreferredName(), null));
} }
if (!RestActions.hasBodyContent(request)) { if (false == request.hasContentOrSourceParam()) {
throw new ElasticsearchParseException("Body missing for graph request"); throw new ElasticsearchParseException("Body missing for graph request");
} }
BytesReference qBytes = RestActions.getRestContent(request);
Hop currentHop = graphRequest.createNextHop(null); Hop currentHop = graphRequest.createNextHop(null);
try(XContentParser parser = XContentFactory.xContent(qBytes).createParser(qBytes)) { try (XContentParser parser = request.contentOrSourceParamParser()) {
QueryParseContext context = new QueryParseContext(indicesQueriesRegistry, parser, parseFieldMatcher); QueryParseContext context = new QueryParseContext(indicesQueriesRegistry, parser, parseFieldMatcher);
XContentParser.Token token = parser.nextToken(); XContentParser.Token token = parser.nextToken();

View File

@ -59,7 +59,7 @@ public class RestMonitoringBulkAction extends MonitoringRestHandler {
throw new IllegalArgumentException("no [" + INTERVAL + "] for monitoring bulk request"); throw new IllegalArgumentException("no [" + INTERVAL + "] for monitoring bulk request");
} }
if (!RestActions.hasBodyContent(request)) { if (false == request.hasContentOrSourceParam()) {
throw new ElasticsearchParseException("no body content for monitoring bulk request"); throw new ElasticsearchParseException("no body content for monitoring bulk request");
} }

View File

@ -343,8 +343,7 @@ public class AuthenticationService extends AbstractComponent {
*/ */
private void lookupRunAsUser(final User user, String runAsUsername, Consumer<User> userConsumer) { private void lookupRunAsUser(final User user, String runAsUsername, Consumer<User> userConsumer) {
final List<Realm> realmsList = realms.asList(); final List<Realm> realmsList = realms.asList();
final BiConsumer<Realm, ActionListener<User>> realmLookupConsumer = (realm, lookupUserListener) -> { final BiConsumer<Realm, ActionListener<User>> realmLookupConsumer = (realm, lookupUserListener) ->
if (realm.userLookupSupported()) {
realm.lookupUser(runAsUsername, ActionListener.wrap((lookedupUser) -> { realm.lookupUser(runAsUsername, ActionListener.wrap((lookedupUser) -> {
if (lookedupUser != null) { if (lookedupUser != null) {
lookedupBy = new RealmRef(realm.name(), realm.type(), nodeName); lookedupBy = new RealmRef(realm.name(), realm.type(), nodeName);
@ -353,10 +352,6 @@ public class AuthenticationService extends AbstractComponent {
lookupUserListener.onResponse(null); lookupUserListener.onResponse(null);
} }
}, lookupUserListener::onFailure)); }, lookupUserListener::onFailure));
} else {
lookupUserListener.onResponse(null);
}
};
final IteratingActionListener<User, Realm> userLookupListener = final IteratingActionListener<User, Realm> userLookupListener =
new IteratingActionListener<>(ActionListener.wrap((lookupUser) -> userConsumer.accept(new User(user, lookupUser)), new IteratingActionListener<>(ActionListener.wrap((lookupUser) -> userConsumer.accept(new User(user, lookupUser)),

View File

@ -71,44 +71,24 @@ public abstract class Realm implements Comparable<Realm> {
public abstract AuthenticationToken token(ThreadContext context); public abstract AuthenticationToken token(ThreadContext context);
/** /**
* Authenticates the given token in a blocking fashion. A successful authentication will return the User associated * Authenticates the given token in an asynchronous fashion. A successful authentication will call the
* with the given token. An unsuccessful authentication returns {@code null}. This method is deprecated in favor of * {@link ActionListener#onResponse} with the User associated with the given token. An unsuccessful authentication calls
* {@link #authenticate(AuthenticationToken, ActionListener)}. * with {@code null} on the argument.
* *
* @param token The authentication token * @param token The authentication token
* @return The authenticated user or {@code null} if authentication failed. * @param listener The listener to pass the authentication result to
*
*/ */
@Deprecated public abstract void authenticate(AuthenticationToken token, ActionListener<User> listener);
public abstract User authenticate(AuthenticationToken token);
public void authenticate(AuthenticationToken token, ActionListener<User> listener) {
try {
listener.onResponse(authenticate(token));
} catch (Exception e) {
listener.onFailure(e);
}
}
/** /**
* Looks up the user identified the String identifier. A successful lookup will return the {@link User} identified * Looks up the user identified the String identifier. A successful lookup will call the {@link ActionListener#onResponse}
* by the username. An unsuccessful lookup returns {@code null}. This method is deprecated in favor of * with the {@link User} identified by the username. An unsuccessful lookup call with {@code null} as the argument. If lookup is not
* {@link #lookupUser(String, ActionListener)} * supported, simply return {@code null} when called.
* *
* @param username the String identifier for the user * @param username the String identifier for the user
* @return the {@link User} or {@code null} if lookup failed * @param listener The listener to pass the lookup result to
*/ */
@Deprecated public abstract void lookupUser(String username, ActionListener<User> listener);
public abstract User lookupUser(String username);
public void lookupUser(String username, ActionListener<User> listener) {
try {
User user = lookupUser(username);
listener.onResponse(user);
} catch (Exception e) {
listener.onFailure(e);
}
}
public Map<String, Object> usageStats() { public Map<String, Object> usageStats() {
Map<String, Object> stats = new HashMap<>(); Map<String, Object> stats = new HashMap<>();
@ -117,14 +97,6 @@ public abstract class Realm implements Comparable<Realm> {
return stats; return stats;
} }
/**
* Indicates whether this realm supports user lookup. This method is deprecated. In the future if lookup is not supported, simply
* return null when called.
* @return true if the realm supports user lookup
*/
@Deprecated
public abstract boolean userLookupSupported();
@Override @Override
public String toString() { public String toString() {
return type + "/" + config.name; return type + "/" + config.name;

View File

@ -25,11 +25,6 @@ public class NativeRealm extends CachingUsernamePasswordRealm {
this.userStore = usersStore; this.userStore = usersStore;
} }
@Override
public boolean userLookupSupported() {
return true;
}
@Override @Override
protected void doLookupUser(String username, ActionListener<User> listener) { protected void doLookupUser(String username, ActionListener<User> listener) {
userStore.getUser(username, listener); userStore.getUser(username, listener);

View File

@ -108,11 +108,6 @@ public class ReservedRealm extends CachingUsernamePasswordRealm {
} }
} }
@Override
public boolean userLookupSupported() {
return true;
}
public static boolean isReserved(String username, Settings settings) { public static boolean isReserved(String username, Settings settings) {
assert username != null; assert username != null;
switch (username) { switch (username) {

View File

@ -18,8 +18,8 @@ public class FileRealm extends CachingUsernamePasswordRealm {
public static final String TYPE = "file"; public static final String TYPE = "file";
final FileUserPasswdStore userPasswdStore; private final FileUserPasswdStore userPasswdStore;
final FileUserRolesStore userRolesStore; private final FileUserRolesStore userRolesStore;
public FileRealm(RealmConfig config, ResourceWatcherService watcherService) { public FileRealm(RealmConfig config, ResourceWatcherService watcherService) {
this(config, new FileUserPasswdStore(config, watcherService), new FileUserRolesStore(config, watcherService)); this(config, new FileUserPasswdStore(config, watcherService), new FileUserRolesStore(config, watcherService));
@ -61,9 +61,4 @@ public class FileRealm extends CachingUsernamePasswordRealm {
stats.put("size", userPasswdStore.usersCount()); stats.put("size", userPasswdStore.usersCount());
return stats; return stats;
} }
@Override
public boolean userLookupSupported() {
return true;
}
} }

View File

@ -101,11 +101,6 @@ public final class LdapRealm extends CachingUsernamePasswordRealm {
} }
} }
@Override
public boolean userLookupSupported() {
return sessionFactory.supportsUnauthenticatedSession();
}
@Override @Override
public Map<String, Object> usageStats() { public Map<String, Object> usageStats() {
Map<String, Object> usage = super.usageStats(); Map<String, Object> usage = super.usageStats();

View File

@ -80,11 +80,6 @@ public class PkiRealm extends Realm {
return token(context.getTransient(PKI_CERT_HEADER_NAME), principalPattern, logger); return token(context.getTransient(PKI_CERT_HEADER_NAME), principalPattern, logger);
} }
@Override
public User authenticate(AuthenticationToken authToken) {
throw new UnsupportedOperationException("internal realms do not support blocking calls");
}
@Override @Override
public void authenticate(AuthenticationToken authToken, ActionListener<User> listener) { public void authenticate(AuthenticationToken authToken, ActionListener<User> listener) {
X509AuthenticationToken token = (X509AuthenticationToken)authToken; X509AuthenticationToken token = (X509AuthenticationToken)authToken;
@ -97,13 +92,8 @@ public class PkiRealm extends Realm {
} }
@Override @Override
public User lookupUser(String username) { public void lookupUser(String username, ActionListener<User> listener) {
return null; listener.onResponse(null);
}
@Override
public boolean userLookupSupported() {
return false;
} }
static X509AuthenticationToken token(Object pkiHeaderValue, Pattern principalPattern, Logger logger) { static X509AuthenticationToken token(Object pkiHeaderValue, Pattern principalPattern, Logger logger) {

View File

@ -140,9 +140,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm
@Override @Override
public final void lookupUser(String username, ActionListener<User> listener) { public final void lookupUser(String username, ActionListener<User> listener) {
if (!userLookupSupported()) { if (cache != null) {
listener.onResponse(null);
} else if (cache != null) {
UserWithHash withHash = cache.get(username); UserWithHash withHash = cache.get(username);
if (withHash == null) { if (withHash == null) {
try { try {

View File

@ -25,12 +25,4 @@ abstract class UsernamePasswordRealm extends Realm {
public boolean supports(AuthenticationToken token) { public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken; return token instanceof UsernamePasswordToken;
} }
public final User authenticate(AuthenticationToken token) {
throw new UnsupportedOperationException("internal realms should not support blocking calls!!");
}
public final User lookupUser(String username) {
throw new UnsupportedOperationException("internal realms should not support blocking calls!");
}
} }

View File

@ -8,11 +8,13 @@ package org.elasticsearch.xpack.security.transport;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.DestructiveOperations; import org.elasticsearch.action.support.DestructiveOperations;
import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.CheckedConsumer;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.tasks.Task; import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportChannel; import org.elasticsearch.transport.TransportChannel;
import org.elasticsearch.transport.TransportException; import org.elasticsearch.transport.TransportException;
import org.elasticsearch.transport.TransportInterceptor; import org.elasticsearch.transport.TransportInterceptor;
@ -78,25 +80,25 @@ public class SecurityServerTransportInterceptor implements TransportInterceptor
public AsyncSender interceptSender(AsyncSender sender) { public AsyncSender interceptSender(AsyncSender sender) {
return new AsyncSender() { return new AsyncSender() {
@Override @Override
public <T extends TransportResponse> void sendRequest(DiscoveryNode node, String action, TransportRequest request, public <T extends TransportResponse> void sendRequest(Transport.Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler<T> handler) { TransportRequestOptions options, TransportResponseHandler<T> handler) {
if (licenseState.isAuthAllowed()) { if (licenseState.isAuthAllowed()) {
// Sometimes a system action gets executed like a internal create index request or update mappings request // Sometimes a system action gets executed like a internal create index request or update mappings request
// which means that the user is copied over to system actions so we need to change the user // which means that the user is copied over to system actions so we need to change the user
if (AuthorizationUtils.shouldReplaceUserWithSystem(threadPool.getThreadContext(), action)) { if (AuthorizationUtils.shouldReplaceUserWithSystem(threadPool.getThreadContext(), action)) {
securityContext.executeAsUser(SystemUser.INSTANCE, (original) -> sendWithUser(node, action, request, options, securityContext.executeAsUser(SystemUser.INSTANCE, (original) -> sendWithUser(connection, action, request, options,
new ContextRestoreResponseHandler<>(threadPool.getThreadContext(), original, handler), sender)); new ContextRestoreResponseHandler<>(threadPool.getThreadContext(), original, handler), sender));
} else { } else {
sendWithUser(node, action, request, options, handler, sender); sendWithUser(connection, action, request, options, handler, sender);
} }
} else { } else {
sender.sendRequest(node, action, request, options, handler); sender.sendRequest(connection, action, request, options, handler);
} }
} }
}; };
} }
private <T extends TransportResponse> void sendWithUser(DiscoveryNode node, String action, TransportRequest request, private <T extends TransportResponse> void sendWithUser(Transport.Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler<T> handler, TransportRequestOptions options, TransportResponseHandler<T> handler,
AsyncSender sender) { AsyncSender sender) {
// There cannot be a request outgoing from this node that is not associated with a user. // There cannot be a request outgoing from this node that is not associated with a user.
@ -105,7 +107,7 @@ public class SecurityServerTransportInterceptor implements TransportInterceptor
} }
try { try {
sender.sendRequest(node, action, request, options, handler); sender.sendRequest(connection, action, request, options, handler);
} catch (Exception e) { } catch (Exception e) {
handler.handleException(new TransportException("failed sending request", e)); handler.handleException(new TransportException("failed sending request", e));
} }
@ -213,7 +215,7 @@ public class SecurityServerTransportInterceptor implements TransportInterceptor
assert filter != null; assert filter != null;
final Thread executingThread = Thread.currentThread(); final Thread executingThread = Thread.currentThread();
ActionListener.CheckedConsumer<Void> consumer = (x) -> { CheckedConsumer<Void, Exception> consumer = (x) -> {
final Executor executor; final Executor executor;
if (executingThread == Thread.currentThread()) { if (executingThread == Thread.currentThread()) {
// only fork off if we get called on another thread this means we moved to // only fork off if we get called on another thread this means we moved to

View File

@ -34,6 +34,7 @@ import org.joda.time.DateTime;
import java.time.Clock; import java.time.Clock;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@ -187,16 +188,13 @@ public class ExecutionService extends AbstractComponent {
logger.debug("saving watch records [{}]", triggeredWatches.size()); logger.debug("saving watch records [{}]", triggeredWatches.size());
triggeredWatchStore.putAll(triggeredWatches, new ActionListener<List<Integer>>() { triggeredWatchStore.putAll(triggeredWatches, new ActionListener<BitSet>() {
@Override @Override
public void onResponse(List<Integer> successFullSlots) { public void onResponse(BitSet slots) {
for (Integer slot : successFullSlots) { int slot = 0;
TriggeredWatch triggeredWatch = triggeredWatches.get(slot); while ((slot = slots.nextSetBit(slot)) != -1) {
try { executeAsync(contexts.get(slot), triggeredWatches.get(slot));
executeAsync(contexts.get(slot), triggeredWatch); slot++;
} catch (Exception e) {
logger.error((Supplier<?>) () -> new ParameterizedMessage("failed to execute watch [{}]", triggeredWatch.id()), e);
}
} }
} }
@ -236,9 +234,11 @@ public class ExecutionService extends AbstractComponent {
return; return;
} }
List<Integer> slots = triggeredWatchStore.putAll(triggeredWatches); BitSet slots = triggeredWatchStore.putAll(triggeredWatches);
for (Integer slot : slots) { int slot = 0;
while ((slot = slots.nextSetBit(slot)) != -1) {
executeAsync(contexts.get(slot), triggeredWatches.get(slot)); executeAsync(contexts.get(slot), triggeredWatches.get(slot));
slot++;
} }
} }

View File

@ -33,6 +33,7 @@ import org.elasticsearch.xpack.watcher.watch.WatchStoreUtils;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -129,10 +130,10 @@ public class TriggeredWatchStore extends AbstractComponent {
} }
} }
public void putAll(final List<TriggeredWatch> triggeredWatches, final ActionListener<List<Integer>> listener) throws Exception { public void putAll(final List<TriggeredWatch> triggeredWatches, final ActionListener<BitSet> listener) throws Exception {
if (triggeredWatches.isEmpty()) { if (triggeredWatches.isEmpty()) {
listener.onResponse(Collections.emptyList()); listener.onResponse(new BitSet(0));
return; return;
} }
@ -140,7 +141,9 @@ public class TriggeredWatchStore extends AbstractComponent {
put(triggeredWatches.get(0), new ActionListener<Boolean>() { put(triggeredWatches.get(0), new ActionListener<Boolean>() {
@Override @Override
public void onResponse(Boolean success) { public void onResponse(Boolean success) {
listener.onResponse(Collections.singletonList(0)); BitSet bitSet = new BitSet(1);
bitSet.set(0);
listener.onResponse(bitSet);
} }
@Override @Override
@ -163,15 +166,14 @@ public class TriggeredWatchStore extends AbstractComponent {
client.bulk(request, new ActionListener<BulkResponse>() { client.bulk(request, new ActionListener<BulkResponse>() {
@Override @Override
public void onResponse(BulkResponse response) { public void onResponse(BulkResponse response) {
List<Integer> successFullSlots = new ArrayList<Integer>(); BitSet successFullSlots = new BitSet(triggeredWatches.size());
for (int i = 0; i < response.getItems().length; i++) { for (int i = 0; i < response.getItems().length; i++) {
BulkItemResponse itemResponse = response.getItems()[i]; BulkItemResponse itemResponse = response.getItems()[i];
if (itemResponse.isFailed()) { if (itemResponse.isFailed()) {
logger.error("could store triggered watch with id [{}], because failed [{}]", itemResponse.getId(), logger.error("could store triggered watch with id [{}], because failed [{}]", itemResponse.getId(),
itemResponse.getFailureMessage()); itemResponse.getFailureMessage());
} else { } else {
IndexResponse indexResponse = itemResponse.getResponse(); successFullSlots.set(i);
successFullSlots.add(i);
} }
} }
listener.onResponse(successFullSlots); listener.onResponse(successFullSlots);
@ -187,7 +189,7 @@ public class TriggeredWatchStore extends AbstractComponent {
} }
} }
public List<Integer> putAll(final List<TriggeredWatch> triggeredWatches) throws Exception { public BitSet putAll(final List<TriggeredWatch> triggeredWatches) throws Exception {
ensureStarted(); ensureStarted();
try { try {
BulkRequest request = new BulkRequest(); BulkRequest request = new BulkRequest();
@ -198,15 +200,14 @@ public class TriggeredWatchStore extends AbstractComponent {
request.add(indexRequest); request.add(indexRequest);
} }
BulkResponse response = client.bulk(request, (TimeValue) null); BulkResponse response = client.bulk(request, (TimeValue) null);
List<Integer> successFullSlots = new ArrayList<>(); BitSet successFullSlots = new BitSet(triggeredWatches.size());
for (int i = 0; i < response.getItems().length; i++) { for (int i = 0; i < response.getItems().length; i++) {
BulkItemResponse itemResponse = response.getItems()[i]; BulkItemResponse itemResponse = response.getItems()[i];
if (itemResponse.isFailed()) { if (itemResponse.isFailed()) {
logger.error("could store triggered watch with id [{}], because failed [{}]", itemResponse.getId(), logger.error("could store triggered watch with id [{}], because failed [{}]", itemResponse.getId(),
itemResponse.getFailureMessage()); itemResponse.getFailureMessage());
} else { } else {
IndexResponse indexResponse = itemResponse.getResponse(); successFullSlots.set(i);
successFullSlots.add(i);
} }
} }
return successFullSlots; return successFullSlots;

View File

@ -172,7 +172,7 @@ public class AuthenticationServiceTests extends ESTestCase {
assertThat(result.getUser(), is(user)); assertThat(result.getUser(), is(user));
verify(auditTrail).authenticationSuccess(secondRealm.name(), user, "_action", message); verify(auditTrail).authenticationSuccess(secondRealm.name(), user, "_action", message);
verifyNoMoreInteractions(auditTrail); verifyNoMoreInteractions(auditTrail);
verify(firstRealm, never()).authenticate(token); verify(firstRealm, never()).authenticate(eq(token), any(ActionListener.class));
assertThreadContextContainsAuthentication(result); assertThreadContextContainsAuthentication(result);
} }
@ -600,9 +600,9 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"})); mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"}));
mockRealmLookupReturnsNull(firstRealm, "run_as");
doThrow(authenticationError("realm doesn't want to lookup")) doThrow(authenticationError("realm doesn't want to lookup"))
.when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class)); .when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
when(secondRealm.userLookupSupported()).thenReturn(true);
try { try {
authenticateBlocking("_action", message, null); authenticateBlocking("_action", message, null);
@ -619,9 +619,9 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"})); mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"}));
mockRealmLookupReturnsNull(firstRealm, "run_as");
doThrow(authenticationError("realm doesn't want to " + "lookup")) doThrow(authenticationError("realm doesn't want to " + "lookup"))
.when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class)); .when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
when(secondRealm.userLookupSupported()).thenReturn(true);
try { try {
authenticateBlocking(restRequest); authenticateBlocking(restRequest);
@ -640,12 +640,12 @@ public class AuthenticationServiceTests extends ESTestCase {
final User user = new User("lookup user", new String[]{"user"}, "lookup user", "lookup@foo.foo", final User user = new User("lookup user", new String[]{"user"}, "lookup user", "lookup@foo.foo",
Collections.singletonMap("foo", "bar"), true); Collections.singletonMap("foo", "bar"), true);
mockAuthenticate(secondRealm, token, user); mockAuthenticate(secondRealm, token, user);
mockRealmLookupReturnsNull(firstRealm, "run_as");
doAnswer((i) -> { doAnswer((i) -> {
ActionListener listener = (ActionListener) i.getArguments()[1]; ActionListener listener = (ActionListener) i.getArguments()[1];
listener.onResponse(new User("looked up user", new String[]{"some role"})); listener.onResponse(new User("looked up user", new String[]{"some role"}));
return null; return null;
}).when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class)); }).when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
when(secondRealm.userLookupSupported()).thenReturn(true);
Authentication result; Authentication result;
if (randomBoolean()) { if (randomBoolean()) {
@ -676,13 +676,11 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"})); mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"}));
when(firstRealm.userLookupSupported()).thenReturn(true);
doAnswer((i) -> { doAnswer((i) -> {
ActionListener listener = (ActionListener) i.getArguments()[1]; ActionListener listener = (ActionListener) i.getArguments()[1];
listener.onResponse(new User("looked up user", new String[]{"some role"})); listener.onResponse(new User("looked up user", new String[]{"some role"}));
return null; return null;
}).when(firstRealm).lookupUser(eq("run_as"), any(ActionListener.class)); }).when(firstRealm).lookupUser(eq("run_as"), any(ActionListener.class));
when(firstRealm.userLookupSupported()).thenReturn(true);
Authentication result; Authentication result;
if (randomBoolean()) { if (randomBoolean()) {
@ -709,7 +707,6 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, user); mockAuthenticate(secondRealm, token, user);
when(secondRealm.userLookupSupported()).thenReturn(true);
try { try {
authenticateBlocking(restRequest); authenticateBlocking(restRequest);
@ -727,7 +724,6 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, user); mockAuthenticate(secondRealm, token, user);
when(secondRealm.userLookupSupported()).thenReturn(true);
try { try {
authenticateBlocking("_action", message, null); authenticateBlocking("_action", message, null);
@ -744,12 +740,12 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"})); mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"}));
mockRealmLookupReturnsNull(firstRealm, "run_as");
doAnswer((i) -> { doAnswer((i) -> {
ActionListener listener = (ActionListener) i.getArguments()[1]; ActionListener listener = (ActionListener) i.getArguments()[1];
listener.onResponse(new User("looked up user", new String[]{"some role"}, null, null, null, false)); listener.onResponse(new User("looked up user", new String[]{"some role"}, null, null, null, false));
return null; return null;
}).when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class)); }).when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
when(secondRealm.userLookupSupported()).thenReturn(true);
User fallback = randomBoolean() ? SystemUser.INSTANCE : null; User fallback = randomBoolean() ? SystemUser.INSTANCE : null;
ElasticsearchSecurityException e = ElasticsearchSecurityException e =
expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking("_action", message, fallback)); expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking("_action", message, fallback));
@ -764,12 +760,12 @@ public class AuthenticationServiceTests extends ESTestCase {
when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.token(threadContext)).thenReturn(token);
when(secondRealm.supports(token)).thenReturn(true); when(secondRealm.supports(token)).thenReturn(true);
mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"})); mockAuthenticate(secondRealm, token, new User("lookup user", new String[]{"user"}));
mockRealmLookupReturnsNull(firstRealm, "run_as");
doAnswer((i) -> { doAnswer((i) -> {
ActionListener listener = (ActionListener) i.getArguments()[1]; ActionListener listener = (ActionListener) i.getArguments()[1];
listener.onResponse(new User("looked up user", new String[]{"some role"}, null, null, null, false)); listener.onResponse(new User("looked up user", new String[]{"some role"}, null, null, null, false));
return null; return null;
}).when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class)); }).when(secondRealm).lookupUser(eq("run_as"), any(ActionListener.class));
when(secondRealm.userLookupSupported()).thenReturn(true);
ElasticsearchSecurityException e = ElasticsearchSecurityException e =
expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking(restRequest)); expectThrows(ElasticsearchSecurityException.class, () -> authenticateBlocking(restRequest));
@ -816,6 +812,14 @@ public class AuthenticationServiceTests extends ESTestCase {
return future.actionGet(); return future.actionGet();
} }
private static void mockRealmLookupReturnsNull(Realm realm, String username) {
doAnswer((i) -> {
ActionListener listener = (ActionListener) i.getArguments()[1];
listener.onResponse(null);
return null;
}).when(realm).lookupUser(eq(username), any(ActionListener.class));
}
static class TestRealms extends Realms { static class TestRealms extends Realms {
TestRealms(Settings settings, Environment env, Map<String, Factory> factories, XPackLicenseState licenseState, TestRealms(Settings settings, Environment env, Map<String, Factory> factories, XPackLicenseState licenseState,

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.xpack.security.authc; package org.elasticsearch.xpack.security.authc;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
@ -433,18 +434,13 @@ public class RealmsTests extends ESTestCase {
} }
@Override @Override
public User authenticate(AuthenticationToken token) { public void authenticate(AuthenticationToken token, ActionListener<User> listener) {
return null; listener.onResponse(null);
} }
@Override @Override
public User lookupUser(String username) { public void lookupUser(String username, ActionListener<User> listener) {
return null; listener.onResponse(null);
}
@Override
public boolean userLookupSupported() {
return false;
} }
} }
} }

View File

@ -58,11 +58,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
protected void doLookupUser(String username, ActionListener<User> listener) { protected void doLookupUser(String username, ActionListener<User> listener) {
listener.onFailure(new UnsupportedOperationException("this method should not be called")); listener.onFailure(new UnsupportedOperationException("this method should not be called"));
} }
@Override
public boolean userLookupSupported() {
return false;
}
}; };
assertThat(realm.hasher, sameInstance(Hasher.resolve(hashAlgo))); assertThat(realm.hasher, sameInstance(Hasher.resolve(hashAlgo)));
@ -213,26 +208,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
assertThat(e.getMessage() , containsString("lookup exception")); assertThat(e.getMessage() , containsString("lookup exception"));
} }
public void testThatLookupIsNotCalledIfNotSupported() throws Exception {
LookupNotSupportedRealm realm = new LookupNotSupportedRealm(globalSettings);
assertThat(realm.userLookupSupported(), is(false));
PlainActionFuture<User> future = new PlainActionFuture<>();
realm.lookupUser("a", future);
User user = future.actionGet();
assertThat(user, is(nullValue()));
assertThat(realm.lookupInvocationCounter.intValue(), is(0));
// try to lookup more
future = new PlainActionFuture<>();
realm.lookupUser("b", future);
future.actionGet();
future = new PlainActionFuture<>();
realm.lookupUser("c", future);
future.actionGet();
assertThat(realm.lookupInvocationCounter.intValue(), is(0));
}
public void testCacheConcurrency() throws Exception { public void testCacheConcurrency() throws Exception {
final String username = "username"; final String username = "username";
final SecuredString password = new SecuredString("changeme".toCharArray()); final SecuredString password = new SecuredString("changeme".toCharArray());
@ -255,11 +230,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
protected void doLookupUser(String username, ActionListener<User> listener) { protected void doLookupUser(String username, ActionListener<User> listener) {
listener.onFailure(new UnsupportedOperationException("this method should not be called")); listener.onFailure(new UnsupportedOperationException("this method should not be called"));
} }
@Override
public boolean userLookupSupported() {
return false;
}
}; };
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
@ -317,11 +287,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
protected void doLookupUser(String username, ActionListener<User> listener) { protected void doLookupUser(String username, ActionListener<User> listener) {
listener.onResponse(new User(username, new String[]{"r1", "r2", "r3"})); listener.onResponse(new User(username, new String[]{"r1", "r2", "r3"}));
} }
@Override
public boolean userLookupSupported() {
return true;
}
}; };
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
@ -366,11 +331,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
super("failing", new RealmConfig("failing-test", settings, global)); super("failing", new RealmConfig("failing-test", settings, global));
} }
@Override
public boolean userLookupSupported() {
return true;
}
@Override @Override
protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) { protected void doAuthenticate(UsernamePasswordToken token, ActionListener<User> listener) {
listener.onResponse(null); listener.onResponse(null);
@ -397,11 +357,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
protected void doLookupUser(String username, ActionListener<User> listener) { protected void doLookupUser(String username, ActionListener<User> listener) {
listener.onFailure(new RuntimeException("lookup exception")); listener.onFailure(new RuntimeException("lookup exception"));
} }
@Override
public boolean userLookupSupported() {
return true;
}
} }
static class AlwaysAuthenticateCachingRealm extends CachingUsernamePasswordRealm { static class AlwaysAuthenticateCachingRealm extends CachingUsernamePasswordRealm {
@ -424,11 +379,6 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
lookupInvocationCounter.incrementAndGet(); lookupInvocationCounter.incrementAndGet();
listener.onResponse(new User(username, new String[] { "lookupRole1", "lookupRole2" })); listener.onResponse(new User(username, new String[] { "lookupRole1", "lookupRole2" }));
} }
@Override
public boolean userLookupSupported() {
return true;
}
} }
static class LookupNotSupportedRealm extends CachingUsernamePasswordRealm { static class LookupNotSupportedRealm extends CachingUsernamePasswordRealm {
@ -451,10 +401,5 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase {
lookupInvocationCounter.incrementAndGet(); lookupInvocationCounter.incrementAndGet();
listener.onFailure(new UnsupportedOperationException("don't call lookup if lookup isn't supported!!!")); listener.onFailure(new UnsupportedOperationException("don't call lookup if lookup isn't supported!!!"));
} }
@Override
public boolean userLookupSupported() {
return false;
}
} }
} }

View File

@ -6,7 +6,6 @@
package org.elasticsearch.xpack.security.transport; package org.elasticsearch.xpack.security.transport;
import org.elasticsearch.action.support.DestructiveOperations; import org.elasticsearch.action.support.DestructiveOperations;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
@ -14,6 +13,7 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.TransportException; import org.elasticsearch.transport.TransportException;
import org.elasticsearch.transport.TransportInterceptor.AsyncSender; import org.elasticsearch.transport.TransportInterceptor.AsyncSender;
import org.elasticsearch.transport.TransportRequest; import org.elasticsearch.transport.TransportRequest;
@ -77,7 +77,7 @@ public class SecurityServerTransportInterceptorTests extends ESTestCase {
AtomicBoolean calledWrappedSender = new AtomicBoolean(false); AtomicBoolean calledWrappedSender = new AtomicBoolean(false);
AsyncSender sender = interceptor.interceptSender(new AsyncSender() { AsyncSender sender = interceptor.interceptSender(new AsyncSender() {
@Override @Override
public <T extends TransportResponse> void sendRequest(DiscoveryNode node, String action, TransportRequest request, public <T extends TransportResponse> void sendRequest(Transport.Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler<T> handler) { TransportRequestOptions options, TransportResponseHandler<T> handler) {
if (calledWrappedSender.compareAndSet(false, true) == false) { if (calledWrappedSender.compareAndSet(false, true) == false) {
fail("sender called more than once!"); fail("sender called more than once!");
@ -104,7 +104,7 @@ public class SecurityServerTransportInterceptorTests extends ESTestCase {
AtomicReference<User> sendingUser = new AtomicReference<>(); AtomicReference<User> sendingUser = new AtomicReference<>();
AsyncSender sender = interceptor.interceptSender(new AsyncSender() { AsyncSender sender = interceptor.interceptSender(new AsyncSender() {
@Override @Override
public <T extends TransportResponse> void sendRequest(DiscoveryNode node, String action, TransportRequest request, public <T extends TransportResponse> void sendRequest(Transport.Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler<T> handler) { TransportRequestOptions options, TransportResponseHandler<T> handler) {
if (calledWrappedSender.compareAndSet(false, true) == false) { if (calledWrappedSender.compareAndSet(false, true) == false) {
fail("sender called more than once!"); fail("sender called more than once!");
@ -136,7 +136,7 @@ public class SecurityServerTransportInterceptorTests extends ESTestCase {
AtomicReference<User> sendingUser = new AtomicReference<>(); AtomicReference<User> sendingUser = new AtomicReference<>();
AsyncSender sender = interceptor.interceptSender(new AsyncSender() { AsyncSender sender = interceptor.interceptSender(new AsyncSender() {
@Override @Override
public <T extends TransportResponse> void sendRequest(DiscoveryNode node, String action, TransportRequest request, public <T extends TransportResponse> void sendRequest(Transport.Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler<T> handler) { TransportRequestOptions options, TransportResponseHandler<T> handler) {
if (calledWrappedSender.compareAndSet(false, true) == false) { if (calledWrappedSender.compareAndSet(false, true) == false) {
fail("sender called more than once!"); fail("sender called more than once!");
@ -163,7 +163,7 @@ public class SecurityServerTransportInterceptorTests extends ESTestCase {
assertNull(securityContext.getUser()); assertNull(securityContext.getUser());
AsyncSender sender = interceptor.interceptSender(new AsyncSender() { AsyncSender sender = interceptor.interceptSender(new AsyncSender() {
@Override @Override
public <T extends TransportResponse> void sendRequest(DiscoveryNode node, String action, TransportRequest request, public <T extends TransportResponse> void sendRequest(Transport.Connection connection, String action, TransportRequest request,
TransportRequestOptions options, TransportResponseHandler<T> handler) { TransportRequestOptions options, TransportResponseHandler<T> handler) {
fail("sender should not be called!"); fail("sender should not be called!");
} }

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.example.realm; package org.elasticsearch.example.realm;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.authc.AuthenticationToken; import org.elasticsearch.xpack.security.authc.AuthenticationToken;
@ -46,22 +47,18 @@ public class CustomRealm extends Realm {
} }
@Override @Override
public User authenticate(AuthenticationToken authToken) { public void authenticate(AuthenticationToken authToken, ActionListener<User> listener) {
UsernamePasswordToken token = (UsernamePasswordToken)authToken; UsernamePasswordToken token = (UsernamePasswordToken)authToken;
final String actualUser = token.principal(); final String actualUser = token.principal();
if (KNOWN_USER.equals(actualUser) && SecuredString.constantTimeEquals(token.credentials(), KNOWN_PW)) { if (KNOWN_USER.equals(actualUser) && SecuredString.constantTimeEquals(token.credentials(), KNOWN_PW)) {
return new User(actualUser, ROLES); listener.onResponse(new User(actualUser, ROLES));
} else {
listener.onResponse(null);
} }
return null;
} }
@Override @Override
public User lookupUser(String username) { public void lookupUser(String username, ActionListener<User> listener) {
return null; listener.onResponse(null);
}
@Override
public boolean userLookupSupported() {
return false;
} }
} }

View File

@ -5,6 +5,7 @@
*/ */
package org.elasticsearch.example.realm; package org.elasticsearch.example.realm;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.RealmConfig;
@ -22,7 +23,9 @@ public class CustomRealmTests extends ESTestCase {
CustomRealm realm = new CustomRealm(new RealmConfig("test", Settings.EMPTY, globalSettings)); CustomRealm realm = new CustomRealm(new RealmConfig("test", Settings.EMPTY, globalSettings));
SecuredString password = new SecuredString(CustomRealm.KNOWN_PW.toCharArray()); SecuredString password = new SecuredString(CustomRealm.KNOWN_PW.toCharArray());
UsernamePasswordToken token = new UsernamePasswordToken(CustomRealm.KNOWN_USER, password); UsernamePasswordToken token = new UsernamePasswordToken(CustomRealm.KNOWN_USER, password);
User user = realm.authenticate(token); PlainActionFuture<User> plainActionFuture = new PlainActionFuture<>();
realm.authenticate(token, plainActionFuture);
User user = plainActionFuture.actionGet();
assertThat(user, notNullValue()); assertThat(user, notNullValue());
assertThat(user.roles(), equalTo(CustomRealm.ROLES)); assertThat(user.roles(), equalTo(CustomRealm.ROLES));
assertThat(user.principal(), equalTo(CustomRealm.KNOWN_USER)); assertThat(user.principal(), equalTo(CustomRealm.KNOWN_USER));
@ -33,7 +36,8 @@ public class CustomRealmTests extends ESTestCase {
CustomRealm realm = new CustomRealm(new RealmConfig("test", Settings.EMPTY, globalSettings)); CustomRealm realm = new CustomRealm(new RealmConfig("test", Settings.EMPTY, globalSettings));
SecuredString password = new SecuredString(CustomRealm.KNOWN_PW.toCharArray()); SecuredString password = new SecuredString(CustomRealm.KNOWN_PW.toCharArray());
UsernamePasswordToken token = new UsernamePasswordToken(CustomRealm.KNOWN_USER + "1", password); UsernamePasswordToken token = new UsernamePasswordToken(CustomRealm.KNOWN_USER + "1", password);
User user = realm.authenticate(token); PlainActionFuture<User> plainActionFuture = new PlainActionFuture<>();
assertThat(user, nullValue()); realm.authenticate(token, plainActionFuture);
assertThat(plainActionFuture.actionGet(), nullValue());
} }
} }