]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14582 SSF-124
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Wed, 24 Mar 2021 20:59:35 +0000 (15:59 -0500)
committersonartech <sonartech@sonarsource.com>
Mon, 29 Mar 2021 20:03:43 +0000 (20:03 +0000)
13 files changed:
server/sonar-webserver-auth/src/main/java/org/sonar/server/authentication/CredentialsLocalAuthentication.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsAuthenticationTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/CredentialsLocalAuthenticationTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/DefaultAdminCredentialsVerifierImplTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/HttpHeadersAuthenticationTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/authentication/UserRegistrarImplTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterUpdateTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/ChangePasswordActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/CreateActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/UpdateIdentityProviderActionTest.java

index e11c11073cb5629a769550642ea108a48fe73f3b..e54b106c156a47f42f308f99366951068564771b 100644 (file)
  */
 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<HashMethod, HashFunction> 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
index 114085f28ec8d5a8a01f3d4755b038b2dd5caad9..7ad9affa9f078440ee62fcd9f38bb70fe7b20a91 100644 (file)
@@ -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
index d6865fb122c40c994acfc972d4d829f891e299c8..e7cafffc61a9809db19c08b7a79953e7dc7dbe55 100644 (file)
@@ -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<UserDto> 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<UserDto> 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);
+  }
 }
index df125fdeeb37f8274c9042e1c4c903be499dbba6..7b41c2424683e8ae8dcbc9e1be7ad5fe08f02578 100644 (file)
@@ -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);
index 6674e614b808e8965f50988531df9d1a4e6c4adb..089038661c70dba8860356f662d3e393c7285370 100644 (file)
@@ -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());
 
index 86c79481eb5a860269ef34110dc2be49b2b16a24..280f8cb5c6c4fb684d2afb7e230294a2f7f0c2d6 100644 (file)
@@ -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),
index 8783752bf77086cf2ae9929a5ed71e56953cf32b..6bb357642d42ab444a8d1ce3ce4296f5b29aa69e 100644 (file)
@@ -74,8 +74,8 @@ public class UserUpdaterCreateTest {
   private final ArgumentCaptor<NewUserHandler.Context> 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()
index cf5a5facab082e18b5a65277c161effd606b26fd..25c55506b0d628313f577cb15143ccb7927405ca 100644 (file)
@@ -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());
index 9d7287ece0bbbf7cb2da47c3a31be9e31fbc2f8c..1f4ca04f52c0f7602e5b1e63bc026757bbd74c9c 100644 (file)
@@ -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);
 
index 56619a51aac2166a536c6a7452cdfaeff31fa8c4..9648c2db8ed33cb3ac3f2e7bd83fbb33fd16663f 100644 (file)
@@ -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()),
index 30fd3561fbda7c530e04e8d7bc3f2eb3966ab35d..d17a60f9b54e3dec322f59d8c9277f68e2d056c8 100644 (file)
@@ -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));
 
index e8f91d4b53dc9f6be7d86d1b3b0ca57891d1bc18..c9eced59f3836b4aad399f8eb10aa8c45fa6ffb9 100644 (file)
@@ -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));
index d601be555e3de81203a2e977b0abe72243d2bb05..a7425109bc462c187a61d4844f05d13bc06e976b 100644 (file)
@@ -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),