From 95889c7f11fa494e0432c1e64906f9d0cdef2946 Mon Sep 17 00:00:00 2001 From: Eric Hartmann Date: Fri, 8 Jun 2018 15:27:35 +0200 Subject: [PATCH] SONAR-10830 Allow passcode even if forceAuthentication is true --- .../authentication/UserSessionInitializer.java | 16 +++++++++++++--- .../UserSessionInitializerTest.java | 15 +++++++++++++++ .../tests/authorization/SystemPasscodeTest.java | 16 ++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java index f505e4d6d40..5e3fd482570 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/authentication/UserSessionInitializer.java @@ -65,12 +65,20 @@ public class UserSessionInitializer { "/api/users/identity_providers", "/api/l10n/index", LOGIN_URL, LOGOUT_URL, VALIDATE_URL); + private static final Set URL_USING_PASSCODE = ImmutableSet.of( + "/api/ce/info", "/api/ce/pause", "/api/ce/resume", "/api/system/health" + ); + private static final UrlPattern URL_PATTERN = UrlPattern.builder() .includes("/*") .excludes(staticResourcePatterns()) .excludes(SKIPPED_URLS) .build(); + private static final UrlPattern PASSCODE_URLS = UrlPattern.builder() + .includes(URL_USING_PASSCODE) + .build(); + private final Configuration config; private final ThreadLocalUserSession threadLocalSession; private final AuthenticationEvent authenticationEvent; @@ -91,7 +99,7 @@ public class UserSessionInitializer { try { // Do not set user session when url is excluded if (URL_PATTERN.matches(path)) { - loadUserSession(request, response); + loadUserSession(request, response, PASSCODE_URLS.matches(path)); } return true; } catch (AuthenticationException e) { @@ -115,13 +123,15 @@ public class UserSessionInitializer { return provider != AuthenticationEvent.Provider.LOCAL && provider != AuthenticationEvent.Provider.JWT; } - private void loadUserSession(HttpServletRequest request, HttpServletResponse response) { + private void loadUserSession(HttpServletRequest request, HttpServletResponse response, boolean usingPasscode) { UserSession session; Optional user = authenticators.authenticate(request, response); if (user.isPresent()) { session = userSessionFactory.create(user.get()); } else { - failIfAuthenticationIsRequired(); + if (!usingPasscode) { + failIfAuthenticationIsRequired(); + } session = userSessionFactory.createAnonymous(); } threadLocalSession.set(session); diff --git a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java index f52b779f7bd..de82d3b190e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/authentication/UserSessionInitializerTest.java @@ -105,6 +105,12 @@ public class UserSessionInitializerTest { assertPathIsIgnored("/api/users/identity_providers"); assertPathIsIgnored("/api/l10n/index"); + // exlude passcode urls + assertPathIsIgnoredWithAnonymousAccess("/api/ce/info"); + assertPathIsIgnoredWithAnonymousAccess("/api/ce/pause"); + assertPathIsIgnoredWithAnonymousAccess("/api/ce/resume"); + assertPathIsIgnoredWithAnonymousAccess("/api/system/health"); + // exclude static resources assertPathIsIgnored("/css/style.css"); assertPathIsIgnored("/images/logo.png"); @@ -185,6 +191,15 @@ public class UserSessionInitializerTest { reset(userSession, authenticators); } + private void assertPathIsIgnoredWithAnonymousAccess(String path) { + when(request.getRequestURI()).thenReturn(path); + + assertThat(underTest.initUserSession(request, response)).isTrue(); + + verify(userSession).set(any(UserSession.class)); + reset(userSession, authenticators); + } + private void assertPathIsNotIgnored(String path) { when(request.getRequestURI()).thenReturn(path); when(authenticators.authenticate(request, response)).thenReturn(Optional.of(user)); diff --git a/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java b/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java index b6c9d71acd9..fbdafe3697c 100644 --- a/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java +++ b/tests/src/test/java/org/sonarqube/tests/authorization/SystemPasscodeTest.java @@ -20,6 +20,7 @@ package org.sonarqube.tests.authorization; import com.sonar.orchestrator.Orchestrator; +import java.util.Arrays; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; @@ -70,6 +71,21 @@ public class SystemPasscodeTest { assertThat(response.code()).isEqualTo(401); } + @Test + public void system_access_is_granted_even_with_forceAuthentication_is_set_to_true() { + tester.settings().setGlobalSetting("sonar.forceAuthentication", "true"); + Arrays.asList("/api/ce/pause", "/api/ce/resume", "/api/system/health", "/api/system/info") + .forEach(url -> { + WsRequest request = new GetRequest("api/system/health") + .setHeader(PASSCODE_HEADER, VALID_PASSCODE); + + WsResponse response = tester.asAnonymous().wsClient().wsConnector().call(request); + assertThat(response.code()).isEqualTo(200); + } + ); + tester.settings().setGlobalSetting("sonar.forceAuthentication", "false"); + } + private static GetRequest newRequest() { return new GetRequest("api/system_passcode/check"); } -- 2.39.5