def new_eng_for_app(request, pid): prod = Product.objects.get(id=pid) if request.method == 'POST': form = EngForm(request.POST) if form.is_valid(): new_eng = form.save(commit=False) new_eng.product = prod if new_eng.threat_model: new_eng.progress = 'threat_model' else: new_eng.progress = 'other' new_eng.save() messages.add_message(request, messages.SUCCESS, 'Engagement added successfully.', extra_tags='alert-success') if "_Add Tests" in request.POST: return HttpResponseRedirect(reverse('add_tests', args=(new_eng.id,))) else: return HttpResponseRedirect(reverse('view_engagement', args=(new_eng.id,))) else: form = EngForm(initial={}) add_breadcrumb(parent=prod, title="New Engagement", top_level=False, request=request) return render(request, 'dojo/new_eng.html', {'form': form, 'pid': pid, })
def delete_product(request, pid): product = get_object_or_404(Product, pk=pid) form = DeleteProductForm(instance=product) from django.contrib.admin.util import NestedObjects from django.db import DEFAULT_DB_ALIAS collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([product]) rels = collector.nested() if request.method == 'POST': if 'id' in request.POST and str(product.id) == request.POST['id']: form = DeleteProductForm(request.POST, instance=product) if form.is_valid(): product.delete() messages.add_message(request, messages.SUCCESS, 'Product and relationships removed.', extra_tags='alert-success') return HttpResponseRedirect(reverse('product')) add_breadcrumb(parent=product, title="Delete", top_level=False, request=request) return render(request, 'dojo/delete_product.html', {'product': product, 'form': form, 'rels': rels, })
def gmap(request, pid): prod = get_object_or_404(Product, id=pid) if request.user.is_staff or request.user in prod.authorized_users.all(): pass # user is authorized for this product else: raise PermissionDenied form = ScanSettingsForm() if request.method == 'POST': form = ScanSettingsForm(data=request.POST) if form.is_valid(): new_scan = form.save(commit=False) new_scan.product = prod new_scan.user = request.user new_scan.save() messages.add_message(request, messages.SUCCESS, 'Scan settings saved.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_product', args=(pid,))) else: messages.add_message(request, messages.ERROR, 'Scan settings not saved.', extra_tags='alert-danger') add_breadcrumb(title="Scan", top_level=False, request=request) return render(request, 'dojo/gmap.html', {'form': form, 'pid': pid})
def add_stub_finding(request, tid): test = get_object_or_404(Test, id=tid) form = StubFindingForm() if request.method == 'POST': form = StubFindingForm(request.POST) if form.is_valid(): stub_finding = form.save(commit=False) stub_finding.test = test stub_finding.reporter = request.user stub_finding.save() messages.add_message(request, messages.SUCCESS, 'Stub Finding created successfully.', extra_tags='alert-success') if request.is_ajax(): data = {'message': 'Stub Finding created successfully.', 'id': stub_finding.id, 'severity': 'None', 'date': formats.date_format(stub_finding.date, "DATE_FORMAT")} return HttpResponse(json.dumps(data)) else: if request.is_ajax(): data = {'message': 'Stub Finding form has error, please revise and try again.',} return HttpResponse(json.dumps(data)) messages.add_message(request, messages.ERROR, 'Stub Finding form has error, please revise and try again.', extra_tags='alert-danger') add_breadcrumb(title="Add Stub Finding", top_level=False, request=request) return HttpResponseRedirect(reverse('view_test', args=(tid,)))
def add_template(request): form = FindingTemplateForm() if request.method == 'POST': form = FindingTemplateForm(request.POST) if form.is_valid(): template = form.save(commit=False) template.numerical_severity = Finding.get_numerical_severity(template.severity) template.save() tags = request.POST.getlist('tags') t = ", ".join(tags) template.tags = t messages.add_message(request, messages.SUCCESS, 'Template created successfully.', extra_tags='alert-success') return HttpResponseRedirect(reverse('templates')) else: messages.add_message(request, messages.ERROR, 'Template form has error, please revise and try again.', extra_tags='alert-danger') add_breadcrumb(title="Add Template", top_level=False, request=request) return render(request, 'dojo/add_template.html', {'form': form, 'name': 'Add Template' })
def close_finding(request, fid): finding = get_object_or_404(Finding, id=fid) # in order to close a finding, we need to capture why it was closed # we can do this with a Note if request.method == 'POST': form = CloseFindingForm(request.POST) if form.is_valid(): now = datetime.now(tz=localtz) new_note = form.save(commit=False) new_note.author = request.user new_note.date = now new_note.save() finding.notes.add(new_note) finding.active = False finding.mitigated = now finding.mitigated_by = request.user finding.last_reviewed = finding.mitigated finding.last_reviewed_by = request.user finding.endpoints.clear() finding.save() messages.add_message(request, messages.SUCCESS, 'Finding closed.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_test', args=(finding.test.id,))) else: form = CloseFindingForm() add_breadcrumb(parent=finding, title="Close", top_level=False, request=request) return render(request, 'dojo/close_finding.html', {'finding': finding, 'user': request.user, 'form': form})
def accepted_findings(request): user = request.user fids = [finding.id for ra in Risk_Acceptance.objects.all() for finding in ra.accepted_findings.all()] findings = Finding.objects.filter(id__in=fids) findings = AcceptedFingingSuperFilter(request.GET, queryset=findings) title_words = [word for ra in Risk_Acceptance.objects.all() for finding in ra.accepted_findings.order_by( 'title').values('title').distinct() for word in finding['title'].split() if len(word) > 2] title_words = sorted(set(title_words)) paged_findings = get_page_items(request, findings, 25) add_breadcrumb(title="Accepted findings", top_level=not len(request.GET), request=request) return render(request, 'dojo/accepted_findings.html', {"findings": paged_findings, "filtered": findings, "title_words": title_words, })
def edit_template(request, tid): template = get_object_or_404(Finding_Template, id=tid) form = FindingTemplateForm(instance=template) if request.method == 'POST': form = FindingTemplateForm(request.POST, instance=template) if form.is_valid(): template = form.save(commit=False) template.numerical_severity = Finding.get_numerical_severity(template.severity) template.save() messages.add_message(request, messages.SUCCESS, 'Template updated successfully.', extra_tags='alert-success') return HttpResponseRedirect(reverse('templates')) else: messages.add_message(request, messages.ERROR, 'Template form has error, please revise and try again.', extra_tags='alert-danger') add_breadcrumb(title="Edit Template", top_level=False, request=request) return render(request, 'dojo/add_template.html', {'form': form, 'name': 'Edit Template', 'template': template, })
def open_findings(request): findings = Finding.objects.filter(mitigated__isnull=True, verified=True, false_p=False, duplicate=False, out_of_scope=False) if request.user.is_staff: findings = OpenFingingSuperFilter(request.GET, queryset=findings, user=request.user) else: findings = findings.filter(product__authorized_users__in=[request.user]) findings = OpenFindingFilter(request.GET, queryset=findings, user=request.user) title_words = [word for finding in findings for word in finding.title.split() if len(word) > 2] title_words = sorted(set(title_words)) paged_findings = get_page_items(request, findings, 25) product_type = None if 'product__prod_type' in request.GET: p = request.GET.getlist('product__prod_type', []) if len(p) == 1: product_type = get_object_or_404(Product_Type, id=p[0]) add_breadcrumb(title="Open findings", top_level=not len(request.GET), request=request) return render(request, 'dojo/open_findings.html', {"findings": paged_findings, "filtered": findings, "title_words": title_words, })
def delete_engagement_survey(request, eid, sid): engagement = get_object_or_404(Engagement, id=eid) survey = get_object_or_404(Answered_Survey, id=sid) questions = get_answered_questions(survey=survey, read_only=True) form = Delete_Survey_Form(instance=survey) if request.method == 'POST': form = Delete_Survey_Form(request.POST, instance=survey) if form.is_valid(): answers = Answer.objects.filter( question__in=[ question.id for question in survey.survey.questions.all()], answered_survey=survey) for answer in answers: answer.delete() survey.delete() messages.add_message(request, messages.SUCCESS, 'Survey deleted successfully.', extra_tags='alert-success') return HttpResponseRedirect('/engagement/%s' % eid) else: messages.add_message(request, messages.ERROR, 'Unable to delete survey.', extra_tags='alert-danger') add_breadcrumb(title="Delete " + survey.survey.name + " Survey", top_level=False, request=request) return render(request, 'defectDojo-engagement-survey/delete_survey.html', {'survey': survey, 'form': form, 'engagement': engagement, 'questions': questions, })
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,))) add_breadcrumb(parent=test, title="Delete", top_level=False, request=request) return render(request, 'dojo/delete_test.html', {'test': test, 'form': form, 'rels': rels, 'deletable_objects': rels, })
def edit_object(request, pid, ttid): object = Objects.objects.get(pk=ttid) if request.method == 'POST': tform = ObjectSettingsForm(request.POST, instance=object) if tform.is_valid(): tform.save() tags = request.POST.getlist('tags') t = ", ".join(tags) object.tags = t 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, initial={'tags': get_tag_list(Tag.objects.get_for_object(object))}) tform.initial['tags'] = [tag.name for tag in object.tags] add_breadcrumb(title="Edit Tracked Files", top_level=False, request=request) return render(request, 'dojo/edit_object.html', { 'tform': tform, })
def edit_user(request, uid): user = get_object_or_404(Dojo_User, id=uid) authed_products = Product.objects.filter(authorized_users__in=[user]) form = AddDojoUserForm(instance=user, initial={'authorized_products': authed_products}) if request.method == 'POST': form = AddDojoUserForm(request.POST, instance=user, initial={'authorized_products': authed_products}) if form.is_valid(): form.save() if 'authorized_products' in form.cleaned_data and len(form.cleaned_data['authorized_products']) > 0: for p in form.cleaned_data['authorized_products']: p.authorized_users.add(user) p.save() messages.add_message(request, messages.SUCCESS, 'User saved successfully.', extra_tags='alert-success') else: messages.add_message(request, messages.ERROR, 'User was not saved successfully.', extra_tags='alert-danger') add_breadcrumb(title="Edit User", top_level=False, request=request) return render(request, "dojo/add_user.html", { 'name': 'Edit User', 'form': form, 'to_edit': user})
def alerts(request): alerts = get_alerts(request.user) paged_alerts = get_page_items(request, alerts, 25) add_breadcrumb(title="Alerts for " + request.user.get_full_name(), top_level=True, request=request) return render(request, 'dojo/alerts.html', {'alerts': paged_alerts})
def add_user(request): form = AddDojoUserForm() user = None if request.method == 'POST': form = AddDojoUserForm(request.POST) if form.is_valid(): user = form.save(commit=False) user.set_unusable_password() user.is_staff = False user.is_superuser = False user.active = True user.save() if 'authorized_products' in form.cleaned_data and len(form.cleaned_data['authorized_products']) > 0: for p in form.cleaned_data['authorized_products']: p.authorized_users.add(user) p.save() messages.add_message(request, messages.SUCCESS, 'User added successfully, you may edit if necessary.', extra_tags='alert-success') return HttpResponseRedirect(reverse('edit_user', args=(user.id,))) else: messages.add_message(request, messages.ERROR, 'User was not added successfully.', extra_tags='alert-danger') add_breadcrumb(title="Add User", top_level=False, request=request) return render(request, "dojo/add_user.html", { 'name': 'Add User', 'form': form, 'to_add': True})
def new_object(request, pid): prod = get_object_or_404(Product, id=pid) if request.method == 'POST': tform = ObjectSettingsForm(request.POST) if tform.is_valid(): new_prod = tform.save(commit=False) new_prod.product = prod new_prod.save() tags = request.POST.getlist('tags') t = ", ".join(tags) new_prod.tags = t messages.add_message(request, messages.SUCCESS, 'Added Tracked File to a Product', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_objects', args=(pid,))) else: tform = ObjectSettingsForm() add_breadcrumb(title="Add Tracked Files to a Product", top_level=False, request=request) return render(request, 'dojo/new_object.html', {'tform': tform, 'pid': prod.id})
def delete_user(request, uid): user = get_object_or_404(Dojo_User, id=uid) form = DeleteUserForm(instance=user) from django.contrib.admin.utils import NestedObjects from django.db import DEFAULT_DB_ALIAS collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([user]) rels = collector.nested() if user.id == request.user.id: messages.add_message(request, messages.ERROR, 'You may not delete yourself.', extra_tags='alert-danger') return HttpResponseRedirect(reverse('edit_user', args=(user.id,))) if request.method == 'POST': if 'id' in request.POST and str(user.id) == request.POST['id']: form = DeleteUserForm(request.POST, instance=user) if form.is_valid(): user.delete() messages.add_message(request, messages.SUCCESS, 'User and relationships removed.', extra_tags='alert-success') return HttpResponseRedirect(reverse('users')) add_breadcrumb(title="Delete User", top_level=False, request=request) return render(request, 'dojo/delete_user.html', {'to_delete': user, 'form': form, 'rels': rels, })
def create_survey(request): form = CreateSurveyForm() survey = None if request.method == 'POST': form = CreateSurveyForm(request.POST) if form.is_valid(): survey = form.save() messages.add_message(request, messages.SUCCESS, 'Survey successfully created, you may now add questions.', extra_tags='alert-success') if 'add_questions' in request.POST: return HttpResponseRedirect(reverse('edit_survey_questions', args=(survey.id,))) else: return HttpResponseRedirect(reverse('edit_survey', args=(survey.id,))) else: messages.add_message(request, messages.ERROR, 'Please correct any errors displayed below.', extra_tags='alert-danger') add_breadcrumb(title="Create Survey", top_level=False, request=request) return render(request, 'defectDojo-engagement-survey/create_survey.html', {"survey": survey, "form": form, "name": "Create Survey", })
def api_key(request): api_key = '' form = APIKeyForm(instance=request.user) if request.method == 'POST': # new key requested form = APIKeyForm(request.POST, instance=request.user) if form.is_valid() and form.cleaned_data['id'] == request.user.id: try: api_key = ApiKey.objects.get(user=request.user) api_key.key = None api_key.save() except ApiKey.DoesNotExist: api_key = ApiKey.objects.create(user=request.user) messages.add_message(request, messages.SUCCESS, 'API Key generated successfully.', extra_tags='alert-success') else: raise PermissionDenied else: try: api_key = ApiKey.objects.get(user=request.user) except ApiKey.DoesNotExist: api_key = ApiKey.objects.create(user=request.user) add_breadcrumb(title="API Key", top_level=True, request=request) return render(request, 'dojo/api_key.html', {'name': 'API Key', 'metric': False, 'user': request.user, 'key': api_key, 'form': form, })
def report_builder(request): add_breadcrumb(title="Report Builder", top_level=True, request=request) findings = Finding.objects.all() findings = ReportAuthedFindingFilter(request.GET, queryset=findings, user=request.user) endpoints = Endpoint.objects.filter(finding__active=True, finding__verified=True, finding__false_p=False, finding__duplicate=False, finding__out_of_scope=False, ).distinct() ids = get_endpoint_ids(endpoints) endpoints = Endpoint.objects.filter(id__in=ids) endpoints = EndpointFilter(request.GET, queryset=endpoints) in_use_widgets = [ReportOptions(request=request)] available_widgets = [CoverPage(request=request), TableOfContents(request=request), WYSIWYGContent(request=request), FindingList(request=request, findings=findings), EndpointList(request=request, endpoints=endpoints), PageBreak()] return render(request, 'dojo/report_builder.html', {"available_widgets": available_widgets, "in_use_widgets": in_use_widgets})
def delete_survey(request, sid): survey = get_object_or_404(Engagement_Survey, id=sid) form = Delete_Eng_Survey_Form(instance=survey) from django.contrib.admin.util import NestedObjects from django.db import DEFAULT_DB_ALIAS collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([survey]) rels = collector.nested() if request.method == 'POST': if 'id' in request.POST and str(survey.id) == request.POST['id']: form = Delete_Eng_Survey_Form(request.POST, instance=survey) if form.is_valid(): survey.delete() messages.add_message(request, messages.SUCCESS, 'Survey and relationships removed.', extra_tags='alert-success') return HttpResponseRedirect(reverse('survey')) add_breadcrumb(title="Delete Survey", top_level=False, request=request) return render(request, 'defectDojo-engagement-survey/delete_survey.html', {'survey': survey, 'form': form, 'rels': rels, })
def view_profile(request): user = get_object_or_404(Dojo_User, pk=request.user.id) try: user_contact = UserContactInfo.objects.get(user=user) except UserContactInfo.DoesNotExist: user_contact = None form = DojoUserForm(instance=user) if user_contact is None: contact_form = UserContactInfoForm() else: contact_form = UserContactInfoForm(instance=user_contact) if request.method == 'POST': form = DojoUserForm(request.POST, instance=user) contact_form = UserContactInfoForm(request.POST, instance=user_contact) if form.is_valid() and contact_form.is_valid(): form.save() contact = contact_form.save(commit=False) contact.user = user contact.save() messages.add_message(request, messages.SUCCESS, 'Profile updated successfully.', extra_tags='alert-success') add_breadcrumb(title="User Profile - " + user.get_full_name(), top_level=True, request=request) return render(request, 'dojo/profile.html', { 'name': 'Engineer Profile', 'metric': False, 'user': user, 'form': form, 'contact_form': contact_form})
def view_engagement(request, eid): eng = Engagement.objects.get(id=eid) tests = Test.objects.filter(engagement=eng) risks_accepted = eng.risk_acceptance.all() 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': eng.progress = 'check_list' eng.save() add_breadcrumb(parent=eng, top_level=False, request=request) return render(request, 'dojo/view_eng.html', {'eng': eng, 'tests': tests, 'check': check, 'threat': eng.tmodel_path, 'risk': eng.risk_path, 'form': form, 'risks_accepted': risks_accepted, 'can_add_risk': len(eng_findings), })
def view_product_details(request, pid): prod = get_object_or_404(Product, id=pid) scan_sets = ScanSettings.objects.filter(product=prod) tools = Tool_Product_Settings.objects.filter(product=prod).order_by('name') auth = request.user.is_staff or request.user in prod.authorized_users.all() creds = Cred_Mapping.objects.filter(product=prod).select_related('cred_id').order_by('cred_id') langSummary = Languages.objects.filter(product=prod).aggregate(Sum('files'), Sum('code'), Count('files')) languages = Languages.objects.filter(product=prod).order_by('-code') app_analysis = App_Analysis.objects.filter(product=prod).order_by('name') benchmark_type = Benchmark_Type.objects.filter(enabled=True).order_by('name') benchmarks = Benchmark_Product_Summary.objects.filter(product=prod, publish=True, benchmark_type__enabled=True).order_by('benchmark_type__name') system_settings = System_Settings.objects.get() if not auth: # will render 403 raise PermissionDenied product_metadata = dict(prod.product_meta.values_list('name', 'value')) add_breadcrumb(parent=product, title="Details", top_level=False, request=request) return render(request, 'dojo/view_product_details.html', {'prod': prod, 'benchmark_type': benchmark_type, 'benchmarks': benchmarks, 'product_metadata': product_metadata, 'scan_sets': scan_sets, 'tools': tools, 'creds': creds, 'user': request.user, 'languages': languages, 'langSummary': langSummary, 'app_analysis': app_analysis, 'system_settings': system_settings, 'authorized': auth})
def product(request): if request.user.is_staff: initial_queryset = Product.objects.all() name_words = [product.name for product in Product.objects.all()] else: initial_queryset = Product.objects.filter( authorized_users__in=[request.user]) name_words = [word for product in Product.objects.filter( authorized_users__in=[request.user]) for word in product.name.split() if len(word) > 2] product_type = None if 'prod_type' in request.GET: p = request.GET.getlist('prod_type', []) if len(p) == 1: product_type = get_object_or_404(Product_Type, id=p[0]) """ if 'tags' in request.GET: tags = request.GET.getlist('tags', []) initial_queryset = TaggedItem.objects.get_by_model(initial_queryset, Tag.objects.filter(name__in=tags)) """ prods = ProductFilter(request.GET, queryset=initial_queryset, user=request.user) prod_list = get_page_items(request, prods.qs, 25) add_breadcrumb(title="Product List", top_level=not len(request.GET), request=request) return render(request, 'dojo/product.html', {'prod_list': prod_list, 'prods': prods, 'name_words': sorted(set(name_words)), 'user': request.user})
def add_survey(request, eid): user = request.user engagement = get_object_or_404(Engagement, id=eid) ids = [survey.survey.id for survey in Answered_Survey.objects.filter(engagement=engagement)] surveys = Engagement_Survey.objects.exclude( id__in=ids) form = Add_Survey_Form() if request.method == 'POST': form = Add_Survey_Form(request.POST) if form.is_valid(): survey = form.save(commit=False) survey.engagement = engagement survey.save() messages.add_message(request, messages.SUCCESS, 'Survey successfully added, answers pending.', extra_tags='alert-success') if 'respond_survey' in request.POST: return HttpResponseRedirect( '/engagement/%s/survey/%s/answer' % (eid, survey.id)) return HttpResponseRedirect('/engagement/%s' % eid) else: messages.add_message(request, messages.ERROR, 'Survey could not be added.', extra_tags='alert-danger') form.fields["survey"].queryset = surveys add_breadcrumb(title="Add Survey", top_level=False, request=request) return render(request, 'defectDojo-engagement-survey/add_survey.html', {'surveys': surveys, 'user': user, 'form': form, 'engagement': engagement})
def edit_tool_config(request, ttid): tool_config = Tool_Configuration.objects.get(pk=ttid) if request.method == 'POST': tform = ToolConfigForm(request.POST, instance=tool_config) if tform.is_valid(): form_copy = tform.save(commit=False) form_copy.password = dojo_crypto_encrypt(tform.cleaned_data['password']) print "######" print tform.cleaned_data['ssh'] form_copy.ssh = dojo_crypto_encrypt(tform.cleaned_data['ssh']) form_copy.save() messages.add_message(request, messages.SUCCESS, 'Tool Configuration Successfully Updated.', extra_tags='alert-success') return HttpResponseRedirect(reverse('tool_config', )) else: tool_config.password = prepare_for_view(tool_config.password) tool_config.ssh = prepare_for_view(tool_config.ssh) tform = ToolConfigForm(instance=tool_config) add_breadcrumb(title="Edit Tool Configuration", top_level=False, request=request) return render(request, 'dojo/edit_tool_config.html', { 'tform': tform, })
def view_tool_product(request, pid, ttid): tool = Tool_Product_Settings.objects.get(pk=ttid) notes = tool.notes.all() if request.method == 'POST': 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() tool.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() add_breadcrumb( title="View Product Tool Configuration", top_level=False, request=request) return render(request, 'dojo/view_tool_product.html', { 'tool': tool, 'notes': notes, 'form': form })
def tool_config(request): confs = Tool_Configuration.objects.all().order_by('name') add_breadcrumb(title="Tool Configuration List", top_level=not len(request.GET), request=request) return render(request, 'dojo/tool_config.html', {'confs': confs, })
def tool_type(request): confs = Tool_Type.objects.all().order_by('name') add_breadcrumb(title="Tool Type List", top_level=not len(request.GET), request=request) return render(request, 'dojo/tool_type.html', {'confs': confs, })
def benchmark_view(request, pid, type, cat=None): product = get_object_or_404(Product, id=pid) benchmark_type = get_object_or_404(Benchmark_Type, id=type) benchmark_category = Benchmark_Category.objects.filter(type=type, enabled=True).order_by('name') category_name = "" # Add requirements to the product add_benchmark(Benchmark_Requirement.objects.filter(category__type=type, category__type__enabled=True, enabled=True).all(), product) if cat: category_name = Benchmark_Category.objects.get(id=cat, enabled=True).name # Create the benchmark summary category try: benchmark_product_summary = Benchmark_Product_Summary.objects.get(product=product, benchmark_type=benchmark_type) except: pass benchmark_product_summary = Benchmark_Product_Summary(product=product, benchmark_type=benchmark_type) benchmark_product_summary.save() # Insert any new benchmarks since last created new_benchmarks = Benchmark_Requirement.objects.filter(category__type=type, category__type__enabled=True, enabled=True).exclude(id__in=Benchmark_Product.objects.filter(product=product).values_list('control_id', flat=True)) add_benchmark(new_benchmarks, product) Benchmark_ProductFormSet = modelformset_factory(Benchmark_Product, exclude=['product, control'], extra=0) if request.method == 'POST': form = Benchmark_ProductFormSet(request.POST) summary_form = Benchmark_Product_SummaryForm(request.POST, instance=benchmark_product_summary) if form.is_valid(): # print summary_form.errors summary_form_save = summary_form.save() form_save = form.save() score_asvs(product, benchmark_type) benchmark_product_summary = Benchmark_Product_Summary.objects.get(product=product, benchmark_type=benchmark_type) messages.add_message(request, messages.SUCCESS, 'Benchmarks saved.', extra_tags='alert-success') add_breadcrumb(title="Benchmarks", top_level=False, request=request) if cat: benchmarks = Benchmark_Product.objects.filter(product=product.id, control__category=cat, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__objective_number') benchmark_formset = Benchmark_ProductFormSet(queryset=Benchmark_Product.objects.filter(product=product.id, control__category=cat, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__objective_number')) else: benchmarks = Benchmark_Product.objects.filter(product=product.id, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__category__name', 'control__objective_number') benchmark_formset = Benchmark_ProductFormSet(queryset=Benchmark_Product.objects.filter(product=product.id, control__category__enabled=True, control__category__type=type, control__enabled=True).all().order_by('control__category__name', 'control__objective_number')) benchmark_summary_form = Benchmark_Product_SummaryForm(instance=benchmark_product_summary) product_tab = Product_Tab(pid, title="Benchmarks", tab="benchmarks") return render(request, 'dojo/benchmark.html', {'benchmarks': benchmarks, 'active_tab': 'benchmarks', 'product_tab': product_tab, 'benchmark_product_summary': benchmark_product_summary, 'benchmark_summary_form': benchmark_summary_form, 'benchmark_formset': benchmark_formset, 'benchmark_type': benchmark_type, 'product': product, 'category_name': category_name, 'benchmark_category': benchmark_category})
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) endpoints = endpoints.filter(endpoint_status__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 += " 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]) 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 view_engineer(request, eid): user = get_object_or_404(Dojo_User, pk=eid) if not (request.user.is_superuser or request.user.username == 'root' or request.user.username == user.username): return HttpResponseRedirect(reverse('engineer_metrics')) now = localtz.localize(datetime.today()) findings = Finding.objects.filter(reporter=user, verified=True) closed_findings = Finding.objects.filter(mitigated_by=user) open_findings = findings.exclude(mitigated__isnull=False) open_month = findings.filter(date__year=now.year, date__month=now.month) accepted_month = [finding for ra in Risk_Acceptance.objects.filter( created__range=[datetime(now.year, now.month, 1, tzinfo=localtz), datetime(now.year, now.month, monthrange(now.year, now.month)[1], tzinfo=localtz)], reporter=user) for finding in ra.accepted_findings.all()] closed_month = [] for f in closed_findings: if f.mitigated and f.mitigated.year == now.year and f.mitigated.month == now.month: closed_month.append(f) o_dict, open_count = count_findings(open_month) c_dict, closed_count = count_findings(closed_month) a_dict, accepted_count = count_findings(accepted_month) day_list = [now - relativedelta(weeks=1, weekday=x, hour=0, minute=0, second=0) for x in range(now.weekday())] day_list.append(now) q_objects = (Q(date=d) for d in day_list) closed_week = [] open_week = findings.filter(reduce(operator.or_, q_objects)) accepted_week = [finding for ra in Risk_Acceptance.objects.filter( reporter=user, created__range=[day_list[0], day_list[-1]]) for finding in ra.accepted_findings.all()] q_objects = (Q(mitigated=d) for d in day_list) # closed_week= findings.filter(reduce(operator.or_, q_objects)) for f in closed_findings: if f.mitigated and f.mitigated >= day_list[0]: closed_week.append(f) o_week_dict, open_week_count = count_findings(open_week) c_week_dict, closed_week_count = count_findings(closed_week) a_week_dict, accepted_week_count = count_findings(accepted_week) stuff = [] o_stuff = [] a_stuff = [] findings_this_period(findings, 1, stuff, o_stuff, a_stuff) # findings_this_period no longer fits the need for accepted findings # however will use its week finding output to use here for month in a_stuff: month_start = localtz.localize(datetime.strptime( month[0].strip(), "%b %Y")) month_end = datetime(month_start.year, month_start.month, monthrange( month_start.year, month_start.month)[1], tzinfo=localtz) for finding in [finding for ra in Risk_Acceptance.objects.filter( created__range=[month_start, month_end], reporter=user) for finding in ra.accepted_findings.all()]: if finding.severity == 'Critical': month[1] += 1 if finding.severity == 'High': month[2] += 1 if finding.severity == 'Medium': month[3] += 1 if finding.severity == 'Low': month[4] += 1 month[5] = sum(month[1:]) week_stuff = [] week_o_stuff = [] week_a_stuff = [] findings_this_period(findings, 0, week_stuff, week_o_stuff, week_a_stuff) # findings_this_period no longer fits the need for accepted findings # however will use its week finding output to use here for week in week_a_stuff: wk_range = week[0].split('-') week_start = localtz.localize(datetime.strptime( wk_range[0].strip() + " " + str(now.year), "%b %d %Y")) week_end = localtz.localize(datetime.strptime( wk_range[1].strip() + " " + str(now.year), "%b %d %Y")) for finding in [finding for ra in Risk_Acceptance.objects.filter( created__range=[week_start, week_end], reporter=user) for finding in ra.accepted_findings.all()]: if finding.severity == 'Critical': week[1] += 1 if finding.severity == 'High': week[2] += 1 if finding.severity == 'Medium': week[3] += 1 if finding.severity == 'Low': week[4] += 1 week[5] = sum(week[1:]) products = Product.objects.all() vulns = {} for product in products: f_count = 0 engs = Engagement.objects.filter(product=product) for eng in engs: tests = Test.objects.filter(engagement=eng) for test in tests: f_count += findings.filter(test=test, mitigated__isnull=True, active=True).count() vulns[product.id] = f_count od = OrderedDict(sorted(vulns.items(), key=itemgetter(1))) items = od.items() items.reverse() top = items[: 10] update = [] for t in top: product = t[0] z_count = 0 o_count = 0 t_count = 0 h_count = 0 engs = Engagement.objects.filter( product=Product.objects.get(id=product)) for eng in engs: tests = Test.objects.filter(engagement=eng) for test in tests: z_count += findings.filter( test=test, mitigated__isnull=True, severity='Critical' ).count() o_count += findings.filter( test=test, mitigated__isnull=True, severity='High' ).count() t_count += findings.filter( test=test, mitigated__isnull=True, severity='Medium' ).count() h_count += findings.filter( test=test, mitigated__isnull=True, severity='Low' ).count() prod = Product.objects.get(id=product) all_findings_link = "<a href='%s'>%s</a>" % ( reverse('view_product_findings', args=(prod.id,)), escape(prod.name)) update.append([all_findings_link, z_count, o_count, t_count, h_count, z_count + o_count + t_count + h_count]) total_update = [] for i in items: product = i[0] z_count = 0 o_count = 0 t_count = 0 h_count = 0 engs = Engagement.objects.filter( product=Product.objects.get(id=product)) for eng in engs: tests = Test.objects.filter(engagement=eng) for test in tests: z_count += findings.filter( test=test, mitigated__isnull=True, severity='Critical').count() o_count += findings.filter( test=test, mitigated__isnull=True, severity='High').count() t_count += findings.filter( test=test, mitigated__isnull=True, severity='Medium').count() h_count += findings.filter( test=test, mitigated__isnull=True, severity='Low').count() prod = Product.objects.get(id=product) all_findings_link = "<a href='%s'>%s</a>" % ( reverse('view_product_findings', args=(prod.id,)), escape(prod.name)) total_update.append([all_findings_link, z_count, o_count, t_count, h_count, z_count + o_count + t_count + h_count]) neg_length = len(stuff) findz = findings.filter(mitigated__isnull=True, active=True, test__engagement__risk_acceptance=None) findz = findz.filter(Q(severity="Critical") | Q(severity="High")) less_thirty = 0 less_sixty = 0 less_nine = 0 more_nine = 0 for finding in findz: elapsed = date.today() - finding.date if elapsed <= timedelta(days=30): less_thirty += 1 elif elapsed <= timedelta(days=60): less_sixty += 1 elif elapsed <= timedelta(days=90): less_nine += 1 else: more_nine += 1 # Data for the monthly charts chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']] for thing in o_stuff: chart_data.insert(1, thing) a_chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']] for thing in a_stuff: a_chart_data.insert(1, thing) # Data for the weekly charts week_chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']] for thing in week_o_stuff: week_chart_data.insert(1, thing) week_a_chart_data = [['Date', 'S0', 'S1', 'S2', 'S3', 'Total']] for thing in week_a_stuff: week_a_chart_data.insert(1, thing) details = [] for find in open_findings: team = find.test.engagement.product.prod_type.name name = find.test.engagement.product.name severity = find.severity description = find.title life = date.today() - find.date life = life.days status = 'Active' if len(find.risk_acceptance_set.all()) > 0: status = 'Accepted' detail = [team, name, severity, description, life, status, find.reporter] details.append(detail) details = sorted(details, key=lambda x: x[2]) add_breadcrumb(title="%s Metrics" % user.get_full_name(), top_level=False, request=request) return render(request, 'dojo/view_engineer.html', { 'open_month': open_month, 'a_month': accepted_month, 'low_a_month': accepted_count["low"], 'medium_a_month': accepted_count["med"], 'high_a_month': accepted_count["high"], 'critical_a_month': accepted_count["crit"], 'closed_month': closed_month, 'low_open_month': open_count["low"], 'medium_open_month': open_count["med"], 'high_open_month': open_count["high"], 'critical_open_month': open_count["crit"], 'low_c_month': closed_count["low"], 'medium_c_month': closed_count["med"], 'high_c_month': closed_count["high"], 'critical_c_month': closed_count["crit"], 'week_stuff': week_stuff, 'week_a_stuff': week_a_stuff, 'a_total': a_stuff, 'total': stuff, 'sub': neg_length, 'update': update, 'lt': less_thirty, 'ls': less_sixty, 'ln': less_nine, 'mn': more_nine, 'chart_data': chart_data, 'a_chart_data': a_chart_data, 'week_chart_data': week_chart_data, 'week_a_chart_data': week_a_chart_data, 'name': '%s Metrics' % user.get_full_name(), 'metric': True, 'total_update': total_update, 'details': details, 'open_week': open_week, 'closed_week': closed_week, 'accepted_week': accepted_week, 'a_dict': a_dict, 'o_dict': o_dict, 'c_dict': c_dict, 'o_week_dict': o_week_dict, 'a_week_dict': a_week_dict, 'c_week_dict': c_week_dict, 'open_week_count': open_week_count, 'accepted_week_count': accepted_week_count, 'closed_week_count': closed_week_count, 'user': request.user, })
def metrics(request, mtype): template = 'dojo/metrics.html' page_name = 'Product Type Metrics' show_pt_filter = True findings = Finding.objects.filter(verified=True, severity__in=('Critical', 'High', 'Medium', 'Low', 'Info')).prefetch_related( 'test__engagement__product', 'test__engagement__product__prod_type', 'test__engagement__risk_acceptance', 'risk_acceptance_set', 'reporter').extra( select={ 'ra_count': 'SELECT COUNT(*) FROM dojo_risk_acceptance INNER JOIN ' 'dojo_risk_acceptance_accepted_findings ON ' '( dojo_risk_acceptance.id = dojo_risk_acceptance_accepted_findings.risk_acceptance_id ) ' 'WHERE dojo_risk_acceptance_accepted_findings.finding_id = dojo_finding.id', "sql_age": 'SELECT IF(dojo_finding.mitigated IS NULL, DATEDIFF(CURDATE(), dojo_finding.date), ' 'DATEDIFF(dojo_finding.mitigated, dojo_finding.date))' }, ) active_findings = Finding.objects.filter(verified=True, active=True, severity__in=('Critical', 'High', 'Medium', 'Low', 'Info')).prefetch_related( 'test__engagement__product', 'test__engagement__product__prod_type', 'test__engagement__risk_acceptance', 'risk_acceptance_set', 'reporter').extra( select={ 'ra_count': 'SELECT COUNT(*) FROM dojo_risk_acceptance INNER JOIN ' 'dojo_risk_acceptance_accepted_findings ON ' '( dojo_risk_acceptance.id = dojo_risk_acceptance_accepted_findings.risk_acceptance_id ) ' 'WHERE dojo_risk_acceptance_accepted_findings.finding_id = dojo_finding.id', "sql_age": 'SELECT IF(dojo_finding.mitigated IS NULL, DATEDIFF(CURDATE(), dojo_finding.date), ' 'DATEDIFF(dojo_finding.mitigated, dojo_finding.date))' }, ) if mtype != 'All': pt = Product_Type.objects.filter(id=mtype) request.GET._mutable = True request.GET.appendlist('test__engagement__product__prod_type', mtype) request.GET._mutable = False mtype = pt[0].name show_pt_filter = False page_name = '%s Metrics' % mtype prod_type = pt elif 'test__engagement__product__prod_type' in request.GET: prod_type = Product_Type.objects.filter(id__in=request.GET.getlist('test__engagement__product__prod_type', [])) else: prod_type = Product_Type.objects.all() findings = MetricsFindingFilter(request.GET, queryset=findings) active_findings = MetricsFindingFilter(request.GET, queryset=active_findings) findings.qs # this is needed to load details from filter since it is lazy active_findings.qs # this is needed to load details from filter since it is lazy start_date = findings.filters['date'].start_date start_date = datetime(start_date.year, start_date.month, start_date.day, tzinfo=localtz) end_date = findings.filters['date'].end_date end_date = datetime(end_date.year, end_date.month, end_date.day, tzinfo=localtz) if len(prod_type) > 0: findings_closed = Finding.objects.filter(mitigated__range=[start_date, end_date], test__engagement__product__prod_type__in=prod_type).prefetch_related( 'test__engagement__product') # capture the accepted findings in period accepted_findings = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date], test__engagement__product__prod_type__in=prod_type). \ prefetch_related('test__engagement__product') accepted_findings_counts = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date], test__engagement__product__prod_type__in=prod_type). \ prefetch_related('test__engagement__product').aggregate( total=Sum( Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'), then=Value(1)), output_field=IntegerField())), critical=Sum( Case(When(severity='Critical', then=Value(1)), output_field=IntegerField())), high=Sum( Case(When(severity='High', then=Value(1)), output_field=IntegerField())), medium=Sum( Case(When(severity='Medium', then=Value(1)), output_field=IntegerField())), low=Sum( Case(When(severity='Low', then=Value(1)), output_field=IntegerField())), info=Sum( Case(When(severity='Info', then=Value(1)), output_field=IntegerField())), ) else: findings_closed = Finding.objects.filter(mitigated__range=[start_date, end_date]).prefetch_related( 'test__engagement__product') accepted_findings = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date]). \ prefetch_related('test__engagement__product') accepted_findings_counts = Finding.objects.filter(risk_acceptance__created__range=[start_date, end_date]). \ prefetch_related('test__engagement__product').aggregate( total=Sum( Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'), then=Value(1)), output_field=IntegerField())), critical=Sum( Case(When(severity='Critical', then=Value(1)), output_field=IntegerField())), high=Sum( Case(When(severity='High', then=Value(1)), output_field=IntegerField())), medium=Sum( Case(When(severity='Medium', then=Value(1)), output_field=IntegerField())), low=Sum( Case(When(severity='Low', then=Value(1)), output_field=IntegerField())), info=Sum( Case(When(severity='Info', then=Value(1)), output_field=IntegerField())), ) r = relativedelta(end_date, start_date) months_between = (r.years * 12) + r.months # include current month months_between += 1 weeks_between = int(ceil((((r.years * 12) + r.months) * 4.33) + (r.days / 7))) if weeks_between <= 0: weeks_between += 2 monthly_counts = get_period_counts(active_findings.qs, findings.qs, findings_closed, accepted_findings, months_between, start_date, relative_delta='months') weekly_counts = get_period_counts(active_findings.qs, findings.qs, findings_closed, accepted_findings, weeks_between, start_date, relative_delta='weeks') top_ten = Product.objects.filter(engagement__test__finding__verified=True, engagement__test__finding__false_p=False, engagement__test__finding__duplicate=False, engagement__test__finding__out_of_scope=False, engagement__test__finding__mitigated__isnull=True, engagement__test__finding__severity__in=( 'Critical', 'High', 'Medium', 'Low'), prod_type__in=prod_type).annotate( critical=Sum( Case(When(engagement__test__finding__severity='Critical', then=Value(1)), output_field=IntegerField()) ), high=Sum( Case(When(engagement__test__finding__severity='High', then=Value(1)), output_field=IntegerField()) ), medium=Sum( Case(When(engagement__test__finding__severity='Medium', then=Value(1)), output_field=IntegerField()) ), low=Sum( Case(When(engagement__test__finding__severity='Low', then=Value(1)), output_field=IntegerField()) ), total=Sum( Case(When(engagement__test__finding__severity__in=( 'Critical', 'High', 'Medium', 'Low'), then=Value(1)), output_field=IntegerField())) ).order_by('-critical', '-high', '-medium', '-low')[:10] age_detail = [0, 0, 0, 0] in_period_counts = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0, "Info": 0, "Total": 0} in_period_details = {} closed_in_period_counts = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0, "Info": 0, "Total": 0} closed_in_period_details = {} accepted_in_period_details = {} for finding in findings.qs: if 0 <= finding.sql_age <= 30: age_detail[0] += 1 elif 30 < finding.sql_age <= 60: age_detail[1] += 1 elif 60 < finding.sql_age <= 90: age_detail[2] += 1 elif finding.sql_age > 90: age_detail[3] += 1 in_period_counts[finding.severity] += 1 in_period_counts['Total'] += 1 if finding.test.engagement.product.name not in in_period_details: in_period_details[finding.test.engagement.product.name] = { 'path': reverse('view_product_findings', args=(finding.test.engagement.product.id,)), 'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0} in_period_details[ finding.test.engagement.product.name ][finding.severity] += 1 in_period_details[finding.test.engagement.product.name]['Total'] += 1 for finding in accepted_findings: if finding.test.engagement.product.name not in accepted_in_period_details: accepted_in_period_details[finding.test.engagement.product.name] = { 'path': reverse('accepted_findings') + '?test__engagement__product=' + str( finding.test.engagement.product.id), 'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0} accepted_in_period_details[ finding.test.engagement.product.name ][finding.severity] += 1 accepted_in_period_details[finding.test.engagement.product.name]['Total'] += 1 for f in findings_closed: closed_in_period_counts[f.severity] += 1 closed_in_period_counts['Total'] += 1 if f.test.engagement.product.name not in closed_in_period_details: closed_in_period_details[f.test.engagement.product.name] = { 'path': reverse('closed_findings') + '?test__engagement__product=' + str( f.test.engagement.product.id), 'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0} closed_in_period_details[ f.test.engagement.product.name ][f.severity] += 1 closed_in_period_details[f.test.engagement.product.name]['Total'] += 1 punchcard = list() ticks = list() highest_count = 0 if 'view' in request.GET and 'dashboard' == request.GET['view']: punchcard, ticks, highest_count = get_punchcard_data(findings.qs, weeks_between, start_date) page_name = (get_system_setting('team_name')) + " Metrics" template = 'dojo/dashboard-metrics.html' add_breadcrumb(title=page_name, top_level=not len(request.GET), request=request) return render(request, template, { 'name': page_name, 'start_date': start_date, 'end_date': end_date, 'findings': findings, 'opened_per_month': monthly_counts['opened_per_period'], 'active_per_month': monthly_counts['active_per_period'], 'opened_per_week': weekly_counts['opened_per_period'], 'accepted_per_month': monthly_counts['accepted_per_period'], 'accepted_per_week': weekly_counts['accepted_per_period'], 'top_ten_products': top_ten, 'age_detail': age_detail, 'in_period_counts': in_period_counts, 'in_period_details': in_period_details, 'accepted_in_period_counts': accepted_findings_counts, 'accepted_in_period_details': accepted_in_period_details, 'closed_in_period_counts': closed_in_period_counts, 'closed_in_period_details': closed_in_period_details, 'punchcard': punchcard, 'ticks': ticks, 'highest_count': highest_count, 'show_pt_filter': show_pt_filter, })
def product_type_counts(request): form = ProductTypeCountsForm() opened_in_period_list = [] oip = None cip = None aip = None all_current_in_pt = None top_ten = None pt = None today = datetime.now(tz=localtz) first_of_month = today.replace(day=1, hour=0, minute=0, second=0, microsecond=0) mid_month = first_of_month.replace(day=15, hour=23, minute=59, second=59, microsecond=999999) end_of_month = mid_month.replace(day=monthrange(today.year, today.month)[1], hour=23, minute=59, second=59, microsecond=999999) start_date = first_of_month end_date = end_of_month if request.method == 'GET' and 'month' in request.GET and 'year' in request.GET and 'product_type' in request.GET: form = ProductTypeCountsForm(request.GET) if form.is_valid(): pt = form.cleaned_data['product_type'] month = int(form.cleaned_data['month']) year = int(form.cleaned_data['year']) first_of_month = first_of_month.replace(month=month, year=year) month_requested = datetime(year, month, 1) end_of_month = month_requested.replace(day=monthrange(month_requested.year, month_requested.month)[1], hour=23, minute=59, second=59, microsecond=999999) start_date = first_of_month start_date = datetime(start_date.year, start_date.month, start_date.day, tzinfo=localtz) end_date = end_of_month end_date = datetime(end_date.year, end_date.month, end_date.day, tzinfo=localtz) oip = opened_in_period(start_date, end_date, pt) # trending data - 12 months for x in range(12, 0, -1): opened_in_period_list.append( opened_in_period(start_date + relativedelta(months=-x), end_of_month + relativedelta(months=-x), pt)) opened_in_period_list.append(oip) closed_in_period = Finding.objects.filter(mitigated__range=[start_date, end_date], test__engagement__product__prod_type=pt, severity__in=('Critical', 'High', 'Medium', 'Low')).values( 'numerical_severity').annotate(Count('numerical_severity')).order_by('numerical_severity') total_closed_in_period = Finding.objects.filter(mitigated__range=[start_date, end_date], test__engagement__product__prod_type=pt, severity__in=( 'Critical', 'High', 'Medium', 'Low')).aggregate( total=Sum( Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'), then=Value(1)), output_field=IntegerField())))['total'] overall_in_pt = Finding.objects.filter(date__lt=end_date, verified=True, false_p=False, duplicate=False, out_of_scope=False, mitigated__isnull=True, test__engagement__product__prod_type=pt, severity__in=('Critical', 'High', 'Medium', 'Low')).values( 'numerical_severity').annotate(Count('numerical_severity')).order_by('numerical_severity') total_overall_in_pt = Finding.objects.filter(date__lte=end_date, verified=True, false_p=False, duplicate=False, out_of_scope=False, mitigated__isnull=True, test__engagement__product__prod_type=pt, severity__in=('Critical', 'High', 'Medium', 'Low')).aggregate( total=Sum( Case(When(severity__in=('Critical', 'High', 'Medium', 'Low'), then=Value(1)), output_field=IntegerField())))['total'] all_current_in_pt = Finding.objects.filter(date__lte=end_date, verified=True, false_p=False, duplicate=False, out_of_scope=False, mitigated__isnull=True, test__engagement__product__prod_type=pt, severity__in=( 'Critical', 'High', 'Medium', 'Low')).prefetch_related( 'test__engagement__product', 'test__engagement__product__prod_type', 'test__engagement__risk_acceptance', 'reporter').order_by( 'numerical_severity') top_ten = Product.objects.filter(engagement__test__finding__date__lte=end_date, engagement__test__finding__verified=True, engagement__test__finding__false_p=False, engagement__test__finding__duplicate=False, engagement__test__finding__out_of_scope=False, engagement__test__finding__mitigated__isnull=True, engagement__test__finding__severity__in=( 'Critical', 'High', 'Medium', 'Low'), prod_type=pt).annotate( critical=Sum( Case(When(engagement__test__finding__severity='Critical', then=Value(1)), output_field=IntegerField()) ), high=Sum( Case(When(engagement__test__finding__severity='High', then=Value(1)), output_field=IntegerField()) ), medium=Sum( Case(When(engagement__test__finding__severity='Medium', then=Value(1)), output_field=IntegerField()) ), low=Sum( Case(When(engagement__test__finding__severity='Low', then=Value(1)), output_field=IntegerField()) ), total=Sum( Case(When(engagement__test__finding__severity__in=( 'Critical', 'High', 'Medium', 'Low'), then=Value(1)), output_field=IntegerField())) ).order_by('-critical', '-high', '-medium', '-low')[:10] cip = {'S0': 0, 'S1': 0, 'S2': 0, 'S3': 0, 'Total': total_closed_in_period} aip = {'S0': 0, 'S1': 0, 'S2': 0, 'S3': 0, 'Total': total_overall_in_pt} for o in closed_in_period: cip[o['numerical_severity']] = o['numerical_severity__count'] for o in overall_in_pt: aip[o['numerical_severity']] = o['numerical_severity__count'] else: messages.add_message(request, messages.ERROR, "Please choose month and year and the Product Type.", extra_tags='alert-danger') add_breadcrumb(title="Bi-Weekly Metrics", top_level=True, request=request) return render(request, 'dojo/pt_counts.html', {'form': form, 'start_date': start_date, 'end_date': end_date, 'opened_in_period': oip, 'trending_opened': opened_in_period_list, 'closed_in_period': cip, 'overall_in_pt': aip, 'all_current_in_pt': all_current_in_pt, 'top_ten': top_ten, 'pt': pt} )
def simple_metrics(request): now = localtz.localize(datetime.today()) if request.method == 'POST': form = SimpleMetricsForm(request.POST) if form.is_valid(): now = form.cleaned_data['date'] form = SimpleMetricsForm({'date': now}) else: form = SimpleMetricsForm({'date': now}) findings_by_product_type = collections.OrderedDict() # for each product type find each product with open findings and # count the S0, S1, S2 and S3 for pt in Product_Type.objects.order_by('name'): total_critical = [] total_high = [] total_medium = [] total_low = [] total_info = [] total_closed = [] total_opened = [] findings_broken_out = {} total = Finding.objects.filter(test__engagement__product__prod_type=pt, verified=True, false_p=False, duplicate=False, out_of_scope=False, date=now, ).distinct() for f in total.all(): if f.severity == "Critical": total_critical.append(f) elif f.severity == 'High': total_high.append(f) elif f.severity == 'Medium': total_medium.append(f) elif f.severity == 'Low': total_low.append(f) else: total_info.append(f) if f.mitigated and f.mitigated.year == now.year and f.mitigated.month == now.month: total_closed.append(f) if f.date.year == now.year and f.date.month == now.month: total_opened.append(f) findings_broken_out['Total'] = total.count() findings_broken_out['S0'] = len(total_critical) findings_broken_out['S1'] = len(total_high) findings_broken_out['S2'] = len(total_medium) findings_broken_out['S3'] = len(total_low) findings_broken_out['S4'] = len(total_info) findings_broken_out['Opened'] = len(total_opened) findings_broken_out['Closed'] = len(total_closed) findings_by_product_type[pt] = findings_broken_out add_breadcrumb(title="Simple Metrics", top_level=True, request=request) return render(request, 'dojo/simple_metrics.html', { 'findings': findings_by_product_type, 'name': 'Simple Metrics', 'metric': True, 'user': request.user, 'form': form, })
def import_scan_results(request, eid): engagement = get_object_or_404(Engagement, id=eid) finding_count = 0 form = ImportScanForm() cred_form = CredMappingForm() 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(): 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() try: parser = import_parser_factory(file, t) except ValueError: raise Http404() try: for item in parser.items: 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 item.date = t.target_start item.reporter = request.user item.last_reviewed = datetime.now(tz=localtz) item.last_reviewed_by = request.user item.active = active item.verified = verified item.save() 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) 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') 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') add_breadcrumb(parent=engagement, title="Import Scan Results", top_level=False, request=request) return render(request, 'dojo/import_scan_results.html', {'form': form, 'eid': engagement.id, 'cred_form': cred_form, })
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, engagement=eng) 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() # 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=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(engagement=eng) 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 view_engagement(request, eid): eng = get_object_or_404(Engagement, id=eid) tests = (Test.objects.filter(engagement=eng).prefetch_related( 'tags', 'test_type').annotate( count_findings_test_all=Count('finding__id')).annotate( count_findings_test_active_verified=Count( 'finding__id', filter=Q(finding__active=True)) ).annotate(count_findings_test_mitigated=Count( 'finding__id', filter=Q(finding__is_Mitigated=True))).annotate( count_findings_test_dups=Count( 'finding__id', filter=Q( finding__duplicate=True))).order_by( 'test_type__name', '-updated')) prod = eng.product risks_accepted = eng.risk_acceptance.all().select_related('owner') 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() jissue = jira_helper.get_jira_issue(eng) jira_project = jira_helper.get_jira_project(eng) 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 notes = eng.notes.all() note_type_activation = Note_Type.objects.filter(is_active=True).count() if note_type_activation: available_note_types = find_available_notetypes(notes) if request.method == 'POST' and request.user.is_staff: eng.progress = 'check_list' eng.save() if note_type_activation: form = TypedNoteForm(request.POST, available_note_types=available_note_types) else: 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() eng.notes.add(new_note) if note_type_activation: form = TypedNoteForm(available_note_types=available_note_types) else: form = NoteForm() url = request.build_absolute_uri( reverse("view_engagement", args=(eng.id, ))) title = "Engagement: %s on %s" % (eng.name, eng.product.name) messages.add_message(request, messages.SUCCESS, 'Note added successfully.', extra_tags='alert-success') else: if note_type_activation: form = TypedNoteForm(available_note_types=available_note_types) else: form = NoteForm() 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, 'notes': notes, 'risks_accepted': risks_accepted, 'can_add_risk': eng_findings.count(), 'jissue': jissue, 'jira_project': jira_project, 'accepted_findings': accepted_findings, 'start_date': start_date, 'creds': creds, 'cred_eng': cred_eng, 'network': network, 'preset_test_type': preset_test_type })
def simple_search(request): ip_addresses = [] dashes = [] query = [] tests = None findings = None finding_templates = None products = None tagged_tests = None tagged_findings = None tagged_products = None tagged_endpoints = None tagged_engagements = None tagged_finding_templates = None engagements = None endpoints = None languages = None app_analysis = None clean_query = '' cookie = False terms = '' form = SimpleSearchForm() original_clean_query = "" findings_filter = None title_words = None component_words = None paged_generic = None max_results = settings.SEARCH_MAX_RESULTS # if request.method == 'GET' and "query" in request.GET: if request.method == 'GET': form = SimpleSearchForm(request.GET) if form.is_valid(): # logger.debug('form vars: %s', vars(form)) cookie = True clean_query = form.cleaned_data['query'] or '' search_operator, operator = "", "" # Check for search operator like finding:, endpoint:, test: product: original_clean_query = clean_query # print('clean_query: ', clean_query) if ":" in clean_query: operator = clean_query.split(":") search_operator = operator[0] clean_query = operator[1].lstrip() logger.debug('operator: %s', operator) logger.debug('search_operator: %s', search_operator) logger.debug('clean_query: %s', clean_query) # if the query contains hyphens, django-watson will escape these leading to problems. # for cve we make this workaround because we really want to be able to search for CVEs # problem still remains for other case, i.e. searching for "valentijn-scholten" will return no results because of the hyphen. # see: # - https://github.com/etianen/django-watson/issues/223 # - https://github.com/DefectDojo/django-DefectDojo/issues/1092 # - https://github.com/DefectDojo/django-DefectDojo/issues/2081 # it's not google grade parsing, but let's do some basic stuff right query_parts = clean_query.split(" ") new_parts = "" for part in query_parts: if bool(cve_pattern.match(part)): part = '\'' + part + '\'' clean_query = '\'' + clean_query + '\'' print('new part: ', part) else: print('old part: ', part) new_parts += (part + " ") clean_query = new_parts.strip() # clean_query = '\'' + clean_query + '\'' logger.debug('cve clean_query: [%s]', clean_query) search_tags = "tag" in search_operator or search_operator == "" search_findings = "finding" in search_operator or "cve" in search_operator or "id" in search_operator or search_operator == "" search_finding_templates = "template" in search_operator or search_operator == "" search_tests = "test" in search_operator or search_operator == "" search_engagements = "engagement" in search_operator or search_operator == "" search_products = "product" in search_operator or search_operator == "" search_endpoints = "endpoint" in search_operator or search_operator == "" search_languages = "language" in search_operator or search_operator == "" search_technologies = "technology" in search_operator or search_operator == "" findings = Finding.objects.all() tests = Test.objects.all() engagements = Engagement.objects.all() products = Product.objects.all() endpoints = Endpoint.objects.all() finding_templates = Finding_Template.objects.all() if not request.user.is_staff: findings = findings.filter( Q(test__engagement__product__authorized_users__in=[ request.user ]) | Q(test__engagement__product__prod_type__authorized_users__in =[request.user])) tests = tests.filter( Q(engagement__product__authorized_users__in=[request.user]) | Q(engagement__product__prod_type__authorized_users__in=[ request.user ])) engagements = engagements.filter( Q(product__authorized_users__in=[request.user]) | Q(product__prod_type__authorized_users__in=[request.user])) products = products.filter( Q(authorized_users__in=[request.user]) | Q(prod_type__authorized_users__in=[request.user])) endpoints = endpoints.filter( Q(product__authorized_users__in=[request.user]) | Q(product__prod_type__authorized_users__in=[request.user])) # TODO better get findings in their own query and match on id. that would allow filtering on additional fields such cve, prod_id, etc. findings_filter = None title_words = None component_words = None tags = clean_query # search tags first to avoid errors due to slicing too early if search_tags: tagged_findings = TaggedItem.objects.get_by_model( findings, tags)[:max_results] tagged_finding_templates = TaggedItem.objects.get_by_model( Finding_Template, tags)[:max_results] tagged_tests = TaggedItem.objects.get_by_model( tests, tags)[:max_results] tagged_engagements = TaggedItem.objects.get_by_model( engagements, tags)[:max_results] tagged_products = TaggedItem.objects.get_union_by_model( products, tags)[:max_results] tagged_endpoints = TaggedItem.objects.get_by_model( endpoints, tags)[:max_results] else: tagged_findings = None tagged_finding_templates = None tagged_tests = None tagged_engagements = None tagged_products = None tagged_endpoints = None if search_findings: findings_filter = OpenFindingFilter(request.GET, queryset=findings, user=request.user, pid=None, prefix='finding') title_words = get_words_for_field(findings_filter.qs, 'title') component_words = get_words_for_field(findings_filter.qs, 'component_name') findings = findings_filter.qs if clean_query: logger.debug('going watson with: %s', clean_query) watson_results = watson.filter(findings_filter.qs, clean_query)[:max_results] findings = findings.filter( id__in=[watson.id for watson in watson_results]) # prefetch after watson to avoid inavlid query errors due to watson not understanding prefetching findings = prefetch_for_findings(findings) # some over the top tag displaying happening... findings = findings.prefetch_related( 'test__engagement__product__tagged_items__tag') findings = findings[:max_results] else: findings = None findings_filter = None component_words = None # logger.debug('%s', findings.query) # paged_findings = get_page_items(request, findings, 25) # findings = prefetch_for_findings(findings) # some over the top tag displaying happening... # findings = findings.prefetch_related('test__engagement__product__tagged_items__tag') # paged_findings.object_list = findings # for result in findings: # if False: # logger.debug('findings result: %s', vars(result)) if search_finding_templates: watson_results = watson.filter(finding_templates, clean_query) finding_templates = finding_templates.filter( id__in=[watson.id for watson in watson_results]) finding_templates = finding_templates[:max_results] else: finding_templates = None if search_tests: watson_results = watson.filter(tests, clean_query) tests = tests.filter( id__in=[watson.id for watson in watson_results]) tests = tests.prefetch_related( 'engagement', 'engagement__product', 'test_type', 'tagged_items__tag', 'engagement__tagged_items__tag', 'engagement__product__tagged_items__tag') tests = tests[:max_results] else: tests = None if search_engagements: watson_results = watson.filter(engagements, clean_query) engagements = engagements.filter( id__in=[watson.id for watson in watson_results]) engagements = engagements.prefetch_related( 'product', 'product__tagged_items__tag', 'tagged_items__tag') engagements = engagements[:max_results] else: engagements = None if search_products: watson_results = watson.filter(products, clean_query) products = products.filter( id__in=[watson.id for watson in watson_results]) products = products.prefetch_related('tagged_items__tag') products = products[:max_results] else: products = None if search_endpoints: endpoints = endpoints.filter( Q(host__icontains=clean_query) | Q(path__icontains=clean_query) | Q(fqdn__icontains=clean_query) | Q(protocol__icontains=clean_query)) endpoints = endpoints.prefetch_related( 'product', 'tagged_items__tag', 'product__tagged_items__tag') endpoints = endpoints[:max_results] else: endpoints = None if search_languages: languages = Languages.objects.filter( language__language__icontains=clean_query) languages = languages.prefetch_related( 'product', 'product__tagged_items__tag') languages = languages[:max_results] else: languages = None if search_technologies: app_analysis = App_Analysis.objects.filter( name__icontains=clean_query) app_analysis = app_analysis[:max_results] else: app_analysis = None # generic = watson.search(clean_query, models=(Finding,)).prefetch_related('object') generic = watson.search(clean_query).prefetch_related( 'object')[:max_results] # paging doesn't work well with django_watson # paged_generic = get_page_items(request, generic, 25) # generic = get_page_items(request, generic, 25) # generic = watson.search(original_clean_query)[:50].prefetch_related('object') # generic = watson.search("qander document 'CVE-2019-8331'")[:10].prefetch_related('object') # generic = watson.search("'CVE-2020-6754'")[:10].prefetch_related('object') # generic = watson.search(" 'ISEC-433'")[:10].prefetch_related('object') # for result in generic: # if False: # logger.debug('generic result: %s', vars(result)) else: logger.debug('search form invalid') logger.debug(form.errors) form = SimpleSearchForm() add_breadcrumb(title="Simple Search", top_level=True, request=request) activetab = 'findings' if findings \ else 'products' if products \ else 'engagements' if engagements else \ 'tests' if tests else \ 'endpoint' if endpoints else \ 'generic' if generic else \ 'tagged' response = render( request, 'dojo/simple_search.html', { 'clean_query': original_clean_query, 'languages': languages, 'app_analysis': app_analysis, 'tests': tests, 'findings': findings, 'finding_templates': finding_templates, 'filtered': findings_filter, 'title_words': title_words, 'component_words': component_words, 'products': products, 'tagged_tests': tagged_tests, 'tagged_findings': tagged_findings, 'tagged_finding_templates': tagged_finding_templates, 'tagged_products': tagged_products, 'tagged_endpoints': tagged_endpoints, 'tagged_engagements': tagged_engagements, 'engagements': engagements, 'endpoints': endpoints, 'name': 'Simple Search', 'metric': False, 'user': request.user, 'form': form, 'activetab': activetab, 'show_product_column': True, 'generic': generic }) if cookie: response.set_cookie("highlight", value=clean_query, max_age=None, expires=None, path='/', secure=True, httponly=False) else: response.delete_cookie("highlight", path='/') return response
def view_engagement(request, eid): eng = Engagement.objects.get(id=eid) tests = Test.objects.filter(engagement=eng) risks_accepted = eng.risk_acceptance.all() 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': 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 = localtz.localize(datetime.today()) end_date = localtz.localize(datetime.today()) 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()] week_date = end_date - timedelta(days=7) # seven days and /newer are considered "new" new_verified_findings = Finding.objects.filter(test__engagement__product=eng.product, date__range=[week_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False).order_by("date") open_findings = Finding.objects.filter(test__engagement__product=eng.product, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False, active=True, mitigated__isnull=True) closed_findings = Finding.objects.filter(test__engagement__product=eng.product, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False, mitigated__isnull=False) return render(request, 'dojo/view_eng.html', {'eng': eng, '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, 'open_findings': open_findings, 'closed_findings': closed_findings, 'accepted_findings': accepted_findings, 'new_findings': new_verified_findings, 'start_date': start_date, 'creds': creds, 'cred_eng': cred_eng })
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 = datetime.now(tz=localtz) 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) add_breadcrumb(parent=risk_approval, top_level=False, request=request) return render(request, 'dojo/view_risk.html', {'risk_approval': risk_approval, '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 edit_finding(request, fid): finding = get_object_or_404(Finding, id=fid) old_status = finding.status() form = FindingForm(instance=finding) form.initial['tags'] = [tag.name for tag in finding.tags] form_error = False jform = None try: jissue = JIRA_Issue.objects.get(finding=finding) enabled = True except: enabled = False pass if hasattr(settings, 'ENABLE_JIRA'): if settings.ENABLE_JIRA: if JIRA_PKey.objects.filter( product=finding.test.engagement.product) != 0: jform = JIRAFindingForm(enabled=enabled, prefix='jiraform') if request.method == 'POST': form = FindingForm(request.POST, instance=finding) if form.is_valid(): new_finding = form.save(commit=False) new_finding.test = finding.test 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 = datetime.now(tz=localtz) new_finding.mitigated_by = request.user if new_finding.active is True: new_finding.false_p = False new_finding.mitigated = None new_finding.mitigated_by = None 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.endpoints = form.cleaned_data['endpoints'] new_finding.last_reviewed = datetime.now(tz=localtz) new_finding.last_reviewed_by = request.user tags = request.POST.getlist('tags') t = ", ".join(tags) new_finding.tags = t new_finding.save() if 'jiraform-push_to_jira' in request.POST: jform = JIRAFindingForm(request.POST, prefix='jiraform', enabled=enabled) if jform.is_valid(): try: jissue = JIRA_Issue.objects.get(finding=new_finding) update_issue_task.delay( new_finding, old_status, jform.cleaned_data.get('push_to_jira')) except: add_issue_task.delay( new_finding, jform.cleaned_data.get('push_to_jira')) pass tags = request.POST.getlist('tags') t = ", ".join(tags) new_finding.tags = t messages.add_message(request, messages.SUCCESS, 'Finding saved 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_finding', args=(new_finding.id, ))) else: messages.add_message( request, messages.ERROR, 'There appears to be errors on the form, please correct below.', extra_tags='alert-danger') form_error = True if form_error and 'endpoints' in form.cleaned_data: form.fields['endpoints'].queryset = form.cleaned_data['endpoints'] else: form.fields['endpoints'].queryset = finding.endpoints.all() form.initial['tags'] = [tag.name for tag in finding.tags] add_breadcrumb(parent=finding, title="Edit", top_level=False, request=request) return render(request, 'dojo/edit_findings.html', { 'form': form, 'finding': finding, 'jform': jform })
def edit_user(request, uid): user = get_object_or_404(Dojo_User, id=uid) authed_products = Product.objects.filter(authorized_users__in=[user]) authed_product_types = Product_Type.objects.filter(authorized_users__in=[user]) form = AddDojoUserForm(instance=user, initial={ 'authorized_products': authed_products, 'authorized_product_types': authed_product_types }) if not request.user.is_superuser: form.fields['is_staff'].widget.attrs['disabled'] = True form.fields['is_superuser'].widget.attrs['disabled'] = True form.fields['is_active'].widget.attrs['disabled'] = True user_contact = user.usercontactinfo if hasattr(user, 'usercontactinfo') else None if user_contact is None: contact_form = UserContactInfoForm() else: contact_form = UserContactInfoForm(instance=user_contact) if request.method == 'POST': form = AddDojoUserForm(request.POST, instance=user) if user_contact is None: contact_form = UserContactInfoForm(request.POST) else: contact_form = UserContactInfoForm(request.POST, instance=user_contact) if form.is_valid() and contact_form.is_valid(): form.save() for init_auth_prods in authed_products: init_auth_prods.authorized_users.remove(user) init_auth_prods.save() for init_auth_prod_types in authed_product_types: init_auth_prod_types.authorized_users.remove(user) init_auth_prod_types.save() if 'authorized_products' in form.cleaned_data and len(form.cleaned_data['authorized_products']) > 0: for p in form.cleaned_data['authorized_products']: p.authorized_users.add(user) p.save() if 'authorized_product_types' in form.cleaned_data and len(form.cleaned_data['authorized_product_types']) > 0: for pt in form.cleaned_data['authorized_product_types']: pt.authorized_users.add(user) pt.save() contact = contact_form.save(commit=False) contact.user = user contact.save() messages.add_message(request, messages.SUCCESS, 'User saved successfully.', extra_tags='alert-success') else: messages.add_message(request, messages.ERROR, 'User was not saved successfully.', extra_tags='alert-danger') add_breadcrumb(title="Edit User", top_level=False, request=request) return render(request, "dojo/add_user.html", { 'name': 'Edit User', 'form': form, 'contact_form': contact_form, 'to_edit': user})
def view_finding(request, fid): finding = get_object_or_404(Finding, id=fid) user = request.user try: jissue = JIRA_Issue.objects.get(finding=finding) except: jissue = None pass try: jpkey = JIRA_PKey.objects.get(product=finding.test.engagement.product) jconf = jpkey.conf except: jconf = None pass dojo_user = get_object_or_404(Dojo_User, id=user.id) if user.is_staff or user in finding.test.engagement.product.authorized_users.all( ): pass # user is authorized for this product else: raise PermissionDenied notes = finding.notes.all() if request.method == 'POST': form = NoteForm(request.POST) if form.is_valid(): new_note = form.save(commit=False) new_note.author = request.user new_note.date = datetime.now(tz=localtz) new_note.save() finding.notes.add(new_note) finding.last_reviewed = new_note.date finding.last_reviewed_by = user finding.save() if jissue is not None: add_comment_task(finding, new_note) form = NoteForm() messages.add_message(request, messages.SUCCESS, 'Note saved.', extra_tags='alert-success') else: form = NoteForm() try: reqres = BurpRawRequestResponse.objects.get(finding=finding) burp_request = base64.b64decode(reqres.burpRequestBase64) burp_response = base64.b64decode(reqres.burpResponseBase64) except: reqres = None burp_request = None burp_response = None add_breadcrumb(parent=finding, top_level=False, request=request) return render( request, 'dojo/view_finding.html', { 'finding': finding, 'burp_request': burp_request, 'jissue': jissue, 'jconf': jconf, 'burp_response': burp_response, 'dojo_user': dojo_user, 'user': user, 'notes': notes, 'form': form })
def promote_to_finding(request, fid): finding = get_object_or_404(Stub_Finding, id=fid) test = finding.test form_error = False jira_available = False if hasattr(settings, 'ENABLE_JIRA'): if settings.ENABLE_JIRA: if JIRA_PKey.objects.filter(product=test.engagement.product) != 0: jform = JIRAFindingForm( request.POST, prefix='jiraform', enabled=JIRA_PKey.objects.get( product=test.engagement.product).push_all_issues) jira_available = True else: jform = None form = PromoteFindingForm( initial={ 'title': finding.title, 'date': finding.date, 'severity': finding.severity, 'description': finding.description, 'test': finding.test, 'reporter': finding.reporter }) if request.method == 'POST': form = PromoteFindingForm(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.active = True new_finding.false_p = False new_finding.duplicate = False new_finding.mitigated = None new_finding.verified = True new_finding.out_of_scope = False new_finding.save() new_finding.endpoints = form.cleaned_data['endpoints'] new_finding.save() finding.delete() if 'jiraform' in request.POST: jform = JIRAFindingForm( request.POST, prefix='jiraform', enabled=JIRA_PKey.objects.get( product=test.engagement.product).push_all_issues) if jform.is_valid(): add_issue_task.delay( new_finding, jform.cleaned_data.get('push_to_jira')) messages.add_message(request, messages.SUCCESS, 'Finding promoted successfully.', extra_tags='alert-success') return HttpResponseRedirect(reverse('view_test', 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') add_breadcrumb(parent=test, title="Promote Finding", top_level=False, request=request) return render( request, 'dojo/promote_to_finding.html', { 'form': form, 'test': test, 'stub_finding': finding, 'form_error': form_error, })
def system_settings(request): system_settings_obj = System_Settings.objects.get(no_cache=True) """ **** To be Finished JIRA Status info **** jira_bool = True jira_msg = 'None' if not celery_bool: jira_bool = False jira_msg = 'Celery is not working properly' else: try: jira_server = jform.cleaned_data.get('url').rstrip('/') jira = JIRA(server=jform.cleaned_data.get('url').rstrip('/'), basic_auth=(jform.cleaned_data.get('username'), jform.cleaned_data.get('password'))) new_j = jform.save(commit=False) new_j.url = jira_server new_j.save() messages.add_message(request, messages.SUCCESS, 'JIRA Configuration Successfully Created.', extra_tags='alert-success') return HttpResponseRedirect(reverse('jira', )) except: messages.add_message(request, messages.ERROR, 'Unable to authenticate. Please check the URL, username, and password.', extra_tags='alert-danger') """ form = SystemSettingsForm(instance=system_settings_obj) if request.method == 'POST': form = SystemSettingsForm(request.POST, instance=system_settings_obj) if form.is_valid(): new_settings = form.save() enable_disable_auditlog(enable=new_settings.enable_auditlog) messages.add_message(request, messages.SUCCESS, 'Settings saved.', extra_tags='alert-success') return HttpResponseRedirect(reverse('system_settings', )) else: # Celery needs to be set with the setting: CELERY_RESULT_BACKEND = 'db+sqlite:///dojo.celeryresults.sqlite' if hasattr(settings, 'CELERY_RESULT_BACKEND'): # Check the status of Celery by sending calling a celery task celery_bool = get_celery_worker_status() if celery_bool: celery_msg = "Celery is processing tasks." celery_status = "Running" else: celery_msg = "Celery does not appear to be up and running. Please ensure celery is running." celery_status = "Not Running" else: celery_bool = False celery_msg = "Celery needs to have the setting CELERY_RESULT_BACKEND = 'db+sqlite:///dojo.celeryresults.sqlite' set in settings.py." celery_status = "Unkown" add_breadcrumb(title="Application settings", top_level=False, request=request) return render( request, 'dojo/system_settings.html', { 'form': form, 'celery_bool': celery_bool, 'celery_msg': celery_msg, 'celery_status': celery_status })
def view_product_metrics(request, pid): prod = get_object_or_404(Product, id=pid) engs = Engagement.objects.filter(product=prod, active=True) result = EngagementFilter( request.GET, queryset=Engagement.objects.filter(product=prod, active=False).order_by('-target_end')) i_engs_page = get_page_items(request, result.qs, 10) scan_sets = ScanSettings.objects.filter(product=prod) auth = request.user.is_staff or request.user in prod.authorized_users.all() if not auth: # will render 403 raise PermissionDenied ct = ContentType.objects.get_for_model(prod) product_cf = CustomField.objects.filter(content_type=ct) product_metadata = {} for cf in product_cf: cfv = CustomFieldValue.objects.filter(field=cf, object_id=prod.id) if len(cfv): product_metadata[cf.name] = cfv[0].value try: start_date = Finding.objects.filter(test__engagement__product=prod).order_by('date')[:1][0].date except: start_date = timezone.now() end_date = timezone.now() tests = Test.objects.filter(engagement__product=prod) risk_acceptances = Risk_Acceptance.objects.filter(engagement__in=Engagement.objects.filter(product=prod)) accepted_findings = [finding for ra in risk_acceptances for finding in ra.accepted_findings.all()] verified_findings = Finding.objects.filter(test__engagement__product=prod, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False).order_by("date") week_date = end_date - timedelta(days=7) # seven days and /newnewer are considered "new" new_verified_findings = Finding.objects.filter(test__engagement__product=prod, date__range=[week_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False).order_by("date") open_findings = Finding.objects.filter(test__engagement__product=prod, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False, active=True, mitigated__isnull=True) closed_findings = Finding.objects.filter(test__engagement__product=prod, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False, mitigated__isnull=False) open_vulnerabilities = Finding.objects.filter( test__engagement__product=prod, false_p=False, verified=True, duplicate=False, out_of_scope=False, active=True, mitigated__isnull=True, ).order_by('cwe').values( 'cwe' ).annotate( count=Count('cwe') ) all_vulnerabilities = Finding.objects.filter( test__engagement__product=prod, duplicate=False, ).order_by('cwe').values( 'cwe' ).annotate( count=Count('cwe') ) start_date = timezone.make_aware(datetime.combine(start_date, datetime.min.time())) r = relativedelta(end_date, start_date) weeks_between = int(ceil((((r.years * 12) + r.months) * 4.33) + (r.days / 7))) if weeks_between <= 0: weeks_between += 2 punchcard, ticks, highest_count = get_punchcard_data(verified_findings, weeks_between, start_date) add_breadcrumb(parent=prod, top_level=False, request=request) open_close_weekly = OrderedDict() new_weekly = OrderedDict() severity_weekly = OrderedDict() critical_weekly = OrderedDict() high_weekly = OrderedDict() medium_weekly = OrderedDict() for v in verified_findings: iso_cal = v.date.isocalendar() x = iso_to_gregorian(iso_cal[0], iso_cal[1], 1) y = x.strftime("<span class='small'>%m/%d<br/>%Y</span>") x = (tcalendar.timegm(x.timetuple()) * 1000) if x not in critical_weekly: critical_weekly[x] = {'count': 0, 'week': y} if x not in high_weekly: high_weekly[x] = {'count': 0, 'week': y} if x not in medium_weekly: medium_weekly[x] = {'count': 0, 'week': y} if x in open_close_weekly: if v.mitigated: open_close_weekly[x]['closed'] += 1 else: open_close_weekly[x]['open'] += 1 else: if v.mitigated: open_close_weekly[x] = {'closed': 1, 'open': 0, 'accepted': 0} else: open_close_weekly[x] = {'closed': 0, 'open': 1, 'accepted': 0} open_close_weekly[x]['week'] = y if x in severity_weekly: if v.severity in severity_weekly[x]: severity_weekly[x][v.severity] += 1 else: severity_weekly[x][v.severity] = 1 else: severity_weekly[x] = {'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0} severity_weekly[x][v.severity] = 1 severity_weekly[x]['week'] = y if v.severity == 'Critical': if x in critical_weekly: critical_weekly[x]['count'] += 1 else: critical_weekly[x] = {'count': 1, 'week': y} elif v.severity == 'High': if x in high_weekly: high_weekly[x]['count'] += 1 else: high_weekly[x] = {'count': 1, 'week': y} elif v.severity == 'Medium': if x in medium_weekly: medium_weekly[x]['count'] += 1 else: medium_weekly[x] = {'count': 1, 'week': y} for a in accepted_findings: iso_cal = a.date.isocalendar() x = iso_to_gregorian(iso_cal[0], iso_cal[1], 1) y = x.strftime("<span class='small'>%m/%d<br/>%Y</span>") x = (tcalendar.timegm(x.timetuple()) * 1000) if x in open_close_weekly: open_close_weekly[x]['accepted'] += 1 else: open_close_weekly[x] = {'closed': 0, 'open': 0, 'accepted': 1} open_close_weekly[x]['week'] = y test_data = {} for t in tests: if t.test_type.name in test_data: test_data[t.test_type.name] += t.verified_finding_count() else: test_data[t.test_type.name] = t.verified_finding_count() product_tab = Product_Tab(pid, title="Product", tab="metrics") return render(request, 'dojo/product_metrics.html', {'prod': prod, 'product_tab': product_tab, 'product_metadata': product_metadata, 'engs': engs, 'i_engs': i_engs_page, 'scan_sets': scan_sets, 'verified_findings': verified_findings, 'open_findings': open_findings, 'closed_findings': closed_findings, 'accepted_findings': accepted_findings, 'new_findings': new_verified_findings, 'open_vulnerabilities': open_vulnerabilities, 'all_vulnerabilities': all_vulnerabilities, 'start_date': start_date, 'punchcard': punchcard, 'ticks': ticks, 'highest_count': highest_count, 'open_close_weekly': open_close_weekly, 'severity_weekly': severity_weekly, 'critical_weekly': critical_weekly, 'high_weekly': high_weekly, 'medium_weekly': medium_weekly, 'test_data': test_data, 'user': request.user, 'authorized': auth})
def product_endpoint_report(request, pid): user = Dojo_User.objects.get(id=request.user.id) product = get_object_or_404(Product.objects.all().prefetch_related( 'engagement_set__test_set__test_type', 'engagement_set__test_set__environment'), id=pid) endpoint_ids = Endpoint.objects.filter( product=product, finding__active=True, finding__verified=True, finding__false_p=False, finding__duplicate=False, finding__out_of_scope=False, ).values_list('id', flat=True) endpoints = prefetch_related_endpoints_for_report( Endpoint.objects.filter(id__in=endpoint_ids)) endpoints = EndpointReportFilter(request.GET, queryset=endpoints) paged_endpoints = get_page_items(request, endpoints.qs, 25) 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)) include_disclaimer = int(request.GET.get('include_disclaimer', 0)) disclaimer = get_system_setting('disclaimer') if include_disclaimer and len(disclaimer) == 0: disclaimer = 'Please configure in System Settings.' generate = "_generate" in request.GET add_breadcrumb(parent=product, title="Vulnerable Product Endpoints Report", top_level=False, request=request) report_form = ReportOptionsForm() template = "dojo/product_endpoint_pdf_report.html" report_name = "Product Endpoint Report: " + str(product) report_title = "Product Endpoint Report" report_subtitle = str(product) report_info = "Generated By %s on %s" % (user.get_full_name(), ( timezone.now().strftime("%m/%d/%Y %I:%M%p %Z"))) try: start_date = Finding.objects.filter( endpoints__in=endpoints.qs).order_by('date')[:1][0].date except: start_date = timezone.now() end_date = timezone.now() risk_acceptances = Risk_Acceptance.objects.filter( engagement__test__finding__endpoints__in=endpoints.qs) accepted_findings = [ finding for ra in risk_acceptances for finding in ra.accepted_findings.filter(endpoints__in=endpoints.qs) ] verified_findings = Finding.objects.filter( endpoints__in=endpoints.qs, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False) open_findings = Finding.objects.filter(endpoints__in=endpoints.qs, false_p=False, verified=True, duplicate=False, out_of_scope=False, active=True, mitigated__isnull=True) closed_findings = Finding.objects.filter(endpoints__in=endpoints.qs, false_p=False, verified=True, duplicate=False, out_of_scope=False, mitigated__isnull=False) if generate: report_form = ReportOptionsForm(request.GET) if report_format == 'AsciiDoc': return render( request, 'dojo/asciidoc_report.html', { 'product_type': None, 'product': product, 'accepted_findings': accepted_findings, 'open_findings': open_findings, 'closed_findings': closed_findings, 'verified_findings': verified_findings, 'engagement': None, 'test': None, 'endpoints': endpoints, 'endpoint': None, 'findings': None, '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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': request.user, 'title': 'Generate Report', }) elif report_format == 'HTML': return render( request, template, { 'product_type': None, 'product': product, 'engagement': None, 'test': None, 'endpoint': None, 'endpoints': endpoints.qs, 'findings': None, '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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': request.user, 'title': 'Generate Report', }) else: raise Http404() product_tab = Product_Tab(product.id, "Product Endpoint Report", tab="endpoints") return render( request, 'dojo/request_endpoint_report.html', { "endpoints": paged_endpoints, "filtered": endpoints, "product_tab": product_tab, 'report_form': report_form, "name": "Vulnerable Product Endpoints", })
def view_engagement(request, eid): eng = get_object_or_404(Engagement, id=eid) tests = Test.objects.filter(engagement=eng).prefetch_related( 'tagged_items__tag', 'test_type').order_by('test_type__name', '-updated') prod = eng.product auth = request.user.is_staff or request.user in prod.authorized_users.all() risks_accepted = eng.risk_acceptance.all().select_related('owner') 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': eng_findings.count(), '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 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='Test added', 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 add_breadcrumb(parent=eng, title="Add Tests", top_level=False, request=request) return render(request, 'dojo/add_tests.html', { 'form': form, 'cred_form': cred_form, 'eid': eid })
def generate_report(request, obj, host_view=False): user = Dojo_User.objects.get(id=request.user.id) product_type = None product = None engagement = None test = None endpoint = None endpoints = 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_Type": if settings.FEATURE_AUTHORIZATION_V2: user_has_permission_or_403(request.user, obj, Permissions.Product_Type_View) else: if not (request.user.is_staff or check_auth_users_list(request.user, obj)): raise PermissionDenied elif type(obj).__name__ == "Product": if settings.FEATURE_AUTHORIZATION_V2: user_has_permission_or_403(request.user, obj, Permissions.Product_View) else: if not (request.user.is_staff or check_auth_users_list(request.user, obj)): raise PermissionDenied elif type(obj).__name__ == "Engagement": if settings.FEATURE_AUTHORIZATION_V2: user_has_permission_or_403(request.user, obj, Permissions.Engagement_View) else: if not (request.user.is_staff or check_auth_users_list(request.user, obj)): raise PermissionDenied elif type(obj).__name__ == "Test": if settings.FEATURE_AUTHORIZATION_V2: user_has_permission_or_403(request.user, obj, Permissions.Test_View) else: if not (request.user.is_staff or check_auth_users_list(request.user, obj)): raise PermissionDenied elif type(obj).__name__ == "Endpoint": if settings.FEATURE_AUTHORIZATION_V2: user_has_permission_or_403(request.user, obj, Permissions.Endpoint_View) else: if not (request.user.is_staff or check_auth_users_list(request.user, obj)): raise PermissionDenied elif type(obj).__name__ == "QuerySet" or type( obj).__name__ == "CastTaggedQuerySet": # 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)) include_disclaimer = int(request.GET.get('include_disclaimer', 0)) disclaimer = get_system_setting('disclaimer') if include_disclaimer and len(disclaimer) == 0: disclaimer = 'Please configure in System Settings.' 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 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, prod_type=product_type, queryset=prefetch_related_findings_for_report( Finding.objects.filter( test__engagement__product__prod_type=product_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 len(findings.qs) > 0: 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.distinct().order_by('numerical_severity'), 'findings': findings.qs.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, 'host': report_url_resolver(request), 'user_id': request.user.id } elif type(obj).__name__ == "Product": product = obj template = "dojo/product_pdf_report.html" report_name = "Product Report: " + str(product) report_title = "Product Report" report_subtitle = str(product) findings = ReportFindingFilter( request.GET, product=product, queryset=prefetch_related_findings_for_report( Finding.objects.filter(test__engagement__product=product))) 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() endpoints = Endpoint.objects.filter(product=product).distinct() context = { 'product': product, 'engagements': engagements, 'tests': tests, 'report_name': report_name, 'findings': findings.qs.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, 'endpoints': endpoints, 'host': report_url_resolver(request), 'user_id': request.user.id } elif type(obj).__name__ == "Engagement": logger.debug('generating report for Engagement') engagement = obj findings = ReportFindingFilter( request.GET, engagement=engagement, queryset=prefetch_related_findings_for_report( Finding.objects.filter(test__engagement=engagement))) report_name = "Engagement Report: " + str(engagement) 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() endpoints = Endpoint.objects.filter( product=engagement.product).distinct() context = { 'engagement': engagement, 'tests': tests, 'report_name': report_name, 'findings': findings.qs.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, 'host': report_url_resolver(request), 'user_id': request.user.id, 'endpoints': endpoints } elif type(obj).__name__ == "Test": test = obj findings = ReportFindingFilter( request.GET, engagement=test.engagement, queryset=prefetch_related_findings_for_report( Finding.objects.filter(test=test))) 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.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, 'host': report_url_resolver(request), 'user_id': request.user.id } elif type(obj).__name__ == "Endpoint": endpoint = obj if host_view: report_name = "Endpoint Host Report: " + endpoint.host endpoints = Endpoint.objects.filter( host=endpoint.host, product=endpoint.product).distinct() report_title = "Endpoint Host Report" report_subtitle = endpoint.host else: report_name = "Endpoint Report: " + str(endpoint) endpoints = Endpoint.objects.filter(pk=endpoint.id).distinct() report_title = "Endpoint Report" report_subtitle = str(endpoint) report_type = "Endpoint" template = 'dojo/endpoint_pdf_report.html' findings = ReportFindingFilter( request.GET, queryset=prefetch_related_findings_for_report( Finding.objects.filter(endpoints__in=endpoints))) context = { 'endpoint': endpoint, 'endpoints': endpoints, 'report_name': report_name, 'findings': findings.qs.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': get_system_setting('team_name'), 'title': report_title, 'host': report_url_resolver(request), 'user_id': request.user.id } elif type(obj).__name__ == "QuerySet" or type( obj).__name__ == "CastTaggedQuerySet": findings = ReportFindingFilter( request.GET, queryset=prefetch_related_findings_for_report(obj).distinct()) report_name = 'Finding' report_type = 'Finding' template = 'dojo/finding_pdf_report.html' report_title = "Finding Report" report_subtitle = '' context = { 'findings': findings.qs.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, '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.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, 'user_id': request.user.id, 'host': report_url_resolver(request), 'host_view': host_view, 'context': context, }) 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.distinct().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, 'include_disclaimer': include_disclaimer, 'disclaimer': disclaimer, 'user': user, 'team_name': settings.TEAM_NAME, 'title': report_title, 'user_id': request.user.id, 'host': "", 'host_view': host_view, 'context': context, }) else: raise Http404() paged_findings = get_page_items( request, findings.qs.distinct().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: if host_view: product_tab = Product_Tab(endpoint.product.id, title="Endpoint Host Report", tab="endpoints") else: 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, 'host_view': host_view, 'context': context, })
def cred(request): confs = Cred_User.objects.all().order_by('name', 'environment', 'username') add_breadcrumb(title="Credential Manager", top_level=True, request=request) return render(request, 'dojo/view_cred.html', { 'confs': confs, })
def research_metrics(request): now = timezone.now() findings = Finding.objects.filter( test__test_type__name='Security Research') findings = findings.filter(date__year=now.year, date__month=now.month) verified_month = findings.filter(verified=True) month_all_by_product, month_all_aggregate = count_findings(findings) month_verified_by_product, month_verified_aggregate = count_findings( verified_month) end_of_week = now + relativedelta(weekday=6, hour=23, minute=59, second=59) day_list = [ end_of_week - relativedelta(weeks=1, weekday=x, hour=0, minute=0, second=0) for x in range(end_of_week.weekday()) ] q_objects = (Q(date=d) for d in day_list) week_findings = Finding.objects.filter(reduce(operator.or_, q_objects)) open_week = week_findings.exclude(mitigated__isnull=False) verified_week = week_findings.filter(verified=True) week_all_by_product, week_all_aggregate = count_findings(week_findings) week_verified_by_product, week_verified_aggregate = count_findings( verified_week) week_remaining_by_product, week_remaining_aggregate = count_findings( open_week) remaining_by_product, remaining_aggregate = count_findings( Finding.objects.filter(mitigated__isnull=True, test__test_type__name='Security Research')) closed_findings = Finding.objects.filter( mitigated__isnull=False, test__test_type__name='Security Research') closed_findings_dict = { 'S0': closed_findings.filter(severity='Critical'), 'S1': closed_findings.filter(severity='High'), 'S2': closed_findings.filter(severity='Medium'), 'S3': closed_findings.filter(severity='Low') } time_to_close = {} for sev, finds in list(closed_findings_dict.items()): total = 0 for f in finds: total += (datetime.date(f.mitigated) - f.date).days if finds.count() != 0: time_to_close[sev] = total / finds.count() else: time_to_close[sev] = 'N/A' add_breadcrumb(title="Security Research Metrics", top_level=True, request=request) return render( request, 'dojo/research_metrics.html', { 'user': request.user, 'month_all_by_product': month_all_by_product, 'month_verified_by_product': month_verified_by_product, 'remaining_by_product': remaining_by_product, 'remaining_aggregate': remaining_aggregate, 'time_to_close': time_to_close, })
def metrics(request, mtype): template = 'dojo/metrics.html' show_pt_filter = True view = identify_view(request) page_name = 'Product Type Metrics by ' age_detail = [0, 0, 0, 0] in_period_counts = { "Critical": 0, "High": 0, "Medium": 0, "Low": 0, "Info": 0, "Total": 0 } in_period_details = {} closed_in_period_counts = { "Critical": 0, "High": 0, "Medium": 0, "Low": 0, "Info": 0, "Total": 0 } closed_in_period_details = {} accepted_in_period_details = {} if mtype != 'All': pt = Product_Type.objects.filter(id=mtype) request.GET._mutable = True request.GET.appendlist('test__engagement__product__prod_type', mtype) request.GET._mutable = False mtype = pt[0].name show_pt_filter = False page_name = '%s Metrics' % mtype prod_type = pt elif 'test__engagement__product__prod_type' in request.GET: prod_type = Product_Type.objects.filter(id__in=request.GET.getlist( 'test__engagement__product__prod_type', [])) else: prod_type = Product_Type.objects.all() filters = dict() if view == 'Finding': page_name += 'Findings' filters = finding_querys(prod_type, request) elif view == 'Endpoint': page_name += 'Affected Endpoints' filters = endpoint_querys(prod_type, request) for obj in queryset_check(filters['all']): if view == 'Endpoint': obj = obj.finding if 0 <= obj.age <= 30: age_detail[0] += 1 elif 30 < obj.age <= 60: age_detail[1] += 1 elif 60 < obj.age <= 90: age_detail[2] += 1 elif obj.age > 90: age_detail[3] += 1 in_period_counts[obj.severity] += 1 in_period_counts['Total'] += 1 if obj.test.engagement.product.name not in in_period_details: in_period_details[obj.test.engagement.product.name] = { 'path': reverse('product_open_findings', args=(obj.test.engagement.product.id, )), 'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0 } in_period_details[obj.test.engagement.product.name][obj.severity] += 1 in_period_details[obj.test.engagement.product.name]['Total'] += 1 for obj in filters['accepted']: if view == 'Endpoint': obj = finding.finding if obj.test.engagement.product.name not in accepted_in_period_details: accepted_in_period_details[obj.test.engagement.product.name] = { 'path': reverse('accepted_findings') + '?test__engagement__product=' + str(obj.test.engagement.product.id), 'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0 } accepted_in_period_details[obj.test.engagement.product.name][ obj.severity] += 1 accepted_in_period_details[ obj.test.engagement.product.name]['Total'] += 1 for obj in filters['closed']: if view == 'Endpoint': obj = obj.finding closed_in_period_counts[obj.severity] += 1 closed_in_period_counts['Total'] += 1 if obj.test.engagement.product.name not in closed_in_period_details: closed_in_period_details[obj.test.engagement.product.name] = { 'path': reverse('closed_findings') + '?test__engagement__product=' + str(obj.test.engagement.product.id), 'Critical': 0, 'High': 0, 'Medium': 0, 'Low': 0, 'Info': 0, 'Total': 0 } closed_in_period_details[obj.test.engagement.product.name][ obj.severity] += 1 closed_in_period_details[ obj.test.engagement.product.name]['Total'] += 1 punchcard = list() ticks = list() monthly_counts = filters['monthly_counts'] weekly_counts = filters['weekly_counts'] if 'view' in request.GET and 'dashboard' == request.GET['view']: punchcard, ticks = get_punchcard_data(queryset_check(filters['all']), filters['start_date'], filters['weeks_between'], view) page_name = (get_system_setting('team_name')) + " Metrics" template = 'dojo/dashboard-metrics.html' add_breadcrumb(title=page_name, top_level=not len(request.GET), request=request) return render( request, template, { 'name': page_name, 'start_date': filters['start_date'], 'end_date': filters['end_date'], 'findings': filters['all'], 'opened_per_month': monthly_counts['opened_per_period'], 'active_per_month': monthly_counts['active_per_period'], 'opened_per_week': weekly_counts['opened_per_period'], 'accepted_per_month': monthly_counts['accepted_per_period'], 'accepted_per_week': weekly_counts['accepted_per_period'], 'top_ten_products': filters['top_ten'], 'age_detail': age_detail, 'in_period_counts': in_period_counts, 'in_period_details': in_period_details, 'accepted_in_period_counts': filters['accepted_count'], 'accepted_in_period_details': accepted_in_period_details, 'closed_in_period_counts': closed_in_period_counts, 'closed_in_period_details': closed_in_period_details, 'punchcard': punchcard, 'ticks': ticks, 'show_pt_filter': show_pt_filter, })
def delete_cred_controller(request, destination_url, id, ttid): cred = None try: cred = Cred_Mapping.objects.get(pk=ttid) except: pass if request.method == 'POST': tform = CredMappingForm(request.POST, instance=cred) message = "" status_tag = "" delete_cred = False # Determine if the credential can be deleted if destination_url == "cred": if cred is None: delete_cred = True else: cred_lookup = Cred_Mapping.objects.filter( cred_id=cred.cred_id).exclude(product__isnull=True) message = "Credential is associated with product(s). Remove the credential from the product(s) before this credential can be deleted." if cred_lookup.exists() is False: delete_cred = True elif destination_url == "all_cred_product": cred_lookup = Cred_Mapping.objects.filter( cred_id=cred.cred_id).exclude(engagement__isnull=True) message = "Credential is associated with engagement(s). Remove the credential from the engagement(s) before this credential can be deleted." if cred_lookup.exists() is False: delete_cred = True elif destination_url == "view_engagement": cred_lookup = Cred_Mapping.objects.filter( cred_id=cred.cred_id).exclude(test__isnull=True) message = "Credential is associated with test(s). Remove the test(s) before this credential can be deleted." if cred_lookup.exists() is False: cred_lookup = Cred_Mapping.objects.filter( cred_id=cred.cred_id).exclude(finding__isnull=True) message = "Credential is associated with finding(s). Remove the finding(s) before this credential can be deleted." if cred_lookup.exists() is False: delete_cred = True else: if cred_lookup.exists() is False: delete_cred = True elif destination_url == "view_test" or destination_url == "view_finding": delete_cred = True # Allow deletion if no credentials are associated if delete_cred is True: message = "Credential Successfully Deleted." status_tag = "alert-success" # check if main cred delete if destination_url == "cred": cred = Cred_User.objects.get(pk=ttid) cred.delete() else: cred.delete() else: status_tag = 'alert-danger' messages.add_message(request, messages.SUCCESS, message, extra_tags=status_tag) if destination_url == "cred": return HttpResponseRedirect(reverse(destination_url)) else: return HttpResponseRedirect(reverse(destination_url, args=(id, ))) else: tform = CredMappingForm(instance=cred) add_breadcrumb(title="Delete Credential", top_level=False, request=request) product_tab = None if id: product_tab = Product_Tab(id, title="Delete Credential Mapping", tab="settings") return render(request, 'dojo/delete_cred_all.html', { 'tform': tform, 'product_tab': product_tab })
def product_endpoint_report(request, pid): user = Dojo_User.objects.get(id=request.user.id) product = get_object_or_404(Product, id=pid) endpoints = Endpoint.objects.filter(product=product, finding__active=True, finding__verified=True, finding__false_p=False, finding__duplicate=False, finding__out_of_scope=False, ) ids = get_endpoint_ids(endpoints) endpoints = Endpoint.objects.filter(id__in=ids) if request.user.is_staff or request.user in product.authorized_users.all(): pass # user is authorized for this product else: raise PermissionDenied endpoints = EndpointReportFilter(request.GET, queryset=endpoints) paged_endpoints = get_page_items(request, endpoints, 25) report_format = request.GET.get('report_type', 'AsciiDoc') include_finding_notes = int(request.GET.get('include_finding_notes', 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 add_breadcrumb(parent=product, title="Vulnerable Product Endpoints Report", top_level=False, request=request) report_form = ReportOptionsForm() filename = "product_endpoint_report.pdf" template = "dojo/product_endpoint_pdf_report.html" report_name = "Product Endpoint Report: " + str(product) report_title = "Product Endpoint Report" report_subtitle = str(product) report_info = "Generated By %s on %s" % ( user.get_full_name(), (datetime.now(tz=localtz).strftime("%m/%d/%Y %I:%M%p %Z"))) try: start_date = Finding.objects.filter(endpoints__in=endpoints.qs).order_by('date')[:1][0].date except: start_date = localtz.localize(datetime.today()) end_date = localtz.localize(datetime.today()) risk_acceptances = Risk_Acceptance.objects.filter(engagement__test__finding__endpoints__in=endpoints.qs) accepted_findings = [finding for ra in risk_acceptances for finding in ra.accepted_findings.filter(endpoints__in=endpoints.qs)] verified_findings = Finding.objects.filter(endpoints__in=endpoints.qs, date__range=[start_date, end_date], false_p=False, verified=True, duplicate=False, out_of_scope=False) open_findings = Finding.objects.filter(endpoints__in=endpoints.qs, false_p=False, verified=True, duplicate=False, out_of_scope=False, active=True, mitigated__isnull=True) closed_findings = Finding.objects.filter(endpoints__in=endpoints.qs, false_p=False, verified=True, duplicate=False, out_of_scope=False, mitigated__isnull=False) if generate: report_form = ReportOptionsForm(request.GET) if report_format == 'AsciiDoc': return render(request, 'dojo/asciidoc_report.html', {'product_type': None, 'product': product, 'accepted_findings': accepted_findings, 'open_findings': open_findings, 'closed_findings': closed_findings, 'verified_findings': verified_findings, 'engagement': None, 'test': None, 'endpoints': endpoints, 'endpoint': None, 'findings': None, 'include_finding_notes': include_finding_notes, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': request.user, 'title': 'Generate Report', }) elif report_format == 'PDF': endpoints = endpoints.qs.order_by('finding__numerical_severity') # lets create the report object and send it in to celery task 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 = datetime.now(tz=localtz) report.status = 'requested' if report.requester.username != request.user.username: report.requester = request.user else: report = Report(name="Product Endpoints " + str(product), type="Product Endpoint", 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={'product': product, 'endpoints': endpoints, 'accepted_findings': accepted_findings, 'open_findings': open_findings, 'closed_findings': closed_findings, 'verified_findings': verified_findings, 'report_name': report_name, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']}, uri=request.build_absolute_uri(report.get_url())) messages.add_message(request, messages.SUCCESS, 'Your report is building, you will receive an email when it is ready.', extra_tags='alert-success') return HttpResponseRedirect(reverse('reports')) else: raise Http404() return render(request, 'dojo/request_endpoint_report.html', {"endpoints": paged_endpoints, "filtered": endpoints, 'report_form': report_form, "name": "Vulnerable Product Endpoints", })
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 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(), (datetime.now(tz=localtz).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_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 = localtz.localize(datetime.combine(findings.qs.last().date, datetime.min.time())) else: start_date = localtz.localize(datetime.today()) end_date = localtz.localize(datetime.today()) 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(findings.qs, findings.qs, 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, 'findings': findings.qs, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']} 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) engagements = Engagement.objects.filter(test__finding__id__in=ids).distinct() tests = Test.objects.filter(finding__id__in=ids).distinct() context = {'product': product, 'engagements': engagements, 'tests': tests, 'report_name': report_name, 'findings': findings.qs, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']} 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) tests = Test.objects.filter(finding__id__in=ids).distinct() context = {'engagement': engagement, 'tests': tests, 'report_name': report_name, 'findings': findings.qs, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']} 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, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']} 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, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']} 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, 'report_name': report_name, 'include_finding_notes': include_finding_notes, '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': request.scheme + "://" + request.META['HTTP_HOST']} 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, 'include_finding_notes': include_finding_notes, 'include_executive_summary': include_executive_summary, 'include_table_of_contents': include_table_of_contents, 'user': user, 'team_name': settings.TEAM_NAME, 'title': 'Generate Report', }) 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 = datetime.now(tz=localtz) 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, you will receive an email when it is ready.', extra_tags='alert-success') return HttpResponseRedirect(reverse('reports')) else: raise Http404() paged_findings = get_page_items(request, findings, 25) return render(request, 'dojo/request_report.html', {'product_type': product_type, 'product': product, 'engagement': engagement, 'test': test, 'endpoint': endpoint, 'findings': findings, 'paged_findings': paged_findings, 'report_form': report_form, })
def express_new_jira(request): if request.method == 'POST': jform = ExpressJIRAForm(request.POST, instance=JIRA_Conf()) if jform.is_valid(): try: jira_server = jform.cleaned_data.get('url').rstrip('/') jira_username = jform.cleaned_data.get('username') jira_password = jform.cleaned_data.get('password') # Instantiate JIRA instance for validating url, username and password try: jira = JIRA(server=jira_server, basic_auth=(jira_username, jira_password), options={"verify": settings.JIRA_SSL_VERIFY}) except Exception as e: logger.exception(e) messages.add_message( request, messages.ERROR, 'Unable to authenticate. Please check the URL, username, and password.', extra_tags='alert-danger') return render(request, 'dojo/express_new_jira.html', {'jform': jform}) # authentication successful # Get the open and close keys issue_id = jform.cleaned_data.get('issue_key') key_url = jira_server + '/rest/api/latest/issue/' + issue_id + '/transitions?expand=transitions.fields' data = json.loads( requests.get(key_url, auth=(jira_username, jira_password)).text) for node in data['transitions']: if node['to']['name'] == 'To Do': open_key = int(node['to']['id']) if node['to']['name'] == 'Done': close_key = int(node['to']['id']) # Get the epic id name key_url = jira_server + '/rest/api/2/field' data = json.loads( requests.get(key_url, auth=(jira_username, jira_password)).text) for node in data: if 'Epic Name' in node['clauseNames']: epic_name = int(node['clauseNames'][0][3:-1]) break jira_conf = JIRA_Conf( username=jira_username, password=jira_password, url=jira_server, configuration_name=jform.cleaned_data.get( 'configuration_name'), info_mapping_severity='Lowest', low_mapping_severity='Low', medium_mapping_severity='Medium', high_mapping_severity='High', critical_mapping_severity='Highest', epic_name_id=epic_name, open_status_key=open_key, close_status_key=close_key, finding_text='', default_issue_type=jform.cleaned_data.get( 'default_issue_type')) jira_conf.save() messages.add_message( request, messages.SUCCESS, 'JIRA Configuration Successfully Created.', extra_tags='alert-success') create_notification( event='other', title='New addition of JIRA: %s' % jform.cleaned_data.get('configuration_name'), description='JIRA "%s" was added by %s' % (jform.cleaned_data.get('configuration_name'), request.user), url=request.build_absolute_uri(reverse('jira')), ) return HttpResponseRedirect(reverse('jira', )) except: messages.add_message( request, messages.ERROR, 'Unable to query other required fields. They must be entered manually.', extra_tags='alert-danger') return HttpResponseRedirect(reverse('add_jira', )) return render(request, 'dojo/express_new_jira.html', {'jform': jform}) else: jform = ExpressJIRAForm() add_breadcrumb(title="New Jira Configuration (Express)", top_level=False, request=request) return render(request, 'dojo/express_new_jira.html', {'jform': jform})
def answer_empty_survey(request, esid): general_survey = get_object_or_404(General_Survey, id=esid) engagement_survey = get_object_or_404(Engagement_Survey, id=general_survey.survey_id) engagement, survey = None, None settings = System_Settings.objects.all()[0] if not settings.allow_anonymous_survey_repsonse: auth = request.user.is_staff if not auth: messages.add_message(request, messages.ERROR, 'You must be logged in to respond. Otherwise, enable anonymous response in system settings.', extra_tags='alert-danger') # will render 403 raise PermissionDenied questions = [q.get_form()(prefix=str(q.id), engagement_survey=engagement_survey, question=q, form_tag=False) for q in engagement_survey.questions.all() ] if request.method == 'POST': survey = Answered_Survey(survey=engagement_survey) survey.save() questions = [ q.get_form()(request.POST or None, prefix=str(q.id), answered_survey=survey, question=q, form_tag=False) for q in survey.survey.questions.all() ] questions_are_valid = [] for question in questions: valid = question.is_valid() questions_are_valid.append(valid) if valid: question.save() questions_are_valid = all(questions_are_valid) if questions_are_valid: survey.completed = True survey.responder = request.user if not request.user.is_anonymous else None survey.answered_on = date.today() survey.save() general_survey.num_responses = general_survey.num_responses + 1 general_survey.save() if request.user.is_anonymous: message = 'Your responses have been recorded.' else: message = 'Successfully answered, all answers valid.' messages.add_message(request, messages.SUCCESS, message, extra_tags='alert-success') return HttpResponseRedirect( reverse('dashboard')) else: messages.add_message(request, messages.ERROR, 'Errors found, please correct.', extra_tags='alert-danger') add_breadcrumb(title="Respond - " + engagement_survey.name + " ", top_level=False, request=request) if survey is None: survey = engagement_survey return render(request, 'defectDojo-engagement-survey/answer_survey.html', {'survey': survey, 'engagement': engagement, 'questions': questions, })