From: Julien Lancelot Date: Fri, 28 Oct 2016 09:46:25 +0000 (+0200) Subject: SONAR-5430 Load SSO settings only at startup X-Git-Tag: 6.2-RC1~239 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fpull%2F1344%2Fhead;p=sonarqube.git SONAR-5430 Load SSO settings only at startup --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/SsoAuthenticator.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/SsoAuthenticator.java index 17aba9a45b4..3eafed1f6da 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/authentication/SsoAuthenticator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/authentication/SsoAuthenticator.java @@ -32,12 +32,15 @@ import java.util.Optional; import javax.annotation.CheckForNull; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.sonar.api.Startable; import org.sonar.api.config.Settings; import org.sonar.api.server.authentication.Display; import org.sonar.api.server.authentication.IdentityProvider; import org.sonar.api.server.authentication.UnauthorizedException; import org.sonar.api.server.authentication.UserIdentity; import org.sonar.api.utils.System2; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.BadRequestException; @@ -45,7 +48,9 @@ import static org.apache.commons.lang.StringUtils.defaultIfBlank; import static org.apache.commons.lang.time.DateUtils.addMinutes; import static org.sonar.server.user.UserUpdater.SQ_AUTHORITY; -public class SsoAuthenticator { +public class SsoAuthenticator implements Startable { + + private static final Logger LOG = Loggers.get(SsoAuthenticator.class); private static final Splitter COMA_SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings(); @@ -68,7 +73,7 @@ public class SsoAuthenticator { private static final String LAST_REFRESH_TIME_TOKEN_PARAM = "ssoLastRefreshTime"; - private static final Map DEFAULT_VALUES_BY_PARAMETERS = ImmutableMap.of( + private static final Map DEFAULT_VALUES_BY_SETTING_KEYS = ImmutableMap.of( LOGIN_HEADER_PARAM, LOGIN_HEADER_DEFAULT_VALUE, NAME_HEADER_PARAM, NAME_HEADER_DEFAULT_VALUE, EMAIL_HEADER_PARAM, EMAIL_HEADER_DEFAULT_VALUE, @@ -80,6 +85,9 @@ public class SsoAuthenticator { private final UserIdentityAuthenticator userIdentityAuthenticator; private final JwtHttpHandler jwtHttpHandler; + private boolean enabled = false; + private Map settingsByKey = new HashMap<>(); + public SsoAuthenticator(System2 system2, Settings settings, UserIdentityAuthenticator userIdentityAuthenticator, JwtHttpHandler jwtHttpHandler) { this.system2 = system2; this.settings = settings; @@ -87,6 +95,21 @@ public class SsoAuthenticator { this.jwtHttpHandler = jwtHttpHandler; } + @Override + public void start() { + if (settings.getBoolean(ENABLE_PARAM)) { + LOG.info("SSO Authentication enabled"); + enabled = true; + DEFAULT_VALUES_BY_SETTING_KEYS.entrySet() + .forEach(entry -> settingsByKey.put(entry.getKey(), defaultIfBlank(settings.getString(entry.getKey()), DEFAULT_VALUES_BY_SETTING_KEYS.get(entry.getKey())))); + } + } + + @Override + public void stop() { + // Nothing to do + } + public Optional authenticate(HttpServletRequest request, HttpServletResponse response) { try { return doAuthenticate(request, response); @@ -96,7 +119,7 @@ public class SsoAuthenticator { } private Optional doAuthenticate(HttpServletRequest request, HttpServletResponse response) { - if (!settings.getBoolean(ENABLE_PARAM)) { + if (!enabled) { return Optional.empty(); } Map headerValuesByNames = getHeaders(request); @@ -120,7 +143,7 @@ public class SsoAuthenticator { return Optional.empty(); } Date now = new Date(system2.now()); - int refreshIntervalInMinutes = Integer.parseInt(getSettingValue(REFRESH_INTERVAL_PARAM)); + int refreshIntervalInMinutes = Integer.parseInt(settingsByKey.get(REFRESH_INTERVAL_PARAM)); Long lastFreshTime = (Long) token.get().getProperties().get(LAST_REFRESH_TIME_TOKEN_PARAM); if (lastFreshTime == null || now.after(addMinutes(new Date(lastFreshTime), refreshIntervalInMinutes))) { return Optional.empty(); @@ -145,7 +168,7 @@ public class SsoAuthenticator { @CheckForNull private String getHeaderValue(Map headerValuesByNames, String settingKey) { - return headerValuesByNames.get(getSettingValue(settingKey).toLowerCase(Locale.ENGLISH)); + return headerValuesByNames.get(settingsByKey.get(settingKey).toLowerCase(Locale.ENGLISH)); } private static Map getHeaders(HttpServletRequest request) { @@ -155,11 +178,7 @@ public class SsoAuthenticator { } private boolean hasHeader(Map headerValuesByNames, String settingKey) { - return headerValuesByNames.keySet().contains(getSettingValue(settingKey).toLowerCase(Locale.ENGLISH)); - } - - private String getSettingValue(String settingKey) { - return defaultIfBlank(settings.getString(settingKey), DEFAULT_VALUES_BY_PARAMETERS.get(settingKey)); + return headerValuesByNames.keySet().contains(settingsByKey.get(settingKey).toLowerCase(Locale.ENGLISH)); } private static class SsoIdentityProvider implements IdentityProvider { diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/SsoAuthenticatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/SsoAuthenticatorTest.java index 310f9385d11..7e7ae6ec728 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/authentication/SsoAuthenticatorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/authentication/SsoAuthenticatorTest.java @@ -112,7 +112,7 @@ public class SsoAuthenticatorTest { @Test public void create_user_when_authenticating_new_user() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); HttpServletRequest request = createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, GROUPS); @@ -124,7 +124,7 @@ public class SsoAuthenticatorTest { @Test public void use_login_when_name_is_not_provided() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); underTest.authenticate(createRequest(DEFAULT_LOGIN, null, null, null), response); @@ -134,7 +134,7 @@ public class SsoAuthenticatorTest { @Test public void update_user_when_authenticating_exiting_user() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); insertUser(newUserDto().setLogin(DEFAULT_LOGIN).setName("old name").setEmail("old email"), group1); // Name, email and groups are different @@ -148,7 +148,7 @@ public class SsoAuthenticatorTest { @Test public void remove_groups_when_group_headers_is_empty() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); insertUser(DEFAULT_USER, group1); @@ -159,7 +159,7 @@ public class SsoAuthenticatorTest { @Test public void remove_groups_when_group_headers_is_null() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); insertUser(DEFAULT_USER, group1); Map headerValuesByName = new HashMap<>(); @@ -173,7 +173,7 @@ public class SsoAuthenticatorTest { @Test public void does_not_update_groups_when_no_group_headers() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); insertUser(DEFAULT_USER, group1); @@ -184,7 +184,7 @@ public class SsoAuthenticatorTest { @Test public void does_not_update_user_when_user_is_in_token_and_refresh_time_is_close() throws Exception { - enableSso(); + startWithSso(); UserDto user = insertUser(DEFAULT_USER, group1); setUserInToken(user, CLOSE_REFRESH_TIME); HttpServletRequest request = createRequest(DEFAULT_LOGIN, "new name", "new email", GROUP2); @@ -198,7 +198,7 @@ public class SsoAuthenticatorTest { @Test public void update_user_when_user_in_token_but_refresh_time_is_old() throws Exception { - enableSso(); + startWithSso(); UserDto user = insertUser(DEFAULT_USER, group1); // Refresh time was updated 6 minutes ago => more than 5 minutes setUserInToken(user, NOW - 6 * 60 * 1000L); @@ -213,7 +213,7 @@ public class SsoAuthenticatorTest { @Test public void update_user_when_user_in_token_but_no_refresh_time() throws Exception { - enableSso(); + startWithSso(); UserDto user = insertUser(DEFAULT_USER, group1); setUserInToken(user, null); HttpServletRequest request = createRequest(DEFAULT_LOGIN, "new name", "new email", GROUP2); @@ -227,8 +227,8 @@ public class SsoAuthenticatorTest { @Test public void use_refresh_time_from_settings() throws Exception { - enableSso(); settings.setProperty("sonar.sso.refreshIntervalInMinutes", "10"); + startWithSso(); UserDto user = insertUser(DEFAULT_USER, group1); // Refresh time was updated 6 minutes ago => less than 10 minutes ago so not updated setUserInToken(user, NOW - 6 * 60 * 1000L); @@ -243,7 +243,7 @@ public class SsoAuthenticatorTest { @Test public void update_user_when_login_from_token_is_different_than_login_from_request() throws Exception { - enableSso(); + startWithSso(); insertUser(DEFAULT_USER, group1); setUserInToken(DEFAULT_USER, CLOSE_REFRESH_TIME); HttpServletRequest request = createRequest("AnotherLogin", "Another name", "Another email", GROUP2); @@ -256,12 +256,12 @@ public class SsoAuthenticatorTest { @Test public void use_headers_from_settings() throws Exception { - enableSso(); - setNotUserInToken(); settings.setProperty("sonar.sso.loginHeader", "head-login"); settings.setProperty("sonar.sso.nameHeader", "head-name"); settings.setProperty("sonar.sso.emailHeader", "head-email"); settings.setProperty("sonar.sso.groupsHeader", "head-groups"); + startWithSso(); + setNotUserInToken(); HttpServletRequest request = createRequest(ImmutableMap.of("head-login", DEFAULT_LOGIN, "head-name", DEFAULT_NAME, "head-email", DEFAULT_EMAIL, "head-groups", GROUPS)); underTest.authenticate(request, response); @@ -271,12 +271,12 @@ public class SsoAuthenticatorTest { @Test public void detect_group_header_even_with_wrong_case() throws Exception { - enableSso(); - setNotUserInToken(); settings.setProperty("sonar.sso.loginHeader", "login"); settings.setProperty("sonar.sso.nameHeader", "name"); settings.setProperty("sonar.sso.emailHeader", "email"); settings.setProperty("sonar.sso.groupsHeader", "Groups"); + startWithSso(); + setNotUserInToken(); HttpServletRequest request = createRequest(ImmutableMap.of("login", DEFAULT_LOGIN, "name", DEFAULT_NAME, "email", DEFAULT_EMAIL, "groups", GROUPS)); underTest.authenticate(request, response); @@ -286,7 +286,7 @@ public class SsoAuthenticatorTest { @Test public void trim_groups() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); HttpServletRequest request = createRequest(DEFAULT_LOGIN, null, null, " dev , admin "); @@ -297,7 +297,7 @@ public class SsoAuthenticatorTest { @Test public void does_not_authenticate_when_no_header() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); underTest.authenticate(createRequest(Collections.emptyMap()), response); @@ -308,7 +308,7 @@ public class SsoAuthenticatorTest { @Test public void does_not_authenticate_when_not_enabled() throws Exception { - settings.setProperty("sonar.sso.enable", false); + startWithoutSso(); underTest.authenticate(createRequest(DEFAULT_LOGIN, DEFAULT_NAME, DEFAULT_EMAIL, GROUPS), response); @@ -318,7 +318,7 @@ public class SsoAuthenticatorTest { @Test public void throw_UnauthorizedException_when_BadRequestException_is_generated() throws Exception { - enableSso(); + startWithSso(); setNotUserInToken(); expectedException.expect(UnauthorizedException.class); @@ -326,8 +326,14 @@ public class SsoAuthenticatorTest { underTest.authenticate(createRequest("invalid login", DEFAULT_NAME, DEFAULT_EMAIL, GROUPS), response); } - private void enableSso() { + private void startWithSso() { settings.setProperty("sonar.sso.enable", true); + underTest.start(); + } + + private void startWithoutSso() { + settings.setProperty("sonar.sso.enable", false); + underTest.start(); } private void setUserInToken(UserDto user, @Nullable Long lastRefreshTime) {