From 1b2921d043afd96a1415f7fafaa11de86027057a Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Wed, 24 Mar 2021 15:59:35 -0500 Subject: [PATCH] SONAR-14582 SSF-124 --- .../CredentialsLocalAuthentication.java | 128 +++++++++++---- .../CredentialsAuthenticationTest.java | 6 +- .../CredentialsLocalAuthenticationTest.java | 155 +++++++++++++++++- ...faultAdminCredentialsVerifierImplTest.java | 4 +- .../HttpHeadersAuthenticationTest.java | 4 +- .../authentication/UserRegistrarImplTest.java | 4 +- .../server/user/UserUpdaterCreateTest.java | 8 +- .../user/UserUpdaterReactivateTest.java | 8 +- .../server/user/UserUpdaterUpdateTest.java | 4 +- .../user/ws/ChangePasswordActionTest.java | 4 +- .../server/user/ws/CreateActionTest.java | 4 +- .../server/user/ws/UpdateActionTest.java | 4 +- .../ws/UpdateIdentityProviderActionTest.java | 4 +- 13 files changed, 280 insertions(+), 57 deletions(-) diff --git a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java index e11c11073cb..e54b106c156 100644 --- a/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java +++ b/server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java @@ -19,10 +19,17 @@ */ package org.sonar.server.authentication; +import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.util.Base64; +import java.util.EnumMap; import javax.annotation.Nullable; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; import org.apache.commons.codec.digest.DigestUtils; import org.mindrot.jbcrypt.BCrypt; +import org.sonar.api.config.Configuration; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.user.UserDto; @@ -39,14 +46,23 @@ import static java.util.Objects.requireNonNull; * database). */ public class CredentialsLocalAuthentication { + private static final SecureRandom SECURE_RANDOM = new SecureRandom(); + private static final HashMethod DEFAULT = HashMethod.PBKDF2; + private static final String PBKDF2_ITERATIONS_PROP = "sonar.internal.pbkdf2.iterations"; private final DbClient dbClient; - private static final SecureRandom SECURE_RANDOM = new SecureRandom(); - // The default hash method that must be used is BCRYPT - private static final HashMethod DEFAULT = HashMethod.BCRYPT; + private final EnumMap hashFunctions = new EnumMap<>(HashMethod.class); + + public enum HashMethod { + SHA1, BCRYPT, PBKDF2; + } - public CredentialsLocalAuthentication(DbClient dbClient) { + public CredentialsLocalAuthentication(DbClient dbClient, Configuration configuration) { this.dbClient = dbClient; + hashFunctions.put(HashMethod.BCRYPT, new BcryptFunction()); + hashFunctions.put(HashMethod.SHA1, new Sha1Function()); + hashFunctions.put(HashMethod.PBKDF2, new PBKDF2Function(configuration.getInt(PBKDF2_ITERATIONS_PROP).orElse(null))); + } /** @@ -75,7 +91,9 @@ public class CredentialsLocalAuthentication { .build(); } - AuthenticationResult result = hashMethod.checkCredentials(user, password); + HashFunction hashFunction = hashFunctions.get(hashMethod); + + AuthenticationResult result = hashFunction.checkCredentials(user, password); if (!result.isSuccessful()) { throw AuthenticationException.newBuilder() .setSource(Source.local(method)) @@ -85,8 +103,8 @@ public class CredentialsLocalAuthentication { } // Upgrade the password if it's an old hashMethod - if (hashMethod != DEFAULT) { - DEFAULT.storeHashPassword(user, password); + if (hashMethod != DEFAULT || result.needsUpdate) { + hashFunctions.get(DEFAULT).storeHashPassword(user, password); dbClient.userDao().update(session, user); } } @@ -96,37 +114,23 @@ public class CredentialsLocalAuthentication { * The crypted_password, salt and hash_method are set */ public void storeHashPassword(UserDto user, String password) { - DEFAULT.storeHashPassword(user, password); - } - - public enum HashMethod implements HashFunction { - SHA1(new Sha1Function()), BCRYPT(new BcryptFunction()); - - private HashFunction hashFunction; - - HashMethod(HashFunction hashFunction) { - this.hashFunction = hashFunction; - } - - @Override - public AuthenticationResult checkCredentials(UserDto user, String password) { - return hashFunction.checkCredentials(user, password); - } - - @Override - public void storeHashPassword(UserDto user, String password) { - hashFunction.storeHashPassword(user, password); - } + hashFunctions.get(DEFAULT).storeHashPassword(user, password); } private static class AuthenticationResult { private final boolean successful; private final String failureMessage; + private final boolean needsUpdate; private AuthenticationResult(boolean successful, String failureMessage) { + this(successful, failureMessage, false); + } + + private AuthenticationResult(boolean successful, String failureMessage, boolean needsUpdate) { checkArgument((successful && failureMessage.isEmpty()) || (!successful && !failureMessage.isEmpty()), "Incorrect parameters"); this.successful = successful; this.failureMessage = failureMessage; + this.needsUpdate = needsUpdate; } public boolean isSuccessful() { @@ -136,6 +140,10 @@ public class CredentialsLocalAuthentication { public String getFailureMessage() { return failureMessage; } + + public boolean isNeedsUpdate() { + return needsUpdate; + } } public interface HashFunction { @@ -179,8 +187,70 @@ public class CredentialsLocalAuthentication { } } + private static final class PBKDF2Function implements HashFunction { + private static final int DEFAULT_ITERATIONS = 100_000; + private static final String ALGORITHM = "PBKDF2WithHmacSHA512"; + private static final int KEY_LEN = 512; + private final int gen_iterations; + + public PBKDF2Function(@Nullable Integer gen_iterations) { + this.gen_iterations = gen_iterations != null ? gen_iterations : DEFAULT_ITERATIONS; + } + + @Override + public AuthenticationResult checkCredentials(UserDto user, String password) { + if (user.getCryptedPassword() == null) { + return new AuthenticationResult(false, "null password in DB"); + } + if (user.getSalt() == null) { + return new AuthenticationResult(false, "null salt"); + } + + int pos = user.getCryptedPassword().indexOf('$'); + if (pos < 1) { + return new AuthenticationResult(false, "invalid hash stored"); + } + int iterations; + try { + iterations = Integer.parseInt(user.getCryptedPassword().substring(0, pos)); + } catch (NumberFormatException e) { + return new AuthenticationResult(false, "invalid hash stored"); + } + String hash = user.getCryptedPassword().substring(pos + 1); + byte[] salt = Base64.getDecoder().decode(user.getSalt()); + + if (!hash.equals(hash(salt, password, iterations))) { + return new AuthenticationResult(false, "wrong password"); + } + boolean needsUpdate = iterations != gen_iterations; + return new AuthenticationResult(true, "", needsUpdate); + } + + @Override + public void storeHashPassword(UserDto user, String password) { + byte[] salt = new byte[20]; + SECURE_RANDOM.nextBytes(salt); + String hashStr = hash(salt, password, gen_iterations); + String saltStr = Base64.getEncoder().encodeToString(salt); + user.setHashMethod(HashMethod.PBKDF2.name()) + .setCryptedPassword(gen_iterations + "$" + hashStr) + .setSalt(saltStr); + } + + private String hash(byte[] salt, String password, int iterations) { + try { + SecretKeyFactory skf = SecretKeyFactory.getInstance(ALGORITHM); + PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, KEY_LEN); + byte[] hash = skf.generateSecret(spec).getEncoded(); + return Base64.getEncoder().encodeToString(hash); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + throw new RuntimeException(e); + } + } + } + /** - * Implementation of bcrypt hash function + * Implementation of deprecated bcrypt hash function */ private static final class BcryptFunction implements HashFunction { @Override diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java index 114085f28ec..7ad9affa9f0 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java @@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletRequest; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.config.internal.MapSettings; import org.sonar.api.utils.System2; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -38,9 +39,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.sonar.db.user.UserTesting.newUserDto; -import static org.sonar.server.authentication.event.AuthenticationEvent.Source; import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC; import static org.sonar.server.authentication.event.AuthenticationEvent.Method.BASIC_TOKEN; +import static org.sonar.server.authentication.event.AuthenticationEvent.Source; import static org.sonar.server.authentication.event.AuthenticationExceptionMatcher.authenticationException; public class CredentialsAuthenticationTest { @@ -58,8 +59,9 @@ public class CredentialsAuthenticationTest { private DbSession dbSession = dbTester.getSession(); private HttpServletRequest request = mock(HttpServletRequest.class); private AuthenticationEvent authenticationEvent = mock(AuthenticationEvent.class); + private MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); private CredentialsExternalAuthentication externalAuthentication = mock(CredentialsExternalAuthentication.class); - private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient); + private CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient, settings.asConfig()); private CredentialsAuthentication underTest = new CredentialsAuthentication(dbClient, authenticationEvent, externalAuthentication, localAuthentication); @Test diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java index d6865fb122c..e7cafffc61a 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java @@ -22,10 +22,12 @@ package org.sonar.server.authentication; import java.util.Optional; import java.util.Random; import org.apache.commons.codec.digest.DigestUtils; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mindrot.jbcrypt.BCrypt; +import org.sonar.api.config.internal.MapSettings; import org.sonar.db.DbTester; import org.sonar.db.user.UserDto; import org.sonar.server.authentication.event.AuthenticationEvent; @@ -35,6 +37,7 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.user.UserTesting.newUserDto; import static org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod.BCRYPT; +import static org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod.PBKDF2; import static org.sonar.server.authentication.CredentialsLocalAuthentication.HashMethod.SHA1; public class CredentialsLocalAuthenticationTest { @@ -44,8 +47,14 @@ public class CredentialsLocalAuthenticationTest { public DbTester db = DbTester.create(); private static final Random RANDOM = new Random(); + private static final MapSettings settings = new MapSettings(); - private CredentialsLocalAuthentication underTest = new CredentialsLocalAuthentication(db.getDbClient()); + private CredentialsLocalAuthentication underTest = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); + + @Before + public void setup() { + settings.setProperty("sonar.internal.pbkdf2.iterations", 1); + } @Test public void incorrect_hash_should_throw_AuthenticationException() { @@ -179,10 +188,150 @@ public class CredentialsLocalAuthenticationTest { Optional myself = db.users().selectUserByLogin("myself"); assertThat(myself).isPresent(); - assertThat(myself.get().getHashMethod()).isEqualTo(BCRYPT.name()); - assertThat(myself.get().getSalt()).isNull(); + assertThat(myself.get().getHashMethod()).isEqualTo(PBKDF2.name()); + assertThat(myself.get().getSalt()).isNotNull(); // authentication must work with upgraded hash method underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); } + + @Test + public void authentication_upgrade_hash_function_when_BCRYPT_was_used() { + String password = randomAlphanumeric(60); + + byte[] saltRandom = new byte[20]; + RANDOM.nextBytes(saltRandom); + String salt = DigestUtils.sha1Hex(saltRandom); + + UserDto user = newUserDto() + .setLogin("myself") + .setHashMethod(BCRYPT.name()) + .setCryptedPassword(BCrypt.hashpw(password, BCrypt.gensalt(12))) + .setSalt(salt); + db.users().insertUser(user); + + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + + Optional myself = db.users().selectUserByLogin("myself"); + assertThat(myself).isPresent(); + assertThat(myself.get().getHashMethod()).isEqualTo(PBKDF2.name()); + assertThat(myself.get().getSalt()).isNotNull(); + + // authentication must work with upgraded hash method + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_updates_db_if_PBKDF2_iterations_changes() { + String password = randomAlphanumeric(60); + + UserDto user = newUserDto().setLogin("myself"); + db.users().insertUser(user); + underTest.storeHashPassword(user, password); + + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + assertThat(user.getCryptedPassword()).startsWith("1$"); + + settings.setProperty("sonar.internal.pbkdf2.iterations", 3); + CredentialsLocalAuthentication underTest = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); + + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + assertThat(user.getCryptedPassword()).startsWith("3$"); + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_with_pbkdf2_with_correct_password_should_work() { + String password = randomAlphanumeric(60); + UserDto user = newUserDto() + .setHashMethod(PBKDF2.name()); + + underTest.storeHashPassword(user, password); + assertThat(user.getCryptedPassword()).hasSize(88 + 2); + assertThat(user.getCryptedPassword()).startsWith("1$"); + assertThat(user.getSalt()).hasSize(28); + + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_with_pbkdf2_with_default_number_of_iterations() { + settings.clear(); + CredentialsLocalAuthentication underTest = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); + + String password = randomAlphanumeric(60); + UserDto user = newUserDto() + .setHashMethod(PBKDF2.name()); + + underTest.storeHashPassword(user, password); + assertThat(user.getCryptedPassword()).hasSize(88 + 7); + assertThat(user.getCryptedPassword()).startsWith("100000$"); + assertThat(user.getSalt()).hasSize(28); + + underTest.authenticate(db.getSession(), user, password, AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_with_pbkdf2_with_incorrect_password_should_throw_AuthenticationException() { + UserDto user = newUserDto() + .setHashMethod(PBKDF2.name()) + .setCryptedPassword("1$hash") + .setSalt("salt"); + + expectedException.expect(AuthenticationException.class); + expectedException.expectMessage("wrong password"); + + underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_with_pbkdf2_with_invalid_password_should_throw_AuthenticationException() { + String password = randomAlphanumeric(60); + + byte[] saltRandom = new byte[20]; + RANDOM.nextBytes(saltRandom); + String salt = DigestUtils.sha1Hex(saltRandom); + + UserDto user = newUserDto() + .setHashMethod(PBKDF2.name()) + .setCryptedPassword(DigestUtils.sha1Hex("--" + salt + "--" + password + "--")) + .setSalt(salt); + + expectedException.expect(AuthenticationException.class); + expectedException.expectMessage("invalid hash stored"); + + underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_with_pbkdf2_with_empty_password_should_throw_AuthenticationException() { + byte[] saltRandom = new byte[20]; + RANDOM.nextBytes(saltRandom); + String salt = DigestUtils.sha1Hex(saltRandom); + + UserDto user = newUserDto() + .setCryptedPassword(null) + .setHashMethod(PBKDF2.name()) + .setSalt(salt); + + expectedException.expect(AuthenticationException.class); + expectedException.expectMessage("null password in DB"); + + underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); + } + + @Test + public void authentication_with_pbkdf2_with_empty_salt_should_throw_AuthenticationException() { + String password = randomAlphanumeric(60); + + UserDto user = newUserDto() + .setHashMethod(PBKDF2.name()) + .setCryptedPassword(DigestUtils.sha1Hex("--0242b0b4c0a93ddfe09dd886de50bc25ba000b51--" + password + "--")) + .setSalt(null); + + expectedException.expect(AuthenticationException.class); + expectedException.expectMessage("null salt"); + + underTest.authenticate(db.getSession(), user, "WHATEVER", AuthenticationEvent.Method.BASIC); + } } diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/DefaultAdminCredentialsVerifierImplTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/DefaultAdminCredentialsVerifierImplTest.java index df125fdeeb3..7b41c242468 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/DefaultAdminCredentialsVerifierImplTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/DefaultAdminCredentialsVerifierImplTest.java @@ -22,6 +22,7 @@ package org.sonar.server.authentication; import org.junit.After; import org.junit.Rule; import org.junit.Test; +import org.sonar.api.config.internal.MapSettings; import org.sonar.api.notifications.Notification; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; @@ -45,7 +46,8 @@ public class DefaultAdminCredentialsVerifierImplTest { @Rule public LogTester logTester = new LogTester(); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final NotificationManager notificationManager = mock(NotificationManager.class); private final DefaultAdminCredentialsVerifierImpl underTest = new DefaultAdminCredentialsVerifierImpl(db.getDbClient(), localAuthentication, notificationManager); diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java index 6674e614b80..089038661c7 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java @@ -61,7 +61,7 @@ import static org.sonar.server.authentication.event.AuthenticationExceptionMatch public class HttpHeadersAuthenticationTest { - private final MapSettings settings = new MapSettings(); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); @Rule public ExpectedException expectedException = none(); @@ -92,7 +92,7 @@ public class HttpHeadersAuthenticationTest { private GroupDto sonarUsers; private final System2 system2 = mock(System2.class); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client()); diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java index 86c79481eb5..280f8cb5c6c 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java @@ -67,7 +67,7 @@ public class UserRegistrarImplTest { .setEnabled(true) .setAllowsUsersToSignUp(true); - private final MapSettings settings = new MapSettings(); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); @Rule public ExpectedException expectedException = ExpectedException.none(); @@ -76,7 +76,7 @@ public class UserRegistrarImplTest { @Rule public EsTester es = EsTester.create(); private final UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client()); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final DefaultGroupFinder groupFinder = new DefaultGroupFinder(db.getDbClient()); private final UserUpdater userUpdater = new UserUpdater( mock(NewUserNotifier.class), diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java index 8783752bf77..6bb357642d4 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java @@ -74,8 +74,8 @@ public class UserUpdaterCreateTest { private final ArgumentCaptor newUserHandler = ArgumentCaptor.forClass(NewUserHandler.Context.class); private final DbSession session = db.getSession(); private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); - private final MapSettings settings = new MapSettings(); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final UserUpdater underTest = new UserUpdater(newUserNotifier, dbClient, userIndexer, new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication); @@ -100,8 +100,8 @@ public class UserUpdaterCreateTest { assertThat(dto.isActive()).isTrue(); assertThat(dto.isLocal()).isTrue(); - assertThat(dto.getSalt()).isNull(); - assertThat(dto.getHashMethod()).isEqualTo(HashMethod.BCRYPT.name()); + assertThat(dto.getSalt()).isNotNull(); + assertThat(dto.getHashMethod()).isEqualTo(HashMethod.PBKDF2.name()); assertThat(dto.getCryptedPassword()).isNotNull(); assertThat(dto.getCreatedAt()) .isPositive() diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java index cf5a5facab0..25c55506b0d 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java @@ -59,8 +59,8 @@ public class UserUpdaterReactivateTest { private final NewUserNotifier newUserNotifier = mock(NewUserNotifier.class); private final DbSession session = db.getSession(); private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); - private final MapSettings settings = new MapSettings(); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final UserUpdater underTest = new UserUpdater(newUserNotifier, dbClient, userIndexer, new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication); @@ -86,8 +86,8 @@ public class UserUpdaterReactivateTest { assertThat(reloaded.getEmail()).isEqualTo("marius2@mail.com"); assertThat(reloaded.getScmAccounts()).isNull(); assertThat(reloaded.isLocal()).isTrue(); - assertThat(reloaded.getSalt()).isNull(); - assertThat(reloaded.getHashMethod()).isEqualTo(HashMethod.BCRYPT.name()); + assertThat(reloaded.getSalt()).isNotNull(); + assertThat(reloaded.getHashMethod()).isEqualTo(HashMethod.PBKDF2.name()); assertThat(reloaded.getCryptedPassword()).isNotNull().isNotEqualTo("650d2261c98361e2f67f90ce5c65a95e7d8ea2fg"); assertThat(reloaded.getCreatedAt()).isEqualTo(user.getCreatedAt()); assertThat(reloaded.getUpdatedAt()).isGreaterThan(user.getCreatedAt()); diff --git a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java index 9d7287ece0b..1f4ca04f52c 100644 --- a/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java +++ b/server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java @@ -72,8 +72,8 @@ public class UserUpdaterUpdateTest { private final NewUserNotifier newUserNotifier = mock(NewUserNotifier.class); private final DbSession session = db.getSession(); private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); - private final MapSettings settings = new MapSettings(); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final UserUpdater underTest = new UserUpdater(newUserNotifier, dbClient, userIndexer, new DefaultGroupFinder(dbClient), settings.asConfig(), localAuthentication); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java index 56619a51aac..9648c2db8ed 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java @@ -54,8 +54,8 @@ public class ChangePasswordActionTest { public EsTester es = EsTester.createCustom(UserIndexDefinition.createForTest()); @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone().logIn(); - - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final UserUpdater userUpdater = new UserUpdater(mock(NewUserNotifier.class), db.getDbClient(), new UserIndexer(db.getDbClient(), es.client()), new DefaultGroupFinder(db.getDbClient()), diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/CreateActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/CreateActionTest.java index 30fd3561fbd..d17a60f9b54 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/CreateActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/CreateActionTest.java @@ -63,7 +63,7 @@ import static org.sonar.server.user.index.UserIndexDefinition.FIELD_SCM_ACCOUNTS public class CreateActionTest { - private final MapSettings settings = new MapSettings(); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); private final System2 system2 = new AlwaysIncreasingSystem2(); @Rule @@ -77,7 +77,7 @@ public class CreateActionTest { private final UserIndexer userIndexer = new UserIndexer(db.getDbClient(), es.client()); private GroupDto defaultGroup; - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final WsActionTester tester = new WsActionTester(new CreateAction(db.getDbClient(), new UserUpdater(mock(NewUserNotifier.class), db.getDbClient(), userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), localAuthentication), userSessionRule)); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java index e8f91d4b53d..c9eced59f38 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java @@ -50,7 +50,7 @@ import static org.sonar.db.user.UserTesting.newUserDto; public class UpdateActionTest { - private final MapSettings settings = new MapSettings(); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); private final System2 system2 = new System2(); @Rule @@ -65,7 +65,7 @@ public class UpdateActionTest { private final DbClient dbClient = db.getDbClient(); private final DbSession dbSession = db.getSession(); private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient()); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient(), settings.asConfig()); private final WsActionTester ws = new WsActionTester(new UpdateAction( new UserUpdater(mock(NewUserNotifier.class), dbClient, userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), localAuthentication), userSession, new UserJsonWriter(userSession), dbClient)); diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateIdentityProviderActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateIdentityProviderActionTest.java index d601be555e3..a7425109bc4 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateIdentityProviderActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateIdentityProviderActionTest.java @@ -62,11 +62,11 @@ public class UpdateIdentityProviderActionTest { @Rule public UserSessionRule userSession = UserSessionRule.standalone().logIn().setSystemAdministrator(); - private final MapSettings settings = new MapSettings(); + private final MapSettings settings = new MapSettings().setProperty("sonar.internal.pbkdf2.iterations", "1"); private final DbClient dbClient = db.getDbClient(); private final DbSession dbSession = db.getSession(); private final UserIndexer userIndexer = new UserIndexer(dbClient, es.client()); - private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient); + private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(dbClient, settings.asConfig()); private final WsActionTester underTest = new WsActionTester(new UpdateIdentityProviderAction(dbClient, identityProviderRepository, new UserUpdater(mock(NewUserNotifier.class), dbClient, userIndexer, new DefaultGroupFinder(db.getDbClient()), settings.asConfig(), localAuthentication), -- 2.39.5