Exemplo n.º 1
0
def add_product_endpoint(request):
    if not settings.FEATURE_AUTHORIZATION_V2 and not request.user.is_staff:
        raise PermissionDenied

    form = AddEndpointForm()
    if request.method == 'POST':
        form = AddEndpointForm(request.POST)
        if form.is_valid():
            if not settings.FEATURE_AUTHORIZATION_V2:
                if not user_is_authorized(request.user, 'change',
                                          form.product):
                    raise PermissionDenied
            else:
                user_has_permission_or_403(request.user, form.product,
                                           Permissions.Endpoint_Add)
            endpoints = form.save()
            tags = request.POST.get('tags')
            for e in endpoints:
                e.tags = tags
                e.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Endpoint added successfully.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(
                reverse('endpoints') + "?product=%s" % form.product.id)
    add_breadcrumb(title="Add Endpoint", top_level=False, request=request)
    return render(request, 'dojo/add_endpoint.html', {
        'name': 'Add Endpoint',
        'form': form,
    })
Exemplo n.º 2
0
    def test_user_has_permission_or_403_success(self, mock_foo):
        mock_foo.select_related.return_value = mock_foo
        mock_foo.select_related.return_value = mock_foo
        mock_foo.filter.return_value = [self.product_type_member_owner]

        user_has_permission_or_403(self.user, self.product_type, Permissions.Product_Type_Delete)

        mock_foo.filter.assert_called_with(user=self.user)
    def test_user_has_permission_or_403_success(self, mock_get):
        mock_get.return_value = self.product_type_member_owner

        user_has_permission_or_403(self.user, self.product_type,
                                   Permissions.Product_Type_Delete)

        self.assertEqual(mock_get.call_args[1]['user'], self.user)
        self.assertEqual(mock_get.call_args[1]['product_type'],
                         self.product_type)
Exemplo n.º 4
0
def process_endpoints_view(request, host_view=False, vulnerable=False):

    if vulnerable:
        endpoints = Endpoint.objects.filter(finding__active=True, finding__verified=True, finding__false_p=False,
                                     finding__duplicate=False, finding__out_of_scope=False, mitigated=False)
    else:
        endpoints = Endpoint.objects.all()

    endpoints = endpoints.prefetch_related('product', 'product__tags', 'tags').distinct()
    endpoints = get_authorized_endpoints(Permissions.Endpoint_View, endpoints, request.user)

    if host_view:
        ids = get_endpoint_ids(EndpointFilter(request.GET, queryset=endpoints, user=request.user).qs)
        endpoints = EndpointFilter(request.GET, queryset=endpoints.filter(id__in=ids), user=request.user)
    else:
        endpoints = EndpointFilter(request.GET, queryset=endpoints, user=request.user)

    paged_endpoints = get_page_items(request, endpoints.qs, 25)

    if vulnerable:
        view_name = "Vulnerable"
    else:
        view_name = "All"

    if host_view:
        view_name += " Endpoint Hosts"
    else:
        view_name += " Endpoints"

    add_breadcrumb(title=view_name, top_level=not len(request.GET), request=request)

    product_tab = None
    if 'product' in request.GET:
        p = request.GET.getlist('product', [])
        if len(p) == 1:
            product = get_object_or_404(Product, id=p[0])
            if not settings.FEATURE_AUTHORIZATION_V2:
                if not user_is_authorized(request.user, 'view', product):
                    raise PermissionDenied
            else:
                user_has_permission_or_403(request.user, product, Permissions.Product_View)
            product_tab = Product_Tab(product.id, view_name, tab="endpoints")

    return render(
        request, 'dojo/endpoints.html', {
            'product_tab': product_tab,
            "endpoints": paged_endpoints,
            "filtered": endpoints,
            "name": view_name,
            "host_view": host_view,
            "product_tab": product_tab
        })
Exemplo n.º 5
0
def all_endpoints(request):
    endpoints = Endpoint.objects.prefetch_related('product', 'tags',
                                                  'product__tags')
    endpoints = get_authorized_endpoints(Permissions.Endpoint_View, endpoints,
                                         request.user)
    show_uri = get_system_setting('display_endpoint_uri')

    product = None
    if 'product' in request.GET:
        p = request.GET.getlist('product', [])
        if len(p) == 1:
            product = get_object_or_404(Product, id=p[0])
            if not settings.FEATURE_AUTHORIZATION_V2:
                if not user_is_authorized(request.user, 'view', product):
                    raise PermissionDenied
            else:
                user_has_permission_or_403(request.user, product,
                                           Permissions.Product_View)

    if show_uri:
        endpoints = EndpointFilter(request.GET,
                                   queryset=endpoints,
                                   user=request.user)
        paged_endpoints = get_page_items(request, endpoints.qs, 25)
    else:
        ids = get_endpoint_ids(
            EndpointFilter(request.GET, queryset=endpoints,
                           user=request.user).qs)
        endpoints = EndpointFilter(request.GET,
                                   queryset=endpoints.filter(id__in=ids),
                                   user=request.user)
        paged_endpoints = get_page_items(request, endpoints.qs, 25)
    add_breadcrumb(title="All Endpoints",
                   top_level=not len(request.GET),
                   request=request)

    product_tab = None
    view_name = "All Endpoints"
    if product:
        view_name = "Endpoints"
        product_tab = Product_Tab(product.id, "Endpoints", tab="endpoints")

    return render(
        request, 'dojo/endpoints.html', {
            'product_tab': product_tab,
            "endpoints": paged_endpoints,
            "filtered": endpoints,
            "name": view_name,
            "show_uri": show_uri
        })
Exemplo n.º 6
0
    def _wrapped(request, *args, **kwargs):
        # Fetch object from database
        if isinstance(arg, int):
            # Lookup value came as a positional argument
            args = list(args)
            lookup_value = args[arg]
        else:
            # Lookup value was passed as keyword argument
            lookup_value = kwargs.get(arg)

        # object must exist
        obj = get_object_or_404(model.objects.filter(**{lookup: lookup_value}))

        user_has_permission_or_403(request.user, obj, permission)

        return func(request, *args, **kwargs)
Exemplo n.º 7
0
def delete_issue(request, id, page, objid):
    note = get_object_or_404(Notes, id=id)
    reverse_url = None
    object_id = None

    if page == "engagement":
        object = get_object_or_404(Engagement, id=objid)
        object_id = object.id
        reverse_url = "view_engagement"
    elif page == "test":
        object = get_object_or_404(Test, id=objid)
        object_id = object.id
        reverse_url = "view_test"
    elif page == "finding":
        object = get_object_or_404(Finding, id=objid)
        object_id = object.id
        reverse_url = "view_finding"
    form = DeleteNoteForm(request.POST, instance=note)

    if page is None:
        raise PermissionDenied
    if str(request.user) != note.author.username:
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, object,
                                       Permissions.Note_Delete)
        else:
            if not request.user.is_staff:
                raise PermissionDenied

    if form.is_valid():
        note.delete()
        messages.add_message(request,
                             messages.SUCCESS,
                             'Note deleted.',
                             extra_tags='alert-success')
    else:
        messages.add_message(request,
                             messages.SUCCESS,
                             'Note was not succesfully deleted.',
                             extra_tags='alert-danger')

    return HttpResponseRedirect(reverse(reverse_url, args=(object_id, )))
Exemplo n.º 8
0
def generate_quick_report(request, findings, obj=None):
    product = engagement = test = None

    if obj:
        if type(obj).__name__ == "Product":
            product = obj
            user_has_permission_or_403(request.user, product, Permissions.Product_View)
        elif type(obj).__name__ == "Engagement":
            engagement = obj
            user_has_permission_or_403(request.user, engagement, Permissions.Engagement_View)
        elif type(obj).__name__ == "Test":
            test = obj
            user_has_permission_or_403(request.user, test, Permissions.Test_View)

    return render(request, 'dojo/finding_pdf_report.html', {
                    'report_name': 'Finding Report',
                    'product': product,
                    'engagement': engagement,
                    'test': test,
                    'findings': findings,
                    'user': request.user,
                    'team_name': settings.TEAM_NAME,
                    'title': 'Finding Report',
                    'user_id': request.user.id,
                  })
Exemplo n.º 9
0
def note_history(request, id, page, objid):
    note = get_object_or_404(Notes, id=id)
    reverse_url = None
    object_id = None

    if page == "engagement":
        object = get_object_or_404(Engagement, id=objid)
        object_id = object.id
        reverse_url = "view_engagement"
    elif page == "test":
        object = get_object_or_404(Test, id=objid)
        object_id = object.id
        reverse_url = "view_test"
    elif page == "finding":
        object = get_object_or_404(Finding, id=objid)
        object_id = object.id
        reverse_url = "view_finding"

    if page is None:
        raise PermissionDenied
    if str(request.user) != note.author.username:
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, object,
                                       Permissions.Note_View_History)
        else:
            if not request.user.is_staff:
                raise PermissionDenied

    history = note.history.all()

    if request.method == 'POST':
        return HttpResponseRedirect(reverse(reverse_url, args=(object_id, )))

    return render(request, 'dojo/view_note_history.html', {
        'history': history,
        'note': note,
        'page': page,
        'objid': objid,
    })
Exemplo n.º 10
0
def add_product_endpoint(request):
    form = AddEndpointForm()
    if request.method == 'POST':
        form = AddEndpointForm(request.POST)
        if form.is_valid():
            user_has_permission_or_403(request.user, form.product, Permissions.Endpoint_Add)
            endpoints = form.save()
            tags = request.POST.get('tags')
            for e in endpoints:
                e.tags = tags
                e.save()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Endpoint added successfully.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('endpoint') + "?product=%s" % form.product.id)
    add_breadcrumb(title="Add Endpoint", top_level=False, request=request)
    return render(request,
                  'dojo/add_endpoint.html',
                  {'name': 'Add Endpoint',
                   'form': form,
                   })
Exemplo n.º 11
0
    def _wrapped(request, *args, **kwargs):
        # Fetch object from database
        if isinstance(arg, int):
            # Lookup value came as a positional argument
            args = list(args)
            lookup_value = args[arg]
        else:
            # Lookup value was passed as keyword argument
            lookup_value = kwargs.get(arg)

        # object must exist
        obj = get_object_or_404(model.objects.filter(**{lookup: lookup_value}))

        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, obj, permission)
        else:
            if legacy_permission:
                if not legacy_check(request.user, legacy_permission, obj):
                    raise PermissionDenied()
            elif not request.user.is_staff:
                raise PermissionDenied()

        return func(request, *args, **kwargs)
Exemplo n.º 12
0
def endpoint_bulk_update_all(request, pid=None):
    if request.method == "POST":
        endpoints_to_update = request.POST.getlist('endpoints_to_update')
        finds = Endpoint.objects.filter(
            id__in=endpoints_to_update).order_by("endpoint_meta__product__id")
        total_endpoint_count = finds.count()

        if request.POST.get('delete_bulk_endpoints') and endpoints_to_update:

            if pid is None:
                if not request.user.is_staff:
                    raise PermissionDenied
            else:
                product = get_object_or_404(Product, id=pid)
                user_has_permission_or_403(request.user, product,
                                           Permissions.Endpoint_Delete)

            finds = get_authorized_endpoints(Permissions.Endpoint_Delete,
                                             finds, request.user)

            skipped_endpoint_count = total_endpoint_count - finds.count()
            deleted_endpoint_count = finds.count()

            product_calc = list(
                Product.objects.filter(
                    endpoint__id__in=endpoints_to_update).distinct())
            finds.delete()
            for prod in product_calc:
                calculate_grade(prod)

            if skipped_endpoint_count > 0:
                add_error_message_to_response(
                    'Skipped deletion of {} endpoints because you are not authorized.'
                    .format(skipped_endpoint_count))

            if deleted_endpoint_count > 0:
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    'Bulk delete of {} endpoints was successful.'.format(
                        deleted_endpoint_count),
                    extra_tags='alert-success')
        else:
            if endpoints_to_update:

                if pid is None:
                    if not request.user.is_staff:
                        raise PermissionDenied
                else:
                    product = get_object_or_404(Product, id=pid)
                    user_has_permission_or_403(request.user, product,
                                               Permissions.Finding_Edit)

                finds = get_authorized_endpoints(Permissions.Endpoint_Edit,
                                                 finds, request.user)

                skipped_endpoint_count = total_endpoint_count - finds.count()
                updated_endpoint_count = finds.count()

                if skipped_endpoint_count > 0:
                    add_error_message_to_response(
                        'Skipped mitigation of {} endpoints because you are not authorized.'
                        .format(skipped_endpoint_count))

                for endpoint in finds:
                    endpoint.mitigated = not endpoint.mitigated
                    endpoint.save()

                if updated_endpoint_count > 0:
                    messages.add_message(
                        request,
                        messages.SUCCESS,
                        'Bulk mitigation of {} endpoints was successful.'.
                        format(updated_endpoint_count),
                        extra_tags='alert-success')
            else:
                messages.add_message(
                    request,
                    messages.ERROR,
                    'Unable to process bulk update. Required fields were not selected.',
                    extra_tags='alert-danger')
    return HttpResponseRedirect(reverse('endpoint', args=()))
Exemplo n.º 13
0
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 = timezone.now()
    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']
            if not settings.FEATURE_AUTHORIZATION_V2:
                if not user_is_authorized(request.user, 'view', pt):
                    raise PermissionDenied
            else:
                user_has_permission_or_403(request.user, pt, Permissions.Product_Type_View)
            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=timezone.get_current_timezone())
            end_date = end_of_month
            end_date = datetime(end_date.year,
                                end_date.month, end_date.day,
                                tzinfo=timezone.get_current_timezone())

            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__date__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__date__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)
            top_ten = severity_count(top_ten, 'annotate', 'engagement__test__finding__severity').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}
                  )
Exemplo n.º 14
0
 def test_user_has_permission_or_403_exception(self):
     with self.assertRaises(PermissionDenied):
         user_has_permission_or_403(self.user, self.product_type, Permissions.Product_Type_Delete)
Exemplo n.º 15
0
def view_engagement(request, eid):
    eng = get_object_or_404(Engagement, id=eid)
    tests = eng.test_set.all().order_by('test_type__name', '-updated')

    default_page_num = 10

    tests_filter = EngagementTestFilter(request.GET, queryset=tests, engagement=eng)
    paged_tests = get_page_items(request, tests_filter.qs, default_page_num)
    # prefetch only after creating the filters to avoid https://code.djangoproject.com/ticket/23771 and https://code.djangoproject.com/ticket/25375
    paged_tests.object_list = prefetch_for_view_tests(paged_tests.object_list)

    prod = eng.product
    risks_accepted = eng.risk_acceptance.all().select_related('owner').annotate(accepted_findings_count=Count('accepted_findings__id'))
    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)

    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)
    form = DoneForm()
    files = eng.files.all()
    if request.method == 'POST':
        user_has_permission_or_403(request.user, eng, Permissions.Note_Add)
        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)

    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': paged_tests,
            'filter': tests_filter,
            'check': check,
            'threat': eng.tmodel_path,
            'form': form,
            'notes': notes,
            'files': files,
            'risks_accepted': risks_accepted,
            'jissue': jissue,
            'jira_project': jira_project,
            'creds': creds,
            'cred_eng': cred_eng,
            'network': network,
            'preset_test_type': preset_test_type
        })
Exemplo n.º 16
0
def edit_issue(request, id, page, objid):
    note = get_object_or_404(Notes, id=id)
    reverse_url = None
    object_id = None

    if page == "engagement":
        object = get_object_or_404(Engagement, id=objid)
        object_id = object.id
        reverse_url = "view_engagement"
    elif page == "test":
        object = get_object_or_404(Test, id=objid)
        object_id = object.id
        reverse_url = "view_test"
    elif page == "finding":
        object = get_object_or_404(Finding, id=objid)
        object_id = object.id
        reverse_url = "view_finding"

    if page is None:
        raise PermissionDenied
    if str(request.user) != note.author.username:
        if settings.FEATURE_AUTHORIZATION_V2:
            user_has_permission_or_403(request.user, object,
                                       Permissions.Note_Edit)
        else:
            if not request.user.is_staff:
                raise PermissionDenied

    note_type_activation = Note_Type.objects.filter(is_active=True).count()
    if note_type_activation:
        available_note_types = find_available_notetypes(object, note)

    if request.method == 'POST':
        if note_type_activation:
            form = TypedNoteForm(request.POST,
                                 available_note_types=available_note_types,
                                 instance=note)
        else:
            form = NoteForm(request.POST, instance=note)
        if form.is_valid():
            note = form.save(commit=False)
            note.edited = True
            note.editor = request.user
            note.edit_time = timezone.now()
            if note_type_activation:
                history = NoteHistory(note_type=note.note_type,
                                      data=note.entry,
                                      time=note.edit_time,
                                      current_editor=note.editor)
            else:
                history = NoteHistory(data=note.entry,
                                      time=note.edit_time,
                                      current_editor=note.editor)
            history.save()
            note.history.add(history)
            note.save()
            object.last_reviewed = note.date
            object.last_reviewed_by = request.user
            object.save()
            form = NoteForm()
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Note edited.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(
                reverse(reverse_url, args=(object_id, )))
        else:
            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Note was not succesfully edited.',
                                 extra_tags='alert-danger')
    else:
        if note_type_activation:
            form = TypedNoteForm(available_note_types=available_note_types,
                                 instance=note)
        else:
            form = NoteForm(instance=note)

    return render(request, 'dojo/edit_note.html', {
        'note': note,
        'form': form,
        'page': page,
        'objid': objid,
    })
Exemplo n.º 17
0
def get_findings(request):
    url = request.META.get('QUERY_STRING')
    if not url:
        raise Http404('Please use the report button when viewing findings')
    else:
        if url.startswith('url='):
            url = url[4:]

    views = [
        'all', 'open', 'inactive', 'verified', 'closed', 'accepted',
        'out_of_scope', 'false_positive', 'inactive'
    ]
    # request.path = url
    obj_name = obj_id = view = query = None
    path_items = list(filter(None, re.split('/|\?', url)))  # noqa W605

    try:
        finding_index = path_items.index('finding')
    except ValueError:
        finding_index = -1
    # There is a engagement or product here
    if finding_index > 0:
        # path_items ['product', '1', 'finding', 'closed', 'test__engagement__product=1']
        obj_name = get_list_index(path_items, 0)
        obj_id = get_list_index(path_items, 1)
        view = get_list_index(path_items, 3)
        query = get_list_index(path_items, 4)
        # Try to catch a mix up
        query = query if view in views else view
    # This is findings only. Accomodate view and query
    elif finding_index == 0:
        # path_items ['finding', 'closed', 'title=blah']
        obj_name = get_list_index(path_items, 0)
        view = get_list_index(path_items, 1)
        query = get_list_index(path_items, 2)
        # Try to catch a mix up
        query = query if view in views else view
    # This is a test or engagement only
    elif finding_index == -1:
        # path_items ['test', '1', 'test__engagement__product=1']
        obj_name = get_list_index(path_items, 0)
        obj_id = get_list_index(path_items, 1)
        query = get_list_index(path_items, 2)

    filter_name = None
    if view:
        if view == 'open':
            filter_name = 'Open'
        elif view == 'inactive':
            filter_name = 'Inactive'
        elif view == 'verified':
            filter_name = 'Verified'
        elif view == 'closed':
            filter_name = 'Closed'
        elif view == 'accepted':
            filter_name = 'Accepted'
        elif view == 'out_of_scope':
            filter_name = 'Out of Scope'
        elif view == 'false_positive':
            filter_name = 'False Positive'

    obj = pid = eid = tid = None
    if obj_id:
        if 'product' in obj_name:
            pid = obj_id
            obj = get_object_or_404(Product, id=pid)
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Product_View)
        elif 'engagement' in obj_name:
            eid = obj_id
            obj = get_object_or_404(Engagement, id=eid)
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Engagement_View)
        elif 'test' in obj_name:
            tid = obj_id
            obj = get_object_or_404(Test, id=tid)
            user_has_permission_or_403(request.user, obj,
                                       Permissions.Test_View)

    request.GET = QueryDict(query)
    findings = get_filtered_findings(request, pid, eid, tid, filter_name).qs

    return findings, obj
Exemplo n.º 18
0
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,
        })
Exemplo n.º 19
0
def view_test(request, tid):
    test_prefetched = get_authorized_tests(Permissions.Test_View)
    test_prefetched = test_prefetched.annotate(
        total_reimport_count=Count('test_import__id', distinct=True))
    # tests_prefetched = test_prefetched.prefetch_related(Prefetch('test_import_set', queryset=Test_Import.objects.filter(~Q(findings_affected=None))))
    # tests_prefetched = test_prefetched.prefetch_related('test_import_set')
    # test_prefetched = test_prefetched.prefetch_related('test_import_set__test_import_finding_action_set')

    test = get_object_or_404(test_prefetched, pk=tid)
    # test = get_object_or_404(Test, pk=tid)

    prod = test.engagement.product
    notes = test.notes.all()
    note_type_activation = Note_Type.objects.filter(is_active=True).count()
    if note_type_activation:
        available_note_types = find_available_notetypes(notes)
    files = test.files.all()
    person = request.user.username
    findings = Finding.objects.filter(test=test).order_by('numerical_severity')
    findings = FindingFilter(request.GET, queryset=findings)
    stub_findings = Stub_Finding.objects.filter(test=test)
    cred_test = Cred_Mapping.objects.filter(
        test=test).select_related('cred_id').order_by('cred_id')
    creds = Cred_Mapping.objects.filter(
        engagement=test.engagement).select_related('cred_id').order_by(
            'cred_id')
    system_settings = get_object_or_404(System_Settings, id=1)
    if request.method == 'POST':
        user_has_permission_or_403(request.user, test, Permissions.Note_Add)
        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()
            test.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_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:
        if note_type_activation:
            form = TypedNoteForm(available_note_types=available_note_types)
        else:
            form = NoteForm()

    title_words = get_words_for_field(Finding, 'title')
    component_words = get_words_for_field(Finding, 'component_name')

    # test_imports = test.test_import_set.all()
    test_imports = Test_Import.objects.filter(test=test)
    test_import_filter = TestImportFilter(request.GET, test_imports)

    paged_test_imports = get_page_items_and_count(request,
                                                  test_import_filter.qs,
                                                  5,
                                                  prefix='test_imports')
    paged_test_imports.object_list = paged_test_imports.object_list.prefetch_related(
        'test_import_finding_action_set')

    paged_findings = get_page_items_and_count(request,
                                              prefetch_for_findings(
                                                  findings.qs),
                                              25,
                                              prefix='findings')
    paged_stub_findings = get_page_items(request, stub_findings, 25)
    show_re_upload = any(test.test_type.name in code
                         for code in get_choices_sorted())

    product_tab = Product_Tab(prod.id, title="Test", tab="engagements")
    product_tab.setEngagement(test.engagement)
    jira_project = jira_helper.get_jira_project(test)

    finding_groups = test.finding_group_set.all().prefetch_related(
        'findings', 'jira_issue', 'creator')

    bulk_edit_form = FindingBulkUpdateForm(request.GET)

    google_sheets_enabled = system_settings.enable_google_sheets
    sheet_url = None
    if google_sheets_enabled and system_settings.credentials:
        spreadsheet_name = test.engagement.product.name + "-" + test.engagement.name + "-" + str(
            test.id)
        system_settings = get_object_or_404(System_Settings, id=1)
        service_account_info = json.loads(system_settings.credentials)
        SCOPES = ['https://www.googleapis.com/auth/drive']
        credentials = service_account.Credentials.from_service_account_info(
            service_account_info, scopes=SCOPES)
        try:
            drive_service = googleapiclient.discovery.build(
                'drive', 'v3', credentials=credentials, cache_discovery=False)
            folder_id = system_settings.drive_folder_ID
            gs_files = drive_service.files().list(
                q="mimeType='application/vnd.google-apps.spreadsheet' and parents in '%s' and name='%s'"
                % (folder_id, spreadsheet_name),
                spaces='drive',
                pageSize=10,
                fields='files(id, name)').execute()

        except googleapiclient.errors.HttpError:
            messages.add_message(
                request,
                messages.ERROR,
                "There is a problem with the Google Sheets Sync Configuration. Contact your system admin to solve the issue. Until fixed, the Google Sheets Sync feature cannot be used.",
                extra_tags="alert-danger",
            )
            google_sheets_enabled = False
        except httplib2.ServerNotFoundError:
            messages.add_message(
                request,
                messages.ERROR,
                "Unable to reach the Google Sheet API.",
                extra_tags="alert-danger",
            )
        else:
            spreadsheets = gs_files.get('files')
            if len(spreadsheets) == 1:
                spreadsheetId = spreadsheets[0].get('id')
                sheet_url = 'https://docs.google.com/spreadsheets/d/' + spreadsheetId
    return render(
        request, 'dojo/view_test.html', {
            'test': test,
            'prod': prod,
            'product_tab': product_tab,
            'findings': paged_findings,
            'filtered': findings,
            'stub_findings': paged_stub_findings,
            'title_words': title_words,
            'component_words': component_words,
            'form': form,
            'notes': notes,
            'files': files,
            'person': person,
            'request': request,
            'show_re_upload': show_re_upload,
            'creds': creds,
            'cred_test': cred_test,
            'jira_project': jira_project,
            'show_export': google_sheets_enabled
            and system_settings.credentials,
            'sheet_url': sheet_url,
            'bulk_edit_form': bulk_edit_form,
            'paged_test_imports': paged_test_imports,
            'test_import_filter': test_import_filter,
            'finding_groups': finding_groups,
            'finding_group_by_options': Finding_Group.GROUP_BY_OPTIONS,
        })
Exemplo n.º 20
0
def manage_files(request, oid, obj_type):
    if obj_type == 'Engagement':
        obj = get_object_or_404(Engagement, pk=oid)
        user_has_permission_or_403(request.user, obj,
                                   Permissions.Engagement_Edit)
        obj_vars = ('view_engagement', 'engagement_set')
    elif obj_type == 'Test':
        obj = get_object_or_404(Test, pk=oid)
        user_has_permission_or_403(request.user, obj, Permissions.Test_Edit)
        obj_vars = ('view_test', 'test_set')
    elif obj_type == 'Finding':
        obj = get_object_or_404(Finding, pk=oid)
        user_has_permission_or_403(request.user, obj, Permissions.Finding_Edit)
        obj_vars = ('view_finding', 'finding_set')
    else:
        raise Http404()

    files_formset = ManageFileFormSet(queryset=obj.files.all())
    error = False

    if request.method == 'POST':
        files_formset = ManageFileFormSet(request.POST,
                                          request.FILES,
                                          queryset=obj.files.all())
        if files_formset.is_valid():
            # remove all from database and disk

            files_formset.save()

            for o in files_formset.deleted_objects:
                logger.debug("removing file: %s", o.file.name)
                os.remove(os.path.join(settings.MEDIA_ROOT, o.file.name))

            for o in files_formset.new_objects:
                logger.debug("adding file: %s", o.file.name)
                obj.files.add(o)

            orphan_files = FileUpload.objects.filter(engagement__isnull=True,
                                                     test__isnull=True,
                                                     finding__isnull=True)
            for o in orphan_files:
                logger.debug("purging orphan file: %s", o.file.name)
                os.remove(os.path.join(settings.MEDIA_ROOT, o.file.name))
                o.delete()

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Files updated successfully.',
                                 extra_tags='alert-success')

        else:
            error = True
            messages.add_message(request,
                                 messages.ERROR,
                                 'Please check form data and try again.',
                                 extra_tags='alert-danger')

        if not error:
            return HttpResponseRedirect(reverse(obj_vars[0], args=(oid, )))
    return render(request, 'dojo/manage_files.html', {
        'files_formset': files_formset,
        'obj': obj,
        'obj_type': obj_type,
    })
Exemplo n.º 21
0
def import_scan_results(request, eid=None, pid=None):
    engagement = None
    form = ImportScanForm()
    cred_form = CredMappingForm()
    finding_count = 0
    jform = None
    user = request.user

    if eid:
        engagement = get_object_or_404(Engagement, id=eid)
        engagement_or_product = engagement
        cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(engagement=engagement).order_by('cred_id')
    elif pid:
        product = get_object_or_404(Product, id=pid)
        engagement_or_product = product
    elif not user.is_staff:
        raise PermissionDenied

    user_has_permission_or_403(user, engagement_or_product, Permissions.Import_Scan_Result)

    push_all_jira_issues = jira_helper.is_push_all_issues(engagement_or_product)

    if request.method == "POST":
        form = ImportScanForm(request.POST, request.FILES)
        cred_form = CredMappingForm(request.POST)
        cred_form.fields["cred_user"].queryset = Cred_Mapping.objects.filter(
            engagement=engagement).order_by('cred_id')

        if jira_helper.get_jira_project(engagement_or_product):
            jform = JIRAImportScanForm(request.POST, push_all=push_all_jira_issues, prefix='jiraform')
            logger.debug('jform valid: %s', jform.is_valid())
            logger.debug('jform errors: %s', jform.errors)

        if form.is_valid() and (jform is None or jform.is_valid()):
            scan = request.FILES.get('file', None)
            scan_date = form.cleaned_data['scan_date']
            minimum_severity = form.cleaned_data['minimum_severity']
            active = form.cleaned_data['active']
            verified = form.cleaned_data['verified']
            scan_type = request.POST['scan_type']
            tags = form.cleaned_data['tags']
            version = form.cleaned_data['version']
            branch_tag = form.cleaned_data.get('branch_tag', None)
            build_id = form.cleaned_data.get('build_id', None)
            commit_hash = form.cleaned_data.get('commit_hash', None)
            api_scan_configuration = form.cleaned_data.get('api_scan_configuration', None)
            service = form.cleaned_data.get('service', None)
            close_old_findings = form.cleaned_data.get('close_old_findings', None)
            # Will save in the provided environment or in the `Development` one if absent
            environment_id = request.POST.get('environment', 'Development')
            environment = Development_Environment.objects.get(id=environment_id)

            group_by = form.cleaned_data.get('group_by', None)

            # TODO move to form validation?
            if scan and is_scan_file_too_large(scan):
                messages.add_message(request,
                                     messages.ERROR,
                                     "Report file is too large. Maximum supported size is {} MB".format(settings.SCAN_FILE_MAX_SIZE),
                                     extra_tags='alert-danger')
                return HttpResponseRedirect(reverse('import_scan_results', args=(engagement,)))

            # Allows for a test to be imported with an engagement created on the fly
            if engagement is None:
                engagement = Engagement()
                engagement.name = "AdHoc Import - " + strftime("%a, %d %b %Y %X", timezone.now().timetuple())
                engagement.threat_model = False
                engagement.api_test = False
                engagement.pen_test = False
                engagement.check_list = False
                engagement.target_start = timezone.now().date()
                engagement.target_end = timezone.now().date()
                engagement.product = product
                engagement.active = True
                engagement.status = 'In Progress'
                engagement.version = version
                engagement.branch_tag = branch_tag
                engagement.build_id = build_id
                engagement.commit_hash = commit_hash
                engagement.save()

            # can't use helper as when push_all_jira_issues is True, the checkbox gets disabled and is always false
            # push_to_jira = jira_helper.is_push_to_jira(new_finding, jform.cleaned_data.get('push_to_jira'))
            push_to_jira = push_all_jira_issues or (jform and jform.cleaned_data.get('push_to_jira'))
            error = False

            # Save newly added endpoints
            added_endpoints = save_endpoints_to_add(form.endpoints_to_add_list, engagement.product)

            try:
                importer = Importer()
                test, finding_count, closed_finding_count = importer.import_scan(scan, scan_type, engagement, user, environment, active=active, verified=verified, tags=tags,
                            minimum_severity=minimum_severity, endpoints_to_add=list(form.cleaned_data['endpoints']) + added_endpoints, scan_date=scan_date,
                            version=version, branch_tag=branch_tag, build_id=build_id, commit_hash=commit_hash, push_to_jira=push_to_jira,
                            close_old_findings=close_old_findings, group_by=group_by, api_scan_configuration=api_scan_configuration, service=service)

                message = f'{scan_type} processed a total of {finding_count} findings'

                if close_old_findings:
                    message = message + ' and closed %d findings' % (closed_finding_count)

                message = message + "."

                add_success_message_to_response(message)

            except Exception as e:
                logger.exception(e)
                add_error_message_to_response('An exception error occurred during the report import:%s' % str(e))
                error = True

            # Save the credential to the test
            if cred_form.is_valid():
                if cred_form.cleaned_data['cred_user']:
                    # Select the credential mapping object from the selected list and only allow if the credential is associated with the product
                    cred_user = Cred_Mapping.objects.filter(
                        pk=cred_form.cleaned_data['cred_user'].id,
                        engagement=eid).first()

                    new_f = cred_form.save(commit=False)
                    new_f.test = test
                    new_f.cred_id = cred_user.cred_id
                    new_f.save()

            if not error:
                return HttpResponseRedirect(
                    reverse('view_test', args=(test.id, )))

    prod_id = None
    custom_breadcrumb = None
    title = "Import Scan Results"
    if engagement:
        prod_id = engagement.product.id
        product_tab = Product_Tab(prod_id, title=title, tab="engagements")
        product_tab.setEngagement(engagement)
    else:
        prod_id = pid
        custom_breadcrumb = {"", ""}
        product_tab = Product_Tab(prod_id, title=title, tab="findings")

    if jira_helper.get_jira_project(engagement_or_product):
        jform = JIRAImportScanForm(push_all=push_all_jira_issues, prefix='jiraform')

    form.fields['endpoints'].queryset = Endpoint.objects.filter(product__id=product_tab.product.id)
    form.fields['api_scan_configuration'].queryset = Product_API_Scan_Configuration.objects.filter(product__id=product_tab.product.id)
    return render(request,
        'dojo/import_scan_results.html',
        {'form': form,
         'product_tab': product_tab,
         'engagement_or_product': engagement_or_product,
         'custom_breadcrumb': custom_breadcrumb,
         'title': title,
         'cred_form': cred_form,
         'jform': jform,
         'scan_types': get_scan_types_sorted(),
         })
Exemplo n.º 22
0
def action_history(request, cid, oid):
    try:
        ct = ContentType.objects.get_for_id(cid)
        obj = ct.get_object_for_this_type(pk=oid)
    except (KeyError, ObjectDoesNotExist):
        raise Http404()

    product_id = None
    active_tab = None
    finding = None
    test = False
    object_value = None

    if ct.model == "product":
        user_has_permission_or_403(request.user, obj, Permissions.Product_View)
        product_id = obj.id
        active_tab = "overview"
        object_value = Product.objects.get(id=obj.id)
    elif ct.model == "engagement":
        user_has_permission_or_403(request.user, obj,
                                   Permissions.Engagement_View)
        object_value = Engagement.objects.get(id=obj.id)
        product_id = object_value.product.id
        active_tab = "engagements"
    elif ct.model == "test":
        user_has_permission_or_403(request.user, obj, Permissions.Test_View)
        object_value = Test.objects.get(id=obj.id)
        product_id = object_value.engagement.product.id
        active_tab = "engagements"
        test = True
    elif ct.model == "finding":
        user_has_permission_or_403(request.user, obj, Permissions.Finding_View)
        object_value = Finding.objects.get(id=obj.id)
        product_id = object_value.test.engagement.product.id
        active_tab = "findings"
        finding = object_value
    elif ct.model == "endpoint":
        user_has_permission_or_403(request.user, obj,
                                   Permissions.Endpoint_View)
        object_value = Endpoint.objects.get(id=obj.id)
        product_id = object_value.product.id
        active_tab = "endpoints"
    elif ct.model == "risk_acceptance":
        engagements = Engagement.objects.filter(risk_acceptance=obj)
        authorized = False
        for engagement in engagements:
            if user_has_permission(request.user, engagement,
                                   Permissions.Engagement_View):
                authorized = True
                break
        if not authorized:
            raise PermissionDenied
    else:
        if not request.user.is_superuser:
            raise PermissionDenied

    product_tab = None
    if product_id:
        product_tab = Product_Tab(product_id, title="History", tab=active_tab)
        if active_tab == "engagements":
            if str(ct) == "engagement":
                product_tab.setEngagement(object_value)
            else:
                product_tab.setEngagement(object_value.engagement)

    history = LogEntry.objects.filter(content_type=ct,
                                      object_pk=obj.id).order_by('-timestamp')
    history = LogEntryFilter(request.GET, queryset=history)
    paged_history = get_page_items(request, history.qs, 25)

    if not get_system_setting('enable_auditlog'):
        messages.add_message(
            request,
            messages.WARNING,
            'Audit logging is currently disabled in System Settings.',
            extra_tags='alert-danger')

    return render(
        request, 'dojo/action_history.html', {
            "history": paged_history,
            'product_tab': product_tab,
            "filtered": history,
            "obj": obj,
            "test": test,
            "object_value": object_value,
            "finding": finding
        })