def test_parser(self): parser = SonarQubeApiImporter() findings = parser.get_findings(None, self.test) self.assertEqual(2, len(findings)) finding = findings[0] self.assertEqual('Remove this useless assignment to local variable "currentValue".', finding.title) self.assertEqual(None, finding.cwe) self.assertEqual('', finding.description) self.assertEqual('', finding.references) self.assertEqual('Medium', finding.severity) self.assertEqual(242, finding.line) self.assertEqual('internal.dummy.project:src/main/javascript/TranslateDirective.ts', finding.file_path)
def test_parser(self): parser = SonarQubeApiImporter() findings = parser.get_findings(None, self.test) self.assertEqual( findings[0].title, '"password" detected here, make sure this is not a hard-coded credential.' ) self.assertEqual(findings[0].cwe, 798) self.assertMultiLineEqual( '**Ask Yourself Whether**' '\n\n ' '* Credentials allows access to a sensitive component like a database, a file storage, an API or a service. ' '\n ' '* Credentials are used in production environments. ' '\n ' '* Application re-distribution is required before updating the credentials. ' '\n\n' 'There is a risk if you answered yes to any of those questions.' '\n\n', findings[0].description) self.assertEqual(str(findings[0].severity), 'Info') self.assertMultiLineEqual( '[CVE-2019-13466](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-13466)' '\n' '[CVE-2018-15389](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-15389)' '\n' '[OWASP Top 10 2017 Category A2](https://www.owasp.org/index.php/Top_10-2017_A2-Broken_Authentication)' '\n' '[MITRE, CWE-798](http://cwe.mitre.org/data/definitions/798)' '\n' '[MITRE, CWE-259](http://cwe.mitre.org/data/definitions/259)' '\n' '[CERT, MSC03-J.](https://wiki.sei.cmu.edu/confluence/x/OjdGBQ)' '\n' '[SANS Top 25](https://www.sans.org/top25-software-errors/#cat3)' '\n' '[Hard Coded Password](http://h3xstream.github.io/find-sec-bugs/bugs.htm#HARD_CODE_PASSWORD)' '\n', findings[0].references) self.assertEqual( str(findings[0].file_path), 'internal.dummy.project:spec/support/user_fixture.rb') self.assertEqual(findings[0].line, 9) self.assertEqual(findings[0].active, True) self.assertEqual(findings[0].verified, False) self.assertEqual(findings[0].false_p, False) self.assertEqual(findings[0].duplicate, False) self.assertEqual(findings[0].out_of_scope, False) self.assertEqual(findings[0].static_finding, True) self.assertEqual(findings[0].scanner_confidence, 1) self.assertEqual(str(findings[0].sonarqube_issue), 'AXgm6Z-ophPPY0C1qhRq')
def update_sonarqube_finding(self, finding): sonarqube_issue = finding.sonarqube_issue if not sonarqube_issue: return logger.debug( "Checking if finding '{}' needs to be updated in SonarQube".format( finding)) client, _ = SonarQubeApiImporter.prepare_client(finding.test) # we don't care about config, each finding knows which config was used during import target_status = self.get_sonarqube_status_for(finding) issue = client.get_issue(sonarqube_issue.key) if issue: # Issue could have disappeared in SQ because a previous scan has resolved the issue as fixed if issue.get('resolution'): current_status = '{} / {}'.format(issue.get('status'), issue.get('resolution')) else: current_status = issue.get('status') logger.debug( "--> SQ Current status: {}. Current target status: {}".format( current_status, target_status)) transitions = self.get_sonarqube_required_transitions_for( current_status, target_status) if transitions: logger.info( "Updating finding '{}' in SonarQube".format(finding)) for transition in transitions: client.transition_issue(sonarqube_issue.key, transition) # Track Defect Dojo has updated the SonarQube issue Sonarqube_Issue_Transition.objects.create( sonarqube_issue=finding.sonarqube_issue, # not sure if this is needed, but looks like the original author decided to send display status to sonarcube # we changed Accepted into Risk Accepted, but we change it back to be sure we don't break the integration finding_status=finding.status().replace( 'Risk Accepted', 'Accepted') if finding.status() else finding.status(), sonarqube_status=current_status, transitions=','.join(transitions), )
def update(self, finding): sonarqube_issue = finding.sonarqube_issue if not sonarqube_issue: return client, _ = SonarQubeApiImporter.prepare_client(finding.test) # we don't care about config, each finding knows which config was used during import issue = client.get_issue(sonarqube_issue.key) if issue: # Issue could have disappeared in SQ because a previous scan has resolved the issue as fixed current_status = issue.get('resolution') or issue.get('status') current_finding_status = self.get_sonarqube_status_for(finding) logger.debug("--> SQ Current status: {}. Finding status: {}".format(current_status, current_finding_status)) if current_status != "OPEN" and current_finding_status != current_status: logger.info("Original SonarQube issue '{}' has changed. Updating DefectDojo finding '{}'...".format( sonarqube_issue, finding )) self.update_finding_status(finding, current_status)
def import_parser_factory(file, test, active, verified, scan_type=None): if scan_type is None: scan_type = test.test_type.name if scan_type == "Burp Scan": parser = BurpXmlParser(file, test) elif scan_type == "Burp Enterprise Scan": parser = BurpEnterpriseHtmlParser(file, test) elif scan_type == "Nessus Scan": filename = file.name.lower() if filename.endswith("csv"): parser = NessusCSVParser(file, test) elif filename.endswith("xml") or filename.endswith("nessus"): parser = NessusXMLParser(file, test) elif scan_type == "Clair Scan": parser = ClairParser(file, test) elif scan_type == "Nmap Scan": parser = NmapXMLParser(file, test) elif scan_type == "Nikto Scan": parser = NiktoXMLParser(file, test) elif scan_type == "Nexpose Scan": parser = NexposeFullXmlParser(file, test) elif scan_type == "Veracode Scan": parser = VeracodeXMLParser(file, test) elif scan_type == "Checkmarx Scan": parser = CheckmarxXMLParser(file, test) elif scan_type == "Checkmarx Scan detailed": parser = CheckmarxXMLParser(file, test, 'detailed') elif scan_type == "Contrast Scan": parser = ContrastCSVParser(file, test) elif scan_type == "Crashtest Security JSON File": parser = CrashtestSecurityJsonParser(file, test) elif scan_type == "Crashtest Security XML File": parser = CrashtestSecurityXmlParser(file, test) elif scan_type == "Bandit Scan": parser = BanditParser(file, test) elif scan_type == "ESLint Scan": parser = ESLintParser(file, test) elif scan_type == "ZAP Scan": parser = ZapXmlParser(file, test) elif scan_type == "AppSpider Scan": parser = AppSpiderXMLParser(file, test) elif scan_type == "Arachni Scan": parser = ArachniJSONParser(file, test) elif scan_type == 'VCG Scan': parser = VCGParser(file, test) elif scan_type == 'Dependency Check Scan': parser = DependencyCheckParser(file, test) elif scan_type == 'Dependency Track Finding Packaging Format (FPF) Export': parser = DependencyTrackParser(file, test) elif scan_type == 'Retire.js Scan': parser = RetireJsParser(file, test) elif scan_type == 'Node Security Platform Scan': parser = NspParser(file, test) elif scan_type == 'NPM Audit Scan': parser = NpmAuditParser(file, test) elif scan_type == 'PHP Symfony Security Check': parser = PhpSymfonySecurityCheckParser(file, test) elif scan_type == 'Generic Findings Import': parser = GenericFindingUploadCsvParser(file, test, active, verified) elif scan_type == 'Qualys Scan': parser = QualysParser(file, test) elif scan_type == 'Qualys Infrastructure Scan (WebGUI XML)': parser = QualysInfraScanParser(file, test) elif scan_type == 'Qualys Webapp Scan': parser = QualysWebAppParser(file, test) elif scan_type == "OpenVAS CSV": parser = OpenVASUploadCsvParser(file, test) elif scan_type == 'Snyk Scan': parser = SnykParser(file, test) elif scan_type == 'SKF Scan': parser = SKFCsvParser(file, test) elif scan_type == 'SSL Labs Scan': parser = SSLlabsParser(file, test) elif scan_type == 'Trufflehog Scan': parser = TruffleHogJSONParser(file, test) elif scan_type == 'Clair Klar Scan': parser = ClairKlarParser(file, test) elif scan_type == 'Gosec Scanner': parser = GosecScannerParser(file, test) elif scan_type == 'Trustwave Scan (CSV)': parser = TrustwaveUploadCsvParser(file, test) elif scan_type == 'Netsparker Scan': parser = NetsparkerParser(file, test) elif scan_type == 'PHP Security Audit v2': parser = PhpSecurityAuditV2(file, test) elif scan_type == 'Acunetix Scan': parser = AcunetixScannerParser(file, test) elif scan_type == 'Fortify Scan': parser = FortifyXMLParser(file, test) elif scan_type == 'SonarQube Scan': parser = SonarQubeHtmlParser(file, test) elif scan_type == 'SonarQube Scan detailed': parser = SonarQubeHtmlParser(file, test, 'detailed') elif scan_type == SCAN_SONARQUBE_API: parser = SonarQubeApiImporter(test) elif scan_type == 'MobSF Scan': parser = MobSFParser(file, test) elif scan_type == 'AWS Scout2 Scan': parser = AWSScout2Parser(file, test) elif scan_type == 'AWS Prowler Scan': parser = AWSProwlerParser(file, test) elif scan_type == 'Brakeman Scan': parser = BrakemanScanParser(file, test) elif scan_type == 'SpotBugs Scan': parser = SpotbugsXMLParser(file, test) elif scan_type == 'Safety Scan': parser = SafetyParser(file, test) elif scan_type == 'DawnScanner Scan': parser = DawnScannerParser(file, test) elif scan_type == 'Anchore Engine Scan': parser = AnchoreEngineScanParser(file, test) elif scan_type == 'Bundler-Audit Scan': parser = BundlerAuditParser(file, test) elif scan_type == 'Twistlock Image Scan': parser = TwistlockParser(file, test) elif scan_type == 'IBM AppScan DAST': parser = IbmAppScanDASTXMLParser(file, test) elif scan_type == 'Kiuwan Scan': parser = KiuwanCSVParser(file, test) elif scan_type == 'Blackduck Hub Scan': parser = BlackduckHubCSVParser(file, test) elif scan_type == 'Blackduck Component Risk': parser = BlackduckHubParser(file, test) elif scan_type == 'Sonatype Application Scan': parser = SonatypeJSONParser(file, test) elif scan_type == 'Openscap Vulnerability Scan': parser = OpenscapXMLParser(file, test) elif scan_type == 'Immuniweb Scan': parser = ImmuniwebXMLParser(file, test) elif scan_type == 'Wapiti Scan': parser = WapitiXMLParser(file, test) elif scan_type == 'Cobalt.io Scan': parser = CobaltCSVParser(file, test) elif scan_type == 'Mozilla Observatory Scan': parser = MozillaObservatoryJSONParser(file, test) elif scan_type == 'Whitesource Scan': parser = WhitesourceJSONParser(file, test) elif scan_type == 'Microfocus Webinspect Scan': parser = MicrofocusWebinspectXMLParser(file, test) elif scan_type == 'Wpscan': parser = WpscanJSONParser(file, test) elif scan_type == 'Sslscan': parser = SslscanXMLParser(file, test) elif scan_type == 'JFrog Xray Scan': parser = XrayJSONParser(file, test) elif scan_type == 'Sslyze Scan': parser = SslyzeXmlParser(file, test) elif scan_type == 'Testssl Scan': parser = TestsslCSVParser(file, test) elif scan_type == 'Hadolint Dockerfile check': parser = HadolintParser(file, test) elif scan_type == 'Aqua Scan': parser = AquaJSONParser(file, test) elif scan_type == 'HackerOne Cases': parser = HackerOneJSONParser(file, test) elif scan_type == 'Xanitizer Scan': parser = XanitizerXMLParser(file, test) elif scan_type == 'Trivy Scan': parser = TrivyParser(file, test) elif scan_type == 'Outpost24 Scan': parser = Outpost24Parser(file, test) elif scan_type == 'DSOP Scan': parser = DsopParser(file, test) elif scan_type == 'Anchore Enterprise Policy Check': parser = AnchoreEnterprisePolicyCheckParser(file, test) elif scan_type == 'Gitleaks Scan': parser = GitleaksJSONParser(file, test) elif scan_type == 'Harbor Vulnerability Scan': parser = HarborVulnerabilityParser(file, test) elif scan_type == 'Github Vulnerability Scan': parser = GithubVulnerabilityParser(file, test) elif scan_type == 'Choctaw Hog Scan': parser = ChoctawhogParser(file, test) elif scan_type == 'GitLab SAST Report': parser = GitlabSastReportParser(file, test) elif scan_type == 'Yarn Audit Scan': parser = YarnAuditParser(file, test) elif scan_type == 'BugCrowd Scan': parser = BugCrowdCSVParser(file, test) elif scan_type == 'HuskyCI Report': parser = HuskyCIReportParser(file, test) elif scan_type == 'CCVS Report': parser = CCVSReportParser(file, test) else: raise ValueError('Unknown Test Type') return parser
def test_parse_file_with_one_cwe_and_one_no_cwe_vulns(self): parser = SonarQubeApiImporter() findings = parser.get_findings(None, self.test) self.assertEqual(2, len(findings))
def test_parser(self): parser = SonarQubeApiImporter() findings = parser.get_findings(None, self.test) self.assertEqual(2, len(findings))
def test_parser(self): with self.assertRaisesRegex(Exception, 'No SonarQube tool is configured.'): SonarQubeApiImporter.prepare_client(self.test)
def test_product_mismatch(self): with self.assertRaisesRegex(Exception, 'Product API Scan Configuration and Product do not match.'): SonarQubeApiImporter.prepare_client(self.other_test)
def test_parser(self): with self.assertRaisesRegex(Exception, 'More than one Product API Scan Configuration has been configured, but none of them has been chosen.'): SonarQubeApiImporter.prepare_client(self.test)
def test_parser(self): with self.assertRaisesRegex(Exception, 'More than one Tool Configuration for SonarQube exists.'): SonarQubeApiImporter.prepare_client(self.test)
def test_parser(self): with self.assertRaisesRegex( Exception, 'It has configured more than one SonarQube tool.'): SonarQubeApiImporter.prepare_client(self.test)
def test_product_mismatch(self): with self.assertRaisesRegex( Exception, 'Product SonarQube Configuration and "Product" mismatch'): SonarQubeApiImporter.prepare_client(self.other_test)
def test_parser(self): with self.assertRaisesRegex( Exception, 'It has configured more than one Product SonarQube Configuration but non of them has been choosen.' ): SonarQubeApiImporter.prepare_client(self.test)
def test_parse_file_with_one_cwe_and_one_no_cwe_vulns(self): parser = SonarQubeApiImporter(self.test) self.assertEqual(2, len(parser.items))