and cleanup responsibility for parsing serialized tags and security standards into table RULEStags/8.2.0.32929
@@ -19,11 +19,10 @@ | |||
*/ | |||
package org.sonar.db.rule; | |||
import java.util.Arrays; | |||
import java.util.HashSet; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import java.util.TreeSet; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
@@ -37,6 +36,8 @@ import static com.google.common.base.Preconditions.checkArgument; | |||
public class RuleDefinitionDto { | |||
private static final Splitter SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); | |||
private Integer id; | |||
private String repositoryKey; | |||
private String ruleKey; | |||
@@ -91,6 +92,26 @@ public class RuleDefinitionDto { | |||
private long createdAt; | |||
private long updatedAt; | |||
public static Set<String> deserializeTagsString(@Nullable String tags) { | |||
return deserializeStringSet(tags); | |||
} | |||
public static Set<String> deserializeSecurityStandardsString(@Nullable String securityStandards) { | |||
return deserializeStringSet(securityStandards); | |||
} | |||
private static Set<String> deserializeStringSet(@Nullable String securityStandards) { | |||
if (securityStandards == null || securityStandards.isEmpty()) { | |||
return ImmutableSet.of(); | |||
} | |||
return ImmutableSet.copyOf(SPLITTER.split(securityStandards)); | |||
} | |||
private static String serializeStringSet(@Nullable Set<String> strings) { | |||
return strings == null || strings.isEmpty() ? null : StringUtils.join(strings, ','); | |||
} | |||
public RuleKey getKey() { | |||
if (key == null) { | |||
key = RuleKey.of(getRepositoryKey(), getRuleKey()); | |||
@@ -300,7 +321,7 @@ public class RuleDefinitionDto { | |||
} | |||
public Set<String> getSystemTags() { | |||
return systemTags == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(systemTags, ','))); | |||
return deserializeTagsString(systemTags); | |||
} | |||
private String getSystemTagsField() { | |||
@@ -312,12 +333,12 @@ public class RuleDefinitionDto { | |||
} | |||
public RuleDefinitionDto setSystemTags(Set<String> tags) { | |||
this.systemTags = tags.isEmpty() ? null : StringUtils.join(tags, ','); | |||
this.systemTags = serializeStringSet(tags); | |||
return this; | |||
} | |||
public Set<String> getSecurityStandards() { | |||
return securityStandards == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(securityStandards, ','))); | |||
return deserializeSecurityStandardsString(securityStandards); | |||
} | |||
private String getSecurityStandardsField() { | |||
@@ -329,7 +350,7 @@ public class RuleDefinitionDto { | |||
} | |||
public RuleDefinitionDto setSecurityStandards(Set<String> standards) { | |||
this.securityStandards = standards.isEmpty() ? null : StringUtils.join(standards, ','); | |||
this.securityStandards = serializeStringSet(standards); | |||
return this; | |||
} | |||
@@ -19,8 +19,6 @@ | |||
*/ | |||
package org.sonar.db.rule; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Set; | |||
import javax.annotation.CheckForNull; | |||
import org.sonar.api.rule.RuleKey; | |||
@@ -49,9 +47,6 @@ public class RuleForIndexingDto { | |||
private long createdAt; | |||
private long updatedAt; | |||
private static final Splitter TAGS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); | |||
private static final Splitter SECURITY_STANDARDS_SPLITTER = TAGS_SPLITTER; | |||
public Integer getId() { | |||
return id; | |||
} | |||
@@ -88,12 +83,12 @@ public class RuleForIndexingDto { | |||
return isTemplate; | |||
} | |||
public String getSystemTags() { | |||
return systemTags; | |||
public Set<String> getSystemTags() { | |||
return RuleDefinitionDto.deserializeTagsString(systemTags); | |||
} | |||
public String getSecurityStandards() { | |||
return securityStandards; | |||
public Set<String> getSecurityStandards() { | |||
return RuleDefinitionDto.deserializeSecurityStandardsString(securityStandards); | |||
} | |||
public String getTemplateRuleKey() { | |||
@@ -140,12 +135,4 @@ public class RuleForIndexingDto { | |||
public RuleKey getRuleKey() { | |||
return RuleKey.of(repository, pluginRuleKey); | |||
} | |||
public Set<String> getSystemTagsAsSet() { | |||
return ImmutableSet.copyOf(TAGS_SPLITTER.split(systemTags == null ? "" : systemTags)); | |||
} | |||
public Set<String> getSecurityStandardsAsSet() { | |||
return ImmutableSet.copyOf(SECURITY_STANDARDS_SPLITTER.split(securityStandards == null ? "" : securityStandards)); | |||
} | |||
} |
@@ -957,8 +957,8 @@ public class RuleDaoTest { | |||
assertThat(firstRule.getStatus()).isEqualTo(r1.getStatus()); | |||
assertThat(firstRule.isExternal()).isFalse(); | |||
assertThat(firstRule.isTemplate()).isEqualTo(r1.isTemplate()); | |||
assertThat(firstRule.getSystemTagsAsSet()).isEqualTo(r1.getSystemTags()); | |||
assertThat(firstRule.getSecurityStandardsAsSet()).isEqualTo(r1.getSecurityStandards()); | |||
assertThat(firstRule.getSystemTags()).isEqualTo(r1.getSystemTags()); | |||
assertThat(firstRule.getSecurityStandards()).isEqualTo(r1.getSecurityStandards()); | |||
assertThat(firstRule.getTemplateRuleKey()).isNull(); | |||
assertThat(firstRule.getTemplateRepository()).isNull(); | |||
assertThat(firstRule.getInternalKey()).isEqualTo(r1.getConfigKey()); | |||
@@ -1036,8 +1036,8 @@ public class RuleDaoTest { | |||
assertThat(firstRule.getSeverityAsString()).isEqualTo(SeverityUtil.getSeverityFromOrdinal(r1.getSeverity())); | |||
assertThat(firstRule.getStatus()).isEqualTo(r1.getStatus()); | |||
assertThat(firstRule.isTemplate()).isEqualTo(r1.isTemplate()); | |||
assertThat(firstRule.getSystemTagsAsSet()).isEqualTo(r1.getSystemTags()); | |||
assertThat(firstRule.getSecurityStandardsAsSet()).isEqualTo(r1.getSecurityStandards()); | |||
assertThat(firstRule.getSystemTags()).isEqualTo(r1.getSystemTags()); | |||
assertThat(firstRule.getSecurityStandards()).isEqualTo(r1.getSecurityStandards()); | |||
assertThat(firstRule.getInternalKey()).isEqualTo(r1.getConfigKey()); | |||
assertThat(firstRule.getLanguage()).isEqualTo(r1.getLanguage()); | |||
assertThat(firstRule.getType()).isEqualTo(r1.getType()); |
@@ -27,7 +27,6 @@ import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import java.util.Collection; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.IntStream; | |||
import javax.annotation.CheckForNull; | |||
@@ -39,15 +38,13 @@ import org.sonar.db.DatabaseUtils; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
import org.sonar.server.security.SecurityStandards; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static org.sonar.api.utils.DateUtils.longToDate; | |||
import static org.sonar.db.DatabaseUtils.getLong; | |||
import static org.sonar.server.security.SecurityStandardHelper.getCwe; | |||
import static org.sonar.server.security.SecurityStandardHelper.getOwaspTop10; | |||
import static org.sonar.server.security.SecurityStandardHelper.getSansTop25; | |||
import static org.sonar.server.security.SecurityStandardHelper.getSecurityStandards; | |||
import static org.sonar.server.security.SecurityStandardHelper.getSonarSourceSecurityCategories; | |||
import static org.sonar.db.rule.RuleDefinitionDto.deserializeSecurityStandardsString; | |||
import static org.sonar.server.security.SecurityStandards.fromSecurityStandards; | |||
/** | |||
* Scrolls over table ISSUES and reads documents to populate | |||
@@ -231,14 +228,12 @@ class IssueIteratorForSingleChunk implements IssueIterator { | |||
String tags = rs.getString(21); | |||
doc.setTags(IssueIteratorForSingleChunk.TAGS_SPLITTER.splitToList(tags == null ? "" : tags)); | |||
doc.setType(RuleType.valueOf(rs.getInt(22))); | |||
String securityStandards = rs.getString(23); | |||
List<String> standards = getSecurityStandards(securityStandards); | |||
doc.setOwaspTop10(getOwaspTop10(standards)); | |||
List<String> cwe = getCwe(standards); | |||
doc.setCwe(cwe); | |||
doc.setSansTop25(getSansTop25(cwe)); | |||
doc.setSonarSourceSecurityCategories(getSonarSourceSecurityCategories(cwe)); | |||
SecurityStandards securityStandards = fromSecurityStandards(deserializeSecurityStandardsString(rs.getString(23))); | |||
doc.setOwaspTop10(securityStandards.getOwaspTop10()); | |||
doc.setCwe(securityStandards.getCwe()); | |||
doc.setSansTop25(securityStandards.getSansTop25()); | |||
doc.setSonarSourceSecurityCategories(securityStandards.getSq()); | |||
return doc; | |||
} | |||
@@ -35,7 +35,7 @@ import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleForIndexingDto; | |||
import org.sonar.markdown.Markdown; | |||
import org.sonar.server.es.BaseDoc; | |||
import org.sonar.server.security.SecurityStandardHelper; | |||
import org.sonar.server.security.SecurityStandards; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE; | |||
@@ -268,7 +268,7 @@ public class RuleDoc extends BaseDoc { | |||
} | |||
public static RuleDoc of(RuleForIndexingDto dto) { | |||
Collection<String> cwe = SecurityStandardHelper.getCwe(dto.getSecurityStandardsAsSet()); | |||
SecurityStandards securityStandards = SecurityStandards.fromSecurityStandards(dto.getSecurityStandards()); | |||
RuleDoc ruleDoc = new RuleDoc() | |||
.setId(dto.getId()) | |||
.setKey(dto.getRuleKey().toString()) | |||
@@ -277,10 +277,10 @@ public class RuleDoc extends BaseDoc { | |||
.setIsTemplate(dto.isTemplate()) | |||
.setIsExternal(dto.isExternal()) | |||
.setLanguage(dto.getLanguage()) | |||
.setCwe(cwe) | |||
.setOwaspTop10(SecurityStandardHelper.getOwaspTop10(dto.getSecurityStandardsAsSet())) | |||
.setSansTop25(SecurityStandardHelper.getSansTop25(cwe)) | |||
.setSonarSourceSecurityCategories(SecurityStandardHelper.getSonarSourceSecurityCategories(cwe)) | |||
.setCwe(securityStandards.getCwe()) | |||
.setOwaspTop10(securityStandards.getOwaspTop10()) | |||
.setSansTop25(securityStandards.getSansTop25()) | |||
.setSonarSourceSecurityCategories(securityStandards.getSq()) | |||
.setName(dto.getName()) | |||
.setRuleKey(dto.getPluginRuleKey()) | |||
.setSeverity(dto.getSeverityAsString()) |
@@ -81,7 +81,7 @@ public class RuleExtensionDoc extends BaseDoc { | |||
return new RuleExtensionDoc() | |||
.setRuleId(rule.getId()) | |||
.setScope(RuleExtensionScope.system()) | |||
.setTags(rule.getSystemTagsAsSet()); | |||
.setTags(rule.getSystemTags()); | |||
} | |||
public static RuleExtensionDoc of(RuleExtensionForIndexingDto rule) { |
@@ -19,24 +19,23 @@ | |||
*/ | |||
package org.sonar.server.security; | |||
import com.google.common.base.Splitter; | |||
import com.google.common.collect.ImmutableList; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.common.collect.ImmutableSet; | |||
import com.google.common.collect.Ordering; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import javax.annotation.concurrent.Immutable; | |||
import org.sonar.core.util.stream.MoreCollectors; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyList; | |||
import static java.util.Collections.singletonList; | |||
import static java.util.stream.Collectors.toList; | |||
import static java.util.Collections.singleton; | |||
public class SecurityStandardHelper { | |||
@Immutable | |||
public final class SecurityStandards { | |||
public static final String UNKNOWN_STANDARD = "unknown"; | |||
public static final String SANS_TOP_25_INSECURE_INTERACTION = "insecure-interaction"; | |||
@@ -49,12 +48,12 @@ public class SecurityStandardHelper { | |||
private static final Set<String> INSECURE_CWE = new HashSet<>(asList("89", "78", "79", "434", "352", "601")); | |||
private static final Set<String> RISKY_CWE = new HashSet<>(asList("120", "22", "494", "829", "676", "131", "134", "190")); | |||
private static final Set<String> POROUS_CWE = new HashSet<>(asList("306", "862", "798", "311", "807", "250", "863", "732", "327", "307", "759")); | |||
public static final Map<String, Set<String>> SANS_TOP_25_CWE_MAPPING = ImmutableMap.of( | |||
public static final Map<String, Set<String>> CWES_BY_SANS_TOP_25 = ImmutableMap.of( | |||
SANS_TOP_25_INSECURE_INTERACTION, INSECURE_CWE, | |||
SANS_TOP_25_RISKY_RESOURCE, RISKY_CWE, | |||
SANS_TOP_25_POROUS_DEFENSES, POROUS_CWE); | |||
public static final Map<String, Set<String>> SONARSOURCE_CWE_MAPPING = ImmutableMap.<String, Set<String>>builder() | |||
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")) | |||
@@ -75,65 +74,85 @@ public class SecurityStandardHelper { | |||
.put("insecure-conf", ImmutableSet.of("102", "215", "311", "315", "346", "614", "489", "942")) | |||
.put("file-manipulation", ImmutableSet.of("97", "73")) | |||
.build(); | |||
public static final String SONARSOURCE_OTHER_CWES_CATEGORY = "others"; | |||
public static final Ordering<String> SONARSOURCE_CATEGORY_ORDERING = Ordering.explicit( | |||
ImmutableList.<String>builder().addAll(SONARSOURCE_CWE_MAPPING.keySet()).add(SONARSOURCE_OTHER_CWES_CATEGORY).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()); | |||
private final Set<String> standards; | |||
private final Set<String> cwe; | |||
private final Set<String> owaspTop10; | |||
private final Set<String> sansTop25; | |||
private final Set<String> sq; | |||
private SecurityStandards(Set<String> standards, Set<String> cwe, Set<String> owaspTop10, Set<String> sansTop25, Set<String> sq) { | |||
this.standards = standards; | |||
this.cwe = cwe; | |||
this.owaspTop10 = owaspTop10; | |||
this.sansTop25 = sansTop25; | |||
this.sq = sq; | |||
} | |||
private static final Splitter SECURITY_STANDARDS_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings(); | |||
public Set<String> getStandards() { | |||
return standards; | |||
} | |||
private SecurityStandardHelper() { | |||
// Utility class | |||
public Set<String> getCwe() { | |||
return cwe; | |||
} | |||
public static List<String> getSecurityStandards(@Nullable String securityStandards) { | |||
return securityStandards == null ? emptyList() : SECURITY_STANDARDS_SPLITTER.splitToList(securityStandards); | |||
public Set<String> getOwaspTop10() { | |||
return owaspTop10; | |||
} | |||
public static List<String> getSansTop25(Collection<String> cwe) { | |||
return SANS_TOP_25_CWE_MAPPING | |||
.keySet() | |||
.stream() | |||
.filter(k -> cwe.stream().anyMatch(SANS_TOP_25_CWE_MAPPING.get(k)::contains)) | |||
.collect(toList()); | |||
public Set<String> getSansTop25() { | |||
return sansTop25; | |||
} | |||
public static List<String> getSonarSourceSecurityCategories(Collection<String> cwe) { | |||
List<String> result = SONARSOURCE_CWE_MAPPING | |||
.keySet() | |||
.stream() | |||
.filter(k -> cwe.stream().anyMatch(SONARSOURCE_CWE_MAPPING.get(k)::contains)) | |||
.collect(toList()); | |||
return result.isEmpty() ? singletonList(SONARSOURCE_OTHER_CWES_CATEGORY) : result; | |||
public Set<String> getSq() { | |||
return sq; | |||
} | |||
public static SecurityStandards fromSecurityStandards(Set<String> securityStandards) { | |||
Set<String> standards = securityStandards.stream() | |||
.filter(Objects::nonNull) | |||
.collect(MoreCollectors.toSet()); | |||
Set<String> owaspTop10 = toOwaspTop10(standards); | |||
Set<String> cwe = toCwe(standards); | |||
Set<String> sansTop25 = toSansTop25(cwe); | |||
Set<String> sq = toSonarSourceSecurityCategories(cwe); | |||
return new SecurityStandards(standards, cwe, owaspTop10, sansTop25, sq); | |||
} | |||
public static List<String> getOwaspTop10(Collection<String> securityStandards) { | |||
private static Set<String> toOwaspTop10(Set<String> securityStandards) { | |||
return securityStandards.stream() | |||
.filter(s -> s.startsWith(OWASP_TOP10_PREFIX)) | |||
.map(s -> s.substring(OWASP_TOP10_PREFIX.length())) | |||
.collect(toList()); | |||
.collect(MoreCollectors.toSet()); | |||
} | |||
public static List<String> getCwe(Collection<String> securityStandards) { | |||
List<String> result = securityStandards.stream() | |||
private static Set<String> toCwe(Collection<String> securityStandards) { | |||
Set<String> result = securityStandards.stream() | |||
.filter(s -> s.startsWith(CWE_PREFIX)) | |||
.map(s -> s.substring(CWE_PREFIX.length())) | |||
.collect(toList()); | |||
return result.isEmpty() ? singletonList(UNKNOWN_STANDARD) : result; | |||
.collect(MoreCollectors.toSet()); | |||
return result.isEmpty() ? singleton(UNKNOWN_STANDARD) : result; | |||
} | |||
public static List<String> getSansTop25(String securityStandards) { | |||
return getSansTop25(getCwe(getSecurityStandards(securityStandards))); | |||
} | |||
public static List<String> getSonarSourceSecurityCategories(String securityStandards) { | |||
return getSonarSourceSecurityCategories(getCwe(getSecurityStandards(securityStandards))); | |||
} | |||
public static List<String> getOwaspTop10(String securityStandards) { | |||
return getOwaspTop10(getSecurityStandards(securityStandards)); | |||
private static Set<String> toSansTop25(Collection<String> cwe) { | |||
return CWES_BY_SANS_TOP_25 | |||
.keySet() | |||
.stream() | |||
.filter(k -> cwe.stream().anyMatch(CWES_BY_SANS_TOP_25.get(k)::contains)) | |||
.collect(MoreCollectors.toSet()); | |||
} | |||
public static List<String> getCwe(String securityStandards) { | |||
return getCwe(getSecurityStandards(securityStandards)); | |||
private static Set<String> toSonarSourceSecurityCategories(Collection<String> cwe) { | |||
Set<String> result = CWES_BY_SQ_CATEGORY | |||
.keySet() | |||
.stream() | |||
.filter(k -> cwe.stream().anyMatch(CWES_BY_SQ_CATEGORY.get(k)::contains)) | |||
.collect(MoreCollectors.toSet()); | |||
return result.isEmpty() ? singleton(SQ_OTHER_CATEGORY) : result; | |||
} | |||
} |
@@ -48,6 +48,7 @@ import org.sonar.server.es.IndexingResult; | |||
import org.sonar.server.es.ProjectIndexer; | |||
import org.sonar.server.permission.index.AuthorizationScope; | |||
import org.sonar.server.permission.index.IndexPermissions; | |||
import org.sonar.server.security.SecurityStandards; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.emptyList; | |||
@@ -57,10 +58,8 @@ import static org.junit.rules.ExpectedException.none; | |||
import static org.sonar.db.component.ComponentTesting.newFileDto; | |||
import static org.sonar.server.issue.IssueDocTesting.newDoc; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_OTHER_CWES_CATEGORY; | |||
import static org.sonar.server.security.SecurityStandardHelper.UNKNOWN_STANDARD; | |||
import static org.sonar.server.permission.index.IndexAuthorizationConstants.TYPE_AUTHORIZATION; | |||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_POROUS_DEFENSES; | |||
public class IssueIndexerTest { | |||
@@ -136,10 +135,10 @@ public class IssueIndexerTest { | |||
assertThat(doc.line()).isEqualTo(issue.getLine()); | |||
// functional date | |||
assertThat(doc.updateDate()).isEqualToIgnoringMillis(new Date(issue.getIssueUpdateTime())); | |||
assertThat(doc.getCwe()).containsExactlyInAnyOrder(UNKNOWN_STANDARD); | |||
assertThat(doc.getCwe()).containsExactlyInAnyOrder(SecurityStandards.UNKNOWN_STANDARD); | |||
assertThat(doc.getOwaspTop10()).isEmpty(); | |||
assertThat(doc.getSansTop25()).isEmpty(); | |||
assertThat(doc.getSonarSourceSecurityCategories()).containsExactlyInAnyOrder(SONARSOURCE_OTHER_CWES_CATEGORY); | |||
assertThat(doc.getSonarSourceSecurityCategories()).containsOnly(SecurityStandards.SQ_OTHER_CATEGORY); | |||
} | |||
@Test |
@@ -86,8 +86,8 @@ import static org.sonar.server.rule.index.RuleIndex.FACET_TYPES; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE_EXTENSION; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; | |||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_INSECURE_INTERACTION; | |||
import static org.sonar.server.security.SecurityStandards.SANS_TOP_25_RISKY_RESOURCE; | |||
public class RuleIndexTest { | |||
@@ -82,6 +82,7 @@ import org.sonar.server.es.StickyFacetBuilder; | |||
import org.sonar.server.issue.index.IssueQuery.PeriodStart; | |||
import org.sonar.server.permission.index.AuthorizationDoc; | |||
import org.sonar.server.permission.index.WebAuthorizationTypeSupport; | |||
import org.sonar.server.security.SecurityStandards; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonar.server.view.index.ViewIndexDefinition; | |||
@@ -152,12 +153,10 @@ import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_STAT | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_TAGS; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_TYPE; | |||
import static org.sonar.server.issue.index.IssueIndexDefinition.TYPE_ISSUE; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_CWE_MAPPING; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_CWE_MAPPING; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_OTHER_CWES_CATEGORY; | |||
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_RISKY_RESOURCE; | |||
import static org.sonar.server.security.SecurityStandards.SQ_CATEGORIES; | |||
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.FACET_MODE_EFFORT; | |||
@@ -874,15 +873,14 @@ public class IssueIndex { | |||
public List<SecurityStandardCategoryStatistics> getSansTop25Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | |||
SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | |||
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(SANS_TOP_25_CWE_MAPPING)))); | |||
.forEach(sansCategory -> request.addAggregation(createAggregation(FIELD_ISSUE_SANS_TOP_25, sansCategory, includeCwe, Optional.of(SecurityStandards.CWES_BY_SANS_TOP_25)))); | |||
return processSecurityReportSearchResults(request, includeCwe); | |||
} | |||
public List<SecurityStandardCategoryStatistics> getSonarSourceReport(String projectUuid, boolean isViewOrApp, boolean includeCwe) { | |||
SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp); | |||
Stream.concat(SONARSOURCE_CWE_MAPPING.keySet().stream(), Stream.of(SONARSOURCE_OTHER_CWES_CATEGORY)) | |||
.forEach(sonarsourceCategory -> request.addAggregation( | |||
createAggregation(FIELD_ISSUE_SONARSOURCE_SECURITY, sonarsourceCategory, includeCwe, Optional.of(SONARSOURCE_CWE_MAPPING)))); | |||
SQ_CATEGORIES.forEach(sonarsourceCategory -> request.addAggregation( | |||
createAggregation(FIELD_ISSUE_SONARSOURCE_SECURITY, sonarsourceCategory, includeCwe, Optional.of(SecurityStandards.CWES_BY_SQ_CATEGORY)))); | |||
return processSecurityReportSearchResults(request, includeCwe); | |||
} | |||
@@ -54,10 +54,10 @@ import static org.sonar.api.resources.Qualifiers.PROJECT; | |||
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto; | |||
import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; | |||
import static org.sonar.server.issue.IssueDocTesting.newDoc; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; | |||
import static org.sonar.server.security.SecurityStandardHelper.UNKNOWN_STANDARD; | |||
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_RISKY_RESOURCE; | |||
import static org.sonar.server.security.SecurityStandards.UNKNOWN_STANDARD; | |||
public class IssueIndexSecurityReportsTest { | |||
@@ -54,6 +54,7 @@ import org.sonar.server.issue.SearchRequest; | |||
import org.sonar.server.issue.index.IssueIndex; | |||
import org.sonar.server.issue.index.IssueQuery; | |||
import org.sonar.server.issue.index.IssueQueryFactory; | |||
import org.sonar.server.security.SecurityStandards; | |||
import org.sonar.server.user.UserSession; | |||
import org.sonarqube.ws.Issues.SearchWsResponse; | |||
@@ -84,12 +85,11 @@ import static org.sonar.server.issue.index.IssueIndex.FACET_ASSIGNED_TO_ME; | |||
import static org.sonar.server.issue.index.IssueIndex.FACET_PROJECTS; | |||
import static org.sonar.server.issue.index.IssueQuery.SORT_BY_ASSIGNEE; | |||
import static org.sonar.server.issue.index.IssueQueryFactory.UNKNOWN; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_INSECURE_INTERACTION; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_POROUS_DEFENSES; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_RISKY_RESOURCE; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_CWE_MAPPING; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_OTHER_CWES_CATEGORY; | |||
import static org.sonar.server.security.SecurityStandardHelper.UNKNOWN_STANDARD; | |||
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_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.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_PULL_REQUEST_EXAMPLE_001; | |||
@@ -273,10 +273,10 @@ public class SearchAction implements IssuesWsAction, Startable { | |||
.setDescription("Comma-separated list of CWE identifiers. Use '" + UNKNOWN_STANDARD + "' to select issues not associated to any CWE.") | |||
.setExampleValue("12,125," + UNKNOWN_STANDARD); | |||
action.createParam(PARAM_SONARSOURCE_SECURITY) | |||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SONARSOURCE_OTHER_CWES_CATEGORY + "' to select issues not associated" + | |||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SQ_OTHER_CATEGORY + "' to select issues not associated" + | |||
" with any category") | |||
.setSince("7.8") | |||
.setPossibleValues(ImmutableList.builder().addAll(SONARSOURCE_CWE_MAPPING.keySet()).add(SONARSOURCE_OTHER_CWES_CATEGORY).build()); | |||
.setPossibleValues(SecurityStandards.SQ_CATEGORIES); | |||
action.createParam(DEPRECATED_PARAM_AUTHORS) | |||
.setDeprecatedSince("7.7") | |||
.setDescription("This parameter is deprecated, please use '%s' instead", PARAM_AUTHOR) |
@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.server.rule.ws; | |||
import com.google.common.collect.ImmutableList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
@@ -39,6 +38,7 @@ import org.sonar.db.user.UserDto; | |||
import org.sonar.server.organization.DefaultOrganizationProvider; | |||
import org.sonar.server.qualityprofile.ActiveRuleInheritance; | |||
import org.sonar.server.rule.index.RuleIndexDefinition; | |||
import org.sonar.server.security.SecurityStandards; | |||
import org.sonar.server.user.UserSession; | |||
import static org.sonar.api.server.ws.WebService.Param.ASCENDING; | |||
@@ -50,6 +50,7 @@ import static org.sonar.core.util.stream.MoreCollectors.toSet; | |||
import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex; | |||
import static org.sonar.db.organization.OrganizationDto.Subscription.PAID; | |||
import static org.sonar.db.permission.OrganizationPermission.ADMINISTER_QUALITY_PROFILES; | |||
import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVATION; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES; | |||
import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_AVAILABLE_SINCE; | |||
@@ -71,11 +72,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_STATUSES; | |||
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_TYPES; | |||
import static org.sonar.server.security.SecurityStandardHelper.SANS_TOP_25_CWE_MAPPING; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_CWE_MAPPING; | |||
import static org.sonar.server.security.SecurityStandardHelper.SONARSOURCE_OTHER_CWES_CATEGORY; | |||
import static org.sonar.server.security.SecurityStandardHelper.UNKNOWN_STANDARD; | |||
import static org.sonar.server.exceptions.NotFoundException.checkFoundWithOptional; | |||
import static org.sonar.server.security.SecurityStandards.SQ_OTHER_CATEGORY; | |||
@ServerSide | |||
public class RuleWsSupport { | |||
@@ -141,8 +138,8 @@ public class RuleWsSupport { | |||
action | |||
.createParam(PARAM_CWE) | |||
.setDescription("Comma-separated list of CWE identifiers. Use '" + UNKNOWN_STANDARD + "' to select rules not associated to any CWE.") | |||
.setExampleValue("12,125," + UNKNOWN_STANDARD); | |||
.setDescription("Comma-separated list of CWE identifiers. Use '" + SecurityStandards.UNKNOWN_STANDARD + "' to select rules not associated to any CWE.") | |||
.setExampleValue("12,125," + SecurityStandards.UNKNOWN_STANDARD); | |||
action.createParam(PARAM_OWASP_TOP_10) | |||
.setDescription("Comma-separated list of OWASP Top 10 lowercase categories.") | |||
@@ -152,14 +149,14 @@ public class RuleWsSupport { | |||
action.createParam(PARAM_SANS_TOP_25) | |||
.setDescription("Comma-separated list of SANS Top 25 categories.") | |||
.setSince("7.3") | |||
.setPossibleValues(SANS_TOP_25_CWE_MAPPING.keySet()); | |||
.setPossibleValues(SecurityStandards.CWES_BY_SANS_TOP_25.keySet()); | |||
action | |||
.createParam(PARAM_SONARSOURCE_SECURITY) | |||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SONARSOURCE_OTHER_CWES_CATEGORY + "' to select rules not associated" + | |||
.setDescription("Comma-separated list of SonarSource security categories. Use '" + SQ_OTHER_CATEGORY + "' to select rules not associated" + | |||
" with any category") | |||
.setSince("7.8") | |||
.setPossibleValues(ImmutableList.builder().addAll(SONARSOURCE_CWE_MAPPING.keySet()).add(SONARSOURCE_OTHER_CWES_CATEGORY).build()) | |||
.setPossibleValues(SecurityStandards.SQ_CATEGORIES) | |||
.setExampleValue("sql-injection,command-injection,others"); | |||
action |