From e7a50aef7c84f758801dd37d69746b395091c1ce Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 11 Feb 2021 17:01:01 +0100 Subject: [PATCH] SONAR-14442 Add 'cwe' search param to hotspot WS --- .../sonar/server/hotspot/ws/SearchAction.java | 100 +++++++++++------- .../server/hotspot/ws/SearchActionTest.java | 22 ++++ 2 files changed, 81 insertions(+), 41 deletions(-) diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java index 39237997739..befed43c494 100644 --- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java +++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/hotspot/ws/SearchAction.java @@ -106,6 +106,7 @@ public class SearchAction implements HotspotsWsAction { private static final String PARAM_OWASP_TOP_10 = "owaspTop10"; private static final String PARAM_SANS_TOP_25 = "sansTop25"; private static final String PARAM_SONARSOURCE_SECURITY = "sonarsourceSecurity"; + private static final String PARAM_CWE = "cwe"; private static final List STATUSES = ImmutableList.of(STATUS_TO_REVIEW, STATUS_REVIEWED); @@ -127,6 +128,48 @@ public class SearchAction implements HotspotsWsAction { this.system2 = system2; } + private static WsRequest toWsRequest(Request request) { + List hotspotList = request.paramAsStrings(PARAM_HOTSPOTS); + Set hotspotKeys = hotspotList != null ? ImmutableSet.copyOf(hotspotList) : ImmutableSet.of(); + List owaspTop10List = request.paramAsStrings(PARAM_OWASP_TOP_10); + Set owaspTop10 = owaspTop10List != null ? ImmutableSet.copyOf(owaspTop10List) : ImmutableSet.of(); + List sansTop25List = request.paramAsStrings(PARAM_SANS_TOP_25); + Set sansTop25 = sansTop25List != null ? ImmutableSet.copyOf(sansTop25List) : ImmutableSet.of(); + List sonarsourceSecurityList = request.paramAsStrings(PARAM_SONARSOURCE_SECURITY); + Set sonarsourceSecurity = sonarsourceSecurityList != null ? ImmutableSet.copyOf(sonarsourceSecurityList) : ImmutableSet.of(); + List cwesList = request.paramAsStrings(PARAM_CWE); + Set cwes = cwesList != null ? ImmutableSet.copyOf(cwesList) : ImmutableSet.of(); + + return new WsRequest( + request.mandatoryParamAsInt(PAGE), request.mandatoryParamAsInt(PAGE_SIZE), request.param(PARAM_PROJECT_KEY), request.param(PARAM_BRANCH), + request.param(PARAM_PULL_REQUEST), hotspotKeys, request.param(PARAM_STATUS), request.param(PARAM_RESOLUTION), + request.paramAsBoolean(PARAM_SINCE_LEAK_PERIOD), request.paramAsBoolean(PARAM_ONLY_MINE), owaspTop10, sansTop25, sonarsourceSecurity, cwes); + } + + @Override + public void handle(Request request, Response response) throws Exception { + WsRequest wsRequest = toWsRequest(request); + validateParameters(wsRequest); + try (DbSession dbSession = dbClient.openSession(false)) { + checkIfNeedIssueSync(dbSession, wsRequest); + Optional project = getAndValidateProjectOrApplication(dbSession, wsRequest); + SearchResponseData searchResponseData = searchHotspots(wsRequest, dbSession, project.orElse(null)); + loadComponents(dbSession, searchResponseData); + loadRules(dbSession, searchResponseData); + writeProtobuf(formatResponse(searchResponseData), request, response); + } + } + + private void checkIfNeedIssueSync(DbSession dbSession, WsRequest wsRequest) { + Optional projectKey = wsRequest.getProjectKey(); + if (projectKey.isPresent()) { + issueIndexSyncProgressChecker.checkIfComponentNeedIssueSync(dbSession, projectKey.get()); + } else { + // component keys not provided - asking for global + issueIndexSyncProgressChecker.checkIfIssueSyncInProgress(dbSession); + } + } + @Override public void define(WebService.NewController controller) { WebService.NewAction action = controller @@ -185,50 +228,14 @@ public class SearchAction implements HotspotsWsAction { "' to select issues not associated with any category") .setSince("8.6") .setPossibleValues(Arrays.stream(SecurityStandards.SQCategory.values()).map(SecurityStandards.SQCategory::getKey).collect(Collectors.toList())); + action.createParam(PARAM_CWE) + .setDescription("Comma-separated list of CWE numbers") + .setExampleValue("89,434,352") + .setSince("8.8"); action.setResponseExample(getClass().getResource("search-example.json")); } - @Override - public void handle(Request request, Response response) throws Exception { - WsRequest wsRequest = toWsRequest(request); - validateParameters(wsRequest); - try (DbSession dbSession = dbClient.openSession(false)) { - checkIfNeedIssueSync(dbSession, wsRequest); - Optional project = getAndValidateProjectOrApplication(dbSession, wsRequest); - SearchResponseData searchResponseData = searchHotspots(wsRequest, dbSession, project.orElse(null)); - loadComponents(dbSession, searchResponseData); - loadRules(dbSession, searchResponseData); - writeProtobuf(formatResponse(searchResponseData), request, response); - } - } - - private void checkIfNeedIssueSync(DbSession dbSession, WsRequest wsRequest) { - Optional projectKey = wsRequest.getProjectKey(); - if (projectKey.isPresent()) { - issueIndexSyncProgressChecker.checkIfComponentNeedIssueSync(dbSession, projectKey.get()); - } else { - // component keys not provided - asking for global - issueIndexSyncProgressChecker.checkIfIssueSyncInProgress(dbSession); - } - } - - private static WsRequest toWsRequest(Request request) { - List hotspotList = request.paramAsStrings(PARAM_HOTSPOTS); - Set hotspotKeys = hotspotList != null ? ImmutableSet.copyOf(hotspotList) : ImmutableSet.of(); - List owaspTop10List = request.paramAsStrings(PARAM_OWASP_TOP_10); - Set owaspTop10 = owaspTop10List != null ? ImmutableSet.copyOf(owaspTop10List) : ImmutableSet.of(); - List sansTop25List = request.paramAsStrings(PARAM_SANS_TOP_25); - Set sansTop25 = sansTop25List != null ? ImmutableSet.copyOf(sansTop25List) : ImmutableSet.of(); - List sonarsourceSecurityList = request.paramAsStrings(PARAM_SONARSOURCE_SECURITY); - Set sonarsourceSecurity = sonarsourceSecurityList != null ? ImmutableSet.copyOf(sonarsourceSecurityList) : ImmutableSet.of(); - - return new WsRequest( - request.mandatoryParamAsInt(PAGE), request.mandatoryParamAsInt(PAGE_SIZE), request.param(PARAM_PROJECT_KEY), request.param(PARAM_BRANCH), - request.param(PARAM_PULL_REQUEST), hotspotKeys, request.param(PARAM_STATUS), request.param(PARAM_RESOLUTION), - request.paramAsBoolean(PARAM_SINCE_LEAK_PERIOD), request.paramAsBoolean(PARAM_ONLY_MINE), owaspTop10, sansTop25, sonarsourceSecurity); - } - private void validateParameters(WsRequest wsRequest) { Optional projectKey = wsRequest.getProjectKey(); Optional branch = wsRequest.getBranch(); @@ -363,6 +370,10 @@ public class SearchAction implements HotspotsWsAction { builder.sonarsourceSecurity(wsRequest.getSonarsourceSecurity()); } + if (!wsRequest.getCwe().isEmpty()) { + builder.cwe(wsRequest.getCwe()); + } + IssueQuery query = builder.build(); SearchOptions searchOptions = new SearchOptions() .setPage(wsRequest.page, wsRequest.index); @@ -483,12 +494,14 @@ public class SearchAction implements HotspotsWsAction { private final Set owaspTop10; private final Set sansTop25; private final Set sonarsourceSecurity; + private final Set cwe; private WsRequest(int page, int index, @Nullable String projectKey, @Nullable String branch, @Nullable String pullRequest, Set hotspotKeys, @Nullable String status, @Nullable String resolution, @Nullable Boolean sinceLeakPeriod, - @Nullable Boolean onlyMine, Set owaspTop10, Set sansTop25, Set sonarsourceSecurity) { + @Nullable Boolean onlyMine, Set owaspTop10, Set sansTop25, Set sonarsourceSecurity, + Set cwe) { this.page = page; this.index = index; this.projectKey = projectKey; @@ -502,6 +515,7 @@ public class SearchAction implements HotspotsWsAction { this.owaspTop10 = owaspTop10; this.sansTop25 = sansTop25; this.sonarsourceSecurity = sonarsourceSecurity; + this.cwe = cwe; } int getPage() { @@ -555,6 +569,10 @@ public class SearchAction implements HotspotsWsAction { public Set getSonarsourceSecurity() { return sonarsourceSecurity; } + + public Set getCwe() { + return cwe; + } } private static final class SearchResponseData { diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java index 198fdbc078d..953350fa4e6 100644 --- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java +++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/hotspot/ws/SearchActionTest.java @@ -1338,6 +1338,28 @@ public class SearchActionTest { .containsExactly(hotspot2.getKey()); } + @Test + public void returns_hotspots_with_specified_cwes() { + ComponentDto project = dbTester.components().insertPublicProject(); + userSessionRule.registerComponents(project); + indexPermissions(); + ComponentDto file = dbTester.components().insertComponent(newFileDto(project)); + RuleDefinitionDto rule1 = newRule(SECURITY_HOTSPOT); + RuleDefinitionDto rule2 = newRule(SECURITY_HOTSPOT, r -> r.setSecurityStandards(of("cwe:117", "cwe:190"))); + RuleDefinitionDto rule3 = newRule(SECURITY_HOTSPOT, r -> r.setSecurityStandards(of("owaspTop10:a1", "cwe:601"))); + insertHotspot(project, file, rule1); + IssueDto hotspot2 = insertHotspot(project, file, rule2); + insertHotspot(project, file, rule3); + indexIssues(); + + SearchWsResponse response = newRequest(project).setParam("cwe", "117,190") + .executeProtobuf(SearchWsResponse.class); + + assertThat(response.getHotspotsList()) + .extracting(SearchWsResponse.Hotspot::getKey) + .containsExactly(hotspot2.getKey()); + } + @Test public void returns_hotspots_with_specified_owaspTop10_category() { ComponentDto project = dbTester.components().insertPublicProject(); -- 2.39.5