예제 #1
0
def request_finding_review(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    user = get_object_or_404(Dojo_User, id=request.user.id)
    # in order to review a finding, we need to capture why a review is needed
    # we can do this with a Note
    if request.method == 'POST':
        form = ReviewFindingForm(request.POST)

        if form.is_valid():
            now = timezone.now()
            new_note = Notes()

            new_note.entry = "Review Request: " + form.cleaned_data['entry']
            new_note.author = request.user
            new_note.date = now
            new_note.save()
            finding.notes.add(new_note)
            finding.active = False
            finding.verified = False
            finding.under_review = True
            finding.review_requested_by = user
            finding.last_reviewed = now
            finding.last_reviewed_by = request.user

            users = form.cleaned_data['reviewers']
            finding.reviewers = users
            finding.save()

            create_notification(event='review_requested',
                               title='Finding review requested',
                               description='User %s has requested that you please review the finding "%s" for accuracy:\n\n%s' \
                                           % (user, finding.title, new_note),
                               icon='check',
                               url=request.build_absolute_uri(reverse("view_finding", args=(finding.id,))))

            messages.add_message(
                request,
                messages.SUCCESS,
                'Finding marked for review and reviewers notified.',
                extra_tags='alert-success')
            return HttpResponseRedirect(
                reverse('view_finding', args=(finding.id, )))

    else:
        form = ReviewFindingForm()

    add_breadcrumb(parent=finding,
                   title="Review Finding",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/review_finding.html', {
        'finding': finding,
        'user': user,
        'form': form
    })
예제 #2
0
def clear_finding_review(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    user = get_object_or_404(Dojo_User, id=request.user.id)
    # in order to clear a review for a finding, we need to capture why and how it was reviewed
    # we can do this with a Note

    if user == finding.review_requested_by or user in finding.reviewers.all():
        pass
    else:
        return HttpResponseForbidden()

    if request.method == 'POST':
        form = ClearFindingReviewForm(request.POST, instance=finding)

        if form.is_valid():
            now = datetime.now(tz=localtz)
            new_note = Notes()
            new_note.entry = "Review Cleared: " + form.cleaned_data['entry']
            new_note.author = request.user
            new_note.date = now
            new_note.save()

            finding = form.save(commit=False)

            finding.under_review = False
            finding.last_reviewed = now
            finding.last_reviewed_by = request.user

            finding.reviewers = []
            finding.save()

            finding.notes.add(new_note)

            messages.add_message(
                request,
                messages.SUCCESS,
                'Finding review has been updated successfully.',
                extra_tags='alert-success')
            return HttpResponseRedirect(
                reverse('view_finding', args=(finding.id, )))

    else:
        form = ClearFindingReviewForm(instance=finding)

    add_breadcrumb(parent=finding,
                   title="Clear Finding Review",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/clear_finding_review.html', {
        'finding': finding,
        'user': user,
        'form': form
    })
예제 #3
0
def request_finding_review(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    user = get_object_or_404(Dojo_User, id=request.user.id)
    # in order to review a finding, we need to capture why a review is needed
    # we can do this with a Note
    if request.method == 'POST':
        form = ReviewFindingForm(request.POST)

        if form.is_valid():
            now = datetime.now(tz=localtz)
            new_note = Notes()

            new_note.entry = "Review Request: " + form.cleaned_data['entry']
            new_note.author = request.user
            new_note.date = now
            new_note.save()
            finding.notes.add(new_note)
            finding.active = False
            finding.verified = False
            finding.under_review = True
            finding.review_requested_by = user
            finding.last_reviewed = now
            finding.last_reviewed_by = request.user

            users = form.cleaned_data['reviewers']
            finding.reviewers = users
            finding.save()

            send_review_email(request, user, finding, users, new_note)

            messages.add_message(
                request,
                messages.SUCCESS,
                'Finding marked for review and reviewers notified.',
                extra_tags='alert-success')
            return HttpResponseRedirect(
                reverse('view_finding', args=(finding.id, )))

    else:
        form = ReviewFindingForm()

    add_breadcrumb(parent=finding,
                   title="Review Finding",
                   top_level=False,
                   request=request)
    return render(request, 'dojo/review_finding.html', {
        'finding': finding,
        'user': user,
        'form': form
    })
예제 #4
0
def webhook(request):
    # Webhook shouldn't be active if jira isn't enabled
    if not get_system_setting('enable_jira'):
        raise PermissionDenied
    elif not get_system_setting('enable_jira_web_hook'):
        raise PermissionDenied

    if request.method == 'POST':
        parsed = json.loads(request.body)
        if 'issue' in parsed.keys():
            jid = parsed['issue']['id']
            jissue = get_object_or_404(JIRA_Issue, jira_id=jid)
            if jissue.finding is not None:
                finding = jissue.finding
                resolved = True
                if parsed['issue']['fields']['resolution'] is None:
                    resolved = False
                if finding.active == resolved:
                    if finding.active:
                        now = timezone.now()
                        finding.active = False
                        finding.mitigated = now
                        finding.endpoints.clear()
                    else:
                        finding.active = True
                        finding.mitigated = None
                        finding.save()
                    finding.save()
            """
            if jissue.engagement is not None:
                eng = jissue.engagement
                if parsed['issue']['fields']['resolution'] != None:
                    eng.active = False
                    eng.status = 'Completed'
                    eng.save()
           """
        else:
            comment_text = parsed['comment']['body']
            commentor = parsed['comment']['updateAuthor']['displayName']
            jid = parsed['comment']['self'].split('/')[7]
            jissue = JIRA_Issue.objects.get(jira_id=jid)
            finding = jissue.finding
            new_note = Notes()
            new_note.entry = '(%s): %s' % (commentor, comment_text)
            new_note.author, created = User.objects.get_or_create(
                username='******')
            new_note.save()
            finding.notes.add(new_note)
            finding.save()
    return HttpResponse('')
예제 #5
0
def webhook(request):
    # Webhook shouldn't be active if jira isn't enabled
    if not get_system_setting('enable_jira'):
        raise PermissionDenied
    elif not get_system_setting('enable_jira_web_hook'):
        raise PermissionDenied

    if request.method == 'POST':
        parsed = json.loads(request.body)
        if 'issue' in parsed.keys():
            jid = parsed['issue']['id']
            jissue = get_object_or_404(JIRA_Issue, jira_id=jid)
            if jissue.finding is not None:
                finding = jissue.finding
                resolved = True
                if parsed['issue']['fields']['resolution'] is None:
                    resolved = False
                if finding.active == resolved:
                    if finding.active:
                        now = timezone.now()
                        finding.active = False
                        finding.mitigated = now
                        finding.endpoints.clear()
                    else:
                        finding.active = True
                        finding.mitigated = None
                        finding.save()
                    finding.save()
            """
            if jissue.engagement is not None:
                eng = jissue.engagement
                if parsed['issue']['fields']['resolution'] != None:
                    eng.active = False
                    eng.status = 'Completed'
                    eng.save()
           """
        else:
            comment_text = parsed['comment']['body']
            commentor = parsed['comment']['updateAuthor']['displayName']
            jid = parsed['comment']['self'].split('/')[7]
            jissue = JIRA_Issue.objects.get(jira_id=jid)
            finding = jissue.finding
            new_note = Notes()
            new_note.entry = '(%s): %s' % (commentor, comment_text)
            new_note.author, created = User.objects.get_or_create(username='******')
            new_note.save()
            finding.notes.add(new_note)
            finding.save()
    return HttpResponse('')
예제 #6
0
def request_finding_review(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    user = get_object_or_404(Dojo_User, id=request.user.id)
    # in order to review a finding, we need to capture why a review is needed
    # we can do this with a Note
    if request.method == 'POST':
        form = ReviewFindingForm(request.POST)

        if form.is_valid():
            now = timezone.now()
            new_note = Notes()

            new_note.entry = "Review Request: " + form.cleaned_data['entry']
            new_note.author = request.user
            new_note.date = now
            new_note.save()
            finding.notes.add(new_note)
            finding.active = False
            finding.verified = False
            finding.under_review = True
            finding.review_requested_by = user
            finding.last_reviewed = now
            finding.last_reviewed_by = request.user

            users = form.cleaned_data['reviewers']
            finding.reviewers = users
            finding.save()

            create_notification(event='review_requested',
                               title='Finding review requested',
                               description='User %s has requested that you please review the finding "%s" for accuracy:\n\n%s' \
                                           % (user, finding.title, new_note),
                               icon='check',
                               url=request.build_absolute_uri(reverse("view_finding", args=(finding.id,))))

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Finding marked for review and reviewers notified.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('view_finding', args=(finding.id,)))

    else:
        form = ReviewFindingForm()

    add_breadcrumb(parent=finding, title="Review Finding", top_level=False, request=request)
    return render(request, 'dojo/review_finding.html',
                  {'finding': finding,
                   'user': user, 'form': form})
예제 #7
0
def finding_unlink_jira(request, finding):
    logger.debug('removing linked jira issue %s for finding %i',
                 finding.jira_issue.jira_key, finding.id)
    finding.jira_issue.delete()
    finding.save(push_to_jira=False,
                 dedupe_option=False,
                 issue_updater_option=False)

    jira_issue_url = get_jira_url(finding)

    new_note = Notes()
    new_note.entry = 'unlinked JIRA issue %s from finding' % (jira_issue_url)
    new_note.author = request.user
    new_note.save()
    finding.notes.add(new_note)
    return True
예제 #8
0
def clear_finding_review(request, fid):
    finding = get_object_or_404(Finding, id=fid)
    user = get_object_or_404(Dojo_User, id=request.user.id)
    # in order to clear a review for a finding, we need to capture why and how it was reviewed
    # we can do this with a Note

    if user == finding.review_requested_by or user in finding.reviewers.all():
        pass
    else:
        return HttpResponseForbidden()

    if request.method == 'POST':
        form = ClearFindingReviewForm(request.POST, instance=finding)

        if form.is_valid():
            now = timezone.now()
            new_note = Notes()
            new_note.entry = "Review Cleared: " + form.cleaned_data['entry']
            new_note.author = request.user
            new_note.date = now
            new_note.save()

            finding = form.save(commit=False)

            finding.under_review = False
            finding.last_reviewed = now
            finding.last_reviewed_by = request.user

            finding.reviewers = []
            finding.save()

            finding.notes.add(new_note)

            messages.add_message(request,
                                 messages.SUCCESS,
                                 'Finding review has been updated successfully.',
                                 extra_tags='alert-success')
            return HttpResponseRedirect(reverse('view_finding', args=(finding.id,)))

    else:
        form = ClearFindingReviewForm(instance=finding)

    add_breadcrumb(parent=finding, title="Clear Finding Review", top_level=False, request=request)
    return render(request, 'dojo/clear_finding_review.html',
                  {'finding': finding,
                   'user': user, 'form': form})
예제 #9
0
    def handle(self, *args, **options):

        findings = Finding.objects.exclude(jira_issue__isnull=True)
        findings = findings.filter(verified=True, active=True)
        findings = findings.prefetch_related('jira_issue')
        # finding = Finding.objects.get(id=1)
        for finding in findings:
            #    try:
            JIRAError.log_to_tempfile = False
            jira = jira_helper.get_jira_connection(finding)
            j_issue = finding.jira_issue
            issue = jira.issue(j_issue.jira_id)

            # Issue Cloned
            print(issue.fields.issuelinks[0])

            print("Jira Issue: " + str(issue))
            print("Resolution: " + str(issue.fields.resolution))

            if issue.fields.resolution is not None \
                    and not finding.under_defect_review:
                # print issue.fields.__dict__
                print("Jira Issue: " + str(issue) + " changed status")

                # Create Jira Note
                now = timezone.now()
                new_note = Notes()
                new_note.entry = "Please Review Jira Request: " + str(
                    issue) + ". Review status has changed to " + str(
                    issue.fields.resolution) + "."
                new_note.author = User.objects.get(username='******')
                new_note.date = now
                new_note.save()
                finding.notes.add(new_note)
                finding.under_defect_review = True
                dojo_user = Dojo_User.objects.get(username='******')
                finding.defect_review_requested_by = dojo_user

                # Create alert to notify user
                jira_helper.log_jira_message("Jira issue status change, please review.",
                                 finding)
                finding.save()
            else:
                print("No update necessary")
    def handle(self, *args, **options):

        findings = Finding.objects.exclude(jira_issue__isnull=True)
        findings = findings.filter(verified=True, active=True)
        # finding = Finding.objects.get(id=1)
        for finding in findings:
            #    try:
            JIRAError.log_to_tempfile = False
            jira = get_jira_connection(finding)
            j_issue = JIRA_Issue.objects.get(finding=finding)
            issue = jira.issue(j_issue.jira_id)

            # Issue Cloned
            print issue.fields.issuelinks[0]

            print "Jira Issue: " + str(issue)
            print "Resolution: " + str(issue.fields.resolution)

            if issue.fields.resolution is not None \
                    and finding.under_defect_review == False:
                # print issue.fields.__dict__
                print "Jira Issue: " + str(issue) + " changed status"

                # Create Jira Note
                now = timezone.now()
                new_note = Notes()
                new_note.entry = "Please Review Jira Request: " + str(
                    issue) + ". Review status has changed to " + str(
                    issue.fields.resolution) + "."
                new_note.author = User.objects.get(username='******')
                new_note.date = now
                new_note.save()
                finding.notes.add(new_note)
                finding.under_defect_review = True
                dojo_user = Dojo_User.objects.get(username='******')
                finding.defect_review_requested_by = dojo_user

                # Create alert to notify user
                log_jira_message("Jira issue status change, please review.",
                                 finding)
                finding.save()
            else:
                print "No update necessary"
예제 #11
0
def finding_link_jira(request, finding, new_jira_issue_key):
    logger.debug('linking existing jira issue %s for finding %i',
                 new_jira_issue_key, finding.id)

    existing_jira_issue = jira_get_issue(get_jira_project(finding),
                                         new_jira_issue_key)

    jira_project = get_jira_project(finding)

    if not existing_jira_issue:
        raise ValueError('JIRA issue not found or cannot be retrieved: ' +
                         new_jira_issue_key)

    jira_issue = JIRA_Issue(jira_id=existing_jira_issue.id,
                            jira_key=existing_jira_issue.key,
                            finding=finding,
                            jira_project=jira_project)

    jira_issue.jira_key = new_jira_issue_key
    # jira timestampe are in iso format: 'updated': '2020-07-17T09:49:51.447+0200'
    # seems to be a pain to parse these in python < 3.7, so for now just record the curent time as
    # as the timestamp the jira link was created / updated in DD
    jira_issue.jira_creation = timezone.now()
    jira_issue.jira_change = timezone.now()

    jira_issue.save()

    finding.save(push_to_jira=False,
                 dedupe_option=False,
                 issue_updater_option=False)

    jira_issue_url = get_jira_url(finding)

    new_note = Notes()
    new_note.entry = 'linked JIRA issue %s to finding' % (jira_issue_url)
    new_note.author = request.user
    new_note.save()
    finding.notes.add(new_note)
    return True
예제 #12
0
def webhook(request):
    # Webhook shouldn't be active if jira isn't enabled
    if not get_system_setting('enable_jira'):
        raise PermissionDenied
    elif not get_system_setting('enable_jira_web_hook'):
        raise PermissionDenied

    if request.method == 'POST':
        parsed = json.loads(request.body.decode('utf-8'))
        if parsed.get('webhookEvent') == 'jira:issue_updated':
            jid = parsed['issue']['id']
            jissue = get_object_or_404(JIRA_Issue, jira_id=jid)
            if jissue.finding is not None:
                finding = jissue.finding
                jira_conf = finding.jira_conf()
                resolved = True
                resolution = parsed['issue']['fields']['resolution']
                if resolution is None:
                    resolved = False
                if finding.active == resolved:
                    if finding.active:
                        if jira_conf and resolution[
                                'name'] in jira_conf.accepted_resolutions:
                            finding.active = False
                            finding.mitigated = None
                            finding.is_Mitigated = False
                            finding.false_p = False
                            assignee = parsed['issue']['fields'].get(
                                'assignee')
                            assignee_name = assignee[
                                'name'] if assignee else None
                            Risk_Acceptance.objects.create(
                                accepted_by=assignee_name,
                                reporter=finding.reporter,
                            ).accepted_findings.set([finding])
                        elif jira_conf and resolution[
                                'name'] in jira_conf.false_positive_resolutions:
                            finding.active = False
                            finding.verified = False
                            finding.mitigated = None
                            finding.is_Mitigated = False
                            finding.false_p = True
                            finding.remove_from_any_risk_acceptance()
                        else:
                            # Mitigated by default as before
                            now = timezone.now()
                            finding.active = False
                            finding.mitigated = now
                            finding.endpoints.clear()
                            finding.false_p = False
                            finding.remove_from_any_risk_acceptance()
                    else:
                        # Reopen / Open Jira issue
                        finding.active = True
                        finding.mitigated = None
                        finding.is_Mitigated = False
                        finding.false_p = False
                        finding.remove_from_any_risk_acceptance()
                    finding.jira_change = timezone.now()
                    finding.save()
            """
            if jissue.engagement is not None:
                eng = jissue.engagement
                if parsed['issue']['fields']['resolution'] != None:
                    eng.active = False
                    eng.status = 'Completed'
                    eng.save()
           """
        if parsed.get('webhookEvent') == 'comment_created':
            comment_text = parsed['comment']['body']
            commentor = parsed['comment']['updateAuthor']['displayName']
            jid = parsed['comment']['self'].split('/')[7]
            jissue = JIRA_Issue.objects.get(jira_id=jid)
            finding = jissue.finding
            new_note = Notes()
            new_note.entry = '(%s): %s' % (commentor, comment_text)
            new_note.author, created = User.objects.get_or_create(
                username='******')
            new_note.save()
            finding.notes.add(new_note)
            finding.jira_change = timezone.now()
            finding.save()

        if parsed.get('webhookEvent') not in [
                'comment_created', 'jira:issue_updated'
        ]:
            logger.info('Unrecognized JIRA webhook event received: {}'.format(
                parsed.get('webhookEvent')))
    return HttpResponse('')
예제 #13
0
def webhook(request, secret=None):
    if not get_system_setting('enable_jira'):
        logger.debug('ignoring incoming webhook as JIRA is disabled.')
        raise Http404('JIRA disabled')
    elif not get_system_setting('enable_jira_web_hook'):
        logger.debug('ignoring incoming webhook as JIRA Webhook is disabled.')
        raise Http404('JIRA Webhook disabled')
    elif not get_system_setting('disable_jira_webhook_secret'):
        if not get_system_setting('jira_webhook_secret'):
            logger.warning(
                'ignoring incoming webhook as JIRA Webhook secret is empty in Defect Dojo system settings.'
            )
            raise PermissionDenied('JIRA Webhook secret cannot be empty')
        if secret != get_system_setting('jira_webhook_secret'):
            logger.warning('invalid secret provided to JIRA Webhook')
            raise PermissionDenied(
                'invalid or no secret provided to JIRA Webhook')

    # if webhook secret is disabled in system_settings, we ignore the incoming secret, even if it doesn't match

    # example json bodies at the end of this file

    if request.content_type != 'application/json':
        return HttpResponseBadRequest("only application/json supported")

    if request.method == 'POST':
        try:
            parsed = json.loads(request.body.decode('utf-8'))
            if parsed.get('webhookEvent') == 'jira:issue_updated':
                # xml examples at the end of file
                jid = parsed['issue']['id']
                jissue = get_object_or_404(JIRA_Issue, jira_id=jid)
                logging.info("Received issue update for {}".format(
                    jissue.jira_key))
                if jissue.finding:
                    finding = jissue.finding
                    jira_instance = jira_helper.get_jira_instance(finding)
                    resolved = True
                    resolution = parsed['issue']['fields']['resolution']

                    #         "resolution":{
                    #             "self":"http://www.testjira.com/rest/api/2/resolution/11",
                    #             "id":"11",
                    #             "description":"Cancelled by the customer.",
                    #             "name":"Cancelled"
                    #         },

                    # or
                    #         "resolution": null

                    if resolution is None:
                        resolved = False
                        logger.debug(
                            "JIRA resolution is None, therefore resolved is now False"
                        )
                    if finding.active is resolved:
                        if finding.active:
                            if jira_instance and resolution[
                                    'name'] in jira_instance.accepted_resolutions:
                                logger.debug(
                                    "Marking related finding of {} as accepted. Creating risk acceptance."
                                    .format(jissue.jira_key))
                                finding.active = False
                                finding.mitigated = None
                                finding.is_Mitigated = False
                                finding.false_p = False
                                assignee = parsed['issue']['fields'].get(
                                    'assignee')
                                assignee_name = assignee[
                                    'name'] if assignee else None
                                Risk_Acceptance.objects.create(
                                    accepted_by=assignee_name,
                                    owner=finding.reporter,
                                ).accepted_findings.set([finding])
                            elif jira_instance and resolution[
                                    'name'] in jira_instance.false_positive_resolutions:
                                logger.debug(
                                    "Marking related finding of {} as false-positive"
                                    .format(jissue.jira_key))
                                finding.active = False
                                finding.verified = False
                                finding.mitigated = None
                                finding.is_Mitigated = False
                                finding.false_p = True
                                ra_helper.remove_from_any_risk_acceptance(
                                    finding)
                            else:
                                # Mitigated by default as before
                                logger.debug(
                                    "Marking related finding of {} as mitigated (default)"
                                    .format(jissue.jira_key))
                                now = timezone.now()
                                finding.active = False
                                finding.mitigated = now
                                finding.is_Mitigated = True
                                finding.endpoints.clear()
                                finding.false_p = False
                                ra_helper.remove_from_any_risk_acceptance(
                                    finding)
                        else:
                            # Reopen / Open Jira issue
                            logger.debug(
                                "Re-opening related finding of {}".format(
                                    jissue.jira_key))
                            finding.active = True
                            finding.mitigated = None
                            finding.is_Mitigated = False
                            finding.false_p = False
                            ra_helper.remove_from_any_risk_acceptance(finding)
                    else:
                        # Reopen / Open Jira issue
                        finding.active = True
                        finding.mitigated = None
                        finding.is_Mitigated = False
                        finding.false_p = False
                        ra_helper.remove_from_any_risk_acceptance(finding)

                    finding.jira_issue.jira_change = timezone.now()
                    finding.jira_issue.save()
                    finding.save()

                elif jissue.engagement:
                    # if parsed['issue']['fields']['resolution'] != None:
                    #     eng.active = False
                    #     eng.status = 'Completed'
                    #     eng.save()
                    return HttpResponse('Update for engagement ignored')
                else:
                    raise Http404(
                        'No finding or engagement found for JIRA issue {}'.
                        format(jissue.jira_key))

            if parsed.get('webhookEvent') == 'comment_created':
                """
                    example incoming requests from JIRA Server 8.14.0
                    {
                    "timestamp":1610269967824,
                    "webhookEvent":"comment_created",
                    "comment":{
                        "self":"https://jira.host.com/rest/api/2/issue/115254/comment/466578",
                        "id":"466578",
                        "author":{
                            "self":"https://jira.host.com/rest/api/2/user?username=defect.dojo",
                            "name":"defect.dojo",
                            "key":"defect.dojo", # seems to be only present on JIRA Server, not on Cloud
                            "avatarUrls":{
                                "48x48":"https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=48",
                                "24x24":"https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=24",
                                "16x16":"https://www.gravatar.com/avatar9637bfb970eff6176357df615f548f1c?d=mm&s=16",
                                "32x32":"https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=32"
                            },
                            "displayName":"Defect Dojo",
                            "active":true,
                            "timeZone":"Europe/Amsterdam"
                        },
                        "body":"(Valentijn Scholten):test4",
                        "updateAuthor":{
                            "self":"https://jira.host.com/rest/api/2/user?username=defect.dojo",
                            "name":"defect.dojo",
                            "key":"defect.dojo",
                            "avatarUrls":{
                                "48x48":"https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=48",
                                "24x24""https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=24",
                                "16x16":"https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=16",
                                "32x32":"https://www.gravatar.com/avatar/9637bfb970eff6176357df615f548f1c?d=mm&s=32"
                            },
                            "displayName":"Defect Dojo",
                            "active":true,
                            "timeZone":"Europe/Amsterdam"
                        },
                        "created":"2021-01-10T10:12:47.824+0100",
                        "updated":"2021-01-10T10:12:47.824+0100"
                    }
                    }
                """

                comment_text = parsed['comment']['body']
                commentor = ''
                if 'name' in parsed['comment']['updateAuthor']:
                    commentor = parsed['comment']['updateAuthor']['name']
                elif 'emailAddress' in parsed['comment']['updateAuthor']:
                    commentor = parsed['comment']['updateAuthor'][
                        'emailAddress']
                else:
                    logger.debug(
                        'Could not find the author of this jira comment!')
                commentor_display_name = parsed['comment']['updateAuthor'][
                    'displayName']
                # example: body['comment']['self'] = "http://www.testjira.com/jira_under_a_path/rest/api/2/issue/666/comment/456843"
                jid = parsed['comment']['self'].split('/')[-3]
                jissue = get_object_or_404(JIRA_Issue, jira_id=jid)
                logging.info("Received issue comment for {}".format(
                    jissue.jira_key))
                logger.debug('jissue: %s', vars(jissue))
                if jissue.finding:
                    # logger.debug('finding: %s', vars(jissue.finding))
                    jira_usernames = JIRA_Instance.objects.values_list(
                        'username', flat=True)
                    for jira_userid in jira_usernames:
                        # logger.debug('incoming username: %s jira config username: %s', commentor.lower(), jira_userid.lower())
                        if jira_userid.lower() == commentor.lower():
                            logger.debug(
                                'skipping incoming JIRA comment as the user id of the comment in JIRA (%s) matches the JIRA username in DefectDojo (%s)',
                                commentor.lower(), jira_userid.lower())
                            return HttpResponse('')
                            break
                    finding = jissue.finding
                    new_note = Notes()
                    new_note.entry = '(%s (%s)): %s' % (
                        commentor_display_name, commentor, comment_text)
                    new_note.author, created = User.objects.get_or_create(
                        username='******')
                    new_note.save()
                    finding.notes.add(new_note)
                    finding.jira_issue.jira_change = timezone.now()
                    finding.jira_issue.save()
                    finding.save()
                    create_notification(
                        event='other',
                        title='JIRA incoming comment - %s' % (jissue.finding),
                        url=reverse("view_finding",
                                    args=(jissue.finding.id, )),
                        icon='check')
                elif jissue.engagement:
                    return HttpResponse('Comment for engagement ignored')
                else:
                    raise Http404(
                        'No finding or engagement found for JIRA issue {}'.
                        format(jissue.jira_key))

            if parsed.get('webhookEvent') not in [
                    'comment_created', 'jira:issue_updated'
            ]:
                logger.info(
                    'Unrecognized JIRA webhook event received: {}'.format(
                        parsed.get('webhookEvent')))
        except Exception as e:
            if isinstance(e, Http404):
                logger.warning('404 error processing JIRA webhook')
            else:
                logger.exception(e)

            try:
                logger.debug('jira_webhook_body_parsed:')
                logger.debug(json.dumps(parsed, indent=4))
            except:
                logger.debug('jira_webhook_body:')
                logger.debug(request.body.decode('utf-8'))

            # reraise to make sure we don't silently swallow things
            raise
    return HttpResponse('')
예제 #14
0
def handle_uploaded_cvff(request, f):
    output = StringIO.StringIO()
    for chunk in f.chunks():
        output.write(chunk)

    csvString = output.getvalue().splitlines(True)[1:]

    inputCSV = csv.reader(csvString, quoting=csv.QUOTE_NONNUMERIC)
    logger.error('Before moving into loop')

    isHeader = 1
    indexOfResolution = 0
    for row in inputCSV:
        if isHeader == 1:
            for col in row:
                if str(col) == "WSO2_resolution":
                    isHeader = 0
                    break
                indexOfResolution = indexOfResolution + 1
        try:
            finding = Finding.objects.filter(pk=float(row[0]))[0]
            logger.error('Finding note count for id ' + str(row[0]) +
                         ' is : ' + str(finding.notes.count()))
            status = str(row[indexOfResolution]).strip().split("(")[0]
            if finding.notes.count() == 0:
                note = Notes(entry="[ " + status + " ] ~ " +
                             row[indexOfResolution + 2],
                             author=request.user)
                note.save()
                finding.notes.add(note)
                logger.info('Adding new note')
            else:
                note = finding.notes.all()[0]
                note.entry = "[ " + status + " ] ~ " + row[indexOfResolution +
                                                           2]
                note.author = request.user
                note.save()
                logger.info('Updating existing note' + str(note.id))

            status = status.replace('.', '').replace(',',
                                                     '').replace(' ',
                                                                 '').lower()

            finding.false_p = False
            finding.verified = False
            finding.active = False
            finding.out_of_scope = False
            finding.save()

            if status == 'falsepositive':
                finding.false_p = True
                finding.save()
            elif status == 'notathreat':
                finding.verified = True
                finding.save()
            elif status == 'needtobefixed':
                finding.active = True
                finding.save()
            elif status == 'needtofix':
                finding.active = True
                finding.save()
            elif status == 'truepositive':
                finding.active = True
                finding.save()
            elif status == 'alreadymitigated':
                finding.out_of_scope = True
                finding.save()
            elif status == 'notapplicable':
                finding.under_review = True
                finding.save()
            #elif status == 'cannotreproduce':
            #    finding.under_review = True
            #    finding.save()
            else:
                logger.error('Unknown status for : ' + str(row[0]) +
                             ". Status is : " + status)
        except Exception as e:
            logger.error(e.message)
            logger.error('Error in processing row: ' + str(row[0]) +
                         ". Skipping.")
예제 #15
0
def handle_uploaded_cvff(request, f):
    output = StringIO.StringIO()
    for chunk in f.chunks():
       output.write(chunk)

    csvString = output.getvalue().splitlines(True)[1:]

    inputCSV = csv.reader(csvString, quoting=csv.QUOTE_NONNUMERIC)
    logger.error('Before moving into loop')

    isHeader = 1
    indexOfResolution = 0
    for row in inputCSV:
        if isHeader == 1:
            for col in row:
                if str(col) == "WSO2_resolution":
                    isHeader = 0
                    break
                indexOfResolution = indexOfResolution + 1
        try:
            finding = Finding.objects.filter(pk=float(row[0]))[0];
            logger.error('Finding note count for id '+ str(row[0]) +' is : ' + str(finding.notes.count()))
            status = str(row[indexOfResolution]).strip().split("(")[0]
            if finding.notes.count() == 0:
                note = Notes(entry="[ " + status + " ] ~ " + row[indexOfResolution + 2], author=request.user)
                note.save()
                finding.notes.add(note);
                logger.info('Adding new note')
            else:
                note = finding.notes.all()[0]
                note.entry = "[ " + status + " ] ~ " + row[indexOfResolution + 2]
                note.author=request.user
                note.save()
                logger.info('Updating existing note' + str(note.id))

            status = status.replace('.','').replace(',','').replace(' ','').lower()

            finding.false_p = False
            finding.verified = False
            finding.active = False
            finding.out_of_scope = False
            finding.save()

            if status == 'falsepositive':
                finding.false_p = True
                finding.save()
            elif status == 'notathreat':
                finding.verified = True
                finding.save()
            elif status == 'needtobefixed':
                finding.active = True
                finding.save()
            elif status == 'needtofix':
                finding.active = True
                finding.save()
            elif status == 'truepositive':
                finding.active = True
                finding.save()
            elif status == 'alreadymitigated':
                finding.out_of_scope = True
                finding.save()
            elif status == 'notapplicable':
                finding.under_review = True
                finding.save()
            #elif status == 'cannotreproduce':
            #    finding.under_review = True
            #    finding.save()
            else:
                logger.error('Unknown status for : ' + str(row[0]) + ". Status is : " + status)
        except Exception as e:
            logger.error(e.message)
            logger.error('Error in processing row: ' + str(row[0]) + ". Skipping.")