import org.sonar.db.DbSession; | import org.sonar.db.DbSession; | ||||
import org.sonar.db.ResultSetIterator; | import org.sonar.db.ResultSetIterator; | ||||
import org.sonar.server.security.SecurityStandards; | import org.sonar.server.security.SecurityStandards; | ||||
import org.sonar.server.security.SecurityStandards.SQCategory; | |||||
import static com.google.common.base.Preconditions.checkArgument; | import static com.google.common.base.Preconditions.checkArgument; | ||||
import static java.util.stream.Collectors.toList; | |||||
import static org.sonar.api.utils.DateUtils.longToDate; | import static org.sonar.api.utils.DateUtils.longToDate; | ||||
import static org.sonar.db.DatabaseUtils.getLong; | import static org.sonar.db.DatabaseUtils.getLong; | ||||
import static org.sonar.db.rule.RuleDefinitionDto.deserializeSecurityStandardsString; | import static org.sonar.db.rule.RuleDefinitionDto.deserializeSecurityStandardsString; | ||||
doc.setOwaspTop10(securityStandards.getOwaspTop10()); | doc.setOwaspTop10(securityStandards.getOwaspTop10()); | ||||
doc.setCwe(securityStandards.getCwe()); | doc.setCwe(securityStandards.getCwe()); | ||||
doc.setSansTop25(securityStandards.getSansTop25()); | doc.setSansTop25(securityStandards.getSansTop25()); | ||||
doc.setSonarSourceSecurityCategories(securityStandards.getSq()); | |||||
doc.setSonarSourceSecurityCategories(securityStandards.getSq().stream().map(SQCategory::getKey).collect(toList())); | |||||
return doc; | return doc; | ||||
} | } | ||||
import org.sonar.markdown.Markdown; | import org.sonar.markdown.Markdown; | ||||
import org.sonar.server.es.BaseDoc; | import org.sonar.server.es.BaseDoc; | ||||
import org.sonar.server.security.SecurityStandards; | import org.sonar.server.security.SecurityStandards; | ||||
import org.sonar.server.security.SecurityStandards.SQCategory; | |||||
import static java.util.stream.Collectors.toList; | |||||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE; | import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE; | ||||
.setCwe(securityStandards.getCwe()) | .setCwe(securityStandards.getCwe()) | ||||
.setOwaspTop10(securityStandards.getOwaspTop10()) | .setOwaspTop10(securityStandards.getOwaspTop10()) | ||||
.setSansTop25(securityStandards.getSansTop25()) | .setSansTop25(securityStandards.getSansTop25()) | ||||
.setSonarSourceSecurityCategories(securityStandards.getSq()) | |||||
.setSonarSourceSecurityCategories(securityStandards.getSq().stream().map(SQCategory::getKey).collect(toList())) | |||||
.setName(dto.getName()) | .setName(dto.getName()) | ||||
.setRuleKey(dto.getPluginRuleKey()) | .setRuleKey(dto.getPluginRuleKey()) | ||||
.setSeverity(dto.getSeverityAsString()) | .setSeverity(dto.getSeverityAsString()) |
*/ | */ | ||||
package org.sonar.server.security; | package org.sonar.server.security; | ||||
import com.google.common.collect.ImmutableList; | |||||
import com.google.common.collect.ImmutableMap; | import com.google.common.collect.ImmutableMap; | ||||
import com.google.common.collect.ImmutableSet; | import com.google.common.collect.ImmutableSet; | ||||
import com.google.common.collect.Ordering; | import com.google.common.collect.Ordering; | ||||
import java.util.Arrays; | |||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.HashSet; | import java.util.HashSet; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Objects; | import java.util.Objects; | ||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.stream.Collectors; | |||||
import javax.annotation.concurrent.Immutable; | import javax.annotation.concurrent.Immutable; | ||||
import org.sonar.core.util.stream.MoreCollectors; | import org.sonar.core.util.stream.MoreCollectors; | ||||
SANS_TOP_25_RISKY_RESOURCE, RISKY_CWE, | SANS_TOP_25_RISKY_RESOURCE, RISKY_CWE, | ||||
SANS_TOP_25_POROUS_DEFENSES, POROUS_CWE); | SANS_TOP_25_POROUS_DEFENSES, POROUS_CWE); | ||||
public static final Map<String, Set<String>> CWES_BY_SQ_CATEGORY = ImmutableMap.<String, Set<String>>builder() | |||||
.put("sql-injection", ImmutableSet.of("89", "564")) | |||||
.put("command-injection", ImmutableSet.of("77", "78", "88", "214")) | |||||
.put("path-traversal-injection", ImmutableSet.of("22")) | |||||
.put("ldap-injection", ImmutableSet.of("90")) | |||||
.put("xpath-injection", ImmutableSet.of("643")) | |||||
.put("rce", ImmutableSet.of("94", "95")) | |||||
.put("dos", ImmutableSet.of("400", "624")) | |||||
.put("ssrf", ImmutableSet.of("918")) | |||||
.put("csrf", ImmutableSet.of("352")) | |||||
.put("xss", ImmutableSet.of("79", "80", "81", "82", "83", "84", "85", "86", "87")) | |||||
.put("log-injection", ImmutableSet.of("117")) | |||||
.put("http-response-splitting", ImmutableSet.of("113")) | |||||
.put("open-redirect", ImmutableSet.of("601")) | |||||
.put("xxe", ImmutableSet.of("611", "827")) | |||||
.put("object-injection", ImmutableSet.of("134", "470", "502")) | |||||
.put("weak-cryptography", ImmutableSet.of("295", "297", "321", "322", "323", "324", "325", "326", "327", "328", "330", "780")) | |||||
.put("auth", ImmutableSet.of("798", "640", "620", "549", "522", "521", "263", "262", "261", "259", "284")) | |||||
.put("insecure-conf", ImmutableSet.of("102", "215", "311", "315", "346", "614", "489", "942")) | |||||
.put("file-manipulation", ImmutableSet.of("97", "73")) | |||||
public enum SQCategory { | |||||
SQL_INJECTION("sql-injection"), | |||||
COMMAND_INJECTION("command-injection"), | |||||
PATH_TRAVERSAL_INJECTION("path-traversal-injection"), | |||||
LDAP_INJECTION("ldap-injection"), | |||||
XPATH_INJECT("xpath-injection"), | |||||
RCE("rce"), | |||||
DOS("dos"), | |||||
SSRF("ssrf"), | |||||
CSRF("csrf"), | |||||
XSS("xss"), | |||||
LOG_INJECTION("log-injection"), | |||||
HTTP_RESPONSE_SPLITTING("http-response-splitting"), | |||||
OPEN_REDIRECT("open-redirect"), | |||||
XXE("xxe"), | |||||
OBJECT_INJECTION("object-injection"), | |||||
WEAK_CRYPTOGRAPHY("weak-cryptography"), | |||||
AUTH("auth"), | |||||
INSECURE_CONF("insecure-conf"), | |||||
FILE_MANIPULATION("file-manipulation"), | |||||
OTHERS("others"); | |||||
private final String key; | |||||
SQCategory(String key) { | |||||
this.key = key; | |||||
} | |||||
public String getKey() { | |||||
return key; | |||||
} | |||||
} | |||||
public static final Map<SQCategory, Set<String>> CWES_BY_SQ_CATEGORY = ImmutableMap.<SQCategory, Set<String>>builder() | |||||
.put(SQCategory.SQL_INJECTION, ImmutableSet.of("89", "564")) | |||||
.put(SQCategory.COMMAND_INJECTION, ImmutableSet.of("77", "78", "88", "214")) | |||||
.put(SQCategory.PATH_TRAVERSAL_INJECTION, ImmutableSet.of("22")) | |||||
.put(SQCategory.LDAP_INJECTION, ImmutableSet.of("90")) | |||||
.put(SQCategory.XPATH_INJECT, ImmutableSet.of("643")) | |||||
.put(SQCategory.RCE, ImmutableSet.of("94", "95")) | |||||
.put(SQCategory.DOS, ImmutableSet.of("400", "624")) | |||||
.put(SQCategory.SSRF, ImmutableSet.of("918")) | |||||
.put(SQCategory.CSRF, ImmutableSet.of("352")) | |||||
.put(SQCategory.XSS, ImmutableSet.of("79", "80", "81", "82", "83", "84", "85", "86", "87")) | |||||
.put(SQCategory.LOG_INJECTION, ImmutableSet.of("117")) | |||||
.put(SQCategory.HTTP_RESPONSE_SPLITTING, ImmutableSet.of("113")) | |||||
.put(SQCategory.OPEN_REDIRECT, ImmutableSet.of("601")) | |||||
.put(SQCategory.XXE, ImmutableSet.of("611", "827")) | |||||
.put(SQCategory.OBJECT_INJECTION, ImmutableSet.of("134", "470", "502")) | |||||
.put(SQCategory.WEAK_CRYPTOGRAPHY, ImmutableSet.of("295", "297", "321", "322", "323", "324", "325", "326", "327", "328", "330", "780")) | |||||
.put(SQCategory.AUTH, ImmutableSet.of("798", "640", "620", "549", "522", "521", "263", "262", "261", "259", "284")) | |||||
.put(SQCategory.INSECURE_CONF, ImmutableSet.of("102", "215", "311", "315", "346", "614", "489", "942")) | |||||
.put(SQCategory.FILE_MANIPULATION, ImmutableSet.of("97", "73")) | |||||
.build(); | .build(); | ||||
public static final String SQ_OTHER_CATEGORY = "others"; | |||||
public static final Set<String> SQ_CATEGORIES = ImmutableSet.<String>builder().addAll(CWES_BY_SQ_CATEGORY.keySet()).add(SQ_OTHER_CATEGORY).build(); | |||||
public static final Ordering<String> SQ_CATEGORIES_ORDERING = Ordering.explicit( | |||||
ImmutableList.<String>builder().addAll(CWES_BY_SQ_CATEGORY.keySet()).add(SQ_OTHER_CATEGORY).build()); | |||||
public static final Ordering<String> SQ_CATEGORY_KEYS_ORDERING = Ordering.explicit(Arrays.stream(SQCategory.values()).map(SQCategory::getKey).collect(Collectors.toList())); | |||||
private final Set<String> standards; | private final Set<String> standards; | ||||
private final Set<String> cwe; | private final Set<String> cwe; | ||||
private final Set<String> owaspTop10; | private final Set<String> owaspTop10; | ||||
private final Set<String> sansTop25; | private final Set<String> sansTop25; | ||||
private final Set<String> sq; | |||||
private final Set<SQCategory> sq; | |||||
private SecurityStandards(Set<String> standards, Set<String> cwe, Set<String> owaspTop10, Set<String> sansTop25, Set<String> sq) { | |||||
private SecurityStandards(Set<String> standards, Set<String> cwe, Set<String> owaspTop10, Set<String> sansTop25, Set<SQCategory> sq) { | |||||
this.standards = standards; | this.standards = standards; | ||||
this.cwe = cwe; | this.cwe = cwe; | ||||
this.owaspTop10 = owaspTop10; | this.owaspTop10 = owaspTop10; | ||||
return sansTop25; | return sansTop25; | ||||
} | } | ||||
public Set<String> getSq() { | |||||
public Set<SQCategory> getSq() { | |||||
return sq; | return sq; | ||||
} | } | ||||
Set<String> owaspTop10 = toOwaspTop10(standards); | Set<String> owaspTop10 = toOwaspTop10(standards); | ||||
Set<String> cwe = toCwe(standards); | Set<String> cwe = toCwe(standards); | ||||
Set<String> sansTop25 = toSansTop25(cwe); | Set<String> sansTop25 = toSansTop25(cwe); | ||||
Set<String> sq = toSonarSourceSecurityCategories(cwe); | |||||
Set<SQCategory> sq = toSQCategories(cwe); | |||||
return new SecurityStandards(standards, cwe, owaspTop10, sansTop25, sq); | return new SecurityStandards(standards, cwe, owaspTop10, sansTop25, sq); | ||||
} | } | ||||
.collect(MoreCollectors.toSet()); | .collect(MoreCollectors.toSet()); | ||||
} | } | ||||
private static Set<String> toSonarSourceSecurityCategories(Collection<String> cwe) { | |||||
Set<String> result = CWES_BY_SQ_CATEGORY | |||||
private static Set<SQCategory> toSQCategories(Collection<String> cwe) { | |||||
Set<SQCategory> result = CWES_BY_SQ_CATEGORY | |||||
.keySet() | .keySet() | ||||
.stream() | .stream() | ||||
.filter(k -> cwe.stream().anyMatch(CWES_BY_SQ_CATEGORY.get(k)::contains)) | .filter(k -> cwe.stream().anyMatch(CWES_BY_SQ_CATEGORY.get(k)::contains)) | ||||
.collect(MoreCollectors.toSet()); | .collect(MoreCollectors.toSet()); | ||||
return result.isEmpty() ? singleton(SQ_OTHER_CATEGORY) : result; | |||||
return result.isEmpty() ? singleton(SQCategory.OTHERS) : result; | |||||
} | } | ||||
} | } |
import org.sonar.server.permission.index.AuthorizationScope; | import org.sonar.server.permission.index.AuthorizationScope; | ||||
import org.sonar.server.permission.index.IndexPermissions; | import org.sonar.server.permission.index.IndexPermissions; | ||||
import org.sonar.server.security.SecurityStandards; | import org.sonar.server.security.SecurityStandards; | ||||
import org.sonar.server.security.SecurityStandards.SQCategory; | |||||
import static java.util.Arrays.asList; | import static java.util.Arrays.asList; | ||||
import static java.util.Collections.emptyList; | import static java.util.Collections.emptyList; | ||||
assertThat(doc.getCwe()).containsExactlyInAnyOrder(SecurityStandards.UNKNOWN_STANDARD); | assertThat(doc.getCwe()).containsExactlyInAnyOrder(SecurityStandards.UNKNOWN_STANDARD); | ||||
assertThat(doc.getOwaspTop10()).isEmpty(); | assertThat(doc.getOwaspTop10()).isEmpty(); | ||||
assertThat(doc.getSansTop25()).isEmpty(); | assertThat(doc.getSansTop25()).isEmpty(); | ||||
assertThat(doc.getSonarSourceSecurityCategories()).containsOnly(SecurityStandards.SQ_OTHER_CATEGORY); | |||||
assertThat(doc.getSonarSourceSecurityCategories()).containsOnly(SQCategory.OTHERS.getKey()); | |||||
} | } | ||||
@Test | @Test |
import com.google.common.base.Preconditions; | import com.google.common.base.Preconditions; | ||||
import com.google.common.collect.Maps; | import com.google.common.collect.Maps; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Arrays; | |||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Date; | import java.util.Date; | ||||
import org.sonar.server.permission.index.AuthorizationDoc; | import org.sonar.server.permission.index.AuthorizationDoc; | ||||
import org.sonar.server.permission.index.WebAuthorizationTypeSupport; | import org.sonar.server.permission.index.WebAuthorizationTypeSupport; | ||||
import org.sonar.server.security.SecurityStandards; | import org.sonar.server.security.SecurityStandards; | ||||
import org.sonar.server.security.SecurityStandards.SQCategory; | |||||
import org.sonar.server.user.UserSession; | import org.sonar.server.user.UserSession; | ||||
import org.sonar.server.view.index.ViewIndexDefinition; | import org.sonar.server.view.index.ViewIndexDefinition; | ||||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION; | import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION; | ||||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES; | import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES; | ||||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE; | import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE; | ||||
import static org.sonar.server.security.SecurityStandards.SQ_CATEGORIES; | |||||
import static org.sonar.server.view.index.ViewIndexDefinition.TYPE_VIEW; | import static org.sonar.server.view.index.ViewIndexDefinition.TYPE_VIEW; | ||||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_AUTHORS; | import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_AUTHORS; | ||||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT; | import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT; | ||||
public List<SecurityStandardCategoryStatistics> getSansTop25Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | public List<SecurityStandardCategoryStatistics> getSansTop25Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | ||||
SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | ||||
Stream.of(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES) | Stream.of(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES) | ||||
.forEach(sansCategory -> request.addAggregation(createAggregation(FIELD_ISSUE_SANS_TOP_25, sansCategory, includeCwe, Optional.of(SecurityStandards.CWES_BY_SANS_TOP_25)))); | |||||
.forEach(sansCategory -> request.addAggregation(newSecurityReportSubAggregations( | |||||
AggregationBuilders.filter(sansCategory, boolQuery().filter(termQuery(FIELD_ISSUE_SANS_TOP_25, sansCategory))), | |||||
includeCwe, | |||||
Optional.ofNullable(SecurityStandards.CWES_BY_SANS_TOP_25.get(sansCategory))))); | |||||
return processSecurityReportSearchResults(request, includeCwe); | return processSecurityReportSearchResults(request, includeCwe); | ||||
} | } | ||||
public List<SecurityStandardCategoryStatistics> getSonarSourceReport(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | public List<SecurityStandardCategoryStatistics> getSonarSourceReport(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | ||||
SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | ||||
SQ_CATEGORIES.forEach(sonarsourceCategory -> request.addAggregation( | |||||
createAggregation(FIELD_ISSUE_SONARSOURCE_SECURITY, sonarsourceCategory, includeCwe, Optional.of(SecurityStandards.CWES_BY_SQ_CATEGORY)))); | |||||
Arrays.stream(SQCategory.values()) | |||||
.forEach(sonarsourceCategory -> request.addAggregation( | |||||
newSecurityReportSubAggregations( | |||||
AggregationBuilders.filter(sonarsourceCategory.getKey(), boolQuery().filter(termQuery(FIELD_ISSUE_SONARSOURCE_SECURITY, sonarsourceCategory.getKey()))), | |||||
includeCwe, | |||||
Optional.ofNullable(SecurityStandards.CWES_BY_SQ_CATEGORY.get(sonarsourceCategory))))); | |||||
return processSecurityReportSearchResults(request, includeCwe); | return processSecurityReportSearchResults(request, includeCwe); | ||||
} | } | ||||
public List<SecurityStandardCategoryStatistics> getOwaspTop10Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | public List<SecurityStandardCategoryStatistics> getOwaspTop10Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | ||||
SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | ||||
IntStream.rangeClosed(1, 10).mapToObj(i -> "a" + i) | IntStream.rangeClosed(1, 10).mapToObj(i -> "a" + i) | ||||
.forEach(owaspCategory -> request.addAggregation(createAggregation(FIELD_ISSUE_OWASP_TOP_10, owaspCategory, includeCwe, Optional.empty()))); | |||||
.forEach(owaspCategory -> request.addAggregation( | |||||
newSecurityReportSubAggregations( | |||||
AggregationBuilders.filter(owaspCategory, boolQuery().filter(termQuery(FIELD_ISSUE_OWASP_TOP_10, owaspCategory))), | |||||
includeCwe, | |||||
Optional.empty()))); | |||||
return processSecurityReportSearchResults(request, includeCwe); | return processSecurityReportSearchResults(request, includeCwe); | ||||
} | } | ||||
private static AggregationBuilder createAggregation(String categoryField, String category, boolean includeCwe, Optional<Map<String, Set<String>>> categoryToCwesMap) { | |||||
return addSecurityReportSubAggregations(AggregationBuilders | |||||
.filter(category, boolQuery() | |||||
.filter(termQuery(categoryField, category))), | |||||
includeCwe, categoryToCwesMap.map(m -> m.get(category))); | |||||
} | |||||
private static List<SecurityStandardCategoryStatistics> processSecurityReportSearchResults(SearchRequestBuilder request, boolean includeCwe) { | private static List<SecurityStandardCategoryStatistics> processSecurityReportSearchResults(SearchRequestBuilder request, boolean includeCwe) { | ||||
SearchResponse response = request.get(); | SearchResponse response = request.get(); | ||||
return response.getAggregations().asList().stream() | return response.getAggregations().asList().stream() | ||||
reviewedSecurityHotspots, children); | reviewedSecurityHotspots, children); | ||||
} | } | ||||
private static AggregationBuilder addSecurityReportSubAggregations(AggregationBuilder categoriesAggs, boolean includeCwe, Optional<Set<String>> cwesInCategory) { | |||||
private static AggregationBuilder newSecurityReportSubAggregations(AggregationBuilder categoriesAggs, boolean includeCwe, Optional<Set<String>> cwesInCategory) { | |||||
AggregationBuilder aggregationBuilder = addSecurityReportIssueCountAggregations(categoriesAggs); | AggregationBuilder aggregationBuilder = addSecurityReportIssueCountAggregations(categoriesAggs); | ||||
if (includeCwe) { | if (includeCwe) { | ||||
final TermsAggregationBuilder cwesAgg = AggregationBuilders.terms(AGG_CWES) | final TermsAggregationBuilder cwesAgg = AggregationBuilders.terms(AGG_CWES) | ||||
cwesInCategory.ifPresent(set -> { | cwesInCategory.ifPresent(set -> { | ||||
cwesAgg.includeExclude(new IncludeExclude(set.toArray(new String[0]), new String[0])); | cwesAgg.includeExclude(new IncludeExclude(set.toArray(new String[0]), new String[0])); | ||||
}); | }); | ||||
categoriesAggs | |||||
.subAggregation(addSecurityReportIssueCountAggregations(cwesAgg)); | |||||
categoriesAggs.subAggregation(addSecurityReportIssueCountAggregations(cwesAgg)); | |||||
} | } | ||||
return aggregationBuilder; | return aggregationBuilder; | ||||
} | } |
import java.util.Map; | import java.util.Map; | ||||
import java.util.Optional; | import java.util.Optional; | ||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.stream.Collectors; | |||||
import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||
import org.elasticsearch.action.search.SearchResponse; | import org.elasticsearch.action.search.SearchResponse; | ||||
import org.elasticsearch.search.SearchHit; | import org.elasticsearch.search.SearchHit; | ||||
import org.sonar.server.issue.index.IssueIndex; | import org.sonar.server.issue.index.IssueIndex; | ||||
import org.sonar.server.issue.index.IssueQuery; | import org.sonar.server.issue.index.IssueQuery; | ||||
import org.sonar.server.issue.index.IssueQueryFactory; | import org.sonar.server.issue.index.IssueQueryFactory; | ||||
import org.sonar.server.security.SecurityStandards; | |||||
import org.sonar.server.security.SecurityStandards.SQCategory; | |||||
import org.sonar.server.user.UserSession; | import org.sonar.server.user.UserSession; | ||||
import org.sonarqube.ws.Issues.SearchWsResponse; | import org.sonarqube.ws.Issues.SearchWsResponse; | ||||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION; | import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION; | ||||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES; | import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES; | ||||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE; | import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE; | ||||
import static org.sonar.server.security.SecurityStandards.SQ_OTHER_CATEGORY; | |||||
import static org.sonar.server.security.SecurityStandards.UNKNOWN_STANDARD; | import static org.sonar.server.security.SecurityStandards.UNKNOWN_STANDARD; | ||||
import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_BRANCH_EXAMPLE_001; | ||||
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; | ||||
.setDescription("Comma-separated list of CWE identifiers. Use '" + UNKNOWN_STANDARD + "' to select issues not associated to any CWE.") | .setDescription("Comma-separated list of CWE identifiers. Use '" + UNKNOWN_STANDARD + "' to select issues not associated to any CWE.") | ||||
.setExampleValue("12,125," + UNKNOWN_STANDARD); | .setExampleValue("12,125," + UNKNOWN_STANDARD); | ||||
action.createParam(PARAM_SONARSOURCE_SECURITY) | action.createParam(PARAM_SONARSOURCE_SECURITY) | ||||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SQ_OTHER_CATEGORY + "' to select issues not associated" + | |||||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SQCategory.OTHERS.getKey() + "' to select issues not associated" + | |||||
" with any category") | " with any category") | ||||
.setSince("7.8") | .setSince("7.8") | ||||
.setPossibleValues(SecurityStandards.SQ_CATEGORIES); | |||||
.setPossibleValues(Arrays.stream(SQCategory.values()).map(SQCategory::getKey).collect(Collectors.toList())); | |||||
action.createParam(DEPRECATED_PARAM_AUTHORS) | action.createParam(DEPRECATED_PARAM_AUTHORS) | ||||
.setDeprecatedSince("7.7") | .setDeprecatedSince("7.7") | ||||
.setDescription("This parameter is deprecated, please use '%s' instead", PARAM_AUTHOR) | .setDescription("This parameter is deprecated, please use '%s' instead", PARAM_AUTHOR) |
*/ | */ | ||||
package org.sonar.server.rule.ws; | package org.sonar.server.rule.ws; | ||||
import java.util.Arrays; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Objects; | import java.util.Objects; | ||||
import java.util.Optional; | import java.util.Optional; | ||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.stream.Collectors; | |||||
import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||
import org.sonar.api.rule.RuleStatus; | import org.sonar.api.rule.RuleStatus; | ||||
import org.sonar.api.rule.Severity; | import org.sonar.api.rule.Severity; | ||||
import org.sonar.server.qualityprofile.ActiveRuleInheritance; | import org.sonar.server.qualityprofile.ActiveRuleInheritance; | ||||
import org.sonar.server.rule.index.RuleIndexDefinition; | import org.sonar.server.rule.index.RuleIndexDefinition; | ||||
import org.sonar.server.security.SecurityStandards; | import org.sonar.server.security.SecurityStandards; | ||||
import org.sonar.server.security.SecurityStandards.SQCategory; | |||||
import org.sonar.server.user.UserSession; | import org.sonar.server.user.UserSession; | ||||
import static org.sonar.api.server.ws.WebService.Param.ASCENDING; | import static org.sonar.api.server.ws.WebService.Param.ASCENDING; | ||||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TAGS; | import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TAGS; | ||||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TEMPLATE_KEY; | import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TEMPLATE_KEY; | ||||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TYPES; | import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_TYPES; | ||||
import static org.sonar.server.security.SecurityStandards.SQ_OTHER_CATEGORY; | |||||
@ServerSide | @ServerSide | ||||
public class RuleWsSupport { | public class RuleWsSupport { | ||||
action | action | ||||
.createParam(PARAM_SONARSOURCE_SECURITY) | .createParam(PARAM_SONARSOURCE_SECURITY) | ||||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SQ_OTHER_CATEGORY + "' to select rules not associated" + | |||||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SQCategory.OTHERS.getKey() + "' to select rules not associated" + | |||||
" with any category") | " with any category") | ||||
.setSince("7.8") | .setSince("7.8") | ||||
.setPossibleValues(SecurityStandards.SQ_CATEGORIES) | |||||
.setPossibleValues(Arrays.stream(SQCategory.values()).map(SQCategory::getKey).collect(Collectors.toList())) | |||||
.setExampleValue("sql-injection,command-injection,others"); | .setExampleValue("sql-injection,command-injection,others"); | ||||
action | action |