*/
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;
* 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
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
}
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);
}
}
}
+ 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;
}
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;
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
Settings settings = new Settings();
- FeedUsersLocalStartupTask underTest = new FeedUsersLocalStartupTask(system2, dbTester.getDbClient(), settings);
+ FeedUsersLocalStartupTask underTest;
@Before
public void setUp() throws Exception {
@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");
@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();
@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");
@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");
}
@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();
@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)
@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");
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)
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;
+ }
}