diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2021-03-24 15:59:35 -0500 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-03-29 20:03:43 +0000 |
commit | 1b2921d043afd96a1415f7fafaa11de86027057a (patch) | |
tree | bc289229796ea12f7279da817d026f68cf66d42e /server/sonar-webserver-auth/src/test | |
parent | 90636689abac7bebe85d38452e132452879b65fa (diff) | |
download | sonarqube-1b2921d043afd96a1415f7fafaa11de86027057a.tar.gz sonarqube-1b2921d043afd96a1415f7fafaa11de86027057a.zip |
SONAR-14582 SSF-124
Diffstat (limited to 'server/sonar-webserver-auth/src/test')
8 files changed, 173 insertions, 20 deletions
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<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); + } } 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.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() 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); |