From db826ad170e332ca71b93d28d6924b7daf4a9476 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 18 Jul 2016 13:42:37 +0200 Subject: [PATCH] SONAR-7770 Check authentication plugin exists when configuration is using realm --- .../startup/FeedUsersLocalStartupTask.java | 34 +++++++++-- .../FeedUsersLocalStartupTaskTest.java | 60 ++++++++++++++++--- 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java b/server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java index 5be1fdc2cc5..a5316f9b383 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java +++ b/server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java @@ -19,11 +19,16 @@ */ 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. - * + *

* See SONAR-7254. - * + *

* 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 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 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; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/startup/FeedUsersLocalStartupTaskTest.java b/server/sonar-server/src/test/java/org/sonar/server/startup/FeedUsersLocalStartupTaskTest.java index 7b0531cfe37..3de4c5f72e5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/startup/FeedUsersLocalStartupTaskTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/startup/FeedUsersLocalStartupTaskTest.java @@ -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; + } } -- 2.39.5