From 6d04eacdec969483db761886204f9922fa83c2b0 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Thu, 13 Jul 2017 19:59:50 -0500 Subject: [PATCH] Require elastic password be bootstrapped (elastic/x-pack-elasticsearch#1962) This is related to elastic/x-pack-elasticsearch#1217. This commit requires that the elastic password be bootstrapped for the user to be authenticated. As a result it removes the special "setup" mode that allowed the user to be authenticated from localhost. Additionally, this commit updates the tests to work with this functionality. Original commit: elastic/x-pack-elasticsearch@d0d5d697a757dc74d00d2b368b48c721655a836c --- plugin/build.gradle | 42 +------- .../security/authc/AuthenticationService.java | 30 +----- .../xpack/security/authc/IncomingRequest.java | 36 ------- .../xpack/security/authc/Realm.java | 4 +- .../security/authc/esnative/NativeRealm.java | 4 +- .../authc/esnative/ReservedRealm.java | 59 ++--------- .../xpack/security/authc/file/FileRealm.java | 10 +- .../xpack/security/authc/ldap/LdapRealm.java | 18 ++-- .../xpack/security/authc/pki/PkiRealm.java | 28 +++--- .../support/CachingUsernamePasswordRealm.java | 28 +++--- .../security/authz/AuthorizationService.java | 9 -- .../xpack/security/user/ElasticUser.java | 21 +--- .../integration/ClearRealmsCacheTests.java | 8 +- .../test/NativeRealmIntegTestCase.java | 13 ++- .../test/SecurityIntegTestCase.java | 38 +++++++- .../ml/integration/DatafeedJobsRestIT.java | 15 +-- .../xpack/ml/integration/MlJobIT.java | 3 +- .../MlNativeAutodetectIntegTestCase.java | 2 +- .../xpack/security/SecurityTribeIT.java | 85 +++++++--------- .../authc/AuthenticationServiceTests.java | 8 +- .../xpack/security/authc/RealmsTests.java | 13 ++- .../esnative/ESNativeMigrateToolTests.java | 10 +- .../authc/esnative/ReservedRealmTests.java | 97 ++++--------------- .../security/authc/file/FileRealmTests.java | 19 ++-- .../authc/ldap/ActiveDirectoryRealmTests.java | 17 ++-- .../security/authc/ldap/LdapRealmTests.java | 32 +++--- .../security/authc/pki/PkiRealmTests.java | 9 +- .../CachingUsernamePasswordRealmTests.java | 70 ++++++------- .../authz/AuthorizationServiceTests.java | 19 +--- .../xpack/test/rest/XPackRestTestCase.java | 24 +---- qa/full-cluster-restart/build.gradle | 8 +- .../xpack/restart/FullClusterRestartIT.java | 2 +- qa/rolling-upgrade/build.gradle | 6 +- .../UpgradeClusterClientYamlTestSuiteIT.java | 2 +- .../WatchBackwardsCompatibilityIT.java | 2 +- .../example/realm/CustomRealm.java | 8 +- .../example/realm/CustomRealmTests.java | 11 +-- .../test/TribeWithSecurityIT.java | 22 +---- 38 files changed, 264 insertions(+), 568 deletions(-) delete mode 100644 plugin/src/main/java/org/elasticsearch/xpack/security/authc/IncomingRequest.java diff --git a/plugin/build.gradle b/plugin/build.gradle index 80f0d87aeee..5cc8168d501 100644 --- a/plugin/build.gradle +++ b/plugin/build.gradle @@ -201,54 +201,21 @@ integTestCluster { setting 'xpack.monitoring.exporters._local.type', 'local' setting 'xpack.monitoring.exporters._local.enabled', 'false' setting 'xpack.monitoring.collection.interval', '-1' + keystoreSetting 'es.bootstrap.passwd.elastic', 'x-pack-test-password' distribution = 'zip' // this is important since we use the reindex module in ML + setupCommand 'setupTestUser', 'bin/x-pack/users', 'useradd', 'x_pack_rest_user', '-p', 'x-pack-test-password', '-r', 'superuser' + waitCondition = { NodeInfo node, AntBuilder ant -> File tmpFile = new File(node.cwd, 'wait.success') - for (int i = 0; i < 10; i++) { - HttpURLConnection httpURLConnection = null; - try { - httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_xpack/security/user/elastic/_password") - .openConnection(); - httpURLConnection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("elastic:".getBytes(StandardCharsets.UTF_8))); - httpURLConnection.setRequestMethod("PUT"); - httpURLConnection.setDoOutput(true); - httpURLConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); - - httpURLConnection.connect(); - OutputStream out = httpURLConnection.getOutputStream(); - out.write("{\"password\": \"x-pack-test-password\"}".getBytes(StandardCharsets.UTF_8)); - out.close() - - if (httpURLConnection.getResponseCode() == 200) { - break - } - } catch (Exception e) { - httpURLConnection.disconnect() - if (i == 9) { - logger.error("final attempt to set elastic password", e) - } else { - logger.debug("failed to set elastic password", e) - } - } finally { - if (httpURLConnection != null) { - httpURLConnection.disconnect(); - } - } - - // did not start, so wait a bit before trying again - Thread.sleep(500L); - } - for (int i = 0; i < 10; i++) { // we use custom wait logic here as the elastic user is not available immediately and ant.get will fail when a 401 is returned HttpURLConnection httpURLConnection = null; try { httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health?wait_for_nodes=${numNodes}&wait_for_status=yellow").openConnection(); httpURLConnection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("elastic:x-pack-test-password".getBytes(StandardCharsets.UTF_8))); + Base64.getEncoder().encodeToString("x_pack_rest_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8))); httpURLConnection.setRequestMethod("GET"); httpURLConnection.connect(); if (httpURLConnection.getResponseCode() == 200) { @@ -358,4 +325,5 @@ run { setting 'xpack.security.enabled', 'true' setting 'xpack.monitoring.enabled', 'true' setting 'xpack.watcher.enabled', 'true' + keystoreSetting 'es.bootstrap.passwd.elastic', 'password' } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java index bf9c3eb1756..cfd3fd390a1 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/AuthenticationService.java @@ -294,7 +294,7 @@ public class AuthenticationService extends AbstractComponent { "An error occurred while attempting to authenticate [{}] against realm [{}]", authenticationToken.principal(), realm.name()), ex); userListener.onFailure(ex); - }), request); + })); } else { userListener.onResponse(null); } @@ -451,21 +451,16 @@ public class AuthenticationService extends AbstractComponent { } } - abstract static class AuditableRequest implements IncomingRequest { + abstract static class AuditableRequest { final AuditTrail auditTrail; final AuthenticationFailureHandler failureHandler; final ThreadContext threadContext; - private final InetSocketAddress remoteAddress; - private final RequestType requestType; - AuditableRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext, - RequestType requestType, InetSocketAddress remoteAddress) { + AuditableRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext) { this.auditTrail = auditTrail; this.failureHandler = failureHandler; this.threadContext = threadContext; - this.remoteAddress = remoteAddress; - this.requestType = requestType; } abstract void realmAuthenticationFailed(AuthenticationToken token, String realm); @@ -482,13 +477,6 @@ public class AuthenticationService extends AbstractComponent { abstract void authenticationSuccess(String realm, User user); - public InetSocketAddress getRemoteAddress() { - return remoteAddress; - } - - public RequestType getType() { - return requestType; - } } static class AuditableTransportRequest extends AuditableRequest { @@ -498,7 +486,7 @@ public class AuthenticationService extends AbstractComponent { AuditableTransportRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext, String action, TransportMessage message) { - super(auditTrail, failureHandler, threadContext, getType(message), getRemoteAddress(message)); + super(auditTrail, failureHandler, threadContext); this.action = action; this.message = message; } @@ -552,14 +540,6 @@ public class AuthenticationService extends AbstractComponent { return "transport request action [" + action + "]"; } - private static RequestType getType(TransportMessage message) { - return message.remoteAddress() == null ? RequestType.LOCAL_NODE : RequestType.REMOTE_NODE; - } - - private static InetSocketAddress getRemoteAddress(TransportMessage message) { - TransportAddress transportAddress = message.remoteAddress(); - return transportAddress == null ? null : transportAddress.address(); - } } static class AuditableRestRequest extends AuditableRequest { @@ -569,7 +549,7 @@ public class AuthenticationService extends AbstractComponent { @SuppressWarnings("unchecked") AuditableRestRequest(AuditTrail auditTrail, AuthenticationFailureHandler failureHandler, ThreadContext threadContext, RestRequest request) { - super(auditTrail, failureHandler, threadContext, RequestType.REST, (InetSocketAddress) request.getRemoteAddress()); + super(auditTrail, failureHandler, threadContext); this.request = request; } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/IncomingRequest.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/IncomingRequest.java deleted file mode 100644 index f8da624c5f5..00000000000 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/IncomingRequest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.authc; - -import java.net.InetSocketAddress; - -/** - * This represents an incoming request that needs to be authenticated - */ -public interface IncomingRequest { - - /** - * This method returns the remote address for the request. It will be null if the request is a - * local transport request. - * - * @return the remote socket address - */ - InetSocketAddress getRemoteAddress(); - - /** - * This returns the type of request that is incoming. It can be a rest request, a remote - * transport request, or a local transport request. - * - * @return the request type - */ - RequestType getType(); - - enum RequestType { - REST, - REMOTE_NODE, - LOCAL_NODE - } -} diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java index 22ff53d50af..676d19f5030 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/Realm.java @@ -96,10 +96,8 @@ public abstract class Realm implements Comparable { * * @param token The authentication token * @param listener The listener to pass the authentication result to - * @param incomingRequest the request that is being authenticated */ - public abstract void authenticate(AuthenticationToken token, ActionListener listener, - IncomingRequest incomingRequest); + public abstract void authenticate(AuthenticationToken token, ActionListener listener); /** * Looks up the user identified the String identifier. A successful lookup will call the {@link ActionListener#onResponse} diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java index e44137582ee..0e7736018d5 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/NativeRealm.java @@ -8,7 +8,6 @@ package org.elasticsearch.xpack.security.authc.esnative; import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; @@ -36,8 +35,7 @@ public class NativeRealm extends CachingUsernamePasswordRealm { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { userStore.verifyPassword(token.principal(), token.credentials(), listener); } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java index 64c857c2d21..89bc04727c1 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealm.java @@ -9,25 +9,17 @@ import org.apache.logging.log4j.message.ParameterizedMessage; import org.apache.logging.log4j.util.Supplier; import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.common.settings.SecureSetting; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.env.Environment; -import org.elasticsearch.gateway.GatewayService; -import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.XPackSettings; -import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.Security; import org.elasticsearch.xpack.security.SecurityLifecycleService; -import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.action.user.ChangePasswordAction; import org.elasticsearch.xpack.security.action.user.ChangePasswordRequest; -import org.elasticsearch.xpack.security.action.user.ChangePasswordResponse; -import org.elasticsearch.xpack.security.authc.IncomingRequest; +import org.elasticsearch.xpack.security.authc.AuthenticationResult; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore.ReservedUserInfo; import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm; @@ -41,16 +33,11 @@ import org.elasticsearch.xpack.security.user.KibanaUser; import org.elasticsearch.xpack.security.user.LogstashSystemUser; import org.elasticsearch.xpack.security.user.User; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.locks.ReentrantLock; /** * A realm for predefined users. These users can only be modified in terms of changing their passwords; no other modifications are allowed. @@ -62,7 +49,6 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { public static final SecureString EMPTY_PASSWORD_TEXT = new SecureString("".toCharArray()); static final char[] EMPTY_PASSWORD_HASH = Hasher.BCRYPT.hash(EMPTY_PASSWORD_TEXT); - static final char[] OLD_DEFAULT_PASSWORD_HASH = Hasher.BCRYPT.hash(new SecureString("changeme".toCharArray())); private static final ReservedUserInfo DEFAULT_USER_INFO = new ReservedUserInfo(EMPTY_PASSWORD_HASH, true, true); private static final ReservedUserInfo DISABLED_USER_INFO = new ReservedUserInfo(EMPTY_PASSWORD_HASH, false, true); @@ -89,25 +75,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { - if (incomingRequest.getType() != IncomingRequest.RequestType.REST) { - doAuthenticate(token, listener, false); - } else { - InetAddress address = incomingRequest.getRemoteAddress().getAddress(); - - try { - // This checks if the address is the loopback address or if it is bound to one of this machine's - // network interfaces. This is because we want to allow requests that originate from this machine. - final boolean isLocalMachine = address.isLoopbackAddress() || NetworkInterface.getByInetAddress(address) != null; - doAuthenticate(token, listener, isLocalMachine); - } catch (SocketException e) { - listener.onFailure(Exceptions.authenticationError("failed to authenticate user [{}]", e, token.principal())); - } - } - } - - private void doAuthenticate(UsernamePasswordToken token, ActionListener listener, boolean acceptEmptyPassword) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { if (realmEnabled == false) { listener.onResponse(AuthenticationResult.notHandled()); } else if (isReserved(token.principal(), config.globalSettings()) == false) { @@ -118,17 +86,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { if (userInfo != null) { try { if (userInfo.hasEmptyPassword) { - // norelease - // Accepting the OLD_DEFAULT_PASSWORD_HASH is a transition step. We do not want to support - // this in a release. - if (isSetupMode(token.principal(), acceptEmptyPassword) == false) { - result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null); - } else if (verifyPassword(userInfo, token) - || Hasher.BCRYPT.verify(token.credentials(), OLD_DEFAULT_PASSWORD_HASH)) { - result = AuthenticationResult.success(getUser(token.principal(), userInfo)); - } else { - result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null); - } + result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null); } else if (verifyPassword(userInfo, token)) { final User user = getUser(token.principal(), userInfo); result = AuthenticationResult.success(user); @@ -136,7 +94,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { result = AuthenticationResult.terminate("failed to authenticate user [" + token.principal() + "]", null); } } finally { - if (userInfo.passwordHash != EMPTY_PASSWORD_HASH && userInfo.passwordHash != OLD_DEFAULT_PASSWORD_HASH) { + if (userInfo.passwordHash != EMPTY_PASSWORD_HASH) { Arrays.fill(userInfo.passwordHash, (char) 0); } } @@ -149,10 +107,6 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { } } - private boolean isSetupMode(String userName, boolean acceptEmptyPassword) { - return ElasticUser.NAME.equals(userName) && acceptEmptyPassword; - } - private boolean verifyPassword(ReservedUserInfo userInfo, UsernamePasswordToken token) { if (Hasher.BCRYPT.verify(token.credentials(), userInfo.passwordHash)) { return true; @@ -225,7 +179,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { assert username != null; switch (username) { case ElasticUser.NAME: - return new ElasticUser(userInfo.enabled, userInfo.hasEmptyPassword); + return new ElasticUser(userInfo.enabled); case KibanaUser.NAME: return new KibanaUser(userInfo.enabled); case LogstashSystemUser.NAME: @@ -249,8 +203,7 @@ public class ReservedRealm extends CachingUsernamePasswordRealm { List users = new ArrayList<>(4); ReservedUserInfo userInfo = reservedUserInfos.get(ElasticUser.NAME); - users.add(new ElasticUser(userInfo == null || userInfo.enabled, - userInfo == null || userInfo.hasEmptyPassword)); + users.add(new ElasticUser(userInfo == null || userInfo.enabled)); userInfo = reservedUserInfos.get(KibanaUser.NAME); users.add(new KibanaUser(userInfo == null || userInfo.enabled)); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java index e12d035ada4..c49dd3c1242 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/file/FileRealm.java @@ -5,19 +5,18 @@ */ package org.elasticsearch.xpack.security.authc.file; -import java.util.Map; -import java.util.Set; - import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.support.CachingUsernamePasswordRealm; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.user.User; +import java.util.Map; +import java.util.Set; + public class FileRealm extends CachingUsernamePasswordRealm { public static final String TYPE = "file"; @@ -39,8 +38,7 @@ public class FileRealm extends CachingUsernamePasswordRealm { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { final AuthenticationResult result = userPasswdStore.verifyPassword(token.principal(), token.credentials(), () -> { String[] roles = userRolesStore.roles(token.principal()); return new User(token.principal(), roles); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java index 24eb787148d..38cc1d00277 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealm.java @@ -5,13 +5,6 @@ */ package org.elasticsearch.xpack.security.authc.ldap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; -import java.util.function.Supplier; - import com.unboundid.ldap.sdk.LDAPException; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; @@ -29,7 +22,6 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool.Names; import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.RealmSettings; import org.elasticsearch.xpack.security.authc.ldap.support.LdapLoadBalancing; @@ -45,6 +37,13 @@ import org.elasticsearch.xpack.security.authc.support.mapper.NativeRoleMappingSt import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.ssl.SSLService; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Supplier; + /** * Authenticates username/password tokens against ldap, locates groups and maps them to roles. @@ -143,8 +142,7 @@ public final class LdapRealm extends CachingUsernamePasswordRealm { * This user will then be passed to the listener */ @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { // we submit to the threadpool because authentication using LDAP will execute blocking I/O for a bind request and we don't want // network threads stuck waiting for a socket to connect. After the bind, then all interaction with LDAP should be async final CancellableLdapRunnable cancellableLdapRunnable = new CancellableLdapRunnable(listener, diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java index 50cefba90af..3e9b27df7d1 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/pki/PkiRealm.java @@ -5,18 +5,6 @@ */ package org.elasticsearch.xpack.security.authc.pki; -import javax.net.ssl.X509TrustManager; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; import org.apache.logging.log4j.util.Supplier; @@ -31,7 +19,6 @@ import org.elasticsearch.env.Environment; import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.security.authc.AuthenticationResult; import org.elasticsearch.xpack.security.authc.AuthenticationToken; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.RealmSettings; @@ -42,6 +29,18 @@ import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.ssl.CertUtils; import org.elasticsearch.xpack.ssl.SSLConfigurationSettings; +import javax.net.ssl.X509TrustManager; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + public class PkiRealm extends Realm { public static final String PKI_CERT_HEADER_NAME = "__SECURITY_CLIENT_CERTIFICATE"; @@ -83,8 +82,7 @@ public class PkiRealm extends Realm { } @Override - public void authenticate(AuthenticationToken authToken, ActionListener listener, - IncomingRequest incomingRequest) { + public void authenticate(AuthenticationToken authToken, ActionListener listener) { X509AuthenticationToken token = (X509AuthenticationToken)authToken; if (isCertificateChainTrusted(trustManager, token, logger) == false) { listener.onResponse(AuthenticationResult.unsuccessful("Certificate for " + token.dn() + " is not trusted", null)); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java index 2589555c059..5dfca82779a 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealm.java @@ -20,7 +20,6 @@ import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.xpack.security.authc.AuthenticationResult; import org.elasticsearch.xpack.security.authc.AuthenticationToken; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.user.User; @@ -72,17 +71,15 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm * doAuthenticate * @param authToken The authentication token * @param listener to be called at completion - * @param incomingRequest the request that is being authenticated */ @Override - public final void authenticate(AuthenticationToken authToken, ActionListener listener, - IncomingRequest incomingRequest) { + public final void authenticate(AuthenticationToken authToken, ActionListener listener) { UsernamePasswordToken token = (UsernamePasswordToken) authToken; try { if (cache == null) { - doAuthenticate(token, listener, incomingRequest); + doAuthenticate(token, listener); } else { - authenticateWithCache(token, listener, incomingRequest); + authenticateWithCache(token, listener); } } catch (Exception e) { // each realm should handle exceptions, if we get one here it should be considered fatal @@ -90,8 +87,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm } } - private void authenticateWithCache(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + private void authenticateWithCache(UsernamePasswordToken token, ActionListener listener) { UserWithHash userWithHash = cache.get(token.principal()); if (userWithHash == null) { if (logger.isDebugEnabled()) { @@ -104,7 +100,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm logger.debug("realm [{}] authenticated user [{}], with roles [{}]", name(), token.principal(), user.roles()); } listener.onResponse(result); - }, listener::onFailure), incomingRequest); + }, listener::onFailure)); } else if (userWithHash.hasHash()) { if (userWithHash.verify(token.credentials())) { if (userWithHash.user.enabled()) { @@ -122,7 +118,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm user.enabled(), user.roles()); } listener.onResponse(result); - }, listener::onFailure), incomingRequest); + }, listener::onFailure)); } } else { cache.invalidate(token.principal()); @@ -133,7 +129,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm name(), token.principal(), user.roles()); } listener.onResponse(result); - }, listener::onFailure), incomingRequest); + }, listener::onFailure)); } } else { cache.invalidate(token.principal()); @@ -144,12 +140,11 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm "realm [{}] authenticated user [{}] with roles [{}]", name(), token.principal(), user.roles()); } listener.onResponse(result); - }, listener::onFailure), incomingRequest); + }, listener::onFailure)); } } - private void doAuthenticateAndCache(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + private void doAuthenticateAndCache(UsernamePasswordToken token, ActionListener listener) { ActionListener wrapped = ActionListener.wrap((result) -> { Objects.requireNonNull(result, "AuthenticationResult cannot be null"); if (result.getStatus() == AuthenticationResult.Status.SUCCESS) { @@ -160,7 +155,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm listener.onResponse(result); }, listener::onFailure); - doAuthenticate(token, wrapped, incomingRequest); + doAuthenticate(token, wrapped); } @Override @@ -170,8 +165,7 @@ public abstract class CachingUsernamePasswordRealm extends UsernamePasswordRealm return stats; } - protected abstract void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest); + protected abstract void doAuthenticate(UsernamePasswordToken token, ActionListener listener); @Override public final void lookupUser(String username, ActionListener listener) { diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java index 10dfb8dc6ff..c15c57edf06 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/authz/AuthorizationService.java @@ -149,15 +149,6 @@ public class AuthorizationService extends AbstractComponent { throw denial(authentication, action, request); } - // norelease - // TODO: This functionality is disabled as it is not yet compatible with the upgrade process - // If the user is the elastic user in setup mode, then only change password requests can be authorized -// if (ElasticUser.isElasticUserInSetupMode(authentication.getUser()) -// && ChangePasswordAction.NAME.equals(action) == false -// && ClusterHealthAction.NAME.equals(action) == false) { -// throw denial(authentication, action, request); -// } - // get the roles of the authenticated user, which may be different than the effective Role permission = userRole; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/security/user/ElasticUser.java b/plugin/src/main/java/org/elasticsearch/xpack/security/user/ElasticUser.java index e22d97c6276..fe9e401e9bd 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/security/user/ElasticUser.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/security/user/ElasticUser.java @@ -18,27 +18,8 @@ public class ElasticUser extends User { public static final String NAME = "elastic"; private static final String ROLE_NAME = "superuser"; - private static final String SETUP_MODE = "_setup_mode"; public ElasticUser(boolean enabled) { - this(enabled, false); - } - - public ElasticUser(boolean enabled, boolean setupMode) { - super(NAME, new String[] { ROLE_NAME }, null, null, metadata(setupMode), enabled); - } - - public static boolean isElasticUserInSetupMode(User user) { - return NAME.equals(user.principal()) && Boolean.TRUE.equals(user.metadata().get(SETUP_MODE)); - } - - private static Map metadata(boolean setupMode) { - if (setupMode == false) { - return MetadataUtils.DEFAULT_RESERVED_METADATA; - } else { - HashMap metadata = new HashMap<>(MetadataUtils.DEFAULT_RESERVED_METADATA); - metadata.put(SETUP_MODE, true); - return metadata; - } + super(NAME, new String[] { ROLE_NAME }, null, null, MetadataUtils.DEFAULT_RESERVED_METADATA, enabled); } } diff --git a/plugin/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java b/plugin/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java index f75d5a94866..42af765dd15 100644 --- a/plugin/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java +++ b/plugin/src/test/java/org/elasticsearch/integration/ClearRealmsCacheTests.java @@ -19,7 +19,6 @@ import org.elasticsearch.test.SecuritySettingsSource; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheRequest; import org.elasticsearch.xpack.security.action.realm.ClearRealmCacheResponse; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.Realms; import org.elasticsearch.xpack.security.authc.support.Hasher; @@ -42,7 +41,6 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.sameInstance; -import static org.mockito.Mockito.mock; public class ClearRealmsCacheTests extends SecurityIntegTestCase { private static final String USERS_PASSWD_HASHED = new String(Hasher.BCRYPT.hash(new SecureString("passwd".toCharArray()))); @@ -236,7 +234,7 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase { for (Realm realm : realms) { for (String username : usernames) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(tokens.get(username), future, mock(IncomingRequest.class)); + realm.authenticate(tokens.get(username), future); User user = future.actionGet().getUser(); assertThat(user, notNullValue()); Map realmToUser = users.get(username); @@ -253,7 +251,7 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase { for (String username : usernames) { for (Realm realm : realms) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(tokens.get(username), future, mock(IncomingRequest.class)); + realm.authenticate(tokens.get(username), future); User user = future.actionGet().getUser(); assertThat(user, sameInstance(users.get(username).get(realm))); } @@ -266,7 +264,7 @@ public class ClearRealmsCacheTests extends SecurityIntegTestCase { for (String username : usernames) { for (Realm realm : realms) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(tokens.get(username), future, mock(IncomingRequest.class)); + realm.authenticate(tokens.get(username), future); User user = future.actionGet().getUser(); assertThat(user, notNullValue()); scenario.assertEviction(users.get(username).get(realm), user); diff --git a/plugin/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java index 8f36175a652..2c149245a52 100644 --- a/plugin/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/test/NativeRealmIntegTestCase.java @@ -35,7 +35,10 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase { @Before public void ensureNativeStoresStarted() throws Exception { assertSecurityIndexActive(); - setupReservedPasswords(); + if (shouldSetReservedUserPasswords()) { + ensureElasticPasswordBootstrapped(); + setupReservedPasswords(); + } } @After @@ -68,18 +71,14 @@ public abstract class NativeRealmIntegTestCase extends SecurityIntegTestCase { } public void setupReservedPasswords() throws IOException { - if (shouldSetReservedUserPasswords() == false) { - return; - } logger.info("setting up reserved passwords for test"); SecureString defaultPassword = new SecureString("".toCharArray()); - for (String username : Arrays.asList(ElasticUser.NAME, KibanaUser.NAME, BeatsSystemUser.NAME, LogstashSystemUser.NAME)) { - SecureString authPassword = username.equals(ElasticUser.NAME) ? defaultPassword : reservedPassword; + for (String username : Arrays.asList(KibanaUser.NAME, BeatsSystemUser.NAME, LogstashSystemUser.NAME)) { String payload = "{\"password\": \"" + new String(reservedPassword.getChars()) + "\"}"; HttpEntity entity = new NStringEntity(payload, ContentType.APPLICATION_JSON); BasicHeader authHeader = new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, - UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, authPassword)); + UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING)); String route = "/_xpack/security/user/" + username + "/_password"; Response response = getRestClient().performRequest("PUT", route, Collections.emptyMap(), entity, authHeader); } diff --git a/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java index 028785d32f9..255bf4c0cbb 100644 --- a/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/test/SecurityIntegTestCase.java @@ -6,6 +6,7 @@ package org.elasticsearch.test; import org.elasticsearch.AbstractOldXPackIndicesBackwardsCompatibilityTestCase; +import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.node.info.NodeInfo; import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse; @@ -35,6 +36,7 @@ import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.ml.MachineLearning; import org.elasticsearch.xpack.security.InternalClient; import org.elasticsearch.xpack.security.Security; +import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm; import org.elasticsearch.xpack.security.client.SecurityClient; import org.junit.AfterClass; import org.junit.Before; @@ -48,6 +50,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; import java.util.function.Function; import java.util.stream.Collectors; @@ -184,7 +187,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { Collection pluginNames = nodeInfo.getPlugins().getPluginInfos().stream().map(p -> p.getClassname()).collect(Collectors.toList()); assertThat("plugin [" + xpackPluginClass().getName() + "] not found in [" + pluginNames + "]", pluginNames, - hasItem(xpackPluginClass().getName())); + hasItem(xpackPluginClass().getName())); } } @@ -209,7 +212,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { Settings.Builder customBuilder = Settings.builder().put(customSettings); if (customBuilder.getSecureSettings() != null) { SecuritySettingsSource.addSecureSettings(builder, secureSettings -> - secureSettings.merge((MockSecureSettings) customBuilder.getSecureSettings())); + secureSettings.merge((MockSecureSettings) customBuilder.getSecureSettings())); } return builder.build(); } @@ -408,7 +411,7 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { } @Override - protected Function getClientWrapper() { + protected Function getClientWrapper() { Map headers = Collections.singletonMap("Authorization", basicAuthHeaderValue(nodeClientUsername(), nodeClientPassword())); // we need to wrap node clients because we do not specify a user for nodes and all requests will use the system @@ -445,7 +448,11 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { } public void assertSecurityIndexActive() throws Exception { - for (ClusterService clusterService : internalCluster().getInstances(ClusterService.class)) { + assertSecurityIndexActive(internalCluster()); + } + + public void assertSecurityIndexActive(InternalTestCluster internalTestCluster) throws Exception { + for (ClusterService clusterService : internalTestCluster.getInstances(ClusterService.class)) { assertBusy(() -> { ClusterState clusterState = clusterService.state(); assertFalse(clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)); @@ -461,6 +468,29 @@ public abstract class SecurityIntegTestCase extends ESIntegTestCase { } } + public void ensureElasticPasswordBootstrapped() throws Exception { + ensureElasticPasswordBootstrapped(internalCluster()); + } + + public void ensureElasticPasswordBootstrapped(InternalTestCluster internalTestCluster) throws Exception { + CountDownLatch latch = new CountDownLatch(1); + SecureString testPasswordHashed = new SecureString(SecuritySettingsSource.TEST_PASSWORD_HASHED.toCharArray()); + ReservedRealm reservedRealm = internalTestCluster.getInstances(ReservedRealm.class).iterator().next(); + reservedRealm.bootstrapElasticUserCredentials(testPasswordHashed, new ActionListener() { + @Override + public void onResponse(Boolean passwordSet) { + latch.countDown(); + } + + @Override + public void onFailure(Exception e) { + logger.error("Exception attempting to bootstrap password for test", e); + fail("Failed to bootstrap elastic password for test due to exception: " + e.getMessage()); + } + }); + latch.await(); + } + public void assertSecurityIndexWriteable() throws Exception { for (ClusterService clusterService : internalCluster().getInstances(ClusterService.class)) { assertBusy(() -> { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java b/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java index 35d0501a915..f5de544837a 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/DatafeedJobsRestIT.java @@ -32,15 +32,14 @@ import static org.hamcrest.Matchers.equalTo; public class DatafeedJobsRestIT extends ESRestTestCase { - private static final String BASIC_AUTH_VALUE_ELASTIC = - basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); + private static final String BASIC_AUTH_VALUE_SUPER_USER = + basicAuthHeaderValue("x_pack_rest_user", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); private static final String BASIC_AUTH_VALUE_ML_ADMIN = basicAuthHeaderValue("ml_admin", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); @Override protected Settings restClientSettings() { - return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", - BASIC_AUTH_VALUE_ELASTIC).build(); + return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", BASIC_AUTH_VALUE_SUPER_USER).build(); } @Override @@ -51,10 +50,6 @@ public class DatafeedJobsRestIT extends ESRestTestCase { @Before public void setUpData() throws Exception { String password = new String(SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING.getChars()); - String elasticUserPayload = "{\"password\" : \"" + password + "\"}"; - - client().performRequest("put", "_xpack/security/user/elastic/_password", Collections.emptyMap(), - new StringEntity(elasticUserPayload, ContentType.APPLICATION_JSON)); // This user has admin rights on machine learning, but (importantly for the tests) no // rights on any of the data indexes @@ -310,7 +305,7 @@ public class DatafeedJobsRestIT extends ESRestTestCase { new DatafeedBuilder(datafeedId, jobId, "airline-data-aggs", "response").build(); // This should be disallowed, because ml_admin is trying to preview a datafeed created by - // by another user (elastic in this case) that will reveal the content of an index they + // by another user (x_pack_rest_user in this case) that will reveal the content of an index they // don't have permission to search directly ResponseException e = expectThrows(ResponseException.class, () -> client().performRequest("get", @@ -581,7 +576,7 @@ public class DatafeedJobsRestIT extends ESRestTestCase { boolean source; String scriptedFields; String aggregations; - String authHeader = BASIC_AUTH_VALUE_ELASTIC; + String authHeader = BASIC_AUTH_VALUE_SUPER_USER; DatafeedBuilder(String datafeedId, String jobId, String index, String type) { this.datafeedId = datafeedId; diff --git a/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlJobIT.java b/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlJobIT.java index deefd073a5e..5e9d50f1eab 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlJobIT.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlJobIT.java @@ -36,7 +36,8 @@ import static org.hamcrest.Matchers.not; public class MlJobIT extends ESRestTestCase { - private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); + private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("x_pack_rest_user", + SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); @Override protected Settings restClientSettings() { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java index 4a487066d3d..c2c0361ec92 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/ml/integration/MlNativeAutodetectIntegTestCase.java @@ -81,7 +81,7 @@ abstract class MlNativeAutodetectIntegTestCase extends SecurityIntegTestCase { protected Settings externalClusterClientSettings() { Settings.Builder builder = Settings.builder(); builder.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME4); - builder.put(Security.USER_SETTING.getKey(), "elastic:" + SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); + builder.put(Security.USER_SETTING.getKey(), "x_pack_rest_user:" + SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); builder.put(XPackSettings.MACHINE_LEARNING_ENABLED.getKey(), true); return builder.build(); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java b/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java index f86511ed037..81e7dde1b4d 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/SecurityTribeIT.java @@ -5,16 +5,9 @@ */ package org.elasticsearch.xpack.security; -import org.apache.http.HttpEntity; -import org.apache.http.HttpHost; -import org.apache.http.entity.ContentType; -import org.apache.http.message.BasicHeader; -import org.apache.http.nio.entity.NStringEntity; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.client.Client; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.service.ClusterService; @@ -29,7 +22,6 @@ import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.node.MockNode; import org.elasticsearch.node.Node; -import org.elasticsearch.node.NodeValidationException; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.InternalTestCluster; @@ -40,14 +32,11 @@ import org.elasticsearch.xpack.security.action.role.PutRoleResponse; import org.elasticsearch.xpack.security.action.user.PutUserResponse; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; import org.elasticsearch.xpack.security.client.SecurityClient; -import org.elasticsearch.xpack.security.user.ElasticUser; import org.elasticsearch.xpack.security.support.IndexLifecycleManager; - import org.junit.After; import org.junit.AfterClass; import org.junit.BeforeClass; -import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -58,7 +47,6 @@ import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.function.Predicate; -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.containsString; @@ -102,11 +90,7 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { cluster2.beforeTest(random(), 0.1); cluster2.ensureAtLeastNumDataNodes(2); } - } - - @Override - public boolean shouldSetReservedUserPasswords() { - return false; + assertSecurityIndexActive(cluster2); } @Override @@ -132,7 +116,7 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { public void tearDownTribeNodeAndWipeCluster() throws Exception { if (cluster2 != null) { try { - cluster2.wipe(Collections.emptySet()); + cluster2.wipe(Collections.emptySet()); try { // this is a hack to clean up the .security index since only the XPack user or superusers can delete it cluster2.getInstance(InternalClient.class) @@ -160,7 +144,12 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { return true; } - private void setupTribeNode(Settings settings) throws NodeValidationException, InterruptedException { + @Override + protected boolean shouldSetReservedUserPasswords() { + return false; + } + + private void setupTribeNode(Settings settings) throws Exception { SecuritySettingsSource cluster2SettingsSource = new SecuritySettingsSource(1, useGeneratedSSL, createTempDir(), Scope.TEST) { @Override @@ -246,26 +235,14 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { }, nodeCountPredicate); latch.await(); } + + assertTribeNodeHasAllIndices(); } public void testThatTribeCanAuthenticateElasticUser() throws Exception { - InetSocketAddress[] inetSocketAddresses = cluster2.httpAddresses(); - List hosts = new ArrayList<>(); - for (InetSocketAddress address : inetSocketAddresses) { - hosts.add(new HttpHost(address.getAddress(), address.getPort())); - } - RestClientBuilder builder = RestClient.builder(hosts.toArray(new HttpHost[hosts.size()])); - RestClient client = builder.build(); - - String payload = "{\"password\": \"" + SecuritySettingsSource.TEST_PASSWORD + "\"}"; - HttpEntity entity = new NStringEntity(payload, ContentType.APPLICATION_JSON); - BasicHeader authHeader = new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, - UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, new SecureString("".toCharArray()))); - String route = "/_xpack/security/user/" + ElasticUser.NAME + "/_password"; - client.performRequest("PUT", route, Collections.emptyMap(), entity, authHeader); - client.close(); - setupTribeNode(Settings.EMPTY); + ensureElasticPasswordBootstrapped(internalCluster()); + assertTribeNodeHasAllIndices(); ClusterHealthResponse response = tribeClient.filterWithHeader(Collections.singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING))) .admin().cluster().prepareHealth().get(); @@ -274,8 +251,9 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { public void testThatTribeCanAuthenticateElasticUserWithChangedPassword() throws Exception { setupTribeNode(Settings.EMPTY); - Client clusterClient = randomBoolean() ? client() : cluster2.client(); - securityClient(clusterClient).prepareChangePassword("elastic", "password".toCharArray()).get(); + InternalTestCluster cluster = randomBoolean() ? internalCluster() : cluster2; + ensureElasticPasswordBootstrapped(cluster); + securityClient(cluster.client()).prepareChangePassword("elastic", "password".toCharArray()).get(); assertTribeNodeHasAllIndices(); ClusterHealthResponse response = tribeClient.filterWithHeader(Collections.singletonMap("Authorization", @@ -286,6 +264,8 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { public void testThatTribeClustersHaveDifferentPasswords() throws Exception { setupTribeNode(Settings.EMPTY); + ensureElasticPasswordBootstrapped(internalCluster()); + ensureElasticPasswordBootstrapped(cluster2); securityClient().prepareChangePassword("elastic", "password".toCharArray()).get(); securityClient(cluster2.client()).prepareChangePassword("elastic", "password2".toCharArray()).get(); @@ -297,6 +277,9 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { } public void testUsersInBothTribes() throws Exception { + ensureElasticPasswordBootstrapped(internalCluster()); + ensureElasticPasswordBootstrapped(cluster2); + final String preferredTribe = randomBoolean() ? "t1" : "t2"; setupTribeNode(Settings.builder().put("tribe.on_conflict", "prefer_" + preferredTribe).build()); final int randomUsers = scaledRandomIntBetween(3, 8); @@ -305,10 +288,7 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { List shouldBeSuccessfulUsers = new ArrayList<>(); List shouldFailUsers = new ArrayList<>(); final Client preferredClient = "t1".equals(preferredTribe) ? cluster1Client : cluster2Client; - // always ensure the index exists on all of the clusters in this test - assertAcked(internalClient().admin().indices().prepareCreate(IndexLifecycleManager.INTERNAL_SECURITY_INDEX).get()); - assertAcked(cluster2.getInstance(InternalClient.class).admin().indices() - .prepareCreate(IndexLifecycleManager.INTERNAL_SECURITY_INDEX).get()); + for (int i = 0; i < randomUsers; i++) { final String username = "user" + i; Client clusterClient = randomBoolean() ? cluster1Client : cluster2Client; @@ -346,16 +326,16 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { final String preferredTribe = randomBoolean() ? "t1" : "t2"; setupTribeNode(Settings.builder().put("tribe.on_conflict", "prefer_" + preferredTribe).build()); final int randomUsers = scaledRandomIntBetween(3, 8); - final Client cluster1Client = client(); - final Client cluster2Client = cluster2.client(); + List shouldBeSuccessfulUsers = new ArrayList<>(); // only create users in the non preferred client - final Client nonPreferredClient = "t1".equals(preferredTribe) ? cluster2Client : cluster1Client; + final InternalTestCluster nonPreferredCluster = "t1".equals(preferredTribe) ? cluster2 : internalCluster(); + ensureElasticPasswordBootstrapped(nonPreferredCluster); for (int i = 0; i < randomUsers; i++) { final String username = "user" + i; PutUserResponse response = - securityClient(nonPreferredClient).preparePutUser(username, "password".toCharArray(), "superuser").get(); + securityClient(nonPreferredCluster.client()).preparePutUser(username, "password".toCharArray(), "superuser").get(); assertTrue(response.created()); shouldBeSuccessfulUsers.add(username); } @@ -370,6 +350,8 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { } public void testUserModificationUsingTribeNodeAreDisabled() throws Exception { + ensureElasticPasswordBootstrapped(internalCluster()); + setupTribeNode(Settings.EMPTY); SecurityClient securityClient = securityClient(tribeClient); UnsupportedOperationException e = expectThrows(UnsupportedOperationException.class, @@ -385,6 +367,9 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { } public void testRetrieveRolesOnTribeNode() throws Exception { + ensureElasticPasswordBootstrapped(internalCluster()); + ensureElasticPasswordBootstrapped(cluster2); + final String preferredTribe = randomBoolean() ? "t1" : "t2"; setupTribeNode(Settings.builder().put("tribe.on_conflict", "prefer_" + preferredTribe).build()); final int randomRoles = scaledRandomIntBetween(3, 8); @@ -393,10 +378,6 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { List shouldBeSuccessfulRoles = new ArrayList<>(); List shouldFailRoles = new ArrayList<>(); final Client preferredClient = "t1".equals(preferredTribe) ? cluster1Client : cluster2Client; - // always ensure the index exists on all of the clusters in this test - assertAcked(internalClient().admin().indices().prepareCreate(IndexLifecycleManager.INTERNAL_SECURITY_INDEX).get()); - assertAcked(cluster2.getInstance(InternalClient.class).admin().indices() - .prepareCreate(IndexLifecycleManager.INTERNAL_SECURITY_INDEX).get()); for (int i = 0; i < randomRoles; i++) { final String rolename = "role" + i; @@ -432,10 +413,10 @@ public class SecurityTribeIT extends NativeRealmIntegTestCase { final String preferredTribe = randomBoolean() ? "t1" : "t2"; setupTribeNode(Settings.builder().put("tribe.on_conflict", "prefer_" + preferredTribe).build()); final int randomRoles = scaledRandomIntBetween(3, 8); - final Client cluster1Client = client(); - final Client cluster2Client = cluster2.client(); List shouldBeSuccessfulRoles = new ArrayList<>(); - final Client nonPreferredClient = "t1".equals(preferredTribe) ? cluster2Client : cluster1Client; + final InternalTestCluster nonPreferredCluster = "t1".equals(preferredTribe) ? cluster2 : internalCluster(); + ensureElasticPasswordBootstrapped(nonPreferredCluster); + Client nonPreferredClient = nonPreferredCluster.client(); for (int i = 0; i < randomRoles; i++) { final String rolename = "role" + i; diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java index 696c46c173d..a05c221a38b 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java @@ -215,7 +215,7 @@ public class AuthenticationServiceTests extends ESTestCase { }, this::logAndFail)); verify(auditTrail).authenticationSuccess(secondRealm.name(), user, "_action", message); verifyNoMoreInteractions(auditTrail); - verify(firstRealm, never()).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class)); + verify(firstRealm, never()).authenticate(eq(token), any(ActionListener.class)); assertTrue(completed.get()); } @@ -571,7 +571,7 @@ public class AuthenticationServiceTests extends ESTestCase { when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); doThrow(authenticationError("realm doesn't like authenticate")) - .when(secondRealm).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class)); + .when(secondRealm).authenticate(eq(token), any(ActionListener.class)); try { authenticateBlocking("_action", message, null); fail("exception should bubble out"); @@ -586,7 +586,7 @@ public class AuthenticationServiceTests extends ESTestCase { when(secondRealm.token(threadContext)).thenReturn(token); when(secondRealm.supports(token)).thenReturn(true); doThrow(authenticationError("realm doesn't like authenticate")) - .when(secondRealm).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class)); + .when(secondRealm).authenticate(eq(token), any(ActionListener.class)); try { authenticateBlocking(restRequest); fail("exception should bubble out"); @@ -882,7 +882,7 @@ public class AuthenticationServiceTests extends ESTestCase { listener.onResponse(AuthenticationResult.success(user)); } return null; - }).when(realm).authenticate(eq(token), any(ActionListener.class), any(IncomingRequest.class)); + }).when(realm).authenticate(eq(token), any(ActionListener.class)); } private Authentication authenticateBlocking(RestRequest restRequest) { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java index c941d8ee937..c977ecc2214 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/RealmsTests.java @@ -9,14 +9,14 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.env.Environment; -import org.elasticsearch.xpack.security.user.User; -import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm; -import org.elasticsearch.xpack.security.authc.esnative.NativeRealm; -import org.elasticsearch.xpack.security.authc.file.FileRealm; -import org.elasticsearch.xpack.security.authc.ldap.LdapRealm; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.license.XPackLicenseState.AllowedRealmType; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.security.authc.esnative.NativeRealm; +import org.elasticsearch.xpack.security.authc.esnative.ReservedRealm; +import org.elasticsearch.xpack.security.authc.file.FileRealm; +import org.elasticsearch.xpack.security.authc.ldap.LdapRealm; +import org.elasticsearch.xpack.security.user.User; import org.junit.Before; import java.util.ArrayList; @@ -436,8 +436,7 @@ public class RealmsTests extends ESTestCase { } @Override - public void authenticate(AuthenticationToken token, ActionListener listener, - IncomingRequest incomingRequest) { + public void authenticate(AuthenticationToken token, ActionListener listener) { listener.onResponse(AuthenticationResult.notHandled()); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java index 6dae2948591..25ce51cd730 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeMigrateToolTests.java @@ -40,11 +40,6 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase { useSSL = randomBoolean(); } - @Override - public boolean shouldSetReservedUserPasswords() { - return false; - } - @Override public Settings nodeSettings(int nodeOrdinal) { logger.info("--> use SSL? {}", useSSL); @@ -62,6 +57,11 @@ public class ESNativeMigrateToolTests extends NativeRealmIntegTestCase { return useSSL == false; } + @Override + protected boolean shouldSetReservedUserPasswords() { + return false; + } + private Environment nodeEnvironment() throws Exception { return internalCluster().getInstances(Environment.class).iterator().next(); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java index 92ef9af1b3f..37b65d0e30b 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ReservedRealmTests.java @@ -5,16 +5,6 @@ */ package org.elasticsearch.xpack.security.authc.esnative; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ExecutionException; -import java.util.function.Predicate; - import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; @@ -27,9 +17,8 @@ import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.security.SecurityLifecycleService; -import org.elasticsearch.xpack.security.authc.AuthenticationResult; import org.elasticsearch.xpack.security.action.user.ChangePasswordRequest; -import org.elasticsearch.xpack.security.authc.IncomingRequest; +import org.elasticsearch.xpack.security.authc.AuthenticationResult; import org.elasticsearch.xpack.security.authc.esnative.NativeUsersStore.ReservedUserInfo; import org.elasticsearch.xpack.security.authc.support.Hasher; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; @@ -42,11 +31,18 @@ import org.elasticsearch.xpack.security.user.User; import org.junit.Before; import org.mockito.ArgumentCaptor; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; +import java.util.function.Predicate; + import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static org.mockito.Matchers.any; @@ -68,34 +64,16 @@ public class ReservedRealmTests extends ESTestCase { public static final String ACCEPT_DEFAULT_PASSWORDS = ReservedRealm.ACCEPT_DEFAULT_PASSWORD_SETTING.getKey(); private NativeUsersStore usersStore; private SecurityLifecycleService securityLifecycleService; - private IncomingRequest incomingRequest; @Before public void setupMocks() throws Exception { usersStore = mock(NativeUsersStore.class); securityLifecycleService = mock(SecurityLifecycleService.class); - incomingRequest = mock(IncomingRequest.class); when(securityLifecycleService.isSecurityIndexAvailable()).thenReturn(true); when(securityLifecycleService.checkSecurityMappingVersion(any())).thenReturn(true); mockGetAllReservedUserInfo(usersStore, Collections.emptyMap()); } - @SuppressForbidden(reason = "allow getting localhost") - public void testMappingVersionFromBeforeUserExisted() throws ExecutionException, InterruptedException, UnknownHostException { - when(securityLifecycleService.checkSecurityMappingVersion(any())).thenReturn(false); - final ReservedRealm reservedRealm = - new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore, - new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY)); - final String principal = ElasticUser.NAME; - - PlainActionFuture future = new PlainActionFuture<>(); - InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 100); - when(incomingRequest.getRemoteAddress()).thenReturn(address); - when(incomingRequest.getType()).thenReturn(IncomingRequest.RequestType.REST); - reservedRealm.authenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), future, incomingRequest); - assertThat(future.get().getUser().enabled(), equalTo(false)); - } - public void testDisableDefaultPasswordAuthentication() throws Throwable { final User expected = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true)); @@ -106,11 +84,11 @@ public class ReservedRealmTests extends ESTestCase { securityLifecycleService, new ThreadContext(Settings.EMPTY)); PlainActionFuture listener = new PlainActionFuture<>(); - reservedRealm.doAuthenticate(new UsernamePasswordToken(expected.principal(), EMPTY_PASSWORD), listener, incomingRequest); + reservedRealm.doAuthenticate(new UsernamePasswordToken(expected.principal(), EMPTY_PASSWORD), listener); assertFailedAuthentication(listener, expected.principal()); } - public void testElasticEmptyPasswordAuthenticationFailsFromNonLocalhost() throws Throwable { + public void testElasticEmptyPasswordAuthenticationFails() throws Throwable { final User expected = new ElasticUser(true); final String principal = expected.principal(); @@ -121,37 +99,10 @@ public class ReservedRealmTests extends ESTestCase { PlainActionFuture listener = new PlainActionFuture<>(); - InetSocketAddress address = new InetSocketAddress(InetAddress.getByName("128.9.8.1"), 100); - - when(incomingRequest.getRemoteAddress()).thenReturn(address); - reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, incomingRequest); + reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener); assertFailedAuthentication(listener, expected.principal()); } - @SuppressForbidden(reason = "allow getting localhost") - public void testElasticEmptyPasswordAuthenticationSucceedsInSetupModeIfRestRequestComesFromLocalhost() throws Throwable { - final User expected = new ElasticUser(true, true); - final String principal = expected.principal(); - - Settings settings = Settings.builder().put(ACCEPT_DEFAULT_PASSWORDS, true).build(); - final ReservedRealm reservedRealm = - new ReservedRealm(mock(Environment.class), settings, usersStore, - new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY)); - - PlainActionFuture listener = new PlainActionFuture<>(); - - InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 100); - - when(incomingRequest.getRemoteAddress()).thenReturn(address); - when(incomingRequest.getType()).thenReturn(IncomingRequest.RequestType.REST); - reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, incomingRequest); - - User user = listener.actionGet().getUser(); - - assertEquals(expected, user); - assertNotEquals(new ElasticUser(true, false), user); - } - public void testAuthenticationDisabled() throws Throwable { Settings settings = Settings.builder().put(XPackSettings.RESERVED_REALM_ENABLED_SETTING.getKey(), false).build(); final boolean securityIndexExists = randomBoolean(); @@ -165,7 +116,7 @@ public class ReservedRealmTests extends ESTestCase { final String principal = expected.principal(); PlainActionFuture listener = new PlainActionFuture<>(); - reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, mock(IncomingRequest.class)); + reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener); final AuthenticationResult result = listener.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.CONTINUE)); assertNull(result.getUser()); @@ -196,7 +147,7 @@ public class ReservedRealmTests extends ESTestCase { // test empty password final PlainActionFuture listener = new PlainActionFuture<>(); - reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener, incomingRequest); + reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, EMPTY_PASSWORD), listener); assertFailedAuthentication(listener, expectedUser.principal()); // the realm assumes it owns the hashed password so it fills it with 0's @@ -208,7 +159,7 @@ public class ReservedRealmTests extends ESTestCase { // test new password final PlainActionFuture authListener = new PlainActionFuture<>(); - reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, newPassword), authListener, incomingRequest); + reservedRealm.doAuthenticate(new UsernamePasswordToken(principal, newPassword), authListener); final User authenticated = authListener.actionGet().getUser(); assertEquals(expectedUser, authenticated); assertThat(expectedUser.enabled(), is(enabled)); @@ -225,7 +176,7 @@ public class ReservedRealmTests extends ESTestCase { final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore, new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY)); - final User expectedUser = randomFrom(new ElasticUser(true, true), new KibanaUser(true), new LogstashSystemUser(true)); + final User expectedUser = randomFrom(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true)); final String principal = expectedUser.principal(); PlainActionFuture listener = new PlainActionFuture<>(); @@ -313,7 +264,7 @@ public class ReservedRealmTests extends ESTestCase { new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY)); PlainActionFuture> userFuture = new PlainActionFuture<>(); reservedRealm.users(userFuture); - assertThat(userFuture.actionGet(), containsInAnyOrder(new ElasticUser(true, true), new KibanaUser(true), + assertThat(userFuture.actionGet(), containsInAnyOrder(new ElasticUser(true), new KibanaUser(true), new LogstashSystemUser(true), new BeatsSystemUser(true))); } @@ -335,29 +286,21 @@ public class ReservedRealmTests extends ESTestCase { } } - @SuppressForbidden(reason = "allow getting localhost") public void testFailedAuthentication() throws Exception { final ReservedRealm reservedRealm = new ReservedRealm(mock(Environment.class), Settings.EMPTY, usersStore, new AnonymousUser(Settings.EMPTY), securityLifecycleService, new ThreadContext(Settings.EMPTY)); - InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), 100); // maybe cache a successful auth if (randomBoolean()) { PlainActionFuture future = new PlainActionFuture<>(); - IncomingRequest r = mock(IncomingRequest.class); - when(r.getRemoteAddress()).thenReturn(address); - when(r.getType()).thenReturn(IncomingRequest.RequestType.REST); - reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, EMPTY_PASSWORD), future, r); + reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, EMPTY_PASSWORD), future); User user = future.actionGet().getUser(); - assertEquals(new ElasticUser(true, true), user); + assertEquals(new ElasticUser(true), user); } PlainActionFuture future = new PlainActionFuture<>(); - IncomingRequest r = mock(IncomingRequest.class); - when(r.getRemoteAddress()).thenReturn(address); - when(r.getType()).thenReturn(IncomingRequest.RequestType.REST); - reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, new SecureString("foobar".toCharArray())), future, r); + reservedRealm.authenticate(new UsernamePasswordToken(ElasticUser.NAME, new SecureString("foobar".toCharArray())), future); assertFailedAuthentication(future, ElasticUser.NAME); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/file/FileRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/file/FileRealmTests.java index 2fa5df4c8ce..2bf0a77ec65 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/file/FileRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/file/FileRealmTests.java @@ -17,7 +17,6 @@ import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.support.Hasher; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; @@ -66,7 +65,7 @@ public class FileRealmTests extends ESTestCase { RealmConfig config = new RealmConfig("file-test", Settings.EMPTY, globalSettings, new Environment(globalSettings), new ThreadContext(globalSettings)); FileRealm realm = new FileRealm(config, userPasswdStore, userRolesStore); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS)); User user = result.getUser(); @@ -87,10 +86,10 @@ public class FileRealmTests extends ESTestCase { when(userRolesStore.roles("user1")).thenReturn(new String[]{"role1", "role2"}); FileRealm realm = new FileRealm(config, userPasswdStore, userRolesStore); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user1 = future.actionGet().getUser(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user2 = future.actionGet().getUser(); assertThat(user1, sameInstance(user2)); } @@ -104,32 +103,32 @@ public class FileRealmTests extends ESTestCase { doReturn(new String[] { "role1", "role2" }).when(userRolesStore).roles("user1"); FileRealm realm = new FileRealm(config, userPasswdStore, userRolesStore); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user1 = future.actionGet().getUser(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user2 = future.actionGet().getUser(); assertThat(user1, sameInstance(user2)); userPasswdStore.notifyRefresh(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user3 = future.actionGet().getUser(); assertThat(user2, not(sameInstance(user3))); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user4 = future.actionGet().getUser(); assertThat(user3, sameInstance(user4)); userRolesStore.notifyRefresh(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user5 = future.actionGet().getUser(); assertThat(user4, not(sameInstance(user5))); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user1", new SecureString("test123")), future); User user6 = future.actionGet().getUser(); assertThat(user5, sameInstance(user6)); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java index 1ecacb0eaaf..74e2f9a21c6 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/ActiveDirectoryRealmTests.java @@ -20,7 +20,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.env.Environment; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySessionFactory.DownLevelADAuthenticator; import org.elasticsearch.xpack.security.authc.ldap.ActiveDirectorySessionFactory.UpnADAuthenticator; import org.elasticsearch.xpack.security.user.User; @@ -141,7 +140,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS)); final User user = result.getUser(); @@ -158,7 +157,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { // Thor does not have a UPN of form CN=Thor@ad.test.elasticsearch.com PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future); User user = future.actionGet().getUser(); assertThat(user, is(notNullValue())); assertThat(user.roles(), arrayContaining(containsString("Avengers"))); @@ -183,7 +182,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { int count = randomIntBetween(2, 10); for (int i = 0; i < count; i++) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future); future.actionGet(); } @@ -201,7 +200,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { int count = randomIntBetween(2, 10); for (int i = 0; i < count; i++) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future); future.actionGet(); } @@ -219,7 +218,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { int count = randomIntBetween(2, 10); for (int i = 0; i < count; i++) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future); future.actionGet(); } @@ -231,7 +230,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { for (int i = 0; i < count; i++) { PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future); future.actionGet(); } @@ -248,7 +247,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=ironman", new SecureString(PASSWORD)), future); User user = future.actionGet().getUser(); assertThat(user, is(notNullValue())); assertThat(user.roles(), arrayContaining(equalTo("group_role"))); @@ -264,7 +263,7 @@ public class ActiveDirectoryRealmTests extends ESTestCase { LdapRealm realm = new LdapRealm(LdapRealm.AD_TYPE, config, sessionFactory, roleMapper, threadPool); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("CN=Thor", new SecureString(PASSWORD)), future); User user = future.actionGet().getUser(); assertThat(user, is(notNullValue())); assertThat(user.roles(), arrayContainingInAnyOrder(equalTo("group_role"), equalTo("user_role"))); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java index ddf3830590b..d3e69a03a78 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/ldap/LdapRealmTests.java @@ -5,10 +5,6 @@ */ package org.elasticsearch.xpack.security.authc.ldap; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - import com.unboundid.ldap.sdk.LDAPURL; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.PlainActionFuture; @@ -20,7 +16,6 @@ import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.ldap.support.LdapSearchScope; import org.elasticsearch.xpack.security.authc.ldap.support.LdapTestCase; @@ -34,6 +29,10 @@ import org.elasticsearch.xpack.ssl.VerificationMode; import org.junit.After; import org.junit.Before; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + import static org.elasticsearch.xpack.security.authc.ldap.support.SessionFactory.URLS_SETTING; import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.contains; @@ -46,7 +45,6 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -88,7 +86,7 @@ public class LdapRealmTests extends LdapTestCase { threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS)); User user = result.getUser(); @@ -113,7 +111,7 @@ public class LdapRealmTests extends LdapTestCase { new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS)); User user = result.getUser(); @@ -139,11 +137,11 @@ public class LdapRealmTests extends LdapTestCase { new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); assertThat(future.actionGet().getStatus(), is(AuthenticationResult.Status.SUCCESS)); future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); assertThat(future.actionGet().getStatus(), is(AuthenticationResult.Status.SUCCESS)); //verify one and only one session -> caching is working @@ -163,10 +161,10 @@ public class LdapRealmTests extends LdapTestCase { ldapFactory = spy(ldapFactory); LdapRealm ldap = new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, roleMapper, threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); future.actionGet(); future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); future.actionGet(); //verify one and only one session -> caching is working @@ -175,7 +173,7 @@ public class LdapRealmTests extends LdapTestCase { roleMapper.notifyRefresh(); future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); future.actionGet(); //we need to session again @@ -196,10 +194,10 @@ public class LdapRealmTests extends LdapTestCase { LdapRealm ldap = new LdapRealm(LdapRealm.LDAP_TYPE, config, ldapFactory, buildGroupAsRoleMapper(resourceWatcherService), threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); future.actionGet(); future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); future.actionGet(); //verify two and only two binds -> caching is disabled @@ -290,7 +288,7 @@ public class LdapRealmTests extends LdapTestCase { new DnRoleMapper(LdapRealm.LDAP_TYPE, config, resourceWatcherService), threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken("Horatio Hornblower", new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken("Horatio Hornblower", new SecureString(PASSWORD)), future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS)); User user = result.getUser(); @@ -316,7 +314,7 @@ public class LdapRealmTests extends LdapTestCase { threadPool); PlainActionFuture future = new PlainActionFuture<>(); - ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future, mock(IncomingRequest.class)); + ldap.authenticate(new UsernamePasswordToken(VALID_USERNAME, new SecureString(PASSWORD)), future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.CONTINUE)); assertThat(result.getUser(), nullValue()); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java index fae43db964e..a68f0806bc0 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/pki/PkiRealmTests.java @@ -25,7 +25,6 @@ import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.env.Environment; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.support.UserRoleMapper; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; @@ -106,7 +105,7 @@ public class PkiRealmTests extends ESTestCase { }).when(roleMapper).resolveRoles(any(UserRoleMapper.UserData.class), any(ActionListener.class)); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(token, future, mock(IncomingRequest.class)); + realm.authenticate(token, future); final AuthenticationResult result = future.actionGet(); assertThat(result.getStatus(), is(AuthenticationResult.Status.SUCCESS)); User user = result.getUser(); @@ -132,7 +131,7 @@ public class PkiRealmTests extends ESTestCase { X509AuthenticationToken token = realm.token(threadContext); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(token, future, mock(IncomingRequest.class)); + realm.authenticate(token, future); User user = future.actionGet().getUser(); assertThat(user, is(notNullValue())); assertThat(user.principal(), is("elasticsearch")); @@ -163,7 +162,7 @@ public class PkiRealmTests extends ESTestCase { X509AuthenticationToken token = realm.token(threadContext); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(token, future, mock(IncomingRequest.class)); + realm.authenticate(token, future); User user = future.actionGet().getUser(); assertThat(user, is(notNullValue())); assertThat(user.principal(), is("Elasticsearch Test Node")); @@ -194,7 +193,7 @@ public class PkiRealmTests extends ESTestCase { X509AuthenticationToken token = realm.token(threadContext); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(token, future, mock(IncomingRequest.class)); + realm.authenticate(token, future); User user = future.actionGet().getUser(); assertThat(user, is(nullValue())); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java index 917322f9a48..27b57acd3a5 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/support/CachingUsernamePasswordRealmTests.java @@ -14,7 +14,6 @@ import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.SecuritySettingsSource; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.user.User; @@ -59,8 +58,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { RealmConfig config = new RealmConfig("test_realm", settings, globalSettings, new ThreadContext(Settings.EMPTY)); CachingUsernamePasswordRealm realm = new CachingUsernamePasswordRealm("test", config) { @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { listener.onResponse(AuthenticationResult.success(new User("username", new String[]{"r1", "r2", "r3"}))); } @@ -77,25 +75,25 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { AlwaysAuthenticateCachingRealm realm = new AlwaysAuthenticateCachingRealm(globalSettings); SecureString pass = new SecureString("pass"); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("a", pass), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("a", pass), future); future.actionGet(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("b", pass), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("b", pass), future); future.actionGet(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("c", pass), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("c", pass), future); future.actionGet(); assertThat(realm.authInvocationCounter.intValue(), is(3)); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("a", pass), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("a", pass), future); future.actionGet(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("b", pass), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("b", pass), future); future.actionGet(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("c", pass), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("c", pass), future); future.actionGet(); assertThat(realm.authInvocationCounter.intValue(), is(3)); @@ -141,7 +139,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { // now authenticate PlainActionFuture authFuture = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("a", new SecureString("pass")), authFuture, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("a", new SecureString("pass")), authFuture); AuthenticationResult authResult = authFuture.actionGet(); assertThat(authResult.getStatus(), is(AuthenticationResult.Status.SUCCESS)); User user = authResult.getUser(); @@ -152,7 +150,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { // authenticate a different user first authFuture = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("b", new SecureString("pass")), authFuture, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("b", new SecureString("pass")), authFuture); authResult = authFuture.actionGet(); assertThat(authResult.getStatus(), is(AuthenticationResult.Status.SUCCESS)); user = authResult.getUser(); @@ -176,19 +174,19 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { SecureString pass2 = new SecureString("password"); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, pass1), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, pass1), future); future.actionGet(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, pass1), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, pass1), future); future.actionGet(); assertThat(realm.authInvocationCounter.intValue(), is(1)); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, pass2), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, pass2), future); future.actionGet(); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, pass2), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, pass2), future); future.actionGet(); assertThat(realm.authInvocationCounter.intValue(), is(2)); @@ -202,21 +200,21 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { SecureString password = new SecureString("password"); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, password), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, password), future); assertThat(future.actionGet().getUser().enabled(), equalTo(false)); assertThat(realm.authInvocationCounter.intValue(), is(1)); realm.setUsersEnabled(true); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, password), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, password), future); future.actionGet(); assertThat(future.actionGet().getUser().enabled(), equalTo(true)); assertThat(realm.authInvocationCounter.intValue(), is(2)); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken(user, password), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken(user, password), future); future.actionGet(); assertThat(future.actionGet().getUser().enabled(), equalTo(true)); @@ -235,7 +233,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { // authenticate PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(authToken, future, mock(IncomingRequest.class)); + realm.authenticate(authToken, future); final User user1 = future.actionGet().getUser(); assertThat(user1.roles(), arrayContaining("testRole1", "testRole2")); assertThat(realm.authInvocationCounter.intValue(), is(1)); @@ -244,7 +242,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { // authenticate future = new PlainActionFuture<>(); - realm.authenticate(authToken, future, mock(IncomingRequest.class)); + realm.authenticate(authToken, future); final User user2 = future.actionGet().getUser(); assertThat(user2.roles(), arrayContaining("testRole1", "testRole2")); assertThat(user2, not(sameInstance(user1))); @@ -263,7 +261,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { PlainActionFuture future = new PlainActionFuture<>(); // authenticate - realm.authenticate(authToken, future, mock(IncomingRequest.class)); + realm.authenticate(authToken, future); final long start = System.currentTimeMillis(); final User user1 = future.actionGet().getUser(); assertThat(realm.authInvocationCounter.intValue(), is(1)); @@ -271,19 +269,19 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { // After 100 ms (from the original start time), authenticate (read from cache). We don't care about the result sleepUntil(start + 100); future = new PlainActionFuture<>(); - realm.authenticate(authToken, future, mock(IncomingRequest.class)); + realm.authenticate(authToken, future); future.actionGet(); // After 200 ms (from the original start time), authenticate (read from cache). We don't care about the result sleepUntil(start + 200); future = new PlainActionFuture<>(); - realm.authenticate(authToken, future, mock(IncomingRequest.class)); + realm.authenticate(authToken, future); future.actionGet(); // After 300 ms (from the original start time), authenticate again. The cache entry should have expired (despite the previous reads) sleepUntil(start + 300); future = new PlainActionFuture<>(); - realm.authenticate(authToken, future, mock(IncomingRequest.class)); + realm.authenticate(authToken, future); final User user2 = future.actionGet().getUser(); assertThat(user2, not(sameInstance(user1))); // Due to slow VMs etc, the cache might have expired more than once during the test, but we can accept that. @@ -301,13 +299,13 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { public void testAuthenticateContract() throws Exception { Realm realm = new FailingAuthenticationRealm(Settings.EMPTY, globalSettings); PlainActionFuture future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future); User user = future.actionGet().getUser(); assertThat(user, nullValue()); realm = new ThrowingAuthenticationRealm(Settings.EMPTY, globalSettings); future = new PlainActionFuture<>(); - realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future, mock(IncomingRequest.class)); + realm.authenticate(new UsernamePasswordToken("user", new SecureString("pass")), future); RuntimeException e = expectThrows(RuntimeException.class, future::actionGet); assertThat(e.getMessage(), containsString("whatever exception")); } @@ -335,8 +333,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { RealmConfig config = new RealmConfig("test_realm", Settings.EMPTY, globalSettings, new ThreadContext(Settings.EMPTY)); final CachingUsernamePasswordRealm realm = new CachingUsernamePasswordRealm("test", config) { @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { // do something slow if (BCrypt.checkpw(token.credentials(), passwordHash)) { listener.onResponse(AuthenticationResult.success(new User(username, new String[]{"r1", "r2", "r3"}))); @@ -375,7 +372,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { }, (e) -> { logger.error("caught exception", e); fail("unexpected exception - " + e); - }), mock(IncomingRequest.class)); + })); } } catch (InterruptedException e) { @@ -399,8 +396,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { RealmConfig config = new RealmConfig("test_realm", Settings.EMPTY, globalSettings, new ThreadContext(Settings.EMPTY)); final CachingUsernamePasswordRealm realm = new CachingUsernamePasswordRealm("test", config) { @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { listener.onFailure(new UnsupportedOperationException("authenticate should not be called!")); } @@ -454,8 +450,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { listener.onResponse(AuthenticationResult.notHandled()); } @@ -472,8 +467,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { listener.onFailure(new RuntimeException("whatever exception")); } @@ -503,8 +497,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { authInvocationCounter.incrementAndGet(); final User user = new User(token.principal(), new String[]{"testRole1", "testRole2"}, null, null, emptyMap(), usersEnabled); listener.onResponse(AuthenticationResult.success(user)); @@ -527,8 +520,7 @@ public class CachingUsernamePasswordRealmTests extends ESTestCase { } @Override - protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener, - IncomingRequest incomingRequest) { + protected void doAuthenticate(UsernamePasswordToken token, ActionListener listener) { authInvocationCounter.incrementAndGet(); listener.onResponse(AuthenticationResult.success(new User(token.principal(), new String[]{"testRole1", "testRole2"}))); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java index 98e38474b43..98b62892ef0 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authz/AuthorizationServiceTests.java @@ -349,25 +349,8 @@ public class AuthorizationServiceTests extends ESTestCase { verifyNoMoreInteractions(auditTrail); } - @AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1217") - public void testElasticUserOnlyAuthorizedForChangePasswordRequestsInSetupMode() { - final User user = new ElasticUser(true, true); - final ChangePasswordRequest changePasswordrequest = new ChangePasswordRequestBuilder(mock(Client.class)) - .username(user.principal()).request(); - - authorize(createAuthentication(user), ChangePasswordAction.NAME, changePasswordrequest); - - verify(auditTrail).accessGranted(user, ChangePasswordAction.NAME, changePasswordrequest); - - Tuple request = randomCompositeRequest(); - assertThrowsAuthorizationException(() -> authorize(createAuthentication(user), request.v1(), request.v2()), - request.v1(), "elastic"); - - verify(auditTrail).accessDenied(user, request.v1(), request.v2()); - } - public void testElasticUserAuthorizedForNonChangePasswordRequestsWhenNotInSetupMode() { - final User user = new ElasticUser(true, false); + final User user = new ElasticUser(true); Tuple request = randomCompositeRequest(); authorize(createAuthentication(user), request.v1(), request.v2()); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java b/plugin/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java index 65bd68e7a42..e6477cc9ce1 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/test/rest/XPackRestTestCase.java @@ -38,9 +38,7 @@ import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordTok public abstract class XPackRestTestCase extends ESClientYamlSuiteTestCase { private static final String BASIC_AUTH_VALUE = - basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); - - private final SetOnce oneAllowed401 = new SetOnce<>(); + basicAuthHeaderValue("x_pack_rest_user", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING); public XPackRestTestCase(@Name("yaml") ClientYamlTestCandidate testCandidate) { super(testCandidate); @@ -58,26 +56,6 @@ public abstract class XPackRestTestCase extends ESClientYamlSuiteTestCase { .build(); } - - @Before - public void setPasswords() throws IOException { - BasicHeader authHeader = new BasicHeader("Authorization", - basicAuthHeaderValue("elastic", new SecureString("".toCharArray()))); - String elasticUserPayload = "{\"password\" : \"" + SecuritySettingsSource.TEST_PASSWORD + "\"}"; - try { - client().performRequest("put", "_xpack/security/user/elastic/_password", Collections.emptyMap(), - new StringEntity(elasticUserPayload, ContentType.APPLICATION_JSON), authHeader); - } catch (ResponseException e) { - // The password might have already been set by the build.gradle file. So we ignore unsuccessful attempts - // due to failed authentication - if (e.getResponse().getStatusLine().getStatusCode() != 401) { - throw e; - } else { - oneAllowed401.set(e.getResponse().getStatusLine().getStatusCode()); - } - } - } - /** * Waits for the Machine Learning templates to be created by {@link MachineLearningTemplateRegistry}. */ diff --git a/qa/full-cluster-restart/build.gradle b/qa/full-cluster-restart/build.gradle index ff435e56fca..fec9b286fd2 100644 --- a/qa/full-cluster-restart/build.gradle +++ b/qa/full-cluster-restart/build.gradle @@ -28,7 +28,7 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant -> try { httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health?wait_for_nodes=${node.config.numNodes}&wait_for_status=yellow").openConnection(); httpURLConnection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8))); + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8))); httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(1000); httpURLConnection.setReadTimeout(30000); // read needs to wait for nodes! @@ -116,12 +116,11 @@ subprojects { numBwcNodes = 2 numNodes = 2 clusterName = 'full-cluster-restart' + setupCommand 'setupTestUser', 'bin/x-pack/users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser' waitCondition = waitWithAuth setting 'xpack.security.transport.ssl.enabled', 'true' setting 'xpack.ssl.keystore.path', 'testnode.jks' setting 'xpack.ssl.keystore.password', 'testnode' - setting 'xpack.security.authc.realms.native.type', 'native' - setting 'xpack.security.authc.realms.native.order', '0' dependsOn copyTestNodeKeystore extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks') if (withSystemKey) { @@ -152,11 +151,10 @@ subprojects { numNodes = 2 clusterName = 'full-cluster-restart' dataDir = { nodeNum -> oldClusterTest.nodes[nodeNum].dataDir } + setupCommand 'setupTestUser', 'bin/x-pack/users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser' waitCondition = waitWithAuth setting 'xpack.ssl.keystore.path', 'testnode.jks' keystoreSetting 'xpack.ssl.keystore.secure_password', 'testnode' - setting 'xpack.security.authc.realms.native.type', 'native' - setting 'xpack.security.authc.realms.native.order', '0' dependsOn copyTestNodeKeystore extraConfigFile 'testnode.jks', new File(outputDir + '/testnode.jks') if (withSystemKey) { diff --git a/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java b/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java index 4ab8fe23bae..5413c2dcd82 100644 --- a/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java +++ b/qa/full-cluster-restart/src/test/java/org/elasticsearch/xpack/restart/FullClusterRestartIT.java @@ -84,7 +84,7 @@ public class FullClusterRestartIT extends ESRestTestCase { @Override protected Settings restClientSettings() { - String token = "Basic " + Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8)); + String token = "Basic " + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8)); return Settings.builder() .put(ThreadContext.PREFIX + ".Authorization", token) // we increase the timeout here to 90 seconds to handle long waits for a green diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index 55ed25ebdbc..2364d704e76 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -31,7 +31,7 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant -> // TODO this sucks having to hardcode number of nodes, but node.config.numNodes isn't necessarily accurate for rolling httpURLConnection = (HttpURLConnection) new URL("http://${node.httpUri()}/_cluster/health?wait_for_nodes=2&wait_for_status=yellow").openConnection(); httpURLConnection.setRequestProperty("Authorization", "Basic " + - Base64.getEncoder().encodeToString("elastic:changeme".getBytes(StandardCharsets.UTF_8))); + Base64.getEncoder().encodeToString("test_user:x-pack-test-password".getBytes(StandardCharsets.UTF_8))); httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(1000); httpURLConnection.setReadTimeout(30000); // read needs to wait for nodes! @@ -114,6 +114,7 @@ subprojects { configure(extensions.findByName("${baseName}#oldClusterTestCluster")) { dependsOn copyTestNodeKeystore plugin ':x-pack-elasticsearch:plugin' + setupCommand 'setupTestUser', 'bin/x-pack/users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser' distribution = 'zip' bwcVersion = version numBwcNodes = 2 @@ -146,6 +147,7 @@ subprojects { configure(extensions.findByName("${baseName}#mixedClusterTestCluster")) { dependsOn oldClusterTestRunner, "${baseName}#oldClusterTestCluster#node1.stop" plugin ':x-pack-elasticsearch:plugin' + setupCommand 'setupTestUser', 'bin/x-pack/users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser' distribution = 'zip' clusterName = 'rolling-upgrade' unicastTransportUri = { seedNode, node, ant -> oldClusterTest.nodes.get(0).transportUri() } @@ -175,6 +177,7 @@ subprojects { configure(extensions.findByName("${baseName}#upgradedClusterTestCluster")) { dependsOn(mixedClusterTestRunner, "${baseName}#oldClusterTestCluster#node0.stop") plugin ':x-pack-elasticsearch:plugin' + setupCommand 'setupTestUser', 'bin/x-pack/users', 'useradd', 'test_user', '-p', 'x-pack-test-password', '-r', 'superuser' distribution = 'zip' clusterName = 'rolling-upgrade' unicastTransportUri = { seedNode, node, ant -> mixedClusterTest.nodes.get(0).transportUri() } @@ -228,7 +231,6 @@ subprojects { dependsOn = ["v${wireCompatVersions[-1]}#bwcTest"] } } - check.dependsOn(integTest) dependencies { diff --git a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/UpgradeClusterClientYamlTestSuiteIT.java b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/UpgradeClusterClientYamlTestSuiteIT.java index d630e6efe5a..b0ae538c073 100644 --- a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/UpgradeClusterClientYamlTestSuiteIT.java +++ b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/UpgradeClusterClientYamlTestSuiteIT.java @@ -56,7 +56,7 @@ public class UpgradeClusterClientYamlTestSuiteIT extends SecurityClusterClientYa @Override protected Settings restClientSettings() { - String token = "Basic " + Base64.getEncoder().encodeToString(("elastic:changeme").getBytes(StandardCharsets.UTF_8)); + String token = "Basic " + Base64.getEncoder().encodeToString(("test_user:x-pack-test-password").getBytes(StandardCharsets.UTF_8)); return Settings.builder() .put(ThreadContext.PREFIX + ".Authorization", token) // we increase the timeout here to 90 seconds to handle long waits for a green diff --git a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java index da31a73f3c4..3c7e2b607aa 100644 --- a/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java +++ b/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/WatchBackwardsCompatibilityIT.java @@ -112,7 +112,7 @@ public class WatchBackwardsCompatibilityIT extends ESRestTestCase { @Override protected Settings restClientSettings() { String token = "Basic " + Base64.getEncoder() - .encodeToString(("elastic:changeme").getBytes(StandardCharsets.UTF_8)); + .encodeToString(("test_user:x-pack-test-password").getBytes(StandardCharsets.UTF_8)); return Settings.builder() .put(ThreadContext.PREFIX + ".Authorization", token) .build(); diff --git a/qa/security-example-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java b/qa/security-example-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java index ec9a6e26420..d110a6ca071 100644 --- a/qa/security-example-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java +++ b/qa/security-example-extension/src/main/java/org/elasticsearch/example/realm/CustomRealm.java @@ -9,13 +9,12 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; -import org.elasticsearch.xpack.security.authc.support.CharArrays; -import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.authc.AuthenticationToken; import org.elasticsearch.xpack.security.authc.Realm; import org.elasticsearch.xpack.security.authc.RealmConfig; +import org.elasticsearch.xpack.security.authc.support.CharArrays; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; +import org.elasticsearch.xpack.security.user.User; public class CustomRealm extends Realm { @@ -50,8 +49,7 @@ public class CustomRealm extends Realm { } @Override - public void authenticate(AuthenticationToken authToken, ActionListener listener, - IncomingRequest incomingRequest) { + public void authenticate(AuthenticationToken authToken, ActionListener listener) { UsernamePasswordToken token = (UsernamePasswordToken)authToken; final String actualUser = token.principal(); if (KNOWN_USER.equals(actualUser)) { diff --git a/qa/security-example-extension/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java b/qa/security-example-extension/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java index 6c3811372c9..88470b12fbe 100644 --- a/qa/security-example-extension/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java +++ b/qa/security-example-extension/src/test/java/org/elasticsearch/example/realm/CustomRealmTests.java @@ -10,17 +10,14 @@ import org.elasticsearch.common.settings.SecureString; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.env.Environment; +import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.security.authc.AuthenticationResult; -import org.elasticsearch.xpack.security.authc.IncomingRequest; -import org.elasticsearch.xpack.security.user.User; import org.elasticsearch.xpack.security.authc.RealmConfig; import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken; -import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.security.user.User; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.mockito.Mockito.mock; public class CustomRealmTests extends ESTestCase { public void testAuthenticate() { @@ -29,7 +26,7 @@ public class CustomRealmTests extends ESTestCase { SecureString password = CustomRealm.KNOWN_PW.clone(); UsernamePasswordToken token = new UsernamePasswordToken(CustomRealm.KNOWN_USER, password); PlainActionFuture plainActionFuture = new PlainActionFuture<>(); - realm.authenticate(token, plainActionFuture, mock(IncomingRequest.class)); + realm.authenticate(token, plainActionFuture); User user = plainActionFuture.actionGet().getUser(); assertThat(user, notNullValue()); assertThat(user.roles(), equalTo(CustomRealm.ROLES)); @@ -42,7 +39,7 @@ public class CustomRealmTests extends ESTestCase { SecureString password = CustomRealm.KNOWN_PW.clone(); UsernamePasswordToken token = new UsernamePasswordToken(CustomRealm.KNOWN_USER + "1", password); PlainActionFuture plainActionFuture = new PlainActionFuture<>(); - realm.authenticate(token, plainActionFuture, mock(IncomingRequest.class)); + realm.authenticate(token, plainActionFuture); final AuthenticationResult result = plainActionFuture.actionGet(); assertThat(result.getStatus(), equalTo(AuthenticationResult.Status.CONTINUE)); } diff --git a/qa/tribe-tests-with-security/src/test/java/org/elasticsearch/test/TribeWithSecurityIT.java b/qa/tribe-tests-with-security/src/test/java/org/elasticsearch/test/TribeWithSecurityIT.java index a948831c1b7..5b7c7c9f40e 100644 --- a/qa/tribe-tests-with-security/src/test/java/org/elasticsearch/test/TribeWithSecurityIT.java +++ b/qa/tribe-tests-with-security/src/test/java/org/elasticsearch/test/TribeWithSecurityIT.java @@ -12,6 +12,7 @@ import org.apache.http.HttpHost; import org.apache.http.entity.ContentType; import org.apache.http.message.BasicHeader; import org.apache.http.nio.entity.NStringEntity; +import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; @@ -96,24 +97,6 @@ public class TribeWithSecurityIT extends SecurityIntegTestCase { public void addSecurityIndex() throws IOException { client().admin().indices().prepareCreate(INTERNAL_SECURITY_INDEX).get(); cluster2.client().admin().indices().prepareCreate(INTERNAL_SECURITY_INDEX).get(); - - InetSocketAddress[] inetSocketAddresses = cluster2.httpAddresses(); - List hosts = new ArrayList<>(); - for (InetSocketAddress socketAddress : inetSocketAddresses) { - hosts.add(new HttpHost(socketAddress.getAddress(), socketAddress.getPort())); - } - - RestClientBuilder builder = RestClient.builder(hosts.toArray(new HttpHost[hosts.size()])); - RestClient client = builder.build(); - SecureString defaultPassword = new SecureString("".toCharArray()); - - String payload = "{\"password\": \"" + SecuritySettingsSource.TEST_PASSWORD + "\"}"; - HttpEntity entity = new NStringEntity(payload, ContentType.APPLICATION_JSON); - BasicHeader authHeader = new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER, - UsernamePasswordToken.basicAuthHeaderValue(ElasticUser.NAME, defaultPassword)); - String route = "/_xpack/security/user/elastic/_password"; - Response response = getRestClient().performRequest("PUT", route, Collections.emptyMap(), entity, authHeader); - client.close(); } @Override @@ -135,6 +118,7 @@ public class TribeWithSecurityIT extends SecurityIntegTestCase { return new ExternalTestCluster(createTempDir(), externalClusterClientSettings(), transportClientPlugins(), transportAddresses); } + @LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1996") public void testThatTribeCanAuthenticateElasticUser() throws Exception { ClusterHealthResponse response = tribeNode.client().filterWithHeader(Collections.singletonMap("Authorization", UsernamePasswordToken.basicAuthHeaderValue("elastic", SecuritySettingsSource.TEST_PASSWORD_SECURE_STRING))) @@ -142,6 +126,7 @@ public class TribeWithSecurityIT extends SecurityIntegTestCase { assertNoTimeout(response); } + @LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1996") public void testThatTribeCanAuthenticateElasticUserWithChangedPassword() throws Exception { securityClient(client()).prepareChangePassword("elastic", "password".toCharArray()).get(); @@ -152,6 +137,7 @@ public class TribeWithSecurityIT extends SecurityIntegTestCase { assertNoTimeout(response); } + @LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/1996") public void testThatTribeClustersHaveDifferentPasswords() throws Exception { securityClient().prepareChangePassword("elastic", "password".toCharArray()).get(); securityClient(cluster2.client()).prepareChangePassword("elastic", "password2".toCharArray()).get();