aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-core
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2020-11-27 09:16:06 +0100
committersonartech <sonartech@sonarsource.com>2020-12-02 20:06:57 +0000
commit2c21bdec38460b793305079d65247cb548dd440a (patch)
treebdb6fe8c854b8165fffbc52023d8fafa9cef6a03 /server/sonar-webserver-core
parent89d9f0efa05022bb7577ff0d2014accc580da0a6 (diff)
downloadsonarqube-2c21bdec38460b793305079d65247cb548dd440a.tar.gz
sonarqube-2c21bdec38460b793305079d65247cb548dd440a.zip
SONAR-14175 SONAR-14176 Detect usage of admin account with default credential
SONAR-14175 Add a startup task to detect admin default credential usage and set reset_password flag to true SONAR-14176 Warn administrators when default admin credential is detected
Diffstat (limited to 'server/sonar-webserver-core')
-rw-r--r--server/sonar-webserver-core/src/main/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredential.java76
-rw-r--r--server/sonar-webserver-core/src/test/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredentialTest.java102
2 files changed, 178 insertions, 0 deletions
diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredential.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredential.java
new file mode 100644
index 00000000000..09249a02a36
--- /dev/null
+++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredential.java
@@ -0,0 +1,76 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.startup;
+
+import org.picocontainer.Startable;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.authentication.CredentialsLocalAuthentication;
+import org.sonar.server.authentication.event.AuthenticationEvent;
+import org.sonar.server.authentication.event.AuthenticationException;
+
+/**
+ * Detect usage of an active admin account with default credential in order to ask this account to reset its password during authentication.
+ */
+public class DetectActiveAdminAccountWithDefaultCredential implements Startable {
+
+ private static final Logger LOGGER = Loggers.get(DetectActiveAdminAccountWithDefaultCredential.class);
+
+ private final DbClient dbClient;
+ private final CredentialsLocalAuthentication localAuthentication;
+
+ public DetectActiveAdminAccountWithDefaultCredential(DbClient dbClient, CredentialsLocalAuthentication localAuthentication) {
+ this.dbClient = dbClient;
+ this.localAuthentication = localAuthentication;
+ }
+
+ @Override
+ public void start() {
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ UserDto admin = dbClient.userDao().selectActiveUserByLogin(dbSession, "admin");
+ if (admin == null || !isDefaultCredentialUser(dbSession, admin)) {
+ return;
+ }
+ LOGGER.warn("*******************************************************************************************************************");
+ LOGGER.warn("Default Administrator credentials are still being used. Make sure to change the password or deactivate the account.");
+ LOGGER.warn("*******************************************************************************************************************");
+ dbClient.userDao().update(dbSession, admin.setResetPassword(true));
+ dbSession.commit();
+ }
+ }
+
+ private boolean isDefaultCredentialUser(DbSession dbSession, UserDto user) {
+ try {
+ localAuthentication.authenticate(dbSession, user, "admin", AuthenticationEvent.Method.BASIC);
+ return true;
+ } catch (AuthenticationException ex) {
+ return false;
+ }
+ }
+
+ @Override
+ public void stop() {
+ // Nothing to do
+ }
+}
diff --git a/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredentialTest.java b/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredentialTest.java
new file mode 100644
index 00000000000..5fee1484965
--- /dev/null
+++ b/server/sonar-webserver-core/src/test/java/org/sonar/server/startup/DetectActiveAdminAccountWithDefaultCredentialTest.java
@@ -0,0 +1,102 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.startup;
+
+import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
+import org.sonar.db.DbTester;
+import org.sonar.db.user.UserDto;
+import org.sonar.server.authentication.CredentialsLocalAuthentication;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DetectActiveAdminAccountWithDefaultCredentialTest {
+
+ private static final String ADMIN_LOGIN = "admin";
+
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ private final CredentialsLocalAuthentication localAuthentication = new CredentialsLocalAuthentication(db.getDbClient());
+
+ private final DetectActiveAdminAccountWithDefaultCredential underTest = new DetectActiveAdminAccountWithDefaultCredential(db.getDbClient(), localAuthentication);
+
+ @After
+ public void after() {
+ underTest.stop();
+ }
+
+ @Test
+ public void set_reset_flag_to_true_and_add_log_when_admin_account_with_default_credential_is_detected() {
+ UserDto admin = db.users().insertUser(u -> u.setLogin(ADMIN_LOGIN));
+ changePassword(admin, "admin");
+
+ underTest.start();
+
+ assertThat(db.users().selectUserByLogin(admin.getLogin()).get().isResetPassword()).isTrue();
+ assertThat(logTester.logs(LoggerLevel.WARN)).contains("Default Administrator credentials are still being used. Make sure to change the password or deactivate the account.");
+ }
+
+ @Test
+ public void do_nothing_when_admin_is_not_using_default_credential() {
+ UserDto admin = db.users().insertUser(u -> u.setLogin(ADMIN_LOGIN));
+ changePassword(admin, "something_else");
+
+ underTest.start();
+
+ assertThat(db.users().selectUserByLogin(admin.getLogin()).get().isResetPassword()).isFalse();
+ assertThat(logTester.logs()).isEmpty();
+ }
+
+ @Test
+ public void do_nothing_when_no_admin_account_with_default_credential_detected() {
+ UserDto otherUser = db.users().insertUser();
+ changePassword(otherUser, "admin");
+
+ underTest.start();
+
+ assertThat(db.users().selectUserByLogin(otherUser.getLogin()).get().isResetPassword()).isFalse();
+ assertThat(logTester.logs()).isEmpty();
+ }
+
+ @Test
+ public void do_nothing_when_admin_account_with_default_credential_is_disabled() {
+ UserDto admin = db.users().insertUser(u -> u.setLogin(ADMIN_LOGIN).setActive(false));
+ changePassword(admin, "admin");
+
+ underTest.start();
+
+ assertThat(db.users().selectUserByLogin(admin.getLogin()).get().isResetPassword()).isFalse();
+ assertThat(logTester.logs()).isEmpty();
+ }
+
+ private void changePassword(UserDto user, String password) {
+ localAuthentication.storeHashPassword(user, password);
+ db.getDbClient().userDao().update(db.getSession(), user);
+ db.commit();
+ }
+}