def test_import_scan(self): scan = open(get_unit_tests_path() + "/scans/sarif/spotbugs.sarif") scan_type = SarifParser().get_scan_types()[0] # SARIF format implement the new method user, _ = User.objects.get_or_create(username="******") user_reporter, _ = User.objects.get_or_create(username="******") product_type, _ = Product_Type.objects.get_or_create(name="test2") product, _ = Product.objects.get_or_create( name="TestDojoDefaultImporter2", prod_type=product_type, ) engagement, _ = Engagement.objects.get_or_create( name="Test Create Engagement2", product=product, target_start=timezone.now(), target_end=timezone.now(), ) importer = Importer() scan_date = None environment, _ = Development_Environment.objects.get_or_create(name="Development") test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, active=True, verified=True, tags=None, minimum_severity=None, user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) self.assertEqual(f"SpotBugs Scan ({scan_type})", test.test_type.name) self.assertEqual(56, len_new_findings) self.assertEqual(0, len_closed_findings)
def test_import_scan_without_test_scan_type(self): # GitLabSastParser implements get_tests but report has no scanner name scan = open(get_unit_tests_path() + "/scans/gitlab_sast/gl-sast-report-1-vuln.json") scan_type = GitlabSastParser().get_scan_types()[0] user, _ = User.objects.get_or_create(username="******") user_reporter, _ = User.objects.get_or_create(username="******") product_type, _ = Product_Type.objects.get_or_create(name="test2") product, _ = Product.objects.get_or_create( name="TestDojoDefaultImporter2", prod_type=product_type, ) engagement, _ = Engagement.objects.get_or_create( name="Test Create Engagement2", product=product, target_start=timezone.now(), target_end=timezone.now(), ) importer = Importer() scan_date = None environment, _ = Development_Environment.objects.get_or_create(name="Development") test, len_new_findings, len_closed_findings, _ = importer.import_scan(scan, scan_type, engagement, lead=None, environment=environment, active=True, verified=True, tags=None, minimum_severity=None, user=user, endpoints_to_add=None, scan_date=scan_date, version=None, branch_tag=None, build_id=None, commit_hash=None, push_to_jira=None, close_old_findings=False, group_by=None, api_scan_configuration=None) self.assertEqual("GitLab SAST Report", test.test_type.name) self.assertEqual(1, len_new_findings) self.assertEqual(0, len_closed_findings)
def test_parse_findings(self): scan_type = "Acunetix Scan" scan = open("dojo/unittests/scans/acunetix/one_finding.xml") user, created = User.objects.get_or_create(username="******") product_type, created = Product_Type.objects.get_or_create(name="test") if created: product_type.save() product, created = Product.objects.get_or_create( name="TestDojoDefaultImporter", prod_type=product_type, ) if created: product.save() engagement_name = "Test Create Engagement" engagement, created = Engagement.objects.get_or_create( name=engagement_name, product=product, target_start=timezone.now(), target_end=timezone.now(), ) if created: engagement.save() lead = None environment = None # boot importer = Importer() # create the test # by defaut test_type == scan_type test = importer.create_test(scan_type, scan_type, engagement, lead, environment) # parse the findings parser = get_parser(scan_type) parsed_findings = parser.get_findings(scan, test) # process minimum_severity = "Info" active = True verified = True new_findings = importer.process_parsed_findings( test, parsed_findings, scan_type, user, active, verified, minimum_severity=minimum_severity, ) for finding in new_findings: self.assertIn(finding.numerical_severity, ["S0", "S1", "S2", "S3", "S4"])
def import_scan_results(request, eid=None, pid=None): engagement = None form = ImportScanForm() cred_form = CredMappingForm() finding_count = 0 jform = None user = request.user if eid: engagement = get_object_or_404(Engagement, id=eid) engagement_or_product = engagement cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id') elif pid: product = get_object_or_404(Product, id=pid) engagement_or_product = product elif not user.is_staff: raise PermissionDenied user_has_permission_or_403(user, engagement_or_product, Permissions.Import_Scan_Result) push_all_jira_issues = jira_helper.is_push_all_issues(engagement_or_product) if request.method == "POST": form = ImportScanForm(request.POST, request.FILES) cred_form = CredMappingForm(request.POST) cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter( engagement=engagement).order_by('cred_id') if jira_helper.get_jira_project(engagement_or_product): jform = JIRAImportScanForm(request.POST, push_all=push_all_jira_issues, prefix='jiraform') logger.debug('jform valid: %s', jform.is_valid()) logger.debug('jform errors: %s', jform.errors) if form.is_valid() and (jform is None or jform.is_valid()): scan = request.FILES.get('file', None) scan_date = form.cleaned_data['scan_date'] minimum_severity = form.cleaned_data['minimum_severity'] active = form.cleaned_data['active'] verified = form.cleaned_data['verified'] scan_type = request.POST['scan_type'] tags = form.cleaned_data['tags'] version = form.cleaned_data['version'] branch_tag = form.cleaned_data.get('branch_tag', None) build_id = form.cleaned_data.get('build_id', None) commit_hash = form.cleaned_data.get('commit_hash', None) api_scan_configuration = form.cleaned_data.get('api_scan_configuration', None) service = form.cleaned_data.get('service', None) close_old_findings = form.cleaned_data.get('close_old_findings', None) # Will save in the provided environment or in the `Development` one if absent environment_id = request.POST.get('environment', 'Development') environment = Development_Environment.objects.get(id=environment_id) group_by = form.cleaned_data.get('group_by', None) # TODO move to form validation? if scan and is_scan_file_too_large(scan): messages.add_message(request, messages.ERROR, "Report file is too large. Maximum supported size is {} MB".format(settings.SCAN_FILE_MAX_SIZE), extra_tags='alert-danger') return HttpResponseRedirect(reverse('import_scan_results', args=(engagement,))) # Allows for a test to be imported with an engagement created on the fly if engagement is None: engagement = Engagement() engagement.name = "AdHoc Import - " + strftime("%a, %d %b %Y %X", timezone.now().timetuple()) engagement.threat_model = False engagement.api_test = False engagement.pen_test = False engagement.check_list = False engagement.target_start = timezone.now().date() engagement.target_end = timezone.now().date() engagement.product = product engagement.active = True engagement.status = 'In Progress' engagement.version = version engagement.branch_tag = branch_tag engagement.build_id = build_id engagement.commit_hash = commit_hash engagement.save() # can't use helper as when push_all_jira_issues is True, the checkbox gets disabled and is always false # push_to_jira = jira_helper.is_push_to_jira(new_finding, jform.cleaned_data.get('push_to_jira')) push_to_jira = push_all_jira_issues or (jform and jform.cleaned_data.get('push_to_jira')) error = False # Save newly added endpoints added_endpoints = save_endpoints_to_add(form.endpoints_to_add_list, engagement.product) try: importer = Importer() test, finding_count, closed_finding_count = importer.import_scan(scan, scan_type, engagement, user, environment, active=active, verified=verified, tags=tags, minimum_severity=minimum_severity, endpoints_to_add=list(form.cleaned_data['endpoints']) + added_endpoints, scan_date=scan_date, version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, push_to_jira=push_to_jira, close_old_findings=close_old_findings, group_by=group_by, api_scan_configuration=api_scan_configuration, service=service) message = f'{scan_type} processed a total of {finding_count} findings' if close_old_findings: message = message + ' and closed %d findings' % (closed_finding_count) message = message + "." add_success_message_to_response(message) except Exception as e: logger.exception(e) add_error_message_to_response('An exception error occurred during the report import:%s' % str(e)) error = True # Save the credential to the test if cred_form.is_valid(): if cred_form.cleaned_data['cred_user']: # Select the credential mapping object from the selected list and only allow if the credential is associated with the product cred_user = Cred_Mapping.objects.filter( pk=cred_form.cleaned_data['cred_user'].id, engagement=eid).first() new_f = cred_form.save(commit=False) new_f.test = test new_f.cred_id = cred_user.cred_id new_f.save() if not error: return HttpResponseRedirect( reverse('view_test', args=(test.id, ))) prod_id = None custom_breadcrumb = None title = "Import Scan Results" if engagement: prod_id = engagement.product.id product_tab = Product_Tab(prod_id, title=title, tab="engagements") product_tab.setEngagement(engagement) else: prod_id = pid custom_breadcrumb = {"", ""} product_tab = Product_Tab(prod_id, title=title, tab="findings") if jira_helper.get_jira_project(engagement_or_product): jform = JIRAImportScanForm(push_all=push_all_jira_issues, prefix='jiraform') form.fields['endpoints'].queryset = Endpoint.objects.filter(product__id=product_tab.product.id) form.fields['api_scan_configuration'].queryset = Product_API_Scan_Configuration.objects.filter(product__id=product_tab.product.id) return render(request, 'dojo/import_scan_results.html', {'form': form, 'product_tab': product_tab, 'engagement_or_product': engagement_or_product, 'custom_breadcrumb': custom_breadcrumb, 'title': title, 'cred_form': cred_form, 'jform': jform, 'scan_types': get_scan_types_sorted(), })
def save(self, push_to_jira=False): data = self.validated_data close_old_findings = data['close_old_findings'] active = data['active'] verified = data['verified'] minimum_severity = data['minimum_severity'] scan_type = data['scan_type'] endpoint_to_add = data['endpoint_to_add'] scan_date = data['scan_date'] # Will save in the provided environment or in the `Development` one if absent version = data.get('version', None) build_id = data.get('build_id', None) branch_tag = data.get('branch_tag', None) commit_hash = data.get('commit_hash', None) environment_name = data.get('environment', 'Development') environment = Development_Environment.objects.get( name=environment_name) tags = None if 'tags' in data: logger.debug('import scan tags: %s', data['tags']) tags = data['tags'] engagement = data['engagement'] lead = data['lead'] scan = data.get('file', None) endpoints_to_add = [endpoint_to_add] if endpoint_to_add else None importer = Importer() try: test, finding_count, closed_finding_count = importer.import_scan( scan, scan_type, engagement, lead, environment, active=active, verified=verified, tags=tags, minimum_severity=minimum_severity, endpoints_to_add=endpoints_to_add, scan_date=scan_date, version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, push_to_jira=push_to_jira, close_old_findings=close_old_findings) # convert to exception otherwise django rest framework will swallow them as 400 error # exceptions are already logged in the importer except SyntaxError as se: raise Exception(se) except ValueError as ve: raise Exception(ve) # return the id of the created test, can't find a better way because this is not a ModelSerializer.... self.fields['test'] = serializers.IntegerField(read_only=True, default=test.id) return test