]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7994 Clean up migration that feed local users 1150/head
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 17 Aug 2016 14:57:08 +0000 (16:57 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 18 Aug 2016 09:46:41 +0000 (11:46 +0200)
it/it-tests/src/test/java/it/Category5Suite.java
it/it-tests/src/test/java/it/user/RailsExternalAuthenticationTest.java [deleted file]
it/it-tests/src/test/java/it/user/RealmAuthenticationTest.java [new file with mode: 0644]
server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevelStartup.java
server/sonar-server/src/main/java/org/sonar/server/startup/FeedUsersLocalStartupTask.java [deleted file]
server/sonar-server/src/test/java/org/sonar/server/startup/FeedUsersLocalStartupTaskTest.java [deleted file]
sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java

index 1e3af4ff8c257c8994a0321376569eda7427995c..7f5f85b2a7ac4fa13f9a0b8902128333c0b2a309 100644 (file)
@@ -24,7 +24,7 @@ import it.serverSystem.RestartTest;
 import it.serverSystem.ServerSystemRestartingOrchestrator;
 import it.settings.SettingsTestRestartingOrchestrator;
 import it.updateCenter.UpdateCenterTest;
-import it.user.RailsExternalAuthenticationTest;
+import it.user.RealmAuthenticationTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
 
@@ -41,7 +41,7 @@ import org.junit.runners.Suite;
   SettingsTestRestartingOrchestrator.class,
   // update center
   UpdateCenterTest.class,
-  RailsExternalAuthenticationTest.class
+  RealmAuthenticationTest.class
   })
 public class Category5Suite {
 
diff --git a/it/it-tests/src/test/java/it/user/RailsExternalAuthenticationTest.java b/it/it-tests/src/test/java/it/user/RailsExternalAuthenticationTest.java
deleted file mode 100644 (file)
index 0236652..0000000
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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 it.user;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import com.sonar.orchestrator.Orchestrator;
-import com.sonar.orchestrator.selenium.Selenese;
-import java.util.Map;
-import java.util.Objects;
-import org.apache.commons.lang.RandomStringUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.wsclient.Host;
-import org.sonar.wsclient.Sonar;
-import org.sonar.wsclient.base.HttpException;
-import org.sonar.wsclient.connectors.ConnectionException;
-import org.sonar.wsclient.connectors.HttpClient4Connector;
-import org.sonar.wsclient.services.AuthenticationQuery;
-import org.sonar.wsclient.services.UserPropertyCreateQuery;
-import org.sonar.wsclient.services.UserPropertyQuery;
-import org.sonar.wsclient.user.UserParameters;
-import org.sonarqube.ws.client.GetRequest;
-import org.sonarqube.ws.client.HttpConnector;
-import org.sonarqube.ws.client.WsClient;
-import org.sonarqube.ws.client.WsClientFactories;
-import org.sonarqube.ws.client.WsResponse;
-import util.selenium.SeleneseTest;
-
-import static java.net.HttpURLConnection.HTTP_OK;
-import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static util.ItUtils.pluginArtifact;
-import static util.ItUtils.setServerProperty;
-
-/**
- * Test deprecated authentication done by Rails. It's kept has every features has not bee migrated to java yet.
- *
- * It starts its own server as it's using a different authentication system
- */
-public class RailsExternalAuthenticationTest {
-
-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  static final String TECH_USER = "techUser";
-  static final String USER_LOGIN = "tester";
-
-  /**
-   * Property from security-plugin for user management.
-   */
-  private static final String USERS_PROPERTY = "sonar.fakeauthenticator.users";
-  private static String AUTHORIZED = "authorized";
-  private static String NOT_AUTHORIZED = "not authorized";
-
-  @ClassRule
-  public static final Orchestrator orchestrator = Orchestrator.builderEnv()
-    .addPlugin(pluginArtifact("security-plugin"))
-    .setServerProperty("sonar.security.realm", "FakeRealm")
-    .build();
-
-  @Before
-  @After
-  public void resetData() throws Exception {
-    setServerProperty(orchestrator, USERS_PROPERTY, null);
-    setServerProperty(orchestrator, "sonar.security.updateUserAttributes", null);
-    setServerProperty(orchestrator, "sonar.authenticator.createUsers", null);
-    resetUsers(USER_LOGIN, TECH_USER);
-  }
-
-  private void resetUsers(String... logins) {
-    for (String login : logins) {
-      String result = orchestrator.getServer().adminWsClient().get("/api/users/search?q=" + login);
-      if (result.contains(login)) {
-        orchestrator.getServer().adminWsClient().userClient().deactivate(login);
-      }
-    }
-  }
-
-  /**
-   * SONAR-3137, SONAR-2292
-   * Restriction on password length (minimum 4 characters) should be disabled, when external system enabled.
-   */
-  @Test
-  public void shouldSynchronizeDetailsAndGroups() {
-    // Given clean Sonar installation and no users in external system
-    String username = USER_LOGIN;
-    String password = "123";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When user created in external system
-    users.put(username + ".password", password);
-    users.put(username + ".name", "Tester Testerovich");
-    users.put(username + ".email", "tester@example.org");
-    users.put(username + ".groups", "sonar-user");
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
-    // with external details and groups
-    new SeleneseTest(
-      Selenese.builder().setHtmlTestsInClasspath("external-user-details",
-        "/user/ExternalAuthenticationTest/external-user-details.html")
-        .build()).runOn(orchestrator);
-
-    // SONAR-4462
-    new SeleneseTest(
-      Selenese.builder().setHtmlTestsInClasspath("system-info",
-        "/user/ExternalAuthenticationTest/system-info.html")
-        .build()).runOn(orchestrator);
-  }
-
-  /**
-   * SONAR-4034
-   */
-  @Test
-  public void shouldUpdateDetailsByDefault() {
-    // Given clean Sonar installation and no users in external system
-    String username = USER_LOGIN;
-    String password = "123";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When user created in external system
-    users.put(username + ".password", password);
-    users.put(username + ".name", "Tester Testerovich");
-    users.put(username + ".email", "tester@example.org");
-    users.put(username + ".groups", "sonar-user");
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
-    // with external details and groups
-    // TODO replace by WS ? Or with new Selenese utils
-    new SeleneseTest(
-      Selenese.builder().setHtmlTestsInClasspath("external-user-details",
-        "/user/ExternalAuthenticationTest/external-user-details.html")
-        .build()).runOn(orchestrator);
-
-    // Now update user details
-    users.put(username + ".name", "Tester2 Testerovich");
-    users.put(username + ".email", "tester2@example.org");
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
-    // with external details and groups updated
-    new SeleneseTest(
-      Selenese.builder().setHtmlTestsInClasspath("external-user-details2",
-        "/user/ExternalAuthenticationTest/external-user-details2.html").build()).runOn(orchestrator);
-  }
-
-  /**
-   * SONAR-3138
-   */
-  @Test
-  public void shouldNotFallback() {
-    // Given clean Sonar installation and no users in external system
-    String login = USER_LOGIN;
-    String password = "1234567";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When user created in external system
-    users.put(login + ".password", password);
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(login, password)).isEqualTo(AUTHORIZED);
-
-    // When external system does not work
-    users.remove(login + ".password");
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(login, password)).isEqualTo(NOT_AUTHORIZED);
-  }
-
-  /**
-   * SONAR-4543
-   */
-  @Test
-  public void adminIsLocalAccountByDefault() {
-    // Given clean Sonar installation and no users in external system
-    String login = "admin";
-    String localPassword = "admin";
-    String remotePassword = "nimda";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When admin created in external system with a different password
-    users.put(login + ".password", remotePassword);
-    updateUsersInExtAuth(users);
-
-    // Then this is local DB that should be used
-    assertThat(loginAttempt(login, remotePassword)).isEqualTo(NOT_AUTHORIZED);
-    assertThat(loginAttempt(login, localPassword)).isEqualTo(AUTHORIZED);
-  }
-
-  /**
-   * SONAR-1334, SONAR-3185 (createUsers=true is default)
-   */
-  @Test
-  public void shouldCreateNewUsers() {
-    // Given clean Sonar installation and no users in external system
-    String username = USER_LOGIN;
-    String password = "1234567";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When user not exists in external system
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(NOT_AUTHORIZED);
-
-    // When user created in external system
-    users.put(username + ".password", password);
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
-    assertThat(loginAttempt(username, "wrong")).isEqualTo(NOT_AUTHORIZED);
-  }
-
-  /**
-   * SONAR-1334 (createUsers=false)
-   */
-  @Test
-  public void shouldNotCreateNewUsers() {
-    // Given clean Sonar installation and no users in external system
-    setServerProperty(orchestrator, "sonar.authenticator.createUsers", "false");
-    // Use a random user name because if we use existing disabled user then it doesn't work because rails doesn't handle this case
-    // (it's using User.find_by_login to know if user exists or not
-    String username = RandomStringUtils.randomAlphanumeric(20);
-    String password = "1234567";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When user not exists in external system
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(NOT_AUTHORIZED);
-
-    // When user created in external system
-    users.put(username + ".password", password);
-    updateUsersInExtAuth(users);
-    // Then
-    assertThat(loginAttempt(username, password)).isEqualTo(NOT_AUTHORIZED);
-  }
-
-  // SONAR-3258
-  @Test
-  public void shouldAutomaticallyReactivateDeletedUser() throws Exception {
-    // Given clean Sonar installation and no users in external system
-
-    // Let's create and delete the user "tester" in Sonar DB
-    new SeleneseTest(
-      Selenese.builder().setHtmlTestsInClasspath("external-user-create-and-delete-user",
-        "/user/ExternalAuthenticationTest/create-and-delete-user.html").build()).runOn(orchestrator);
-
-    // And now update the security with the user that was deleted
-    String login = USER_LOGIN;
-    String password = "1234567";
-    Map<String, String> users = Maps.newHashMap();
-    users.put(login + ".password", password);
-    updateUsersInExtAuth(users);
-    // check that the deleted/deactivated user "tester" has been reactivated and can now log in
-    assertThat(loginAttempt(login, password)).isEqualTo(AUTHORIZED);
-  }
-
-  /**
-   * SONAR-7036
-   */
-  @Test
-  public void update_password_of_technical_user() throws Exception {
-    // Create user in external authentication
-    updateUsersInExtAuth(ImmutableMap.of(USER_LOGIN + ".password", USER_LOGIN));
-    assertThat(loginAttempt(USER_LOGIN, USER_LOGIN)).isEqualTo(AUTHORIZED);
-
-    // Create technical user in db
-    createUserInDb(TECH_USER, "old_password");
-    assertThat(checkAuthenticationThroughWebService(TECH_USER, "old_password")).isTrue();
-
-    // Updating password of technical user is allowed
-    updateUserPasswordInDb(TECH_USER, "new_password");
-    assertThat(checkAuthenticationThroughWebService(TECH_USER, "new_password")).isTrue();
-
-    // But updating password of none local user is not allowed
-    try {
-      updateUserPasswordInDb(USER_LOGIN, "new_password");
-      fail();
-    } catch (HttpException e) {
-      verifyHttpException(e, 400);
-    }
-  }
-
-  /**
-   * SONAR-7640
-   */
-  @Test
-  public void authentication_with_ws() throws Exception {
-    // Given clean Sonar installation and no users in external system
-    String login = USER_LOGIN;
-    String password = "1234567";
-    Map<String, String> users = Maps.newHashMap();
-
-    // When user created in external system
-    users.put(login + ".password", password);
-    updateUsersInExtAuth(users);
-
-    assertThat(checkAuthenticationWithWebService(login, password).code()).isEqualTo(HTTP_OK);
-    assertThat(checkAuthenticationWithWebService("wrong", password).code()).isEqualTo(HTTP_UNAUTHORIZED);
-    assertThat(checkAuthenticationWithWebService(login, "wrong").code()).isEqualTo(HTTP_UNAUTHORIZED);
-    assertThat(checkAuthenticationWithWebService(login, null).code()).isEqualTo(HTTP_UNAUTHORIZED);
-    assertThat(checkAuthenticationWithWebService(null, null).code()).isEqualTo(HTTP_OK);
-
-    setServerProperty(orchestrator, "sonar.forceAuthentication", "true");
-
-    assertThat(checkAuthenticationWithWebService(login, password).code()).isEqualTo(HTTP_OK);
-    assertThat(checkAuthenticationWithWebService("wrong", password).code()).isEqualTo(HTTP_UNAUTHORIZED);
-    assertThat(checkAuthenticationWithWebService(login, "wrong").code()).isEqualTo(HTTP_UNAUTHORIZED);
-    assertThat(checkAuthenticationWithWebService(login, null).code()).isEqualTo(HTTP_UNAUTHORIZED);
-    assertThat(checkAuthenticationWithWebService(null, null).code()).isEqualTo(HTTP_UNAUTHORIZED);
-  }
-
-  protected void verifyHttpException(Exception e, int expectedCode) {
-    assertThat(e).isInstanceOf(HttpException.class);
-    HttpException exception = (HttpException) e;
-    assertThat(exception.status()).isEqualTo(expectedCode);
-  }
-
-  private boolean checkAuthenticationThroughWebService(String login, String password) {
-    return createWsClient(login, password).find(new AuthenticationQuery()).isValid();
-  }
-
-  /**
-   * Utility method to check that user can be authorized.
-   *
-   * @throws IllegalStateException
-   */
-  private String loginAttempt(String username, String password) {
-    String expectedValue = Long.toString(System.currentTimeMillis());
-    Sonar wsClient = createWsClient(username, password);
-    try {
-      wsClient.create(new UserPropertyCreateQuery("auth", expectedValue));
-    } catch (ConnectionException e) {
-      return NOT_AUTHORIZED;
-    }
-    try {
-      String value = wsClient.find(new UserPropertyQuery("auth")).getValue();
-      if (!Objects.equals(value, expectedValue)) {
-        // exceptional case - update+retrieval were successful, but value doesn't match
-        throw new IllegalStateException("Expected " + expectedValue + " , but got " + value);
-      }
-    } catch (ConnectionException e) {
-      // exceptional case - update was successful, but not retrieval
-      throw new IllegalStateException(e);
-    }
-    return AUTHORIZED;
-  }
-
-  /**
-   * Updates information about users in security-plugin.
-   */
-  private static void updateUsersInExtAuth(Map<String, String> users) {
-    setServerProperty(orchestrator, USERS_PROPERTY, format(users));
-  }
-
-  private void createUserInDb(String login, String password) {
-    orchestrator.getServer().adminWsClient().userClient().create(UserParameters.create().login(login).name(login)
-      .password(password).passwordConfirmation(password));
-  }
-
-  private void updateUserPasswordInDb(String login, String newPassword) {
-    orchestrator.getServer().adminWsClient().post("/api/users/change_password", "login", login, "password", newPassword);
-  }
-
-  /**
-   * Utility method to create {@link Sonar} with specified {@code username} and {@code password}.
-   * Orchestrator does not provide such method.
-   */
-  private Sonar createWsClient(String username, String password) {
-    return new Sonar(new HttpClient4Connector(new Host(orchestrator.getServer().getUrl(), username, password)));
-  }
-
-  private static String format(Map<String, String> map) {
-    StringBuilder sb = new StringBuilder();
-    for (Map.Entry<String, String> entry : map.entrySet()) {
-      sb.append(entry.getKey()).append('=').append(entry.getValue()).append('\n');
-    }
-    return sb.toString();
-  }
-
-  private WsResponse checkAuthenticationWithWebService(String login, String password) {
-    WsClient wsClient = WsClientFactories.getDefault().newClient(HttpConnector.newBuilder().url(orchestrator.getServer().getUrl()).credentials(login, password).build());
-    // Call any WS
-    return wsClient.wsConnector().call(new GetRequest("api/rules/search"));
-  }
-
-}
diff --git a/it/it-tests/src/test/java/it/user/RealmAuthenticationTest.java b/it/it-tests/src/test/java/it/user/RealmAuthenticationTest.java
new file mode 100644 (file)
index 0000000..c61398e
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 it.user;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.selenium.Selenese;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.wsclient.Host;
+import org.sonar.wsclient.Sonar;
+import org.sonar.wsclient.base.HttpException;
+import org.sonar.wsclient.connectors.ConnectionException;
+import org.sonar.wsclient.connectors.HttpClient4Connector;
+import org.sonar.wsclient.services.AuthenticationQuery;
+import org.sonar.wsclient.services.UserPropertyCreateQuery;
+import org.sonar.wsclient.services.UserPropertyQuery;
+import org.sonar.wsclient.user.UserParameters;
+import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.HttpConnector;
+import org.sonarqube.ws.client.WsClient;
+import org.sonarqube.ws.client.WsClientFactories;
+import org.sonarqube.ws.client.WsResponse;
+import util.selenium.SeleneseTest;
+
+import static java.net.HttpURLConnection.HTTP_OK;
+import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static util.ItUtils.pluginArtifact;
+import static util.ItUtils.setServerProperty;
+
+/**
+ * Test REALM authentication.
+ *
+ * It starts its own server as it's using a different authentication system
+ */
+public class RealmAuthenticationTest {
+
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
+  static final String TECH_USER = "techUser";
+  static final String USER_LOGIN = "tester";
+
+  /**
+   * Property from security-plugin for user management.
+   */
+  private static final String USERS_PROPERTY = "sonar.fakeauthenticator.users";
+  private static String AUTHORIZED = "authorized";
+  private static String NOT_AUTHORIZED = "not authorized";
+
+  @ClassRule
+  public static final Orchestrator orchestrator = Orchestrator.builderEnv()
+    .addPlugin(pluginArtifact("security-plugin"))
+    .setServerProperty("sonar.security.realm", "FakeRealm")
+    .build();
+
+  @Before
+  @After
+  public void resetData() throws Exception {
+    setServerProperty(orchestrator, USERS_PROPERTY, null);
+    setServerProperty(orchestrator, "sonar.security.updateUserAttributes", null);
+    setServerProperty(orchestrator, "sonar.authenticator.createUsers", null);
+    resetUsers(USER_LOGIN, TECH_USER);
+  }
+
+  private void resetUsers(String... logins) {
+    for (String login : logins) {
+      String result = orchestrator.getServer().adminWsClient().get("/api/users/search?q=" + login);
+      if (result.contains(login)) {
+        orchestrator.getServer().adminWsClient().userClient().deactivate(login);
+      }
+    }
+  }
+
+  /**
+   * SONAR-3137, SONAR-2292
+   * Restriction on password length (minimum 4 characters) should be disabled, when external system enabled.
+   */
+  @Test
+  public void shouldSynchronizeDetailsAndGroups() {
+    // Given clean Sonar installation and no users in external system
+    String username = USER_LOGIN;
+    String password = "123";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When user created in external system
+    users.put(username + ".password", password);
+    users.put(username + ".name", "Tester Testerovich");
+    users.put(username + ".email", "tester@example.org");
+    users.put(username + ".groups", "sonar-user");
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
+    // with external details and groups
+    new SeleneseTest(
+      Selenese.builder().setHtmlTestsInClasspath("external-user-details",
+        "/user/ExternalAuthenticationTest/external-user-details.html")
+        .build()).runOn(orchestrator);
+
+    // SONAR-4462
+    new SeleneseTest(
+      Selenese.builder().setHtmlTestsInClasspath("system-info",
+        "/user/ExternalAuthenticationTest/system-info.html")
+        .build()).runOn(orchestrator);
+  }
+
+  /**
+   * SONAR-4034
+   */
+  @Test
+  public void shouldUpdateDetailsByDefault() {
+    // Given clean Sonar installation and no users in external system
+    String username = USER_LOGIN;
+    String password = "123";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When user created in external system
+    users.put(username + ".password", password);
+    users.put(username + ".name", "Tester Testerovich");
+    users.put(username + ".email", "tester@example.org");
+    users.put(username + ".groups", "sonar-user");
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
+    // with external details and groups
+    // TODO replace by WS ? Or with new Selenese utils
+    new SeleneseTest(
+      Selenese.builder().setHtmlTestsInClasspath("external-user-details",
+        "/user/ExternalAuthenticationTest/external-user-details.html")
+        .build()).runOn(orchestrator);
+
+    // Now update user details
+    users.put(username + ".name", "Tester2 Testerovich");
+    users.put(username + ".email", "tester2@example.org");
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
+    // with external details and groups updated
+    new SeleneseTest(
+      Selenese.builder().setHtmlTestsInClasspath("external-user-details2",
+        "/user/ExternalAuthenticationTest/external-user-details2.html").build()).runOn(orchestrator);
+  }
+
+  /**
+   * SONAR-3138
+   */
+  @Test
+  public void shouldNotFallback() {
+    // Given clean Sonar installation and no users in external system
+    String login = USER_LOGIN;
+    String password = "1234567";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When user created in external system
+    users.put(login + ".password", password);
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(login, password)).isEqualTo(AUTHORIZED);
+
+    // When external system does not work
+    users.remove(login + ".password");
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(login, password)).isEqualTo(NOT_AUTHORIZED);
+  }
+
+  /**
+   * SONAR-4543
+   */
+  @Test
+  public void adminIsLocalAccountByDefault() {
+    // Given clean Sonar installation and no users in external system
+    String login = "admin";
+    String localPassword = "admin";
+    String remotePassword = "nimda";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When admin created in external system with a different password
+    users.put(login + ".password", remotePassword);
+    updateUsersInExtAuth(users);
+
+    // Then this is local DB that should be used
+    assertThat(loginAttempt(login, remotePassword)).isEqualTo(NOT_AUTHORIZED);
+    assertThat(loginAttempt(login, localPassword)).isEqualTo(AUTHORIZED);
+  }
+
+  /**
+   * SONAR-1334, SONAR-3185 (createUsers=true is default)
+   */
+  @Test
+  public void shouldCreateNewUsers() {
+    // Given clean Sonar installation and no users in external system
+    String username = USER_LOGIN;
+    String password = "1234567";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When user not exists in external system
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(NOT_AUTHORIZED);
+
+    // When user created in external system
+    users.put(username + ".password", password);
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(AUTHORIZED);
+    assertThat(loginAttempt(username, "wrong")).isEqualTo(NOT_AUTHORIZED);
+  }
+
+  /**
+   * SONAR-1334 (createUsers=false)
+   */
+  @Test
+  public void shouldNotCreateNewUsers() {
+    // Given clean Sonar installation and no users in external system
+    setServerProperty(orchestrator, "sonar.authenticator.createUsers", "false");
+    // Use a random user name because if we use existing disabled user then it doesn't work because rails doesn't handle this case
+    // (it's using User.find_by_login to know if user exists or not
+    String username = RandomStringUtils.randomAlphanumeric(20);
+    String password = "1234567";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When user not exists in external system
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(NOT_AUTHORIZED);
+
+    // When user created in external system
+    users.put(username + ".password", password);
+    updateUsersInExtAuth(users);
+    // Then
+    assertThat(loginAttempt(username, password)).isEqualTo(NOT_AUTHORIZED);
+  }
+
+  // SONAR-3258
+  @Test
+  public void shouldAutomaticallyReactivateDeletedUser() throws Exception {
+    // Given clean Sonar installation and no users in external system
+
+    // Let's create and delete the user "tester" in Sonar DB
+    new SeleneseTest(
+      Selenese.builder().setHtmlTestsInClasspath("external-user-create-and-delete-user",
+        "/user/ExternalAuthenticationTest/create-and-delete-user.html").build()).runOn(orchestrator);
+
+    // And now update the security with the user that was deleted
+    String login = USER_LOGIN;
+    String password = "1234567";
+    Map<String, String> users = Maps.newHashMap();
+    users.put(login + ".password", password);
+    updateUsersInExtAuth(users);
+    // check that the deleted/deactivated user "tester" has been reactivated and can now log in
+    assertThat(loginAttempt(login, password)).isEqualTo(AUTHORIZED);
+  }
+
+  /**
+   * SONAR-7036
+   */
+  @Test
+  public void update_password_of_technical_user() throws Exception {
+    // Create user in external authentication
+    updateUsersInExtAuth(ImmutableMap.of(USER_LOGIN + ".password", USER_LOGIN));
+    assertThat(loginAttempt(USER_LOGIN, USER_LOGIN)).isEqualTo(AUTHORIZED);
+
+    // Create technical user in db
+    createUserInDb(TECH_USER, "old_password");
+    assertThat(checkAuthenticationThroughWebService(TECH_USER, "old_password")).isTrue();
+
+    // Updating password of technical user is allowed
+    updateUserPasswordInDb(TECH_USER, "new_password");
+    assertThat(checkAuthenticationThroughWebService(TECH_USER, "new_password")).isTrue();
+
+    // But updating password of none local user is not allowed
+    try {
+      updateUserPasswordInDb(USER_LOGIN, "new_password");
+      fail();
+    } catch (HttpException e) {
+      verifyHttpException(e, 400);
+    }
+  }
+
+  /**
+   * SONAR-7640
+   */
+  @Test
+  public void authentication_with_ws() throws Exception {
+    // Given clean Sonar installation and no users in external system
+    String login = USER_LOGIN;
+    String password = "1234567";
+    Map<String, String> users = Maps.newHashMap();
+
+    // When user created in external system
+    users.put(login + ".password", password);
+    updateUsersInExtAuth(users);
+
+    assertThat(checkAuthenticationWithWebService(login, password).code()).isEqualTo(HTTP_OK);
+    assertThat(checkAuthenticationWithWebService("wrong", password).code()).isEqualTo(HTTP_UNAUTHORIZED);
+    assertThat(checkAuthenticationWithWebService(login, "wrong").code()).isEqualTo(HTTP_UNAUTHORIZED);
+    assertThat(checkAuthenticationWithWebService(login, null).code()).isEqualTo(HTTP_UNAUTHORIZED);
+    assertThat(checkAuthenticationWithWebService(null, null).code()).isEqualTo(HTTP_OK);
+
+    setServerProperty(orchestrator, "sonar.forceAuthentication", "true");
+
+    assertThat(checkAuthenticationWithWebService(login, password).code()).isEqualTo(HTTP_OK);
+    assertThat(checkAuthenticationWithWebService("wrong", password).code()).isEqualTo(HTTP_UNAUTHORIZED);
+    assertThat(checkAuthenticationWithWebService(login, "wrong").code()).isEqualTo(HTTP_UNAUTHORIZED);
+    assertThat(checkAuthenticationWithWebService(login, null).code()).isEqualTo(HTTP_UNAUTHORIZED);
+    assertThat(checkAuthenticationWithWebService(null, null).code()).isEqualTo(HTTP_UNAUTHORIZED);
+  }
+
+  protected void verifyHttpException(Exception e, int expectedCode) {
+    assertThat(e).isInstanceOf(HttpException.class);
+    HttpException exception = (HttpException) e;
+    assertThat(exception.status()).isEqualTo(expectedCode);
+  }
+
+  private boolean checkAuthenticationThroughWebService(String login, String password) {
+    return createWsClient(login, password).find(new AuthenticationQuery()).isValid();
+  }
+
+  /**
+   * Utility method to check that user can be authorized.
+   *
+   * @throws IllegalStateException
+   */
+  private String loginAttempt(String username, String password) {
+    String expectedValue = Long.toString(System.currentTimeMillis());
+    Sonar wsClient = createWsClient(username, password);
+    try {
+      wsClient.create(new UserPropertyCreateQuery("auth", expectedValue));
+    } catch (ConnectionException e) {
+      return NOT_AUTHORIZED;
+    }
+    try {
+      String value = wsClient.find(new UserPropertyQuery("auth")).getValue();
+      if (!Objects.equals(value, expectedValue)) {
+        // exceptional case - update+retrieval were successful, but value doesn't match
+        throw new IllegalStateException("Expected " + expectedValue + " , but got " + value);
+      }
+    } catch (ConnectionException e) {
+      // exceptional case - update was successful, but not retrieval
+      throw new IllegalStateException(e);
+    }
+    return AUTHORIZED;
+  }
+
+  /**
+   * Updates information about users in security-plugin.
+   */
+  private static void updateUsersInExtAuth(Map<String, String> users) {
+    setServerProperty(orchestrator, USERS_PROPERTY, format(users));
+  }
+
+  private void createUserInDb(String login, String password) {
+    orchestrator.getServer().adminWsClient().userClient().create(UserParameters.create().login(login).name(login)
+      .password(password).passwordConfirmation(password));
+  }
+
+  private void updateUserPasswordInDb(String login, String newPassword) {
+    orchestrator.getServer().adminWsClient().post("/api/users/change_password", "login", login, "password", newPassword);
+  }
+
+  /**
+   * Utility method to create {@link Sonar} with specified {@code username} and {@code password}.
+   * Orchestrator does not provide such method.
+   */
+  private Sonar createWsClient(String username, String password) {
+    return new Sonar(new HttpClient4Connector(new Host(orchestrator.getServer().getUrl(), username, password)));
+  }
+
+  private static String format(Map<String, String> map) {
+    StringBuilder sb = new StringBuilder();
+    for (Map.Entry<String, String> entry : map.entrySet()) {
+      sb.append(entry.getKey()).append('=').append(entry.getValue()).append('\n');
+    }
+    return sb.toString();
+  }
+
+  private WsResponse checkAuthenticationWithWebService(String login, String password) {
+    WsClient wsClient = WsClientFactories.getDefault().newClient(HttpConnector.newBuilder().url(orchestrator.getServer().getUrl()).credentials(login, password).build());
+    // Call any WS
+    return wsClient.wsConnector().call(new GetRequest("api/rules/search"));
+  }
+
+}
index 9fc85e9f8a64db1b92cb25efcd121be574fd359a..6a4709b1260c497144255eb65c7242577ba47297 100644 (file)
@@ -107,7 +107,7 @@ public class ComputeEngineContainerImplTest {
         + 26 // level 1
         + 47 // content of DaoModule
         + 2 // content of EsSearchModule
-        + 55 // content of CorePropertyDefinitions
+        + 54 // content of CorePropertyDefinitions
         + 1 // content of CePropertyDefinitions
     );
     assertThat(picoContainer.getParent().getParent().getParent().getParent()).isNull();
index 67fa802f2ad12b69b2d69965421ea79c4d2c0151..0d49dee05870dc28543148ac7c2eae19e5534b39 100644 (file)
@@ -32,7 +32,6 @@ import org.sonar.server.rule.RegisterRules;
 import org.sonar.server.startup.ClearRulesOverloadedDebt;
 import org.sonar.server.startup.DeleteOldAnalysisReportsFromFs;
 import org.sonar.server.startup.DisplayLogOnDeprecatedProjects;
-import org.sonar.server.startup.FeedUsersLocalStartupTask;
 import org.sonar.server.startup.GeneratePluginIndex;
 import org.sonar.server.startup.RegisterDashboards;
 import org.sonar.server.startup.RegisterMetrics;
@@ -53,7 +52,7 @@ public class PlatformLevelStartup extends PlatformLevel {
     add(GeneratePluginIndex.class,
       RegisterServletFilters.class,
       ServerLifecycleNotifier.class);
-    
+
     addIfStartupLeader(
       CheckDatabaseCollationDuringMigration.class,
       IndexerStartupTask.class,
@@ -69,9 +68,7 @@ public class PlatformLevelStartup extends PlatformLevel {
       RenameIssueWidgets.class,
       DisplayLogOnDeprecatedProjects.class,
       ClearRulesOverloadedDebt.class,
-      DeleteOldAnalysisReportsFromFs.class,
-      FeedUsersLocalStartupTask.class);
-
+      DeleteOldAnalysisReportsFromFs.class);
   }
 
   @Override
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
deleted file mode 100644 (file)
index a5316f9..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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 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;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.loadedtemplate.LoadedTemplateDto;
-import org.sonar.db.user.UserDto;
-import org.sonar.server.user.UserUpdater;
-
-import static java.util.Arrays.asList;
-import static org.sonar.api.CoreProperties.CORE_AUTHENTICATOR_REALM;
-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
- */
-public class FeedUsersLocalStartupTask implements Startable {
-
-  private static final Logger LOG = Loggers.get(FeedUsersLocalStartupTask.class);
-
-  private static final String TEMPLATE_KEY = "UpdateUsersLocal";
-  private static final String LOCAL_USERS_PROPERTY = "sonar.security.localUsers";
-
-  private final System2 system2;
-
-  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
-  public void start() {
-    DbSession dbSession = dbClient.openSession(false);
-    try {
-      if (hasAlreadyBeenExecuted(dbSession)) {
-        return;
-      }
-      updateUsersLocal(dbSession);
-      markAsExecuted(dbSession);
-      dbSession.commit();
-
-      if (settings.hasKey(LOCAL_USERS_PROPERTY)) {
-        LOG.info("NOTE : The property '{}' is now no more needed, you can safely remove it.", LOCAL_USERS_PROPERTY);
-      }
-    } finally {
-      dbClient.closeSession(dbSession);
-    }
-  }
-
-  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)));
-    for (UserDto user : dbClient.userDao().selectUsers(dbSession, UserQuery.ALL_ACTIVES)) {
-      if (user.getExternalIdentityProvider().equals(UserUpdater.SQ_AUTHORITY)) {
-        user.setLocal(!realmConfExists || localUsers.contains(user.getLogin()));
-      } else {
-        user.setLocal(false);
-      }
-      user.setUpdatedAt(now);
-      dbClient.userDao().update(dbSession, user);
-    }
-  }
-
-  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;
-  }
-
-  private void markAsExecuted(DbSession dbSession) {
-    dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(TEMPLATE_KEY, ONE_SHOT_TASK_TYPE), dbSession);
-  }
-
-  @Override
-  public void stop() {
-    // Nothing to do
-  }
-}
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
deleted file mode 100644 (file)
index 3de4c5f..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact 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.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;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.user.UserDao;
-import org.sonar.db.user.UserDto;
-import org.sonar.db.user.UserTesting;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.db.loadedtemplate.LoadedTemplateDto.ONE_SHOT_TASK_TYPE;
-
-public class FeedUsersLocalStartupTaskTest {
-
-  static final long NOW = 20000000L;
-  static final long PAST = 10000000L;
-
-  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
-  public LogTester logTester = new LogTester();
-
-  @Rule
-  public DbTester dbTester = DbTester.create(system2);
-
-  DbClient dbClient = dbTester.getDbClient();
-
-  DbSession dbSession = dbTester.getSession();
-
-  UserDao userDao = dbClient.userDao();
-
-  Settings settings = new Settings();
-
-  FeedUsersLocalStartupTask underTest;
-
-  @Before
-  public void setUp() throws Exception {
-    when(system2.now()).thenReturn(NOW);
-  }
-
-  @Test
-  public void set_user_local_when_id_provider_is_sonarqube_and_realm_exists_and_local_users_property_contains_user_login() throws Exception {
-    initTaskWithRealm();
-    settings.setProperty("sonar.security.realm", REALM_NAME);
-    settings.setProperty("sonar.security.localUsers", USER1_LOGIN);
-    UserDto user = addUser(USER1_LOGIN, false, "sonarqube");
-
-    underTest.start();
-
-    verifyUserIsUpdated(user.getId(), true);
-    verifyLogAboutRemovalOfLocalUsersProperty();
-  }
-
-  @Test
-  public void set_user_as_not_local_when_id_provider_is_sonarqube_and_ream_exists_and_no_local_users_property() throws Exception {
-    initTaskWithRealm();
-    settings.setProperty("sonar.security.realm", REALM_NAME);
-    UserDto user = addUser(USER1_LOGIN, false, "sonarqube");
-
-    underTest.start();
-
-    verifyUserIsUpdated(user.getId(), false);
-    verifyEmptyLog();
-  }
-
-  @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 {
-    initTaskWithRealm();
-    settings.setProperty("sonar.security.realm", REALM_NAME);
-    settings.setProperty("sonar.security.localUsers", USER2_LOGIN);
-    UserDto user = addUser(USER1_LOGIN, true, "sonarqube");
-
-    underTest.start();
-
-    verifyUserIsUpdated(user.getId(), false);
-    verifyLogAboutRemovalOfLocalUsersProperty();
-  }
-
-  @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");
-
-    underTest.start();
-
-    verifyUserIsUpdated(user.getId(), true);
-    verifyEmptyLog();
-  }
-
-  @Test
-  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();
-
-    verifyUserIsUpdated(user.getId(), false);
-    verifyEmptyLog();
-  }
-
-  @Test
-  public void does_not_update_removed_user() throws Exception {
-    initTaskWithRealm();
-    settings.setProperty("sonar.security.realm", REALM_NAME);
-
-    UserDto user = UserTesting.newUserDto()
-      .setLogin(USER1_LOGIN)
-      .setActive(false)
-      .setLocal(false)
-      .setCreatedAt(PAST)
-      .setUpdatedAt(PAST);
-    userDao.insert(dbSession, user);
-    dbSession.commit();
-
-    underTest.start();
-
-    UserDto userReloaded = userDao.selectUserById(dbSession, user.getId());
-    assertThat(userReloaded.isLocal()).isFalse();
-    assertThat(userReloaded.getUpdatedAt()).isEqualTo(PAST);
-    verifyTaskIsRegistered();
-  }
-
-  @Test
-  public void does_nothing_when_task_has_already_been_executed() throws Exception {
-    initTaskWithRealm();
-    settings.setProperty("sonar.security.realm", REALM_NAME);
-    settings.setProperty("sonar.security.localUsers", USER1_LOGIN);
-    UserDto user = addUser(USER1_LOGIN, false, "github");
-
-    underTest.start();
-    verifyLogAboutRemovalOfLocalUsersProperty();
-
-    logTester.clear();
-    UserDto userReloaded = userDao.selectUserById(dbSession, user.getId());
-    assertThat(userReloaded.getUpdatedAt()).isEqualTo(NOW);
-    verifyTaskIsRegistered();
-
-    when(system2.now()).thenReturn(NOW + 1000L);
-
-    underTest.start();
-    userReloaded = userDao.selectUserById(dbSession, user.getId());
-    assertThat(userReloaded.getUpdatedAt()).isEqualTo(NOW);
-    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)
-      .setActive(true)
-      .setLocal(local)
-      .setExternalIdentityProvider(externalIdentityProvider)
-      .setExternalIdentity(login)
-      .setCreatedAt(PAST)
-      .setUpdatedAt(PAST);
-    userDao.insert(dbSession, user);
-    dbSession.commit();
-    return user;
-  }
-
-  private void verifyUserIsUpdated(long userId, boolean expectedLocal) {
-    UserDto userReloaded = userDao.selectUserById(dbSession, userId);
-    assertThat(userReloaded.isLocal()).isEqualTo(expectedLocal);
-    assertThat(userReloaded.getUpdatedAt()).isEqualTo(NOW);
-    verifyTaskIsRegistered();
-  }
-
-  private void verifyTaskIsRegistered() {
-    assertThat(dbClient.loadedTemplateDao().countByTypeAndKey(ONE_SHOT_TASK_TYPE, "UpdateUsersLocal")).isEqualTo(1);
-  }
-
-  private void verifyLogAboutRemovalOfLocalUsersProperty() {
-    assertThat(logTester.logs(LoggerLevel.INFO)).containsOnly(
-      "NOTE : The property 'sonar.security.localUsers' is now no more needed, you can safely remove it.");
-  }
-
-  private void verifyEmptyLog() {
-    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;
-  }
-}
index d0728366983facd1adeb6feb1b7b6ba9a26d0cdb..5c173cae78d11f3a840ebcc75472a9c569b5cf23 100644 (file)
@@ -146,14 +146,6 @@ public class CorePropertyDefinitions {
         .type(PropertyType.BOOLEAN)
         .defaultValue(String.valueOf(false))
         .build(),
-      PropertyDefinition.builder(CoreProperties.CORE_AUTHENTICATOR_LOCAL_USERS)
-        .name("Local/technical users")
-        .description("Comma separated list of user logins that will always be authenticated using SonarQube database. "
-          + "When using the LDAP plugin, for these accounts, the user attributes (name, email, ...) are not re-synchronized")
-        .type(PropertyType.STRING)
-        .multiValues(true)
-        .defaultValue("admin")
-        .build(),
       PropertyDefinition.builder(CoreProperties.SCM_DISABLED_KEY)
         .name("Disable the SCM Sensor")
         .description("Disable the retrieval of blame information from Source Control Manager")