3838import org .dependencytrack .model .RepositoryType ;
3939import org .dependencytrack .model .Severity ;
4040import org .dependencytrack .model .Vulnerability ;
41+ import org .dependencytrack .model .Vulnerability .Source ;
4142import org .dependencytrack .tasks .scanners .AnalyzerIdentity ;
4243import org .glassfish .jersey .server .ResourceConfig ;
4344import org .junit .jupiter .api .Assertions ;
4445import org .junit .jupiter .api .Test ;
4546import org .junit .jupiter .api .extension .RegisterExtension ;
47+ import org .junit .jupiter .params .ParameterizedTest ;
48+ import org .junit .jupiter .params .provider .MethodSource ;
49+ import org .junit .jupiter .params .provider .Arguments ;
50+ import java .util .stream .Stream ;
51+ import static org .apache .commons .io .IOUtils .resourceToString ;
52+ import java .nio .charset .StandardCharsets ;
4653
4754import java .util .Date ;
4855import java .util .List ;
4956import java .util .UUID ;
5057
5158import static net .javacrumbs .jsonunit .assertj .JsonAssertions .assertThatJson ;
52- import static net .javacrumbs .jsonunit .assertj .JsonAssertions .json ;
5359import static org .assertj .core .api .Assertions .assertThat ;
5460import static org .dependencytrack .resources .v1 .FindingResource .MEDIA_TYPE_SARIF_JSON ;
55- import static org .hamcrest .CoreMatchers .equalTo ;
5661
5762class FindingResourceTest extends ResourceTest {
5863
@@ -619,8 +624,9 @@ void getAllFindingsGroupedByVulnerabilityWithAclEnabled() {
619624 Assertions .assertEquals (1 , json .getJsonObject (2 ).getJsonObject ("vulnerability" ).getInt ("affectedProjectCount" ));
620625 }
621626
622- @ Test
623- void getSARIFFindingsByProjectTest () {
627+ @ ParameterizedTest
628+ @ MethodSource ("getSARIFFindingsByProjectTestParameters" )
629+ void getSARIFFindingsByProjectTest (String query , String expectedResponsePath ) throws Exception {
624630 Project project = qm .createProject ("Acme Example" , null , "1.0" , null , null , null , true , false );
625631 Component c1 = createComponent (project , "Component 1" , "1.1.4" );
626632 Component c2 = createComponent (project , "Component 2" , "2.78.123" );
@@ -629,192 +635,43 @@ void getSARIFFindingsByProjectTest() {
629635 c1 .
setPurl (
"pkg:maven/org.acme/[email protected] ?type=jar" );
630636 c2 .
setPurl (
"pkg:maven/com.xyz/[email protected] ?type=jar" );
631637
632- Vulnerability v1 = createVulnerability ("Vuln-1" , Severity .CRITICAL , "Vuln Title 1" , "This is a description" , null , 80 );
633- Vulnerability v2 = createVulnerability ("Vuln-2" , Severity .HIGH , "Vuln Title 2" , " Yet another description but with surrounding whitespaces " , "" , 46 );
634- Vulnerability v3 = createVulnerability ("Vuln-3" , Severity .LOW , "Vuln Title 3" , "A description-with-hyphens-(and parentheses)" , " Recommendation with whitespaces " , 23 );
638+ Vulnerability v1 = createVulnerability ("Vuln-1" , Severity .CRITICAL , "Vuln Title 1" , "This is a description" , null , 80 , Source .INTERNAL );
639+ Vulnerability v2 = createVulnerability ("Vuln-2" , Severity .HIGH , "Vuln Title 2" , " Yet another description but with surrounding whitespaces " , "" , 46 , Source .INTERNAL );
640+ Vulnerability v3 = createVulnerability ("Vuln-3" , Severity .LOW , "Vuln Title 3" , "A description-with-hyphens-(and parentheses)" , " Recommendation with whitespaces " , 23 , Source .INTERNAL );
641+ Vulnerability v4 = createVulnerability ("Vuln-4" , Severity .MEDIUM , "Vuln Title 4" , "This is a vulnerability that has GITHUB Advisory as a source" , null , 20 , Source .GITHUB );
635642
636- // Note: Same vulnerability added to multiple components to test whether "rules" field doesn't contain duplicates
637643 qm .addVulnerability (v1 , c1 , AnalyzerIdentity .NONE );
638644 qm .addVulnerability (v2 , c1 , AnalyzerIdentity .NONE );
639645 qm .addVulnerability (v3 , c1 , AnalyzerIdentity .NONE );
640646 qm .addVulnerability (v3 , c2 , AnalyzerIdentity .NONE );
647+ qm .addVulnerability (v4 , c2 , AnalyzerIdentity .NONE );
641648
642- Response response = jersey .target (V1_FINDING + "/project/" + project .getUuid ().toString ()).request ()
649+ var target = jersey .target (V1_FINDING + "/project/" + project .getUuid ().toString ());
650+ if (query != null ) {
651+ target = target .queryParam ("source" , query );
652+ }
653+ Response response = target .request ()
643654 .header (HttpHeaders .ACCEPT , MEDIA_TYPE_SARIF_JSON )
644655 .header (X_API_KEY , apiKey )
645656 .get (Response .class );
646657
647658 Assertions .assertEquals (200 , response .getStatus (), 0 );
648659 Assertions .assertEquals (MEDIA_TYPE_SARIF_JSON , response .getHeaderString (HttpHeaders .CONTENT_TYPE ));
649660 final String jsonResponse = getPlainTextBody (response );
661+ final String version = new About ().getVersion ();
662+ final String fullName = "OWASP Dependency-Track - " + version ;
663+ String expectedTemplate = resourceToString (expectedResponsePath , StandardCharsets .UTF_8 );
664+ String expected = expectedTemplate
665+ .replace ("{{VERSION}}" , version )
666+ .replace ("{{FULL_NAME}}" , fullName );
667+ assertThatJson (jsonResponse ).isEqualTo (expected );
668+ }
650669
651- assertThatJson (jsonResponse )
652- .withMatcher ("version" , equalTo (new About ().getVersion ()))
653- .withMatcher ("fullName" , equalTo ("OWASP Dependency-Track - " + new About ().getVersion ()))
654- .isEqualTo (json ("""
655- {
656- "version": "2.1.0",
657- "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json",
658- "runs": [
659- {
660- "tool": {
661- "driver": {
662- "name": "OWASP Dependency-Track",
663- "fullName": "${json-unit.matches:fullName}",
664- "version": "${json-unit.matches:version}",
665- "informationUri": "https://dependencytrack.org/",
666- "rules": [
667- {
668- "id": "Vuln-1",
669- "name": "ImproperNeutralizationOfScript-relatedHtmlTagsInAWebPage(basicXss)",
670- "shortDescription": {
671- "text": "Vuln-1"
672- },
673- "fullDescription": {
674- "text": "This is a description"
675- }
676- },
677- {
678- "id": "Vuln-2",
679- "name": "PathEquivalence:'filename'(trailingSpace)",
680- "shortDescription": {
681- "text": "Vuln-2"
682- },
683- "fullDescription": {
684- "text": "Yet another description but with surrounding whitespaces"
685- }
686- },
687- {
688- "id": "Vuln-3",
689- "name": "RelativePathTraversal",
690- "shortDescription": {
691- "text": "Vuln-3"
692- },
693- "fullDescription": {
694- "text": "A description-with-hyphens-(and parentheses)"
695- }
696- }
697- ]
698- }
699- },
700- "results": [
701- {
702- "ruleId": "Vuln-1",
703- "message": {
704- "text": "This is a description"
705- },
706- "locations": [
707- {
708- "logicalLocations": [
709- {
710- "fullyQualifiedName": "pkg:maven/org.acme/[email protected] ?type=jar" 711- }
712- ]
713- }
714- ],
715- "level": "error",
716- "properties": {
717- "name": "Component 1",
718- "group": "org.acme",
719- "version": "1.1.4",
720- "source": "INTERNAL",
721- "cweId": "80",
722- "cvssV3BaseScore": "",
723- "epssScore": "",
724- "epssPercentile": "",
725- "severityRank": "0",
726- "recommendation": ""
727- }
728- },
729- {
730- "ruleId": "Vuln-2",
731- "message": {
732- "text": "Yet another description but with surrounding whitespaces"
733- },
734- "locations": [
735- {
736- "logicalLocations": [
737- {
738- "fullyQualifiedName": "pkg:maven/org.acme/[email protected] ?type=jar" 739- }
740- ]
741- }
742- ],
743- "level": "error",
744- "properties": {
745- "name": "Component 1",
746- "group": "org.acme",
747- "version": "1.1.4",
748- "source": "INTERNAL",
749- "cweId": "46",
750- "cvssV3BaseScore": "",
751- "epssScore": "",
752- "epssPercentile": "",
753- "severityRank": "1",
754- "recommendation": ""
755- }
756- },
757- {
758- "ruleId": "Vuln-3",
759- "message": {
760- "text": "A description-with-hyphens-(and parentheses)"
761- },
762- "locations": [
763- {
764- "logicalLocations": [
765- {
766- "fullyQualifiedName": "pkg:maven/org.acme/[email protected] ?type=jar" 767- }
768- ]
769- }
770- ],
771- "level": "note",
772- "properties": {
773- "name": "Component 1",
774- "group": "org.acme",
775- "version": "1.1.4",
776- "source": "INTERNAL",
777- "cweId": "23",
778- "cvssV3BaseScore": "",
779- "epssScore": "",
780- "epssPercentile": "",
781- "severityRank": "3",
782- "recommendation": "Recommendation with whitespaces"
783- }
784- },
785- {
786- "ruleId": "Vuln-3",
787- "message": {
788- "text": "A description-with-hyphens-(and parentheses)"
789- },
790- "locations": [
791- {
792- "logicalLocations": [
793- {
794- "fullyQualifiedName": "pkg:maven/com.xyz/[email protected] ?type=jar" 795- }
796- ]
797- }
798- ],
799- "level": "note",
800- "properties": {
801- "name": "Component 2",
802- "group": "com.xyz",
803- "version": "2.78.123",
804- "source": "INTERNAL",
805- "cweId": "23",
806- "cvssV3BaseScore": "",
807- "epssScore": "",
808- "epssPercentile": "",
809- "severityRank": "3",
810- "recommendation": "Recommendation with whitespaces"
811- }
812- }
813- ]
814- }
815- ]
816- }
817- """ ));
670+ private static Stream <Arguments > getSARIFFindingsByProjectTestParameters () {
671+ return Stream .of (
672+ Arguments .of ("INTERNAL" , "/unit/sarif/expected-internal.sarif.json" ),
673+ Arguments .of (null , "/unit/sarif/expected-all.sarif.json" )
674+ );
818675 }
819676
820677 private Component createComponent (Project project , String name , String version ) {
@@ -834,28 +691,15 @@ private Vulnerability createVulnerability(String vulnId, Severity severity) {
834691 return qm .createVulnerability (vulnerability , false );
835692 }
836693
837- private Vulnerability createVulnerability (String vulnId , Severity severity , String title , String description , String recommendation , Integer cweId ) {
694+ private Vulnerability createVulnerability (String vulnId , Severity severity , String title , String description , String recommendation , Integer cweId , Vulnerability . Source source ) {
838695 Vulnerability vulnerability = new Vulnerability ();
839696 vulnerability .setVulnId (vulnId );
840- vulnerability .setSource (Vulnerability . Source . INTERNAL );
697+ vulnerability .setSource (source );
841698 vulnerability .setSeverity (severity );
842699 vulnerability .setTitle (title );
843700 vulnerability .setDescription (description );
844701 vulnerability .setRecommendation (recommendation );
845702 vulnerability .setCwes (List .of (cweId ));
846703 return qm .createVulnerability (vulnerability , false );
847704 }
848-
849- private static String getSARIFLevelFromSeverity (Severity severity ) {
850- if (Severity .LOW == severity || Severity .INFO == severity ) {
851- return "note" ;
852- }
853- if (Severity .MEDIUM == severity ) {
854- return "warning" ;
855- }
856- if (Severity .HIGH == severity || Severity .CRITICAL == severity ) {
857- return "error" ;
858- }
859- return "none" ;
860- }
861705}
0 commit comments