From: alain <108417558+alain-kermis-sonarsource@users.noreply.github.com> Date: Thu, 20 Oct 2022 09:29:15 +0000 (+0200) Subject: SONAR-17456 Fix SSF-326 X-Git-Tag: 9.8.0.63668~237 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=690cc97185196f8efa976425878cbfd569c74f3c;p=sonarqube.git SONAR-17456 Fix SSF-326 --- diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java index 19306b34ea7..ed824818842 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/plugins/ws/InstalledAction.java @@ -35,12 +35,14 @@ import org.sonar.api.server.ws.WebService; import org.sonar.core.platform.PluginInfo; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.permission.GlobalPermission; import org.sonar.db.plugin.PluginDto; import org.sonar.db.plugin.PluginDto.Type; import org.sonar.core.plugin.PluginType; import org.sonar.server.plugins.ServerPlugin; import org.sonar.server.plugins.ServerPluginRepository; import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.user.UserSession; import org.sonar.updatecenter.common.Plugin; import org.sonarqube.ws.Plugins.InstalledPluginsWsResponse; import org.sonarqube.ws.Plugins.PluginDetails; @@ -53,6 +55,7 @@ import static java.util.stream.Collectors.toMap; import static org.sonar.server.plugins.ws.PluginWSCommons.NAME_KEY_COMPARATOR; import static org.sonar.server.plugins.ws.PluginWSCommons.buildPluginDetails; import static org.sonar.server.plugins.ws.PluginWSCommons.compatiblePluginsByKey; +import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; import static org.sonar.server.ws.WsUtils.writeProtobuf; /** @@ -62,11 +65,13 @@ public class InstalledAction implements PluginsWsAction { private static final String FIELD_CATEGORY = "category"; private static final String PARAM_TYPE = "type"; + private final UserSession userSession; private final ServerPluginRepository serverPluginRepository; private final UpdateCenterMatrixFactory updateCenterMatrixFactory; private final DbClient dbClient; - public InstalledAction(ServerPluginRepository serverPluginRepository, UpdateCenterMatrixFactory updateCenterMatrixFactory, DbClient dbClient) { + public InstalledAction(ServerPluginRepository serverPluginRepository, UserSession userSession, UpdateCenterMatrixFactory updateCenterMatrixFactory, DbClient dbClient) { + this.userSession = userSession; this.serverPluginRepository = serverPluginRepository; this.updateCenterMatrixFactory = updateCenterMatrixFactory; this.dbClient = dbClient; @@ -75,9 +80,11 @@ public class InstalledAction implements PluginsWsAction { @Override public void define(WebService.NewController controller) { WebService.NewAction action = controller.createAction("installed") - .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by plugin name.") + .setDescription("Get the list of all the plugins installed on the SonarQube instance, sorted by plugin name.
" + + "Requires authentication.") .setSince("5.2") .setChangelog( + new Change("9.7", "Authentication check added"), new Change("8.0", "The 'documentationPath' field is added"), new Change("7.0", "The fields 'compressedHash' and 'compressedFilename' are added"), new Change("6.6", "The 'filename' field is added"), @@ -91,7 +98,7 @@ public class InstalledAction implements PluginsWsAction { .setDescription(format("Comma-separated list of the additional fields to be returned in response. No additional field is returned by default. Possible values are:" + "", FIELD_CATEGORY)) .setSince("5.6"); action.createParam(PARAM_TYPE) @@ -103,6 +110,10 @@ public class InstalledAction implements PluginsWsAction { @Override public void handle(Request request, Response response) throws Exception { + if (!userSession.isLoggedIn() && !userSession.hasPermission(GlobalPermission.SCAN)) { + throw insufficientPrivilegesException(); + } + String typeParam = request.param(PARAM_TYPE); SortedSet installedPlugins = loadInstalledPlugins(typeParam); Map dtosByKey; diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java index 423fb7658ca..208032a9a7e 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/plugins/ws/InstalledActionTest.java @@ -41,11 +41,14 @@ import org.sonar.api.utils.System2; import org.sonar.core.platform.PluginInfo; import org.sonar.db.DbTester; import org.sonar.db.plugin.PluginDto.Type; +import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.plugins.PluginFilesAndMd5.FileAndMd5; import org.sonar.core.plugin.PluginType; import org.sonar.server.plugins.ServerPlugin; import org.sonar.server.plugins.ServerPluginRepository; import org.sonar.server.plugins.UpdateCenterMatrixFactory; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.WsActionTester; import org.sonar.updatecenter.common.Plugin; import org.sonar.updatecenter.common.UpdateCenter; @@ -54,10 +57,11 @@ import org.sonar.updatecenter.common.Version; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.sonar.test.JsonAssert.assertJson; @@ -71,10 +75,12 @@ public class InstalledActionTest { public TemporaryFolder temp = new TemporaryFolder(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); + @Rule + public UserSessionRule userSession = UserSessionRule.standalone().logIn(); private UpdateCenterMatrixFactory updateCenterMatrixFactory = mock(UpdateCenterMatrixFactory.class, RETURNS_DEEP_STUBS); private ServerPluginRepository serverPluginRepository = mock(ServerPluginRepository.class); - private InstalledAction underTest = new InstalledAction(serverPluginRepository, updateCenterMatrixFactory, db.getDbClient()); + private InstalledAction underTest = new InstalledAction(serverPluginRepository, userSession, updateCenterMatrixFactory, db.getDbClient()); private WsActionTester tester = new WsActionTester(underTest); @DataProvider @@ -486,6 +492,14 @@ public class InstalledActionTest { assertThat(response).containsOnlyOnce("name2"); } + @Test + public void fail_if_not_logged_in() { + userSession.anonymous(); + TestRequest testRequest = tester.newRequest(); + assertThatThrownBy(testRequest::execute) + .isInstanceOf(ForbiddenException.class); + } + private ServerPlugin plugin(String key, String name) throws IOException { File file = temp.newFile(); PluginInfo info = new PluginInfo(key)