def delete_engagement(request, eid): engagement = get_object_or_404(Engagement, pk=eid) product = engagement.product form = DeleteEngagementForm(instance=engagement) if request.method == 'POST': if 'id' in request.POST and str(engagement.id) == request.POST['id']: form = DeleteEngagementForm(request.POST, instance=engagement) if form.is_valid(): del engagement.tags engagement.delete() messages.add_message( request, messages.SUCCESS, 'Engagement and relationships removed.', extra_tags='alert-success') return HttpResponseRedirect(reverse("view_engagements", args=(product.id, ))) collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([engagement]) rels = collector.nested() product_tab = Product_Tab(product.id, title="Delete Engagement", tab="engagements") product_tab.setEngagement(engagement) return render(request, 'dojo/delete_engagement.html', { 'product_tab': product_tab, 'engagement': engagement, 'form': form, 'rels': rels, })
def edit_test(request, tid): test = get_object_or_404(Test, pk=tid) form = TestForm(instance=test) if request.method == 'POST': form = TestForm(request.POST, instance=test) if form.is_valid(): new_test = form.save() tags = request.POST.getlist('tags') t = ", ".join(tags) new_test.tags = t messages.add_message(request, messages.SUCCESS, 'Test saved.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_engagement', args=(test.engagement.id,))) form.initial['target_start'] = test.target_start.date() form.initial['target_end'] = test.target_end.date() form.initial['tags'] = [tag.name for tag in test.tags] product_tab = Product_Tab(test.engagement.product.id, title="Edit Test", tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/edit_test.html', {'test': test, 'product_tab': product_tab, 'form': form, })
def delete_test(request, tid): test = get_object_or_404(Test, pk=tid) eng = test.engagement form = DeleteTestForm(instance=test) if request.method == 'POST': if 'id' in request.POST and str(test.id) == request.POST['id']: form = DeleteTestForm(request.POST, instance=test) if form.is_valid(): del test.tags test.delete() messages.add_message(request, messages.SUCCESS, 'Test and relationships removed.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_engagement', args=(eng.id,))) collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([test]) rels = collector.nested() product_tab = Product_Tab(test.engagement.product.id, title="Delete Test", tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/delete_test.html', {'test': test, 'product_tab': product_tab, 'form': form, 'rels': rels, 'deletable_objects': rels, })
def action_history(request, cid, oid): try: ct = ContentType.objects.get_for_id(cid) obj = ct.get_object_for_this_type(pk=oid) except KeyError: raise Http404() product_id = None active_tab = None finding = None test = False object_value = None if str(ct) == "product": product_id = obj.id active_tab = "overview" object_value = Product.objects.get(id=obj.id) elif str(ct) == "engagement": object_value = Engagement.objects.get(id=obj.id) product_id = object_value.product.id active_tab = "engagements" elif str(ct) == "test": object_value = Test.objects.get(id=obj.id) product_id = object_value.engagement.product.id active_tab = "engagements" test = True elif str(ct) == "finding": object_value = Finding.objects.get(id=obj.id) product_id = object_value.test.engagement.product.id active_tab = "findings" finding = object_value elif str(ct) == "endpoint": object_value = Endpoint.objects.get(id=obj.id) product_id = object_value.product.id active_tab = "endpoints" product_tab = None if product_id: product_tab = Product_Tab(product_id, title="History", tab=active_tab) if active_tab == "engagements": if str(ct) == "engagement": product_tab.setEngagement(object_value) else: product_tab.setEngagement(object_value.engagement) history = LogEntry.objects.filter(content_type=ct, object_pk=obj.id).order_by('-timestamp') history = LogEntryFilter(request.GET, queryset=history) paged_history = get_page_items(request, history.qs, 25) return render(request, 'dojo/action_history.html', {"history": paged_history, 'product_tab': product_tab, "filtered": history, "obj": obj, "test": test, "object_value": object_value, "finding": finding })
def upload_risk(request, eid): eng = Engagement.objects.get(id=eid) # exclude the findings already accepted exclude_findings = [ finding.id for ra in eng.risk_acceptance.all() for finding in ra.accepted_findings.all() ] eng_findings = Finding.objects.filter(active="True", verified="True", duplicate="False", test__in=eng.test_set.all()) \ .exclude(id__in=exclude_findings).order_by('title') if request.method == 'POST': form = UploadRiskForm(request.POST, request.FILES) if form.is_valid(): findings = form.cleaned_data['accepted_findings'] for finding in findings: finding.active = False finding.save() risk = form.save(commit=False) risk.reporter = form.cleaned_data['reporter'] risk.expiration_date = form.cleaned_data['expiration_date'] risk.accepted_by = form.cleaned_data['accepted_by'] risk.compensating_control = form.cleaned_data['compensating_control'] risk.path = form.cleaned_data['path'] risk.save() # have to save before findings can be added risk.accepted_findings = findings if form.cleaned_data['notes']: notes = Notes( entry=form.cleaned_data['notes'], author=request.user, date=timezone.now()) notes.save() risk.notes.add(notes) risk.save() # saving notes and findings eng.risk_acceptance.add(risk) eng.save() messages.add_message( request, messages.SUCCESS, 'Risk exception saved.', extra_tags='alert-success') return HttpResponseRedirect( reverse('view_engagement', args=(eid, ))) else: form = UploadRiskForm(initial={'reporter': request.user}) form.fields["accepted_findings"].queryset = eng_findings product_tab = Product_Tab(eng.product.id, title="Upload Risk Exception", tab="engagements") product_tab.setEngagement(eng) return render(request, 'dojo/up_risk.html', { 'eng': eng, 'product_tab': product_tab, 'form': form })
def view_object_eng(request, id): object_queryset = Objects_Engagement.objects.filter(engagement=id).order_by('object_id__path', 'object_id__folder', 'object_id__artifact') engagement = Engagement.objects.get(id=id) product_tab = Product_Tab(engagement.product.id, title="Tracked Files, Folders and Artifacts on a Product", tab="engagements") product_tab.setEngagement(engagement) return render(request, 'dojo/view_objects_eng.html', { 'object_queryset': object_queryset, 'product_tab': product_tab, 'id': id })
def view_test(request, tid): test = Test.objects.get(id=tid) prod = test.engagement.product auth = request.user.is_staff or request.user in prod.authorized_users.all() if not auth: # will render 403 raise PermissionDenied notes = test.notes.all() person = request.user.username findings = Finding.objects.filter(test=test).order_by('numerical_severity') stub_findings = Stub_Finding.objects.filter(test=test) cred_test = Cred_Mapping.objects.filter(test=test).select_related('cred_id').order_by('cred_id') creds = Cred_Mapping.objects.filter(engagement=test.engagement).select_related('cred_id').order_by('cred_id') if request.method == 'POST' and request.user.is_staff: form = NoteForm(request.POST) if form.is_valid(): new_note = form.save(commit=False) new_note.author = request.user new_note.date = timezone.now() new_note.save() test.notes.add(new_note) form = NoteForm() url = request.build_absolute_uri(reverse("view_test", args=(test.id,))) title = "Test: %s on %s" % (test.test_type.name, test.engagement.product.name) process_notifications(request, new_note, url, title) messages.add_message(request, messages.SUCCESS, 'Note added successfully.', extra_tags='alert-success') else: form = NoteForm() fpage = get_page_items(request, findings, 25) sfpage = get_page_items(request, stub_findings, 25) show_re_upload = any(test.test_type.name in code for code in ImportScanForm.SCAN_TYPE_CHOICES) product_tab = Product_Tab(prod.id, title="Test", tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/view_test.html', {'test': test, 'product_tab': product_tab, 'findings': fpage, 'findings_count': findings.count(), 'stub_findings': sfpage, 'form': form, 'notes': notes, 'person': person, 'request': request, 'show_re_upload': show_re_upload, 'creds': creds, 'cred_test': cred_test })
def complete_checklist(request, eid): eng = get_object_or_404(Engagement, id=eid) add_breadcrumb( parent=eng, title="Complete checklist", top_level=False, request=request) if request.method == 'POST': tests = Test.objects.filter(engagement=eng) findings = Finding.objects.filter(test__in=tests).all() form = CheckForm(request.POST, findings=findings) if form.is_valid(): cl = form.save(commit=False) try: check_l = Check_List.objects.get(engagement=eng) cl.id = check_l.id cl.save() form.save_m2m() except: cl.engagement = eng cl.save() form.save_m2m() pass messages.add_message( request, messages.SUCCESS, 'Checklist saved.', extra_tags='alert-success') return HttpResponseRedirect( reverse('view_engagement', args=(eid, ))) else: tests = Test.objects.filter(engagement=eng) findings = Finding.objects.filter(test__in=tests).all() form = CheckForm(findings=findings) product_tab = Product_Tab(eng.product.id, title="Checklist", tab="engagements") product_tab.setEngagement(eng) return render(request, 'dojo/checklist.html', { 'form': form, 'product_tab': product_tab, 'eid': eng.id, 'findings': findings, })
def view_endpoint(request, eid): endpoint = get_object_or_404(Endpoint, id=eid) host = endpoint.host_no_port endpoints = Endpoint.objects.filter(host__regex="^" + host + ":?", product=endpoint.product).distinct() endpoint_metadata = dict( endpoint.endpoint_meta.values_list('name', 'value')) all_findings = Finding.objects.filter(endpoints__in=endpoints).distinct() active_findings = Finding.objects.filter(endpoints__in=endpoints, active=True, verified=True).distinct() closed_findings = Finding.objects.filter( endpoints__in=endpoints, mitigated__isnull=False).distinct() if all_findings: start_date = timezone.make_aware( datetime.combine(all_findings.last().date, datetime.min.time())) else: start_date = timezone.now() end_date = timezone.now() r = relativedelta(end_date, start_date) months_between = (r.years * 12) + r.months # include current month months_between += 1 monthly_counts = get_period_counts(active_findings, all_findings, closed_findings, None, months_between, start_date, relative_delta='months') paged_findings = get_page_items(request, active_findings, 25) vulnerable = False if active_findings.count() != 0: vulnerable = True product_tab = Product_Tab(endpoint.product.id, "Endpoint", tab="endpoints") return render( request, "dojo/view_endpoint.html", { "endpoint": endpoint, 'product_tab': product_tab, "endpoints": endpoints, "findings": paged_findings, 'all_findings': all_findings, 'opened_per_month': monthly_counts['opened_per_period'], 'endpoint_metadata': endpoint_metadata, 'vulnerable': vulnerable, })
def all_cred_product(request, pid): prod = get_object_or_404(Product, id=pid) creds = Cred_Mapping.objects.filter(product=prod).order_by('cred_id__name') product_tab = Product_Tab(prod.id, title="Credentials", tab="settings") return render(request, 'dojo/view_cred_prod.html', { 'product_tab': product_tab, 'creds': creds, 'prod': prod })
def delete_test(request, tid): test = get_object_or_404(Test, pk=tid) eng = test.engagement form = DeleteTestForm(instance=test) if request.method == 'POST': if 'id' in request.POST and str(test.id) == request.POST['id']: form = DeleteTestForm(request.POST, instance=test) if form.is_valid(): del test.tags test.delete() messages.add_message(request, messages.SUCCESS, 'Test and relationships removed.', extra_tags='alert-success') create_notification( event='other', title='Deletion of %s' % test.title, description='The test "%s" was deleted by %s' % (test.title, request.user), url=request.build_absolute_uri( reverse('view_engagement', args=(eng.id, ))), recipients=[test.engagement.lead], icon="exclamation-triangle") return HttpResponseRedirect( reverse('view_engagement', args=(eng.id, ))) collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([test]) rels = collector.nested() product_tab = Product_Tab(test.engagement.product.id, title="Delete Test", tab="engagements") product_tab.setEngagement(test.engagement) return render( request, 'dojo/delete_test.html', { 'test': test, 'product_tab': product_tab, 'form': form, 'rels': rels, 'deletable_objects': rels, })
def engagement_presets(request, pid): prod = get_object_or_404(Product, id=pid) presets = Engagement_Presets.objects.filter(product=prod).all() product_tab = Product_Tab(prod.id, title="Engagement Presets", tab="settings") return render(request, 'dojo/view_presets.html', {'product_tab': product_tab, 'presets': presets, 'prod': prod})
def view_objects(request, pid): object_queryset = Objects_Product.objects.filter(product=pid).order_by('path', 'folder', 'artifact') product_tab = Product_Tab(pid, title="Tracked Product Files, Paths and Artifacts", tab="settings") return render(request, 'dojo/view_objects.html', { 'object_queryset': object_queryset, 'product_tab': product_tab, 'pid': pid })
def all_tool_product(request, pid): prod = get_object_or_404(Product, id=pid) tools = Tool_Product_Settings.objects.filter(product=prod).order_by('name') product_tab = Product_Tab(prod.id, title="Tool Configurations", tab="settings") return render(request, 'dojo/view_tool_product_all.html', { 'prod': prod, 'tools': tools, 'product_tab': product_tab })
def action_history(request, cid, oid): try: ct = ContentType.objects.get_for_id(cid) obj = ct.get_object_for_this_type(pk=oid) except KeyError: raise Http404() product_id = None active_tab = None finding = None test = False object_value = None if str(ct) == "product": product_id = obj.id active_tab = "overview" object_value = Product.objects.get(id=obj.id) elif str(ct) == "engagement": object_value = Engagement.objects.get(id=obj.id) product_id = object_value.product.id active_tab = "engagements" elif str(ct) == "test": object_value = Test.objects.get(id=obj.id) product_id = object_value.engagement.product.id active_tab = "engagements" test = True elif str(ct) == "finding": object_value = Finding.objects.get(id=obj.id) product_id = object_value.test.engagement.product.id active_tab = "findings" finding = object_value elif str(ct) == "endpoint": object_value = Endpoint.objects.get(id=obj.id) product_id = object_value.product.id active_tab = "endpoints" product_tab = None if product_id: product_tab = Product_Tab(product_id, title="History", tab=active_tab) if active_tab == "engagements": if str(ct) == "engagement": product_tab.setEngagement(object_value) else: product_tab.setEngagement(object_value.engagement) history = LogEntry.objects.filter(content_type=ct, object_pk=obj.id).order_by('-timestamp') history = LogEntryFilter(request.GET, queryset=history) paged_history = get_page_items(request, history.qs, 25) return render( request, 'dojo/action_history.html', { "history": paged_history, 'product_tab': product_tab, "filtered": history, "obj": obj, "test": test, "object_value": object_value, "finding": finding })
def delete_engagement(request, eid): engagement = get_object_or_404(Engagement, pk=eid) product = engagement.product form = DeleteEngagementForm(instance=engagement) if request.method == 'POST': if 'id' in request.POST and str(engagement.id) == request.POST['id']: form = DeleteEngagementForm(request.POST, instance=engagement) if form.is_valid(): del engagement.tags engagement.delete() messages.add_message( request, messages.SUCCESS, 'Engagement and relationships removed.', extra_tags='alert-success') create_notification(event='other', title='Deletion of %s' % engagement.name, description='The engagement "%s" was deleted by %s' % (engagement.name, request.user), url=request.build_absolute_uri(reverse('view_engagements', args=(product.id, ))), recipients=[engagement.lead], icon="exclamation-triangle") if engagement.engagement_type == 'CI/CD': return HttpResponseRedirect(reverse("view_engagements_cicd", args=(product.id, ))) else: return HttpResponseRedirect(reverse("view_engagements", args=(product.id, ))) collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([engagement]) rels = collector.nested() product_tab = Product_Tab(product.id, title="Delete Engagement", tab="engagements") product_tab.setEngagement(engagement) return render(request, 'dojo/delete_engagement.html', { 'product_tab': product_tab, 'engagement': engagement, 'form': form, 'rels': rels, })
def process_endpoints_view(request, host_view=False, vulnerable=False): if vulnerable: endpoints = Endpoint.objects.filter(finding__active=True, finding__verified=True, finding__false_p=False, finding__duplicate=False, finding__out_of_scope=False, mitigated=False) else: endpoints = Endpoint.objects.all() endpoints = endpoints.prefetch_related('product', 'product__tags', 'tags').distinct() endpoints = get_authorized_endpoints(Permissions.Endpoint_View, endpoints, request.user) if host_view: ids = get_endpoint_ids(EndpointFilter(request.GET, queryset=endpoints, user=request.user).qs) endpoints = EndpointFilter(request.GET, queryset=endpoints.filter(id__in=ids), user=request.user) else: endpoints = EndpointFilter(request.GET, queryset=endpoints, user=request.user) paged_endpoints = get_page_items(request, endpoints.qs, 25) if vulnerable: view_name = "Vulnerable" else: view_name = "All" if host_view: view_name += " Endpoint Hosts" else: view_name += " Endpoints" add_breadcrumb(title=view_name, top_level=not len(request.GET), request=request) product_tab = None if 'product' in request.GET: p = request.GET.getlist('product', []) if len(p) == 1: product = get_object_or_404(Product, id=p[0]) if not settings.FEATURE_AUTHORIZATION_V2: if not user_is_authorized(request.user, 'view', product): raise PermissionDenied else: user_has_permission_or_403(request.user, product, Permissions.Product_View) product_tab = Product_Tab(product.id, view_name, tab="endpoints") return render( request, 'dojo/endpoints.html', { 'product_tab': product_tab, "endpoints": paged_endpoints, "filtered": endpoints, "name": view_name, "host_view": host_view, "product_tab": product_tab })
def vulnerable_endpoints(request): endpoints = Endpoint.objects.filter(finding__active=True, finding__verified=True, finding__false_p=False, finding__duplicate=False, finding__out_of_scope=False, mitigated=False).prefetch_related( 'product', 'product__tags', 'tags').distinct() # are they authorized if request.user.is_staff: pass else: endpoints = Endpoint.objects.filter( Q(product__authorized_users__in=[request.user]) | Q(product__prod_type__authorized_users__in=[request.user])) if not endpoints: raise PermissionDenied product = None if 'product' in request.GET: p = request.GET.getlist('product', []) if len(p) == 1: product = get_object_or_404(Product, id=p[0]) ids = get_endpoint_ids( EndpointFilter(request.GET, queryset=endpoints, user=request.user).qs) endpoints = EndpointFilter(request.GET, queryset=endpoints.filter(id__in=ids), user=request.user) endpoints_query = endpoints.qs.order_by('host') paged_endpoints = get_page_items(request, endpoints_query, 25) add_breadcrumb(title="Vulnerable Endpoints", top_level=not len(request.GET), request=request) system_settings = System_Settings.objects.get() product_tab = None view_name = "All Endpoints" if product: product_tab = Product_Tab(product.id, "Vulnerable Endpoints", tab="endpoints") return render( request, 'dojo/endpoints.html', { 'product_tab': product_tab, "endpoints": paged_endpoints, "filtered": endpoints, "name": "Vulnerable Endpoints", })
def all_endpoints(request): endpoints = Endpoint.objects.all().prefetch_related( 'product', 'tags', 'product__tags') show_uri = get_system_setting('display_endpoint_uri') # are they authorized if request.user.is_staff: pass else: endpoints = Endpoint.objects.filter( Q(product__authorized_users__in=[request.user]) | Q(product__prod_type__authorized_users__in=[request.user])) if not endpoints: raise PermissionDenied product = None if 'product' in request.GET: p = request.GET.getlist('product', []) if len(p) == 1: product = get_object_or_404(Product, id=p[0]) if show_uri: endpoints = EndpointFilter(request.GET, queryset=endpoints, user=request.user) paged_endpoints = get_page_items(request, endpoints.qs, 25) else: ids = get_endpoint_ids( EndpointFilter(request.GET, queryset=endpoints, user=request.user).qs) endpoints = EndpointFilter(request.GET, queryset=endpoints.filter(id__in=ids), user=request.user) paged_endpoints = get_page_items(request, endpoints.qs, 25) add_breadcrumb(title="All Endpoints", top_level=not len(request.GET), request=request) product_tab = None view_name = "All Endpoints" if product: view_name = "Endpoints" product_tab = Product_Tab(product.id, "Endpoints", tab="endpoints") return render( request, 'dojo/endpoints.html', { 'product_tab': product_tab, "endpoints": paged_endpoints, "filtered": endpoints, "name": view_name, "show_uri": show_uri })
def process_endpoint_view(request, eid, host_view=False): endpoint = get_object_or_404(Endpoint, id=eid) if host_view: endpoints = endpoint.host_endpoints() endpoint_metadata = None all_findings = endpoint.host_findings() active_findings = endpoint.host_active_findings() else: endpoints = None endpoint_metadata = dict(endpoint.endpoint_meta.values_list('name', 'value')) all_findings = endpoint.findings() active_findings = endpoint.active_findings() if all_findings: start_date = timezone.make_aware(datetime.combine(all_findings.last().date, datetime.min.time())) else: start_date = timezone.now() end_date = timezone.now() r = relativedelta(end_date, start_date) months_between = (r.years * 12) + r.months # include current month months_between += 1 # closed_findings is needed as a parameter for get_periods_counts, but they are not relevant in the endpoint view closed_findings = Finding.objects.none() monthly_counts = get_period_counts(active_findings, all_findings, closed_findings, None, months_between, start_date, relative_delta='months') paged_findings = get_page_items(request, active_findings, 25) vulnerable = False if active_findings.count() != 0: vulnerable = True product_tab = Product_Tab(endpoint.product.id, "Host" if host_view else "Endpoint", tab="endpoints") return render(request, "dojo/view_endpoint.html", {"endpoint": endpoint, 'product_tab': product_tab, "endpoints": endpoints, "findings": paged_findings, 'all_findings': all_findings, 'opened_per_month': monthly_counts['opened_per_period'], 'endpoint_metadata': endpoint_metadata, 'vulnerable': vulnerable, 'host_view': host_view, })
def delete_engagement(request, eid): engagement = get_object_or_404(Engagement, pk=eid) product = engagement.product form = DeleteEngagementForm(instance=engagement) if request.method == 'POST': if 'id' in request.POST and str(engagement.id) == request.POST['id']: form = DeleteEngagementForm(request.POST, instance=engagement) if form.is_valid(): del engagement.tags engagement.delete() messages.add_message(request, messages.SUCCESS, 'Engagement and relationships removed.', extra_tags='alert-success') if engagement.engagement_type == 'CI/CD': return HttpResponseRedirect( reverse("view_engagements_cicd", args=(product.id, ))) else: return HttpResponseRedirect( reverse("view_engagements", args=(product.id, ))) collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([engagement]) rels = collector.nested() product_tab = Product_Tab(product.id, title="Delete Engagement", tab="engagements") product_tab.setEngagement(engagement) return render( request, 'dojo/delete_engagement.html', { 'product_tab': product_tab, 'engagement': engagement, 'form': form, 'rels': rels, })
def all_endpoints(request): endpoints = Endpoint.objects.prefetch_related('product', 'tags', 'product__tags') endpoints = get_authorized_endpoints(Permissions.Endpoint_View, endpoints, request.user) show_uri = get_system_setting('display_endpoint_uri') product = None if 'product' in request.GET: p = request.GET.getlist('product', []) if len(p) == 1: product = get_object_or_404(Product, id=p[0]) if not settings.FEATURE_AUTHORIZATION_V2: if not user_is_authorized(request.user, 'view', product): raise PermissionDenied else: user_has_permission_or_403(request.user, product, Permissions.Product_View) if show_uri: endpoints = EndpointFilter(request.GET, queryset=endpoints, user=request.user) paged_endpoints = get_page_items(request, endpoints.qs, 25) else: ids = get_endpoint_ids( EndpointFilter(request.GET, queryset=endpoints, user=request.user).qs) endpoints = EndpointFilter(request.GET, queryset=endpoints.filter(id__in=ids), user=request.user) paged_endpoints = get_page_items(request, endpoints.qs, 25) add_breadcrumb(title="All Endpoints", top_level=not len(request.GET), request=request) product_tab = None view_name = "All Endpoints" if product: view_name = "Endpoints" product_tab = Product_Tab(product.id, "Endpoints", tab="endpoints") return render( request, 'dojo/endpoints.html', { 'product_tab': product_tab, "endpoints": paged_endpoints, "filtered": endpoints, "name": view_name, "show_uri": show_uri })
def delete_test(request, tid): test = get_object_or_404(Test, pk=tid) eng = test.engagement form = DeleteTestForm(instance=test) from django.contrib.admin.utils import NestedObjects from django.db import DEFAULT_DB_ALIAS collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([test]) rels = collector.nested() if request.method == 'POST': if 'id' in request.POST and str(test.id) == request.POST['id']: form = DeleteTestForm(request.POST, instance=test) if form.is_valid(): del test.tags test.delete() messages.add_message(request, messages.SUCCESS, 'Test and relationships removed.', extra_tags='alert-success') return HttpResponseRedirect( reverse('view_engagement', args=(eng.id, ))) product_tab = Product_Tab(test.engagement.product.id, title="Delete Test", tab="engagements") product_tab.setEngagement(test.engagement) return render( request, 'dojo/delete_test.html', { 'test': test, 'product_tab': product_tab, 'form': form, 'rels': rels, 'deletable_objects': rels, })
def view_engagements(request, pid, engagement_type="Interactive"): prod = get_object_or_404(Product, id=pid) auth = request.user.is_staff or request.user in prod.authorized_users.all() if not auth: # will render 403 raise PermissionDenied engs = Engagement.objects.filter(product=prod, active=True) default_page_num = 10 result_engs = EngagementFilter( request.GET, queryset=Engagement.objects.filter( product=prod, active=True, engagement_type=engagement_type).order_by('-updated')) engs = get_page_items(request, result_engs.qs, default_page_num, param_name="engs") result = EngagementFilter( request.GET, queryset=Engagement.objects.filter( product=prod, active=False, engagement_type=engagement_type).order_by('-target_end')) i_engs_page = get_page_items(request, result.qs, default_page_num, param_name="i_engs") title = "All Engagements" if engagement_type == "CI/CD": title = "CI/CD Engagements" product_tab = Product_Tab(pid, title=title, tab="engagements") return render( request, 'dojo/view_engagements.html', { 'prod': prod, 'product_tab': product_tab, 'engagement_type': engagement_type, 'engs': engs, 'engs_count': result_engs.qs.count(), 'i_engs': i_engs_page, 'i_engs_count': result.qs.count(), 'user': request.user, 'authorized': auth })
def edit_test(request, tid): test = get_object_or_404(Test, pk=tid) form = TestForm(instance=test) if request.method == 'POST': form = TestForm(request.POST, instance=test) if form.is_valid(): new_test = form.save() messages.add_message(request, messages.SUCCESS, 'Test saved.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_engagement', args=(test.engagement.id,))) form.initial['target_start'] = test.target_start.date() form.initial['target_end'] = test.target_end.date() form.initial['description'] = test.description product_tab = Product_Tab(test.engagement.product.id, title="Edit Test", tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/edit_test.html', {'test': test, 'product_tab': product_tab, 'form': form, })
def view_engagements(request, pid, engagement_type="Interactive"): prod = get_object_or_404(Product, id=pid) auth = request.user.is_staff or request.user in prod.authorized_users.all() if not auth: raise PermissionDenied default_page_num = 10 # In Progress Engagements result_engs = EngagementFilter( request.GET, queryset=Engagement.objects.filter(product=prod, active=True, status="In Progress", engagement_type=engagement_type).order_by('-updated')) engs = get_page_items(request, result_engs.qs, default_page_num, param_name="engs") # Engagements that are queued because they haven't started or paused queued_engs = EngagementFilter( request.GET, queryset=Engagement.objects.filter(~Q(status="In Progress"), product=prod, active=True, engagement_type=engagement_type).order_by('-updated')) result_queued_engs = get_page_items(request, queued_engs.qs, default_page_num, param_name="queued_engs") # Cancelled or Completed Engagements result = EngagementFilter( request.GET, queryset=Engagement.objects.filter(product=prod, active=False, engagement_type=engagement_type).order_by('-target_end')) i_engs_page = get_page_items(request, result.qs, default_page_num, param_name="i_engs") title = "All Engagements" if engagement_type == "CI/CD": title = "CI/CD Engagements" product_tab = Product_Tab(pid, title=title, tab="engagements") return render(request, 'dojo/view_engagements.html', {'prod': prod, 'product_tab': product_tab, 'engagement_type': engagement_type, 'engs': engs, 'engs_count': result_engs.qs.count(), 'queued_engs': result_queued_engs, 'queued_engs_count': queued_engs.qs.count(), 'i_engs': i_engs_page, 'i_engs_count': result.qs.count(), 'user': request.user, 'authorized': auth})
def import_endpoint_meta(request, pid): product = get_object_or_404(Product, id=pid) form = ImportEndpointMetaForm() if request.method == 'POST': form = ImportEndpointMetaForm(request.POST, request.FILES) if form.is_valid(): file = request.FILES.get('file', None) # Make sure size is not too large if file and is_scan_file_too_large(file): 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') create_endpoints = form.cleaned_data['create_endpoints'] create_tags = form.cleaned_data['create_tags'] create_dojo_meta = form.cleaned_data['create_dojo_meta'] try: endpoint_meta_import(file, product, create_endpoints, create_tags, create_dojo_meta, origin='UI', request=request) except Exception as e: logger.exception(e) add_error_message_to_response( 'An exception error occurred during the report import:%s' % str(e)) return HttpResponseRedirect( reverse('endpoint') + "?product=" + pid) add_breadcrumb(title="Endpoint Meta Importer", top_level=False, request=request) product_tab = Product_Tab(product.id, title="Endpoint Meta Importer", tab="endpoints") return render(request, 'dojo/endpoint_meta_importer.html', { 'product_tab': product_tab, 'form': form, })
def delete_finding_group(request, fgid): logger.debug('delete finding group: %s', fgid) finding_group = get_object_or_404(Finding_Group, pk=fgid) form = DeleteFindingGroupForm(instance=finding_group) if request.method == 'POST': if 'id' in request.POST and str( finding_group.id) == request.POST['id']: form = DeleteFindingGroupForm(request.POST, instance=finding_group) if form.is_valid(): product = finding_group.test.engagement.product finding_group.delete() messages.add_message( request, messages.SUCCESS, 'Finding Group and relationships removed.', extra_tags='alert-success') create_notification( event='other', title='Deletion of %s' % finding_group.name, product=product, description='The finding group "%s" was deleted by %s' % (finding_group.name, request.user), url=request.build_absolute_uri( reverse('view_test', args=(finding_group.test.id, ))), icon="exclamation-triangle") return HttpResponseRedirect( reverse('view_test', args=(finding_group.test.id, ))) collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([finding_group]) rels = collector.nested() product_tab = Product_Tab(finding_group.test.engagement.product.id, title="Product", tab="settings") return render( request, 'dojo/delete_finding_group.html', { 'finding_group': finding_group, 'form': form, 'product_tab': product_tab, 'rels': rels, })
def add_meta_data(request, eid): endpoint = Endpoint.objects.get(id=eid) ct = ContentType.objects.get_for_model(endpoint) if request.method == 'POST': form = EndpointMetaDataForm(request.POST) if form.is_valid(): cf, created = CustomField.objects.get_or_create( name=form.cleaned_data['name'], content_type=ct, field_type='a') cf.save() cfv, created = CustomFieldValue.objects.get_or_create( field=cf, object_id=endpoint.id) cfv.value = form.cleaned_data['value'] cfv.clean() cfv.save() messages.add_message(request, messages.SUCCESS, 'Metadata added successfully.', extra_tags='alert-success') if 'add_another' in request.POST: return HttpResponseRedirect( reverse('add_meta_data', args=(eid, ))) else: return HttpResponseRedirect( reverse('view_endpoint', args=(eid, ))) else: form = EndpointMetaDataForm(initial={'content_type': endpoint}) add_breadcrumb(parent=endpoint, title="Add Metadata", top_level=False, request=request) product_tab = Product_Tab(endpoint.product.id, "Add Metadata", tab="endpoints") return render(request, 'dojo/add_endpoint_meta_data.html', { 'form': form, 'product_tab': product_tab, 'endpoint': endpoint, })
def add_engagement_presets(request, pid): prod = get_object_or_404(Product, id=pid) if request.method == 'POST': tform = EngagementPresetsForm(request.POST) if tform.is_valid(): form_copy = tform.save(commit=False) form_copy.product = prod form_copy.save() tform.save_m2m() messages.add_message( request, messages.SUCCESS, 'Engagement Preset Successfully Created.', extra_tags='alert-success') return HttpResponseRedirect(reverse('engagement_presets', args=(pid,))) else: tform = EngagementPresetsForm() product_tab = Product_Tab(pid, title="New Engagement Preset", tab="settings") return render(request, 'dojo/new_params.html', {'tform': tform, 'pid': pid, 'product_tab': product_tab})
def delete_object(request, pid, ttid): object = Objects_Product.objects.get(pk=ttid) if request.method == 'POST': tform = ObjectSettingsForm(request.POST, instance=object) object.delete() messages.add_message(request, messages.SUCCESS, 'Tracked Product Files Deleted.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_objects', args=(pid,))) else: tform = DeleteObjectsSettingsForm(instance=object) product_tab = Product_Tab(pid, title="Delete Product Tool Configuration", tab="settings") return render(request, 'dojo/delete_object.html', { 'tform': tform, 'product_tab': product_tab })
def edit_meta_data(request, eid): endpoint = Endpoint.objects.get(id=eid) ct = ContentType.objects.get_for_model(endpoint) endpoint_cf = CustomField.objects.filter(content_type=ct) endpoint_metadata = {} for cf in endpoint_cf: cfv = CustomFieldValue.objects.filter(field=cf, object_id=endpoint.id) if len(cfv): endpoint_metadata[cf] = cfv[0] if request.method == 'POST': for key, value in request.POST.iteritems(): if key.startswith('cfv_'): cfv_id = int(key.split('_')[1]) cfv = get_object_or_404(CustomFieldValue, id=cfv_id) value = value.strip() if value: cfv.value = value cfv.save() else: cfv.delete() messages.add_message(request, messages.SUCCESS, 'Metadata edited successfully.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_endpoint', args=(eid, ))) product_tab = Product_Tab(endpoint.product.id, "Edit Metadata", tab="endpoints") return render( request, 'dojo/edit_endpoint_meta_data.html', { 'endpoint': endpoint, 'product_tab': product_tab, 'endpoint_metadata': endpoint_metadata, })
def edit_object(request, pid, ttid): object = Objects_Product.objects.get(pk=ttid) if request.method == 'POST': tform = ObjectSettingsForm(request.POST, instance=object) if tform.is_valid(): tform.save() messages.add_message( request, messages.SUCCESS, 'Tool Product Configuration Successfully Updated.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_objects', args=(pid, ))) else: tform = ObjectSettingsForm(instance=object) product_tab = Product_Tab(pid, title="Edit Tracked Files", tab="settings") return render(request, 'dojo/edit_object.html', { 'tform': tform, 'product_tab': product_tab })
def add_endpoint(request, pid): product = get_object_or_404(Product, id=pid) template = 'dojo/add_endpoint.html' if '_popup' in request.GET: template = 'dojo/add_related.html' form = AddEndpointForm(product=product) if request.method == 'POST': form = AddEndpointForm(request.POST, product=product) if form.is_valid(): endpoints = form.save() tags = request.POST.getlist('tags') t = ", ".join(tags) for e in endpoints: e.tags = t messages.add_message(request, messages.SUCCESS, 'Endpoint added successfully.', extra_tags='alert-success') if '_popup' in request.GET: resp = '<script type="text/javascript">opener.emptyEndpoints(window);</script>' for endpoint in endpoints: resp += '<script type="text/javascript">opener.dismissAddAnotherPopupDojo(window, "%s", "%s");</script>' \ % (escape(endpoint._get_pk_val()), escape(endpoint)) resp += '<script type="text/javascript">window.close();</script>' return HttpResponse(resp) else: return HttpResponseRedirect( reverse('endpoints') + "?product=" + pid) product_tab = None if '_popup' not in request.GET: product_tab = Product_Tab(product.id, "Add Endpoint", tab="endpoints") return render(request, template, { 'product_tab': product_tab, 'name': 'Add Endpoint', 'form': form })
def edit_engagement_presets(request, pid, eid): prod = get_object_or_404(Product, id=pid) preset = get_object_or_404(Engagement_Presets, id=eid) product_tab = Product_Tab(prod.id, title="Edit Engagement Preset", tab="settings") if request.method == 'POST': tform = EngagementPresetsForm(request.POST, instance=preset) if tform.is_valid(): tform.save() messages.add_message( request, messages.SUCCESS, 'Engagement Preset Successfully Updated.', extra_tags='alert-success') return HttpResponseRedirect(reverse('engagement_presets', args=(pid,))) else: tform = EngagementPresetsForm(instance=preset) return render(request, 'dojo/edit_presets.html', {'product_tab': product_tab, 'tform': tform, 'prod': prod})
def delete_tool_product(request, pid, ttid): tool_product = Tool_Product_Settings.objects.get(pk=ttid) prod = get_object_or_404(Product, id=pid) if request.method == 'POST': tform = DeleteToolProductSettingsForm(request.POST, instance=tool_product) tool_product.delete() messages.add_message(request, messages.SUCCESS, 'Tool Product Successfully Deleted.', extra_tags='alert-success') return HttpResponseRedirect(reverse('all_tool_product', args=(pid, ))) else: tform = ToolProductSettingsForm(instance=tool_product) product_tab = Product_Tab(pid, title="Delete Product Tool Configuration", tab="settings") return render(request, 'dojo/delete_tool_product.html', { 'tform': tform, 'product_tab': product_tab })
def new_cred_product(request, pid): prod = get_object_or_404(Product, pk=pid) if request.method == 'POST': tform = CredMappingFormProd(request.POST) if tform.is_valid(): # 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( cred_id=tform.cleaned_data['cred_id'].id, product=pid).first() message = "Credential already associated." status_tag = 'alert-danger' if cred_user is None: prod = Product.objects.get(id=pid) new_f = tform.save(commit=False) new_f.product = prod new_f.save() message = 'Credential Successfully Updated.' status_tag = 'alert-success' messages.add_message(request, messages.SUCCESS, message, extra_tags=status_tag) return HttpResponseRedirect( reverse('all_cred_product', args=(pid, ))) else: tform = CredMappingFormProd() product_tab = Product_Tab(pid, title="Add Credential Configuration", tab="settings") return render(request, 'dojo/new_cred_product.html', { 'tform': tform, 'pid': pid, 'product_tab': product_tab })
def generate_report(request, obj): user = Dojo_User.objects.get(id=request.user.id) product_type = None product = None engagement = None test = None endpoint = None endpoints = None endpoint_all_findings = None endpoint_monthly_counts = None endpoint_active_findings = None accepted_findings = None open_findings = None closed_findings = None verified_findings = None report_title = None report_subtitle = None report_info = "Generated By %s on %s" % ( user.get_full_name(), (timezone.now().strftime("%m/%d/%Y %I:%M%p %Z"))) if type(obj).__name__ == "Product": if request.user.is_staff or request.user in obj.authorized_users.all(): pass # user is authorized for this product else: raise PermissionDenied elif type(obj).__name__ == "Endpoint": if request.user.is_staff or request.user in obj.product.authorized_users.all(): pass # user is authorized for this product else: raise PermissionDenied elif type(obj).__name__ == "QuerySet": # authorization taken care of by only selecting findings from product user is authed to see pass else: if not request.user.is_staff: raise PermissionDenied report_format = request.GET.get('report_type', 'AsciiDoc') include_finding_notes = int(request.GET.get('include_finding_notes', 0)) include_finding_images = int(request.GET.get('include_finding_images', 0)) include_executive_summary = int(request.GET.get('include_executive_summary', 0)) include_table_of_contents = int(request.GET.get('include_table_of_contents', 0)) generate = "_generate" in request.GET report_name = str(obj) report_type = type(obj).__name__ add_breadcrumb(title="Generate Report", top_level=False, request=request) if type(obj).__name__ == "Product_Type": product_type = obj filename = "product_type_finding_report.pdf" template = "dojo/product_type_pdf_report.html" report_name = "Product Type Report: " + str(product_type) report_title = "Product Type Report" report_subtitle = str(product_type) findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter( test__engagement__product__prod_type=product_type).distinct().prefetch_related('test', 'test__engagement__product', 'test__engagement__product__prod_type')) products = Product.objects.filter(prod_type=product_type, engagement__test__finding__in=findings.qs).distinct() engagements = Engagement.objects.filter(product__prod_type=product_type, test__finding__in=findings.qs).distinct() tests = Test.objects.filter(engagement__product__prod_type=product_type, finding__in=findings.qs).distinct() if findings: start_date = timezone.make_aware(datetime.combine(findings.qs.last().date, datetime.min.time())) else: start_date = timezone.now() end_date = timezone.now() r = relativedelta(end_date, start_date) months_between = (r.years * 12) + r.months # include current month months_between += 1 endpoint_monthly_counts = get_period_counts_legacy(findings.qs.order_by('numerical_severity'), findings.qs.order_by('numerical_severity'), None, months_between, start_date, relative_delta='months') context = {'product_type': product_type, 'products': products, 'engagements': engagements, 'tests': tests, 'report_name': report_name, 'endpoint_opened_per_month': endpoint_monthly_counts[ 'opened_per_period'] if endpoint_monthly_counts is not None else [], 'endpoint_active_findings': findings.qs.order_by('numerical_severity'), 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'host': report_url_resolver(request), 'user_id': request.user.id} elif type(obj).__name__ == "Product": product = obj filename = "product_finding_report.pdf" template = "dojo/product_pdf_report.html" report_name = "Product Report: " + str(product) report_title = "Product Report" report_subtitle = str(product) findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter( test__engagement__product=product).distinct().prefetch_related('test', 'test__engagement__product', 'test__engagement__product__prod_type')) ids = set(finding.id for finding in findings.qs) engagements = Engagement.objects.filter(test__finding__id__in=ids).distinct() tests = Test.objects.filter(finding__id__in=ids).distinct() ids = get_endpoint_ids(Endpoint.objects.filter(product=product).distinct()) endpoints = Endpoint.objects.filter(id__in=ids) context = {'product': product, 'engagements': engagements, 'tests': tests, 'report_name': report_name, 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'endpoints': endpoints, 'host': report_url_resolver(request), 'user_id': request.user.id} elif type(obj).__name__ == "Engagement": engagement = obj findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter(test__engagement=engagement, ).prefetch_related('test', 'test__engagement__product', 'test__engagement__product__prod_type').distinct()) report_name = "Engagement Report: " + str(engagement) filename = "engagement_finding_report.pdf" template = 'dojo/engagement_pdf_report.html' report_title = "Engagement Report" report_subtitle = str(engagement) ids = set(finding.id for finding in findings.qs) tests = Test.objects.filter(finding__id__in=ids).distinct() ids = get_endpoint_ids(Endpoint.objects.filter(product=engagement.product).distinct()) endpoints = Endpoint.objects.filter(id__in=ids) context = {'engagement': engagement, 'tests': tests, 'report_name': report_name, 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'host': report_url_resolver(request), 'user_id': request.user.id, 'endpoints': endpoints} elif type(obj).__name__ == "Test": test = obj findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter(test=test).prefetch_related('test', 'test__engagement__product', 'test__engagement__product__prod_type').distinct()) filename = "test_finding_report.pdf" template = "dojo/test_pdf_report.html" report_name = "Test Report: " + str(test) report_title = "Test Report" report_subtitle = str(test) context = {'test': test, 'report_name': report_name, 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'host': report_url_resolver(request), 'user_id': request.user.id} elif type(obj).__name__ == "Endpoint": endpoint = obj host = endpoint.host_no_port report_name = "Endpoint Report: " + host report_type = "Endpoint" endpoints = Endpoint.objects.filter(host__regex="^" + host + ":?", product=endpoint.product).distinct() filename = "endpoint_finding_report.pdf" template = 'dojo/endpoint_pdf_report.html' report_title = "Endpoint Report" report_subtitle = host findings = ReportFindingFilter(request.GET, queryset=Finding.objects.filter(endpoints__in=endpoints, ).prefetch_related('test', 'test__engagement__product', 'test__engagement__product__prod_type').distinct()) context = {'endpoint': endpoint, 'endpoints': endpoints, 'report_name': report_name, 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': get_system_setting('team_name'), 'title': 'Generate Report', 'host': report_url_resolver(request), 'user_id': request.user.id} elif type(obj).__name__ == "QuerySet": findings = ReportAuthedFindingFilter(request.GET, queryset=obj.prefetch_related('test', 'test__engagement__product', 'test__engagement__product__prod_type').distinct(), user=request.user) filename = "finding_report.pdf" report_name = 'Finding' report_type = 'Finding' template = 'dojo/finding_pdf_report.html' report_title = "Finding Report" report_subtitle = '' context = {'findings': findings.qs.order_by('numerical_severity'), 'report_name': report_name, 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'host': report_url_resolver(request), 'user_id': request.user.id} else: raise Http404() report_form = ReportOptionsForm() if generate: report_form = ReportOptionsForm(request.GET) if report_format == 'AsciiDoc': return render(request, 'dojo/asciidoc_report.html', {'product_type': product_type, 'product': product, 'engagement': engagement, 'test': test, 'endpoint': endpoint, 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'user_id': request.user.id, 'host': report_url_resolver(request), }) elif report_format == 'PDF': if 'regen' in request.GET: # we should already have a report object, lets get and use it report = get_object_or_404(Report, id=request.GET['regen']) report.datetime = timezone.now() report.status = 'requested' if report.requester.username != request.user.username: report.requester = request.user else: # lets create the report object and send it in to celery task report = Report(name=report_name, type=report_type, format='PDF', requester=request.user, task_id='tbd', options=request.path + "?" + request.GET.urlencode()) report.save() async_pdf_report.delay(report=report, template=template, filename=filename, report_title=report_title, report_subtitle=report_subtitle, report_info=report_info, context=context, uri=request.build_absolute_uri(report.get_url())) messages.add_message(request, messages.SUCCESS, 'Your report is building.', extra_tags='alert-success') return HttpResponseRedirect(reverse('reports')) elif report_format == 'HTML': return render(request, template, {'product_type': product_type, 'product': product, 'engagement': engagement, 'report_name': report_name, 'test': test, 'endpoint': endpoint, 'endpoints': endpoints, 'findings': findings.qs.order_by('numerical_severity'), 'include_finding_notes': include_finding_notes, 'include_finding_images': include_finding_images, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', 'user_id': request.user.id, 'host': "", }) else: raise Http404() paged_findings = get_page_items(request, findings.qs.order_by('numerical_severity'), 25) product_tab = None if engagement: product_tab = Product_Tab(engagement.product.id, title="Engagement Report", tab="engagements") product_tab.setEngagement(engagement) elif test: product_tab = Product_Tab(test.engagement.product.id, title="Test Report", tab="engagements") product_tab.setEngagement(test.engagement) elif product: product_tab = Product_Tab(product.id, title="Product Report", tab="findings") elif endpoints: product_tab = Product_Tab(endpoint.product.id, title="Endpoint Report", tab="endpoints") return render(request, 'dojo/request_report.html', {'product_type': product_type, 'product': product, 'product_tab': product_tab, 'engagement': engagement, 'test': test, 'endpoint': endpoint, 'findings': findings, 'paged_findings': paged_findings, 'report_form': report_form, })
def edit_engagement(request, eid): eng = Engagement.objects.get(pk=eid) ci_cd_form = False if eng.engagement_type == "CI/CD": ci_cd_form = True jform = None if request.method == 'POST': form = EngForm(request.POST, instance=eng, cicd=ci_cd_form, product=eng.product.id) if 'jiraform-push_to_jira' in request.POST: jform = JIRAFindingForm( request.POST, prefix='jiraform', enabled=True) if (form.is_valid() and jform is None) or (form.is_valid() and jform and jform.is_valid()): if 'jiraform-push_to_jira' in request.POST: if JIRA_Issue.objects.filter(engagement=eng).exists(): update_epic_task.delay( eng, jform.cleaned_data.get('push_to_jira')) enabled = True else: enabled = False add_epic_task.delay(eng, jform.cleaned_data.get('push_to_jira')) temp_form = form.save(commit=False) if (temp_form.status == "Cancelled" or temp_form.status == "Completed"): temp_form.active = False elif(temp_form.active is False): temp_form.active = True temp_form.save() tags = request.POST.getlist('tags') t = ", ".join(tags) eng.tags = t messages.add_message( request, messages.SUCCESS, 'Engagement updated successfully.', extra_tags='alert-success') if '_Add Tests' in request.POST: return HttpResponseRedirect( reverse('add_tests', args=(eng.id, ))) else: return HttpResponseRedirect( reverse('view_engagement', args=(eng.id, ))) else: form = EngForm(instance=eng, cicd=ci_cd_form, product=eng.product.id) try: # jissue = JIRA_Issue.objects.get(engagement=eng) enabled = True except: enabled = False pass if get_system_setting('enable_jira') and JIRA_PKey.objects.filter( product=eng.product).count() != 0: jform = JIRAFindingForm(prefix='jiraform', enabled=enabled) else: jform = None form.initial['tags'] = [tag.name for tag in eng.tags] title = "" if eng.engagement_type == "CI/CD": title = " CI/CD" product_tab = Product_Tab(eng.product.id, title="Edit" + title + " Engagement", tab="engagements") product_tab.setEngagement(eng) return render(request, 'dojo/new_eng.html', { 'product_tab': product_tab, 'form': form, 'edit': True, 'jform': jform, 'eng': eng })
def ad_hoc_finding(request, pid): prod = Product.objects.get(id=pid) test = None try: eng = Engagement.objects.get(product=prod, name="Ad Hoc Engagement") tests = Test.objects.filter(engagement=eng) if len(tests) != 0: test = tests[0] else: test = Test(engagement=eng, test_type=Test_Type.objects.get(name="Pen Test"), target_start=timezone.now(), target_end=timezone.now()) test.save() except: eng = Engagement(name="Ad Hoc Engagement", target_start=timezone.now(), target_end=timezone.now(), active=False, product=prod) eng.save() test = Test(engagement=eng, test_type=Test_Type.objects.get(name="Pen Test"), target_start=timezone.now(), target_end=timezone.now()) test.save() form_error = False enabled = False jform = None form = AdHocFindingForm(initial={'date': timezone.now().date()}) if get_system_setting('enable_jira'): if JIRA_PKey.objects.filter(product=test.engagement.product).count() != 0: enabled = JIRA_PKey.objects.get(product=test.engagement.product).push_all_issues jform = JIRAFindingForm(enabled=enabled, prefix='jiraform') else: jform = None if request.method == 'POST': form = AdHocFindingForm(request.POST) if form.is_valid(): new_finding = form.save(commit=False) new_finding.test = test new_finding.reporter = request.user new_finding.numerical_severity = Finding.get_numerical_severity( new_finding.severity) if new_finding.false_p or new_finding.active is False: new_finding.mitigated = timezone.now() new_finding.mitigated_by = request.user create_template = new_finding.is_template # always false now since this will be deprecated soon in favor of new Finding_Template model new_finding.is_template = False new_finding.save() new_finding.endpoints = form.cleaned_data['endpoints'] new_finding.save() if 'jiraform-push_to_jira' in request.POST: jform = JIRAFindingForm(request.POST, prefix='jiraform', enabled=enabled) if jform.is_valid(): add_issue_task.delay(new_finding, jform.cleaned_data.get('push_to_jira')) messages.add_message(request, messages.SUCCESS, 'Finding added successfully.', extra_tags='alert-success') if create_template: templates = Finding_Template.objects.filter(title=new_finding.title) if len(templates) > 0: messages.add_message(request, messages.ERROR, 'A finding template was not created. A template with this title already ' 'exists.', extra_tags='alert-danger') else: template = Finding_Template(title=new_finding.title, cwe=new_finding.cwe, severity=new_finding.severity, description=new_finding.description, mitigation=new_finding.mitigation, impact=new_finding.impact, references=new_finding.references, numerical_severity=new_finding.numerical_severity) template.save() messages.add_message(request, messages.SUCCESS, 'A finding template was also created.', extra_tags='alert-success') if '_Finished' in request.POST: return HttpResponseRedirect(reverse('view_test', args=(test.id,))) else: return HttpResponseRedirect(reverse('add_findings', args=(test.id,))) else: if 'endpoints' in form.cleaned_data: form.fields['endpoints'].queryset = form.cleaned_data['endpoints'] else: form.fields['endpoints'].queryset = Endpoint.objects.none() form_error = True messages.add_message(request, messages.ERROR, 'The form has errors, please correct them below.', extra_tags='alert-danger') product_tab = Product_Tab(pid, title="Add Finding", tab="engagements") product_tab.setEngagement(eng) return render(request, 'dojo/ad_hoc_findings.html', {'form': form, 'product_tab': product_tab, 'temp': False, 'tid': test.id, 'pid': pid, 'form_error': form_error, 'jform': jform, })
def view_engagement(request, eid): eng = get_object_or_404(Engagement, id=eid) tests = Test.objects.filter(engagement=eng).order_by('test_type__name') prod = eng.product auth = request.user.is_staff or request.user in prod.authorized_users.all() risks_accepted = eng.risk_acceptance.all() preset_test_type = None network = None if eng.preset: preset_test_type = eng.preset.test_type.all() network = eng.preset.network_locations.all() system_settings = System_Settings.objects.get() if not auth: # will render 403 raise PermissionDenied try: jissue = JIRA_Issue.objects.get(engagement=eng) except: jissue = None pass try: jconf = JIRA_PKey.objects.get(product=eng.product).conf except: jconf = None pass exclude_findings = [ finding.id for ra in eng.risk_acceptance.all() for finding in ra.accepted_findings.all() ] eng_findings = Finding.objects.filter(test__in=eng.test_set.all()) \ .exclude(id__in=exclude_findings).order_by('title') try: check = Check_List.objects.get(engagement=eng) except: check = None pass form = DoneForm() if request.method == 'POST' and request.user.is_staff: eng.progress = 'check_list' eng.save() creds = Cred_Mapping.objects.filter( product=eng.product).select_related('cred_id').order_by('cred_id') cred_eng = Cred_Mapping.objects.filter( engagement=eng.id).select_related('cred_id').order_by('cred_id') add_breadcrumb(parent=eng, top_level=False, request=request) if hasattr(settings, 'ENABLE_DEDUPLICATION'): if settings.ENABLE_DEDUPLICATION: enabled = True findings = Finding.objects.filter( test__engagement=eng, duplicate=False) else: enabled = False findings = None else: enabled = False findings = None if findings is not None: fpage = get_page_items(request, findings, 15) else: fpage = None # ---------- try: start_date = Finding.objects.filter( test__engagement__product=eng.product).order_by('date')[:1][0].date except: start_date = timezone.now() end_date = timezone.now() risk_acceptances = Risk_Acceptance.objects.filter( engagement__in=Engagement.objects.filter(product=eng.product)) accepted_findings = [ finding for ra in risk_acceptances for finding in ra.accepted_findings.all() ] title = "" if eng.engagement_type == "CI/CD": title = " CI/CD" product_tab = Product_Tab(prod.id, title="View" + title + " Engagement", tab="engagements") product_tab.setEngagement(eng) return render( request, 'dojo/view_eng.html', { 'eng': eng, 'product_tab': product_tab, 'system_settings': system_settings, 'tests': tests, 'findings': fpage, 'enabled': enabled, 'check': check, 'threat': eng.tmodel_path, 'risk': eng.risk_path, 'form': form, 'risks_accepted': risks_accepted, 'can_add_risk': len(eng_findings), 'jissue': jissue, 'jconf': jconf, 'accepted_findings': accepted_findings, 'start_date': start_date, 'creds': creds, 'cred_eng': cred_eng, 'network': network, 'preset_test_type': preset_test_type })
def add_tests(request, eid): eng = Engagement.objects.get(id=eid) cred_form = CredMappingForm() cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter( engagement=eng).order_by('cred_id') if request.method == 'POST': form = TestForm(request.POST) cred_form = CredMappingForm(request.POST) cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter( engagement=eng).order_by('cred_id') if form.is_valid(): new_test = form.save(commit=False) new_test.engagement = eng try: new_test.lead = User.objects.get(id=form['lead'].value()) except: new_test.lead = None pass # Set status to in progress if a test is added if eng.status != "In Progress" and eng.active is True: eng.status = "In Progress" eng.save() new_test.save() tags = request.POST.getlist('tags') t = ", ".join(tags) new_test.tags = t # 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 = new_test new_f.cred_id = cred_user.cred_id new_f.save() messages.add_message( request, messages.SUCCESS, 'Test added successfully.', extra_tags='alert-success') create_notification( event='test_added', title=new_test.test_type.name + " for " + eng.product.name, test=new_test, engagement=eng, url=request.build_absolute_uri( reverse('view_engagement', args=(eng.id, )))) if '_Add Another Test' in request.POST: return HttpResponseRedirect( reverse('add_tests', args=(eng.id, ))) elif '_Add Findings' in request.POST: return HttpResponseRedirect( reverse('add_findings', args=(new_test.id, ))) elif '_Finished' in request.POST: return HttpResponseRedirect( reverse('view_engagement', args=(eng.id, ))) else: form = TestForm() form.initial['target_start'] = eng.target_start form.initial['target_end'] = eng.target_end form.initial['lead'] = request.user add_breadcrumb( parent=eng, title="Add Tests", top_level=False, request=request) product_tab = Product_Tab(eng.product.id, title="Add Tests", tab="engagements") product_tab.setEngagement(eng) return render(request, 'dojo/add_tests.html', { 'product_tab': product_tab, 'form': form, 'cred_form': cred_form, 'eid': eid, 'eng': eng })
def import_scan_results(request, eid=None, pid=None): engagement = None form = ImportScanForm() cred_form = CredMappingForm() finding_count = 0 if eid: engagement = get_object_or_404(Engagement, id=eid) cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id') 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 form.is_valid(): # Allows for a test to be imported with an engagement created on the fly if engagement is None: engagement = Engagement() product = get_object_or_404(Product, id=pid) 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.save() file = request.FILES['file'] scan_date = form.cleaned_data['scan_date'] min_sev = form.cleaned_data['minimum_severity'] active = form.cleaned_data['active'] verified = form.cleaned_data['verified'] scan_type = request.POST['scan_type'] if not any(scan_type in code for code in ImportScanForm.SCAN_TYPE_CHOICES): raise Http404() tt, t_created = Test_Type.objects.get_or_create(name=scan_type) # will save in development environment environment, env_created = Development_Environment.objects.get_or_create( name="Development") t = Test( engagement=engagement, test_type=tt, target_start=scan_date, target_end=scan_date, environment=environment, percent_complete=100) t.lead = request.user t.full_clean() t.save() tags = request.POST.getlist('tags') ts = ", ".join(tags) t.tags = ts # 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 = t new_f.cred_id = cred_user.cred_id new_f.save() parser = import_parser_factory(file, t) try: for item in parser.items: print "item blowup" print item sev = item.severity if sev == 'Information' or sev == 'Informational': sev = 'Info' item.severity = sev if Finding.SEVERITIES[sev] > Finding.SEVERITIES[min_sev]: continue item.test = t if item.date == timezone.now().date(): item.date = t.target_start item.reporter = request.user item.last_reviewed = timezone.now() item.last_reviewed_by = request.user item.active = active item.verified = verified item.save(dedupe_option=False, false_history=True) if hasattr(item, 'unsaved_req_resp') and len( item.unsaved_req_resp) > 0: for req_resp in item.unsaved_req_resp: burp_rr = BurpRawRequestResponse( finding=item, burpRequestBase64=req_resp["req"], burpResponseBase64=req_resp["resp"], ) burp_rr.clean() burp_rr.save() if item.unsaved_request is not None and item.unsaved_response is not None: burp_rr = BurpRawRequestResponse( finding=item, burpRequestBase64=item.unsaved_request, burpResponseBase64=item.unsaved_response, ) burp_rr.clean() burp_rr.save() for endpoint in item.unsaved_endpoints: ep, created = Endpoint.objects.get_or_create( protocol=endpoint.protocol, host=endpoint.host, path=endpoint.path, query=endpoint.query, fragment=endpoint.fragment, product=t.engagement.product) item.endpoints.add(ep) item.save(false_history=True) if item.unsaved_tags is not None: item.tags = item.unsaved_tags finding_count += 1 messages.add_message( request, messages.SUCCESS, scan_type + ' processed, a total of ' + message( finding_count, 'finding', 'processed'), extra_tags='alert-success') create_notification( event='results_added', title=str(finding_count) + " findings for " + engagement.product.name, finding_count=finding_count, test=t, engagement=engagement, url=request.build_absolute_uri( reverse('view_test', args=(t.id, )))) return HttpResponseRedirect( reverse('view_test', args=(t.id, ))) except SyntaxError: messages.add_message( request, messages.ERROR, 'There appears to be an error in the XML report, please check and try again.', extra_tags='alert-danger') 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") return render(request, 'dojo/import_scan_results.html', { 'form': form, 'product_tab': product_tab, 'custom_breadcrumb': custom_breadcrumb, 'title': title, 'cred_form': cred_form, })
def re_import_scan_results(request, tid): additional_message = "When re-uploading a scan, any findings not found in original scan will be updated as " \ "mitigated. The process attempts to identify the differences, however manual verification " \ "is highly recommended." t = get_object_or_404(Test, id=tid) scan_type = t.test_type.name engagement = t.engagement form = ReImportScanForm() form.initial['tags'] = [tag.name for tag in t.tags] if request.method == "POST": form = ReImportScanForm(request.POST, request.FILES) if form.is_valid(): scan_date = form.cleaned_data['scan_date'] min_sev = form.cleaned_data['minimum_severity'] file = request.FILES['file'] scan_type = t.test_type.name active = form.cleaned_data['active'] verified = form.cleaned_data['verified'] tags = request.POST.getlist('tags') ts = ", ".join(tags) t.tags = ts try: parser = import_parser_factory(file, t) except ValueError: raise Http404() try: items = parser.items original_items = t.finding_set.all().values_list("id", flat=True) new_items = [] mitigated_count = 0 finding_count = 0 finding_added_count = 0 reactivated_count = 0 for item in items: sev = item.severity if sev == 'Information' or sev == 'Informational': sev = 'Info' item.severity = sev if Finding.SEVERITIES[sev] > Finding.SEVERITIES[min_sev]: continue if scan_type == 'Veracode Scan' or scan_type == 'Arachni Scan': find = Finding.objects.filter(title=item.title, test__id=t.id, severity=sev, numerical_severity=Finding.get_numerical_severity(sev), description=item.description ) else: find = Finding.objects.filter(title=item.title, test__id=t.id, severity=sev, numerical_severity=Finding.get_numerical_severity(sev), ) if len(find) == 1: find = find[0] if find.mitigated: # it was once fixed, but now back find.mitigated = None find.mitigated_by = None find.active = True find.verified = verified find.save() note = Notes(entry="Re-activated by %s re-upload." % scan_type, author=request.user) note.save() find.notes.add(note) reactivated_count += 1 new_items.append(find.id) else: item.test = t item.date = t.target_start item.reporter = request.user item.last_reviewed = timezone.now() item.last_reviewed_by = request.user item.verified = verified item.active = active item.save() finding_added_count += 1 new_items.append(item.id) find = item if hasattr(item, 'unsaved_req_resp') and len(item.unsaved_req_resp) > 0: for req_resp in item.unsaved_req_resp: burp_rr = BurpRawRequestResponse(finding=find, burpRequestBase64=req_resp["req"], burpResponseBase64=req_resp["resp"], ) burp_rr.clean() burp_rr.save() if item.unsaved_request is not None and item.unsaved_response is not None: burp_rr = BurpRawRequestResponse(finding=find, burpRequestBase64=item.unsaved_request, burpResponseBase64=item.unsaved_response, ) burp_rr.clean() burp_rr.save() if find: finding_count += 1 for endpoint in item.unsaved_endpoints: ep, created = Endpoint.objects.get_or_create(protocol=endpoint.protocol, host=endpoint.host, path=endpoint.path, query=endpoint.query, fragment=endpoint.fragment, product=t.engagement.product) find.endpoints.add(ep) if item.unsaved_tags is not None: find.tags = item.unsaved_tags # calculate the difference to_mitigate = set(original_items) - set(new_items) for finding_id in to_mitigate: finding = Finding.objects.get(id=finding_id) finding.mitigated = datetime.combine(scan_date, timezone.now().time()) finding.mitigated_by = request.user finding.active = False finding.save() note = Notes(entry="Mitigated by %s re-upload." % scan_type, author=request.user) note.save() finding.notes.add(note) mitigated_count += 1 messages.add_message(request, messages.SUCCESS, '%s processed, a total of ' % scan_type + message(finding_count, 'finding', 'processed'), extra_tags='alert-success') if finding_added_count > 0: messages.add_message(request, messages.SUCCESS, 'A total of ' + message(finding_added_count, 'finding', 'added') + ', that are new to scan.', extra_tags='alert-success') if reactivated_count > 0: messages.add_message(request, messages.SUCCESS, 'A total of ' + message(reactivated_count, 'finding', 'reactivated') + ', that are back in scan results.', extra_tags='alert-success') if mitigated_count > 0: messages.add_message(request, messages.SUCCESS, 'A total of ' + message(mitigated_count, 'finding', 'mitigated') + '. Please manually verify each one.', extra_tags='alert-success') create_notification(event='results_added', title=str(finding_count) + " findings for " + engagement.product.name, finding_count=finding_count, test=t, engagement=engagement, url=request.build_absolute_uri(reverse('view_test', args=(t.id,)))) return HttpResponseRedirect(reverse('view_test', args=(t.id,))) except SyntaxError: messages.add_message(request, messages.ERROR, 'There appears to be an error in the XML report, please check and try again.', extra_tags='alert-danger') product_tab = Product_Tab(engagement.product.id, title="Re-upload a %s" % scan_type, tab="engagements") product_tab.setEngagement(engagement) return render(request, 'dojo/import_scan_results.html', {'form': form, 'product_tab': product_tab, 'eid': engagement.id, 'additional_message': additional_message, })
def view_risk(request, eid, raid): risk_approval = get_object_or_404(Risk_Acceptance, pk=raid) eng = get_object_or_404(Engagement, pk=eid) if (request.user.is_staff or request.user in eng.product.authorized_users.all()): pass else: raise PermissionDenied a_file = risk_approval.path if request.method == 'POST': note_form = NoteForm(request.POST) if note_form.is_valid(): new_note = note_form.save(commit=False) new_note.author = request.user new_note.date = timezone.now() new_note.save() risk_approval.notes.add(new_note) messages.add_message( request, messages.SUCCESS, 'Note added successfully.', extra_tags='alert-success') if 'delete_note' in request.POST: note = get_object_or_404(Notes, pk=request.POST['delete_note_id']) if note.author.username == request.user.username: risk_approval.notes.remove(note) note.delete() messages.add_message( request, messages.SUCCESS, 'Note deleted successfully.', extra_tags='alert-success') else: messages.add_message( request, messages.ERROR, "Since you are not the note's author, it was not deleted.", extra_tags='alert-danger') if 'remove_finding' in request.POST: finding = get_object_or_404( Finding, pk=request.POST['remove_finding_id']) risk_approval.accepted_findings.remove(finding) finding.active = True finding.save() messages.add_message( request, messages.SUCCESS, 'Finding removed successfully.', extra_tags='alert-success') if 'replace_file' in request.POST: replace_form = ReplaceRiskAcceptanceForm( request.POST, request.FILES, instance=risk_approval) if replace_form.is_valid(): risk_approval.path.delete(save=False) risk_approval.path = replace_form.cleaned_data['path'] risk_approval.save() messages.add_message( request, messages.SUCCESS, 'File replaced successfully.', extra_tags='alert-success') if 'add_findings' in request.POST: add_findings_form = AddFindingsRiskAcceptanceForm( request.POST, request.FILES, instance=risk_approval) if add_findings_form.is_valid(): findings = add_findings_form.cleaned_data['accepted_findings'] for finding in findings: finding.active = False finding.save() risk_approval.accepted_findings.add(finding) risk_approval.save() messages.add_message( request, messages.SUCCESS, 'Finding%s added successfully.' % ('s' if len(findings) > 1 else ''), extra_tags='alert-success') note_form = NoteForm() replace_form = ReplaceRiskAcceptanceForm() add_findings_form = AddFindingsRiskAcceptanceForm() exclude_findings = [ finding.id for ra in eng.risk_acceptance.all() for finding in ra.accepted_findings.all() ] findings = Finding.objects.filter(test__in=eng.test_set.all()) \ .exclude(id__in=exclude_findings).order_by("title") add_fpage = get_page_items(request, findings, 10, 'apage') add_findings_form.fields[ "accepted_findings"].queryset = add_fpage.object_list fpage = get_page_items( request, risk_approval.accepted_findings.order_by('numerical_severity'), 15) authorized = (request.user == risk_approval.reporter.username or request.user.is_staff) product_tab = Product_Tab(eng.product.id, title="Risk Exception", tab="engagements") product_tab.setEngagement(eng) return render( request, 'dojo/view_risk.html', { 'risk_approval': risk_approval, 'product_tab': product_tab, 'accepted_findings': fpage, 'notes': risk_approval.notes.all(), 'a_file': a_file, 'eng': eng, 'note_form': note_form, 'replace_form': replace_form, 'add_findings_form': add_findings_form, 'show_add_findings_form': len(findings), 'request': request, 'add_findings': add_fpage, 'authorized': authorized, })
def add_temp_finding(request, tid, fid): jform = None test = get_object_or_404(Test, id=tid) finding = get_object_or_404(Finding_Template, id=fid) findings = Finding_Template.objects.all() if request.method == 'POST': form = FindingForm(request.POST) if form.is_valid(): new_finding = form.save(commit=False) new_finding.test = test new_finding.reporter = request.user new_finding.numerical_severity = Finding.get_numerical_severity( new_finding.severity) new_finding.date = datetime.today() if new_finding.false_p or new_finding.active is False: new_finding.mitigated = timezone.now() new_finding.mitigated_by = request.user create_template = new_finding.is_template # is template always False now in favor of new model Finding_Template # no further action needed here since this is already adding from template. new_finding.is_template = False new_finding.save(dedupe_option=False, false_history=False) new_finding.endpoints = form.cleaned_data['endpoints'] new_finding.save(false_history=True) if 'jiraform-push_to_jira' in request.POST: jform = JIRAFindingForm(request.POST, prefix='jiraform', enabled=True) if jform.is_valid(): add_issue_task.delay(new_finding, jform.cleaned_data.get('push_to_jira')) messages.add_message(request, messages.SUCCESS, 'Finding from template added successfully.', extra_tags='alert-success') if create_template: templates = Finding_Template.objects.filter(title=new_finding.title) if len(templates) > 0: messages.add_message(request, messages.ERROR, 'A finding template was not created. A template with this title already ' 'exists.', extra_tags='alert-danger') else: template = Finding_Template(title=new_finding.title, cwe=new_finding.cwe, severity=new_finding.severity, description=new_finding.description, mitigation=new_finding.mitigation, impact=new_finding.impact, references=new_finding.references, numerical_severity=new_finding.numerical_severity) template.save() messages.add_message(request, messages.SUCCESS, 'A finding template was also created.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_test', args=(test.id,))) else: messages.add_message(request, messages.ERROR, 'The form has errors, please correct them below.', extra_tags='alert-danger') else: form = FindingForm(initial={'active': False, 'date': timezone.now().date(), 'verified': False, 'false_p': False, 'duplicate': False, 'out_of_scope': False, 'title': finding.title, 'description': finding.description, 'cwe': finding.cwe, 'severity': finding.severity, 'mitigation': finding.mitigation, 'impact': finding.impact, 'references': finding.references, 'numerical_severity': finding.numerical_severity}) if get_system_setting('enable_jira'): enabled = JIRA_PKey.objects.get(product=test.engagement.product).push_all_issues jform = JIRAFindingForm(enabled=enabled, prefix='jiraform') else: jform = None product_tab = Product_Tab(test.engagement.product.id, title="Add Finding", tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/add_findings.html', {'form': form, 'product_tab': product_tab, 'jform': jform, 'findings': findings, 'temp': True, 'fid': finding.id, 'tid': test.id, 'test': test, })
def add_findings(request, tid): test = Test.objects.get(id=tid) form_error = False enabled = False jform = None form = AddFindingForm(initial={'date': timezone.now().date()}) if get_system_setting('enable_jira') and JIRA_PKey.objects.filter(product=test.engagement.product).count() != 0: enabled = JIRA_PKey.objects.get(product=test.engagement.product).push_all_issues jform = JIRAFindingForm(enabled=enabled, prefix='jiraform') else: jform = None if request.method == 'POST': form = AddFindingForm(request.POST) if form['active'].value() is False or form['verified'].value() is False and 'jiraform-push_to_jira' in request.POST: error = ValidationError('Findings must be active and verified to be pushed to JIRA', code='not_active_or_verified') if form['active'].value() is False: form.add_error('active', error) if form['verified'].value() is False: form.add_error('verified', error) messages.add_message(request, messages.ERROR, 'Findings must be active and verified to be pushed to JIRA', extra_tags='alert-danger') if form['severity'].value() == 'Info' and 'jiraform-push_to_jira' in request.POST: error = ValidationError('Findings with Informational severity cannot be pushed to JIRA.', code='info-severity-to-jira') if form.is_valid(): new_finding = form.save(commit=False) new_finding.test = test new_finding.reporter = request.user new_finding.numerical_severity = Finding.get_numerical_severity( new_finding.severity) if new_finding.false_p or new_finding.active is False: new_finding.mitigated = timezone.now() new_finding.mitigated_by = request.user create_template = new_finding.is_template # always false now since this will be deprecated soon in favor of new Finding_Template model new_finding.is_template = False new_finding.save(dedupe_option=False) new_finding.endpoints = form.cleaned_data['endpoints'] new_finding.save(false_history=True) if 'jiraform-push_to_jira' in request.POST: jform = JIRAFindingForm(request.POST, prefix='jiraform', enabled=enabled) if jform.is_valid(): add_issue_task.delay(new_finding, jform.cleaned_data.get('push_to_jira')) messages.add_message(request, messages.SUCCESS, 'Finding added successfully.', extra_tags='alert-success') if create_template: templates = Finding_Template.objects.filter(title=new_finding.title) if len(templates) > 0: messages.add_message(request, messages.ERROR, 'A finding template was not created. A template with this title already ' 'exists.', extra_tags='alert-danger') else: template = Finding_Template(title=new_finding.title, cwe=new_finding.cwe, severity=new_finding.severity, description=new_finding.description, mitigation=new_finding.mitigation, impact=new_finding.impact, references=new_finding.references, numerical_severity=new_finding.numerical_severity) template.save() messages.add_message(request, messages.SUCCESS, 'A finding template was also created.', extra_tags='alert-success') if '_Finished' in request.POST: return HttpResponseRedirect(reverse('view_test', args=(test.id,))) else: return HttpResponseRedirect(reverse('add_findings', args=(test.id,))) else: if 'endpoints' in form.cleaned_data: form.fields['endpoints'].queryset = form.cleaned_data['endpoints'] else: form.fields['endpoints'].queryset = Endpoint.objects.none() form_error = True messages.add_message(request, messages.ERROR, 'The form has errors, please correct them below.', extra_tags='alert-danger') product_tab = Product_Tab(test.engagement.product.id, title="Add Finding", tab="engagements") product_tab.setEngagement(test.engagement) return render(request, 'dojo/add_findings.html', {'form': form, 'product_tab': product_tab, 'test': test, 'temp': False, 'tid': tid, 'form_error': form_error, 'jform': jform, })