From dcdb0f14b776a8e65ea20dab77ba2486d932b30f Mon Sep 17 00:00:00 2001 From: Léo Geoffroy Date: Thu, 18 Jul 2024 10:08:04 +0200 Subject: SONAR-22542 Index new STIG security standard --- .../sonar/server/issue/index/IssueIndexerIT.java | 4 +- .../java/org/sonar/server/issue/SearchRequest.java | 11 ++++++ .../org/sonar/server/issue/index/IssueDoc.java | 10 +++++ .../server/issue/index/IssueIndexDefinition.java | 2 + .../issue/index/IssueIteratorForSingleChunk.java | 2 + .../sonar/server/security/SecurityStandards.java | 5 +++ .../org/sonar/server/issue/SearchRequestTest.java | 2 + .../server/security/SecurityStandardsTest.java | 46 +++++++++++++++------- 8 files changed, 67 insertions(+), 15 deletions(-) (limited to 'server/sonar-server-common') diff --git a/server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIndexerIT.java b/server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIndexerIT.java index f4e20951b5e..d011f225171 100644 --- a/server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIndexerIT.java +++ b/server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIndexerIT.java @@ -197,6 +197,7 @@ public class IssueIndexerIT { assertThat(doc.updateDate()).isEqualToIgnoringMillis(new Date(issue.getIssueUpdateTime())); assertThat(doc.getCwe()).containsExactlyInAnyOrder(SecurityStandards.UNKNOWN_STANDARD); assertThat(doc.getOwaspTop10()).isEmpty(); + assertThat(doc.getStigAsdV5R3()).isEmpty(); assertThat(doc.getSansTop25()).isEmpty(); assertThat(doc.getSonarSourceSecurityCategory()).isEqualTo(SQCategory.OTHERS); assertThat(doc.getVulnerabilityProbability()).isEqualTo(VulnerabilityProbability.LOW); @@ -209,7 +210,7 @@ public class IssueIndexerIT { @Test public void indexAllIssues_shouldIndexSecurityStandards() { - RuleDto rule = db.rules().insert(r -> r.setSecurityStandards(new HashSet<>(Arrays.asList("cwe:123", "owaspTop10:a3", "cwe:863", "owaspAsvs-4.0:2.1.1")))); + RuleDto rule = db.rules().insert(r -> r.setSecurityStandards(new HashSet<>(Arrays.asList("stig-ASD_V5R3:V-222400", "cwe:123", "owaspTop10:a3", "cwe:863", "owaspAsvs-4.0:2.1.1")))); ComponentDto project = db.components().insertPrivateProject().getMainBranchComponent(); ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java/foo")); ComponentDto file = db.components().insertComponent(newFileDto(project, dir, "F1")); @@ -222,6 +223,7 @@ public class IssueIndexerIT { assertThat(doc.getOwaspTop10()).containsExactlyInAnyOrder("a3"); assertThat(doc.getOwaspAsvs40()).containsExactlyInAnyOrder("2.1.1"); assertThat(doc.getSansTop25()).containsExactlyInAnyOrder(SANS_TOP_25_POROUS_DEFENSES); + assertThat(doc.getStigAsdV5R3()).containsExactlyInAnyOrder("V-222400"); } @Test diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java index 543e2f225d6..309799b18a5 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java @@ -73,6 +73,7 @@ public class SearchRequest { private List owaspTop10; private List owaspAsvs40; private List owaspTop10For2021; + private List stigAsdV5R3; private List sansTop25; private List sonarsourceSecurity; private List cwe; @@ -436,6 +437,16 @@ public class SearchRequest { return this; } + @CheckForNull + public List getStigAsdV5R3() { + return stigAsdV5R3; + } + + public SearchRequest setStigAsdV5R3(@Nullable List stigAsdV5R3) { + this.stigAsdV5R3 = stigAsdV5R3; + return this; + } + @CheckForNull public List getSansTop25() { return sansTop25; diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java index 90c1bc3f016..21888af7366 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java @@ -364,6 +364,16 @@ public class IssueDoc extends BaseDoc { return this; } + @CheckForNull + public Collection getStigAsdV5R3() { + return getNullableField(IssueIndexDefinition.FIELD_ISSUE_STIG_ASD_V5R3); + } + + public IssueDoc setStigAsdV5R3(@Nullable Collection o) { + setField(IssueIndexDefinition.FIELD_ISSUE_STIG_ASD_V5R3, o); + return this; + } + @CheckForNull public Collection getSansTop25() { return getNullableField(IssueIndexDefinition.FIELD_ISSUE_SANS_TOP_25); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java index 088f435eb59..ad815ed9e7d 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java @@ -97,6 +97,7 @@ public class IssueIndexDefinition implements IndexDefinition { public static final String FIELD_ISSUE_OWASP_TOP_10_2021 = "owaspTop10-2021"; public static final String FIELD_ISSUE_SANS_TOP_25 = "sansTop25"; public static final String FIELD_ISSUE_CWE = "cwe"; + public static final String FIELD_ISSUE_STIG_ASD_V5R3 = "stig-ASD_V5R3"; public static final String FIELD_ISSUE_SQ_SECURITY_CATEGORY = "sonarsourceSecurity"; public static final String FIELD_ISSUE_VULNERABILITY_PROBABILITY = "vulnerabilityProbability"; public static final String FIELD_ISSUE_CODE_VARIANTS = "codeVariants"; @@ -184,6 +185,7 @@ public class IssueIndexDefinition implements IndexDefinition { mapping.keywordFieldBuilder(FIELD_ISSUE_CWE).disableNorms().build(); mapping.keywordFieldBuilder(FIELD_ISSUE_SQ_SECURITY_CATEGORY).disableNorms().build(); mapping.keywordFieldBuilder(FIELD_ISSUE_VULNERABILITY_PROBABILITY).disableNorms().build(); + mapping.keywordFieldBuilder(FIELD_ISSUE_STIG_ASD_V5R3).disableNorms().build(); mapping.createBooleanField(FIELD_ISSUE_NEW_CODE_REFERENCE); mapping.keywordFieldBuilder(FIELD_ISSUE_CODE_VARIANTS).disableNorms().build(); mapping.createBooleanField(FIELD_PRIORITIZED_RULE); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java index d17baac5679..c71ba67ad29 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java @@ -35,6 +35,7 @@ import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; import org.sonar.api.rules.CleanCodeAttribute; import org.sonar.api.rules.RuleType; +import org.sonar.api.server.rule.RulesDefinition.StigVersion; import org.sonar.db.DatabaseUtils; import org.sonar.db.DbClient; import org.sonar.db.DbSession; @@ -131,6 +132,7 @@ class IssueIteratorForSingleChunk implements IssueIterator { SecurityStandards.SQCategory sqCategory = securityStandards.getSqCategory(); doc.setOwaspTop10(securityStandards.getOwaspTop10()); doc.setOwaspTop10For2021(securityStandards.getOwaspTop10For2021()); + doc.setStigAsdV5R3(securityStandards.getStig(StigVersion.ASD_V5R3)); doc.setPciDss32(securityStandards.getPciDss32()); doc.setPciDss40(securityStandards.getPciDss40()); doc.setOwaspAsvs40(securityStandards.getOwaspAsvs40()); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java index 090d2f217d1..7058a1a3063 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityStandards.java @@ -36,6 +36,7 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion; import org.sonar.api.server.rule.RulesDefinition.PciDssVersion; +import org.sonar.api.server.rule.RulesDefinition.StigVersion; import static java.util.Arrays.asList; import static java.util.Arrays.stream; @@ -310,6 +311,10 @@ public final class SecurityStandards { return getMatchingStandards(standards, OWASP_TOP10_2021_PREFIX); } + public Set getStig(StigVersion version) { + return getMatchingStandards(standards, version.prefix() + ":"); + } + /** * @deprecated SansTop25 report is outdated, it has been completely deprecated in version 10.0 and will be removed from version 11.0 */ diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java index be5b755ffb1..1779e509993 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java @@ -54,6 +54,7 @@ public class SearchRequestTest { .setOwaspTop10For2021(asList("a2", "a3")) .setOwaspAsvs40(asList("1.1.1", "4.2.2")) .setOwaspAsvsLevel(2) + .setStigAsdV5R3(List.of("V-222400", "V-222401")) .setPciDss32(asList("1", "4")) .setPciDss40(asList("3", "5")) .setCodeVariants(asList("variant1", "variant2")) @@ -81,6 +82,7 @@ public class SearchRequestTest { assertThat(underTest.getAsc()).isTrue(); assertThat(underTest.getInNewCodePeriod()).isTrue(); assertOwasp(underTest); + assertThat(underTest.getStigAsdV5R3()).containsExactly("V-222400", "V-222401"); assertThat(underTest.getPciDss32()).containsExactly("1", "4"); assertThat(underTest.getPciDss40()).containsExactly("3", "5"); assertThat(underTest.getCodeVariants()).containsExactly("variant1", "variant2"); diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java index 7f4e85f4cbb..09d2f53ceb2 100644 --- a/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java +++ b/server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityStandardsTest.java @@ -24,11 +24,13 @@ import java.util.EnumSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.sonar.api.server.rule.RulesDefinition; import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion; import org.sonar.server.security.SecurityStandards.OwaspAsvs; import org.sonar.server.security.SecurityStandards.PciDss; import org.sonar.server.security.SecurityStandards.SQCategory; +import org.sonar.server.security.SecurityStandards.StigSupportedRequirement; import static java.util.Collections.emptySet; import static java.util.Collections.singleton; @@ -42,9 +44,9 @@ import static org.sonar.server.security.SecurityStandards.SQ_CATEGORY_KEYS_ORDER import static org.sonar.server.security.SecurityStandards.fromSecurityStandards; import static org.sonar.server.security.SecurityStandards.getRequirementsForCategoryAndLevel; -public class SecurityStandardsTest { +class SecurityStandardsTest { @Test - public void fromSecurityStandards_from_empty_set_has_SQCategory_OTHERS() { + void fromSecurityStandards_from_empty_set_has_SQCategory_OTHERS() { SecurityStandards securityStandards = fromSecurityStandards(emptySet()); assertThat(securityStandards.getStandards()).isEmpty(); @@ -53,7 +55,7 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_from_empty_set_has_unkwown_cwe_standard() { + void fromSecurityStandards_from_empty_set_has_unkwown_cwe_standard() { SecurityStandards securityStandards = fromSecurityStandards(emptySet()); assertThat(securityStandards.getStandards()).isEmpty(); @@ -61,7 +63,7 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_from_empty_set_has_no_OwaspTop10_standard() { + void fromSecurityStandards_from_empty_set_has_no_OwaspTop10_standard() { SecurityStandards securityStandards = fromSecurityStandards(emptySet()); assertThat(securityStandards.getStandards()).isEmpty(); @@ -69,7 +71,7 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_from_empty_set_has_no_SansTop25_standard() { + void fromSecurityStandards_from_empty_set_has_no_SansTop25_standard() { SecurityStandards securityStandards = fromSecurityStandards(emptySet()); assertThat(securityStandards.getStandards()).isEmpty(); @@ -77,7 +79,7 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_from_empty_set_has_no_CweTop25_standard() { + void fromSecurityStandards_from_empty_set_has_no_CweTop25_standard() { SecurityStandards securityStandards = fromSecurityStandards(emptySet()); assertThat(securityStandards.getStandards()).isEmpty(); @@ -85,7 +87,7 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_finds_SQCategory_from_any_if_the_mapped_CWE_standard() { + void fromSecurityStandards_finds_SQCategory_from_any_if_the_mapped_CWE_standard() { CWES_BY_SQ_CATEGORY.forEach((sqCategory, cwes) -> { cwes.forEach(cwe -> { SecurityStandards securityStandards = fromSecurityStandards(singleton("cwe:" + cwe)); @@ -96,7 +98,7 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_finds_SQCategory_from_multiple_of_the_mapped_CWE_standard() { + void fromSecurityStandards_finds_SQCategory_from_multiple_of_the_mapped_CWE_standard() { CWES_BY_SQ_CATEGORY.forEach((sqCategory, cwes) -> { SecurityStandards securityStandards = fromSecurityStandards(cwes.stream().map(t -> "cwe:" + t).collect(toSet())); @@ -105,7 +107,13 @@ public class SecurityStandardsTest { } @Test - public void fromSecurityStandards_finds_SQCategory_first_in_order_when_CWEs_map_to_multiple_SQCategories() { + void fromSecurityStandards_whenStigStandardIsSet_shouldReturnExpectedCategories() { + SecurityStandards securityStandards = fromSecurityStandards(singleton("stig-ASD_V5R3:V-222400")); + assertThat(securityStandards.getStig(RulesDefinition.StigVersion.ASD_V5R3)).containsExactly("V-222400"); + } + + @Test + void fromSecurityStandards_finds_SQCategory_first_in_order_when_CWEs_map_to_multiple_SQCategories() { EnumSet sqCategories = EnumSet.allOf(SQCategory.class); sqCategories.remove(SQCategory.OTHERS); @@ -126,21 +134,21 @@ public class SecurityStandardsTest { } @Test - public void pciDss_categories_check() { + void pciDss_categories_check() { List pciDssCategories = Arrays.stream(PciDss.values()).map(PciDss::category).toList(); assertThat(pciDssCategories).hasSize(12).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"); } @Test - public void owaspAsvs_categories_check() { + void owaspAsvs_categories_check() { List owaspAsvsCategories = Arrays.stream(OwaspAsvs.values()).map(OwaspAsvs::category).toList(); assertThat(owaspAsvsCategories).hasSize(14).containsExactly("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"); } @Test - public void owaspAsvs40_requirements_distribution_by_level_check() { + void owaspAsvs40_requirements_distribution_by_level_check() { assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.containsKey(OwaspAsvsVersion.V4_0)); assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).containsKey(1)); assertTrue(OWASP_ASVS_REQUIREMENTS_BY_LEVEL.get(OwaspAsvsVersion.V4_0).containsKey(2)); @@ -151,7 +159,7 @@ public class SecurityStandardsTest { } @Test - public void owaspAsvs40_requirements_by_category_and_level_check() { + void owaspAsvs40_requirements_by_category_and_level_check() { assertEquals(0, getRequirementsForCategoryAndLevel(OwaspAsvs.C1, 1).size()); assertEquals(31, getRequirementsForCategoryAndLevel(OwaspAsvs.C2, 1).size()); assertEquals(12, getRequirementsForCategoryAndLevel(OwaspAsvs.C3, 1).size()); @@ -167,4 +175,14 @@ public class SecurityStandardsTest { assertEquals(7, getRequirementsForCategoryAndLevel(OwaspAsvs.C13, 1).size()); assertEquals(16, getRequirementsForCategoryAndLevel(OwaspAsvs.C14, 1).size()); } + + + @Test + void StigSupportedRequirement_values_shouldReturnAllValues() { + Set requirements = Arrays.stream(StigSupportedRequirement.values()) + .map(StigSupportedRequirement::getRequirement) + .collect(toSet()); + + assertThat(requirements).isNotEmpty().allSatisfy(e -> assertThat(e).startsWith("V-")); + } } -- cgit v1.2.3