]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7770 Check authentication plugin exists when configuration is using realm
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 18 Jul 2016 11:42:37 +0000 (13:42 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 18 Jul 2016 12:37:23 +0000 (14:37 +0200)
server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java
server/sonar-server/src/test/java/org/sonar/server/startup/FeedUsersLocalStartupTaskTest.java

index 5be1fdc2cc56ec191f1cda0850c8a9349e4c09b5..a5316f9b383256366f719ad5fc1dd6eba5349cb3 100644 (file)
  */
 package org.sonar.server.startup;
 
+import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 import org.picocontainer.Startable;
 import org.sonar.api.config.Settings;
+import org.sonar.api.security.SecurityRealm;
 import org.sonar.api.user.UserQuery;
+import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
@@ -41,9 +46,9 @@ import static org.sonar.db.loadedtemplate.LoadedTemplateDto.ONE_SHOT_TASK_TYPE;
  * Feed users local property.
  * If a realm is defined, then users are set as local only if their login are found in the property "sonar.security.localUsers",
  * otherwise user are all set as local.
- *
+ * <p>
  * See <a href="https://jira.sonarsource.com/browse/SONAR-7254">SONAR-7254</a>.
- *
+ * <p>
  * Should be removed after LTS 5.X
  *
  * @since 5.5
@@ -59,11 +64,23 @@ public class FeedUsersLocalStartupTask implements Startable {
 
   private final DbClient dbClient;
   private final Settings settings;
+  private final SecurityRealm[] realms;
 
+  /**
+   * Used when no realm plugin
+   */
   public FeedUsersLocalStartupTask(System2 system2, DbClient dbClient, Settings settings) {
     this.system2 = system2;
     this.dbClient = dbClient;
     this.settings = settings;
+    this.realms = new SecurityRealm[]{};
+  }
+
+  public FeedUsersLocalStartupTask(System2 system2, DbClient dbClient, Settings settings, SecurityRealm[] realms) {
+    this.system2 = system2;
+    this.dbClient = dbClient;
+    this.settings = settings;
+    this.realms = realms;
   }
 
   @Override
@@ -86,12 +103,13 @@ public class FeedUsersLocalStartupTask implements Startable {
   }
 
   private void updateUsersLocal(DbSession dbSession) {
+    boolean realmConfExists = settings.getString(CORE_AUTHENTICATOR_REALM) != null;
+    checkConfigurationIfRealmExists(realmConfExists);
     long now = system2.now();
     Set<String> localUsers = new HashSet<>(asList(settings.getStringArray(LOCAL_USERS_PROPERTY)));
-    boolean isRealmExist = settings.getString(CORE_AUTHENTICATOR_REALM) != null;
     for (UserDto user : dbClient.userDao().selectUsers(dbSession, UserQuery.ALL_ACTIVES)) {
       if (user.getExternalIdentityProvider().equals(UserUpdater.SQ_AUTHORITY)) {
-        user.setLocal(!isRealmExist || localUsers.contains(user.getLogin()));
+        user.setLocal(!realmConfExists || localUsers.contains(user.getLogin()));
       } else {
         user.setLocal(false);
       }
@@ -100,6 +118,14 @@ public class FeedUsersLocalStartupTask implements Startable {
     }
   }
 
+  private void checkConfigurationIfRealmExists(boolean realmConfExists) {
+    List<String> realmNames = Arrays.stream(realms).map(SecurityRealm::getName).collect(Collectors.toList());
+    if (!realmNames.isEmpty() && !realmConfExists) {
+      throw MessageException.of(String.format("External authentication plugin %s has been found, but no related configuration has been set. " +
+        "Either update your configuration or remove the plugin", realmNames));
+    }
+  }
+
   private boolean hasAlreadyBeenExecuted(DbSession dbSession) {
     return dbClient.loadedTemplateDao().countByTypeAndKey(ONE_SHOT_TASK_TYPE, TEMPLATE_KEY, dbSession) > 0;
   }
index 7b0531cfe377ec1253504846f2ba73eae08a332d..3de4c5f72e5ac92d3d1d6773923c6244f3d0e6da 100644 (file)
@@ -22,7 +22,10 @@ package org.sonar.server.startup;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.sonar.api.config.Settings;
+import org.sonar.api.security.SecurityRealm;
+import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.log.LogTester;
 import org.sonar.api.utils.log.LoggerLevel;
@@ -46,6 +49,11 @@ public class FeedUsersLocalStartupTaskTest {
   static final String USER1_LOGIN = "USER1";
   static final String USER2_LOGIN = "USER2";
 
+  static final String REALM_NAME = "LDAP";
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
   System2 system2 = mock(System2.class);
 
   @Rule
@@ -62,7 +70,7 @@ public class FeedUsersLocalStartupTaskTest {
 
   Settings settings = new Settings();
 
-  FeedUsersLocalStartupTask underTest = new FeedUsersLocalStartupTask(system2, dbTester.getDbClient(), settings);
+  FeedUsersLocalStartupTask underTest;
 
   @Before
   public void setUp() throws Exception {
@@ -71,7 +79,8 @@ public class FeedUsersLocalStartupTaskTest {
 
   @Test
   public void set_user_local_when_id_provider_is_sonarqube_and_realm_exists_and_local_users_property_contains_user_login() throws Exception {
-    settings.setProperty("sonar.security.realm", "LDAP");
+    initTaskWithRealm();
+    settings.setProperty("sonar.security.realm", REALM_NAME);
     settings.setProperty("sonar.security.localUsers", USER1_LOGIN);
     UserDto user = addUser(USER1_LOGIN, false, "sonarqube");
 
@@ -83,7 +92,8 @@ public class FeedUsersLocalStartupTaskTest {
 
   @Test
   public void set_user_as_not_local_when_id_provider_is_sonarqube_and_ream_exists_and_no_local_users_property() throws Exception {
-    settings.setProperty("sonar.security.realm", "LDAP");
+    initTaskWithRealm();
+    settings.setProperty("sonar.security.realm", REALM_NAME);
     UserDto user = addUser(USER1_LOGIN, false, "sonarqube");
 
     underTest.start();
@@ -94,7 +104,8 @@ public class FeedUsersLocalStartupTaskTest {
 
   @Test
   public void set_user_as_not_local_when_id_provider_is_sonarqube_and_ream_exists_and_local_users_property_does_not_contain_user_login() throws Exception {
-    settings.setProperty("sonar.security.realm", "LDAP");
+    initTaskWithRealm();
+    settings.setProperty("sonar.security.realm", REALM_NAME);
     settings.setProperty("sonar.security.localUsers", USER2_LOGIN);
     UserDto user = addUser(USER1_LOGIN, true, "sonarqube");
 
@@ -106,6 +117,7 @@ public class FeedUsersLocalStartupTaskTest {
 
   @Test
   public void set_user_as_local_when_id_provider_is_sonarqube_and_no_realm() throws Exception {
+    initTaskWithNoRealm();
     settings.setProperty("sonar.security.realm", (String) null);
     UserDto user = addUser(USER1_LOGIN, false, "sonarqube");
 
@@ -116,7 +128,8 @@ public class FeedUsersLocalStartupTaskTest {
   }
 
   @Test
-  public void set_user_as_not_local_when_external_identiy_is_not_sonarqube() throws Exception {
+  public void set_user_as_not_local_when_external_identity_is_not_sonarqube() throws Exception {
+    initTaskWithNoRealm();
     UserDto user = addUser(USER1_LOGIN, false, "github");
 
     underTest.start();
@@ -127,7 +140,8 @@ public class FeedUsersLocalStartupTaskTest {
 
   @Test
   public void does_not_update_removed_user() throws Exception {
-    settings.setProperty("sonar.security.realm", "LDAP");
+    initTaskWithRealm();
+    settings.setProperty("sonar.security.realm", REALM_NAME);
 
     UserDto user = UserTesting.newUserDto()
       .setLogin(USER1_LOGIN)
@@ -148,7 +162,8 @@ public class FeedUsersLocalStartupTaskTest {
 
   @Test
   public void does_nothing_when_task_has_already_been_executed() throws Exception {
-    settings.setProperty("sonar.security.realm", "LDAP");
+    initTaskWithRealm();
+    settings.setProperty("sonar.security.realm", REALM_NAME);
     settings.setProperty("sonar.security.localUsers", USER1_LOGIN);
     UserDto user = addUser(USER1_LOGIN, false, "github");
 
@@ -168,6 +183,16 @@ public class FeedUsersLocalStartupTaskTest {
     verifyEmptyLog();
   }
 
+  @Test
+  public void fail_when_realm_found_but_no_configuration() throws Exception {
+    initTask(createRealm("REALM1"), createRealm("REALM2"));
+
+    expectedException.expect(MessageException.class);
+    expectedException.expectMessage("External authentication plugin [REALM1, REALM2] has been found, but no related configuration has been set. " +
+      "Either update your configuration or remove the plugin");
+    underTest.start();
+  }
+
   private UserDto addUser(String login, boolean local, String externalIdentityProvider) {
     UserDto user = UserTesting.newUserDto()
       .setLogin(login)
@@ -202,4 +227,25 @@ public class FeedUsersLocalStartupTaskTest {
     assertThat(logTester.logs(LoggerLevel.INFO)).isEmpty();
   }
 
+  private void initTask(SecurityRealm... realms) {
+    if (realms.length == 0) {
+      underTest = new FeedUsersLocalStartupTask(system2, dbTester.getDbClient(), settings);
+    } else {
+      underTest = new FeedUsersLocalStartupTask(system2, dbTester.getDbClient(), settings, realms);
+    }
+  }
+
+  private void initTaskWithRealm() {
+    initTask(createRealm(REALM_NAME));
+  }
+
+  private void initTaskWithNoRealm() {
+    initTask();
+  }
+
+  private static SecurityRealm createRealm(String name) {
+    SecurityRealm realm = mock(SecurityRealm.class);
+    when(realm.getName()).thenReturn(name);
+    return realm;
+  }
 }