Example #1
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)

    return True
Example #2
0
def add_issue(find, push_to_jira):
    eng = Engagement.objects.get(test=find.test)
    prod = Product.objects.get(engagement=eng)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf
    if push_to_jira:
        if 'Active' in find.status() and 'Verified' in find.status():
            jira = JIRA(server=jira_conf.url,
                        basic_auth=(jira_conf.username, jira_conf.password))
            new_issue = jira.create_issue(
                project=jpkey.project_key,
                summary=find.title,
                components=[
                    {
                        'name': jpkey.component
                    },
                ],
                description=jira_long_description(find.long_desc(), find.id,
                                                  jira_conf.finding_text),
                issuetype={'name': jira_conf.default_issue_type},
                priority={'name': jira_conf.get_priority(find.severity)})
            j_issue = JIRA_Issue(jira_id=new_issue.id,
                                 jira_key=new_issue,
                                 finding=find)
            j_issue.save()
            issue = jira.issue(new_issue.id)
            #Add labels (security & product)
            add_labels(find, new_issue)
            #Upload dojo finding screenshots to Jira
            for pic in find.images.all():
                jira_attachment(jira, issue,
                                settings.MEDIA_ROOT + pic.image_large.name)
Example #3
0
def add_issue(find, push_to_jira):
    eng = Engagement.objects.get(test=find.test)
    prod = Product.objects.get(engagement=eng)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf

    if push_to_jira:
        if 'Active' in find.status() and 'Verified' in find.status():
            try:
                JIRAError.log_to_tempfile = False
                jira = JIRA(server=jira_conf.url,
                            basic_auth=(jira_conf.username,
                                        jira_conf.password))
                if jpkey.component:
                    new_issue = jira.create_issue(
                        project=jpkey.project_key,
                        summary=find.title,
                        components=[
                            {
                                'name': jpkey.component
                            },
                        ],
                        description=jira_long_description(
                            find.long_desc(), find.id, jira_conf.finding_text),
                        issuetype={'name': jira_conf.default_issue_type},
                        priority={
                            'name': jira_conf.get_priority(find.severity)
                        })
                else:
                    new_issue = jira.create_issue(
                        project=jpkey.project_key,
                        summary=find.title,
                        description=jira_long_description(
                            find.long_desc(), find.id, jira_conf.finding_text),
                        issuetype={'name': jira_conf.default_issue_type},
                        priority={
                            'name': jira_conf.get_priority(find.severity)
                        })
                j_issue = JIRA_Issue(jira_id=new_issue.id,
                                     jira_key=new_issue,
                                     finding=find)
                j_issue.save()
                issue = jira.issue(new_issue.id)

                #Add labels (security & product)
                add_labels(find, new_issue)
                #Upload dojo finding screenshots to Jira
                for pic in find.images.all():
                    jira_attachment(jira, issue,
                                    settings.MEDIA_ROOT + pic.image_large.name)

                    #if jpkey.enable_engagement_epic_mapping:
                    #      epic = JIRA_Issue.objects.get(engagement=eng)
                    #      issue_list = [j_issue.jira_id,]
                    #      jira.add_issues_to_epic(epic_id=epic.jira_id, issue_keys=[str(j_issue.jira_id)], ignore_epics=True)
            except JIRAError as e:
                log_jira_alert(e.text, find)
        else:
            log_jira_alert("Finding not active or verified.", find)
Example #4
0
def add_epic(engagement):
    logger.info('trying to create a new jira EPIC for %d:%s', engagement.id,
                engagement.name)

    if not is_jira_configured_and_enabled(engagement):
        return False

    logger.debug('config found')

    jira_project = get_jira_project(engagement)
    jira_instance = get_jira_instance(engagement)
    if jira_project.enable_engagement_epic_mapping:
        issue_dict = {
            'project': {
                'key': jira_project.project_key
            },
            'summary': engagement.name,
            'description': engagement.name,
            'issuetype': {
                'name': 'Epic'
            },
            'customfield_' + str(jira_instance.epic_name_id): engagement.name,
        }
        try:
            jira = get_jira_connection(jira_instance)
            logger.debug('add_epic: %s', issue_dict)
            new_issue = jira.create_issue(fields=issue_dict)
            j_issue = JIRA_Issue(jira_id=new_issue.id,
                                 jira_key=new_issue.key,
                                 engagement=engagement,
                                 jira_project=jira_project)
            j_issue.save()
            return True
        except JIRAError as e:
            # should we try to parse the errors as JIRA is very strange in how it responds.
            # for example a non existent project_key leads to "project key is required" which sounds like something is missing
            # but it's just a non-existent project (or maybe a project for which the account has no create permission?)
            #
            # {"errorMessages":[],"errors":{"project":"project is required"}}
            logger.exception(e)
            error = str(e)
            message = ""
            if "customfield" in error:
                message = "The 'Epic name id' in your DefectDojo Jira Configuration does not appear to be correct. Please visit, " + jira_instance.url + \
                    "/rest/api/2/field and search for Epic Name. Copy the number out of cf[number] and place in your DefectDojo settings for Jira and try again. For example, if your results are cf[100001] then copy 100001 and place it in 'Epic name id'. (Your Epic Id will be different.) \n\n"

            log_jira_generic_alert('Jira Engagement/Epic Creation Error',
                                   message + error)
            return False
    else:
        messages.add_message(
            get_current_request(),
            messages.ERROR,
            'Push to JIRA for Epic skipped because enable_engagement_epic_mapping is not checked for this engagement',
            extra_tags='alert-danger')
        return False
Example #5
0
def add_issue(find, push_to_jira):
    eng = Engagement.objects.get(test=find.test)
    prod =  Product.objects.get(engagement= eng)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf
    if push_to_jira:
        if 'Active' in find.status() and 'Verified' in find.status():
                jira = JIRA(server=jira_conf.url, basic_auth=(jira_conf.username, jira_conf.password))
                new_issue = jira.create_issue(project=jpkey.project_key, summary=find.title, description=find.long_desc(), issuetype={'name': 'Bug'}, priority={'name': jira_conf.get_priority(find.severity)})
                j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue, finding = find)
                j_issue.save()
                if jpkey.enable_engagement_epic_mapping:
                      epic = JIRA_Issue.objects.get(engagement=eng)
                      issue_list = [j_issue.jira_id,]
                      jira.add_issues_to_epic(epic_id=epic.jira_id, issue_keys=[str(j_issue.jira_id)], ignore_epics=True)
Example #6
0
def add_epic(eng, push_to_jira):
    engagement = eng
    prod = Product.objects.get(engagement=engagement)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf
    if jpkey.enable_engagement_epic_mapping and push_to_jira:
        issue_dict = {
            'project': {'key': jpkey.project_key},
            'summary': engagement.name,
            'description' : engagement.name,
            'issuetype': {'name': 'Epic'},
            'customfield_' + str(jira_conf.epic_name_id) : engagement.name,
            }
        jira = JIRA(server=jira_conf.url, basic_auth=(jira_conf.username, jira_conf.password))
        new_issue = jira.create_issue(fields=issue_dict)
        j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue, engagement=engagement)
        j_issue.save()
Example #7
0
def add_epic(eng, push_to_jira):
    engagement = eng
    prod = Product.objects.get(engagement=engagement)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf
    if jpkey.enable_engagement_epic_mapping and push_to_jira:
        issue_dict = {
            'project': {'key': jpkey.project_key},
            'summary': engagement.name,
            'description' : engagement.name,
            'issuetype': {'name': 'Epic'},
            'customfield_' + str(jira_conf.epic_name_id) : engagement.name,
            }
        jira = JIRA(server=jira_conf.url, basic_auth=(jira_conf.username, jira_conf.password))
        new_issue = jira.create_issue(fields=issue_dict)
        j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue, engagement=engagement)
        j_issue.save()
Example #8
0
def add_issue(find, push_to_jira):
    eng = Engagement.objects.get(test=find.test)
    prod =  Product.objects.get(engagement= eng)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf

    if push_to_jira:
        if 'Active' in find.status() and 'Verified' in find.status():
            try:
                JIRAError.log_to_tempfile=False
                jira = JIRA(server=jira_conf.url, basic_auth=(jira_conf.username, jira_conf.password))
                if jpkey.component:
                    new_issue = jira.create_issue(project=jpkey.project_key, summary=find.title,
                                                  components=[{'name': jpkey.component}, ],
                                                  description=jira_long_description(find.long_desc(), find.id,
                                                                                    jira_conf.finding_text),
                                                  issuetype={'name': jira_conf.default_issue_type},
                                                  priority={'name': jira_conf.get_priority(find.severity)})
                else:
                    new_issue = jira.create_issue(project=jpkey.project_key, summary=find.title,
                                                  description=jira_long_description(find.long_desc(), find.id,
                                                                                    jira_conf.finding_text),
                                                  issuetype={'name': jira_conf.default_issue_type},
                                                  priority={'name': jira_conf.get_priority(find.severity)})
                j_issue = JIRA_Issue(jira_id=new_issue.id, jira_key=new_issue, finding=find)
                j_issue.save()
                issue = jira.issue(new_issue.id)

                #Add labels (security & product)
                add_labels(find, new_issue)
                #Upload dojo finding screenshots to Jira
                for pic in find.images.all():
                    jira_attachment(jira, issue, settings.MEDIA_ROOT + pic.image_large.name)

                    #if jpkey.enable_engagement_epic_mapping:
                    #      epic = JIRA_Issue.objects.get(engagement=eng)
                    #      issue_list = [j_issue.jira_id,]
                    #      jira.add_issues_to_epic(epic_id=epic.jira_id, issue_keys=[str(j_issue.jira_id)], ignore_epics=True)
            except JIRAError as e:
                log_jira_alert(e.text, find)
        else:
            log_jira_alert("Finding not active or verified.", find)
Example #9
0
def add_issue(find, push_to_jira):
    eng = Engagement.objects.get(test=find.test)
    prod = Product.objects.get(engagement=eng)
    jpkey = JIRA_PKey.objects.get(product=prod)
    jira_conf = jpkey.conf
    if push_to_jira:
        if 'Active' in find.status() and 'Verified' in find.status():
            jira = JIRA(server=jira_conf.url,
                        basic_auth=(jira_conf.username, jira_conf.password))
            new_issue = jira.create_issue(
                project=jpkey.project_key,
                summary=find.title,
                description=jira_long_description(find.long_desc(), find.id,
                                                  jira_conf.finding_text),
                issuetype={'name': jira_conf.default_issue_type},
                priority={'name': jira_conf.get_priority(find.severity)})
            j_issue = JIRA_Issue(jira_id=new_issue.id,
                                 jira_key=new_issue,
                                 finding=find)
            j_issue.save()
            issue = jira.issue(new_issue.id)
            #Add labels (security & product)
            add_labels(find, new_issue)
Example #10
0
def add_jira_issue(find):
    logger.info('trying to create a new jira issue for %d:%s', find.id,
                find.title)

    if not is_jira_enabled():
        return False

    if not is_jira_configured_and_enabled(find):
        logger.error(
            "Finding {} cannot be pushed to JIRA as there is no JIRA configuration for this product."
            .format(find.id))
        log_jira_alert(
            'Finding cannot be pushed to JIRA as there is no JIRA configuration for this product.',
            find)
        return False

    jira_project = get_jira_project(find)
    jira_instance = get_jira_instance(find)

    can_be_pushed_to_jira, error_message, error_code = finding_can_be_pushed_to_jira(
        find)
    if not can_be_pushed_to_jira:
        log_jira_alert(error_message, find)
        logger.warn("Finding %s cannot be pushed to JIRA: %s.", find.id,
                    error_message)
        logger.warn("The JIRA issue will NOT be created.")
        return False
    logger.debug('Trying to create a new JIRA issue for finding {}...'.format(
        find.id))
    meta = None
    try:
        JIRAError.log_to_tempfile = False
        jira = get_jira_connection(jira_instance)

        fields = {
            'project': {
                'key': jira_project.project_key
            },
            'summary': find.title,
            'description': jira_description(find),
            'issuetype': {
                'name': jira_instance.default_issue_type
            }
        }

        #CUSTOM HS Code
        fields['customfield_11542'] = [{"value": find.customfield_11542}]

        if jira_project.component:
            fields['components'] = [
                {
                    'name': jira_project.component
                },
            ]

        # populate duedate field, but only if it's available for this project + issuetype
        if not meta:
            meta = get_jira_meta(jira, jira_project)

        epic_name_field = get_epic_name_field_name(jira_instance)
        if epic_name_field in meta['projects'][0]['issuetypes'][0]['fields']:
            # epic name is present in this issuetype
            # epic name is always mandatory in jira, so we populate it
            fields[epic_name_field] = fields['summary']

        if 'priority' in meta['projects'][0]['issuetypes'][0]['fields']:
            fields['priority'] = {
                'name': jira_instance.get_priority(find.severity)
            }

        labels = get_labels(find)
        if labels:
            if 'labels' in meta['projects'][0]['issuetypes'][0]['fields']:
                fields['labels'] = labels

        if System_Settings.objects.get().enable_finding_sla:

            if 'duedate' in meta['projects'][0]['issuetypes'][0]['fields']:
                # jira wants YYYY-MM-DD
                duedate = find.sla_deadline()
                if duedate:
                    fields['duedate'] = duedate.strftime('%Y-%m-%d')

        if len(find.endpoints.all()) > 0:
            if not meta:
                meta = get_jira_meta(jira, jira_project)

            if 'environment' in meta['projects'][0]['issuetypes'][0]['fields']:
                environment = "\n".join(
                    [str(endpoint) for endpoint in find.endpoints.all()])
                fields['environment'] = environment

        logger.debug('sending fields to JIRA: %s', fields)

        new_issue = jira.create_issue(fields)

        j_issue = JIRA_Issue(jira_id=new_issue.id,
                             jira_key=new_issue.key,
                             finding=find,
                             jira_project=jira_project)
        j_issue.jira_creation = timezone.now()
        j_issue.jira_change = timezone.now()
        j_issue.save()
        issue = jira.issue(new_issue.id)

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

        # Upload dojo finding screenshots to Jira
        for pic in find.images.all():
            jira_attachment(find, jira, issue,
                            settings.MEDIA_ROOT + pic.image_large.name)

        if jira_project.enable_engagement_epic_mapping:
            eng = find.test.engagement
            logger.debug('Adding to EPIC Map: %s', eng.name)
            epic = get_jira_issue(eng)
            if epic:
                jira.add_issues_to_epic(epic_id=epic.jira_id,
                                        issue_keys=[str(j_issue.jira_id)],
                                        ignore_epics=True)
            else:
                logger.info('The following EPIC does not exist: %s', eng.name)

        logger.info('Created the following jira issue for %d:%s', find.id,
                    find.title)
        return True
    except JIRAError as e:
        logger.exception(e)
        logger.error("jira_meta for project: %s and url: %s meta: %s",
                     jira_project.project_key, jira_project.jira_instance.url,
                     json.dumps(meta, indent=4))  # this is None safe
        log_jira_alert(e.text, find)
        return False
Example #11
0
def add_jira_issue(find):
    logger.info('trying to create a new jira issue for %d:%s', find.id,
                find.title)

    if not is_jira_enabled():
        return

    if not is_jira_configured_and_enabled(find):
        logger.error(
            "Finding {} cannot be pushed to JIRA as there is no JIRA configuration for this product."
            .format(find.id))
        log_jira_alert(
            'Finding cannot be pushed to JIRA as there is no JIRA configuration for this product.',
            find)
        return

    jira_minimum_threshold = None
    if System_Settings.objects.get().jira_minimum_severity:
        jira_minimum_threshold = Finding.get_number_severity(
            System_Settings.objects.get().jira_minimum_severity)

    jira_project = get_jira_project(find)
    jira_instance = get_jira_instance(find)

    if 'Active' in find.status() and 'Verified' in find.status():
        if jira_minimum_threshold and jira_minimum_threshold > Finding.get_number_severity(
                find.severity):
            log_jira_alert(
                'Finding below the minimum JIRA severity threshold.', find)
            logger.warn(
                "Finding {} is below the minimum JIRA severity threshold.".
                format(find.id))
            logger.warn("The JIRA issue will NOT be created.")
            return

        logger.debug(
            'Trying to create a new JIRA issue for finding {}...'.format(
                find.id))
        meta = None
        try:
            JIRAError.log_to_tempfile = False
            jira = get_jira_connection(jira_instance)

            fields = {
                'project': {
                    'key': jira_project.project_key
                },
                'summary': find.title,
                'description': jira_description(find),
                'issuetype': {
                    'name': jira_instance.default_issue_type
                },
            }

            if jira_project.component:
                fields['components'] = [
                    {
                        'name': jira_project.component
                    },
                ]

            # populate duedate field, but only if it's available for this project + issuetype
            if not meta:
                meta = get_jira_meta(jira, jira_project)

            if 'priority' in meta['projects'][0]['issuetypes'][0]['fields']:
                fields['priority'] = {
                    'name': jira_instance.get_priority(find.severity)
                }

            labels = get_labels(find)
            if labels:
                if 'labels' in meta['projects'][0]['issuetypes'][0]['fields']:
                    fields['labels'] = labels

            if System_Settings.objects.get().enable_finding_sla:

                if 'duedate' in meta['projects'][0]['issuetypes'][0]['fields']:
                    # jira wants YYYY-MM-DD
                    duedate = find.sla_deadline()
                    if duedate:
                        fields['duedate'] = duedate.strftime('%Y-%m-%d')

            if len(find.endpoints.all()) > 0:
                if not meta:
                    meta = get_jira_meta(jira, jira_project)

                if 'environment' in meta['projects'][0]['issuetypes'][0][
                        'fields']:
                    environment = "\n".join(
                        [str(endpoint) for endpoint in find.endpoints.all()])
                    fields['environment'] = environment

            logger.debug('sending fields to JIRA: %s', fields)

            new_issue = jira.create_issue(fields)

            j_issue = JIRA_Issue(jira_id=new_issue.id,
                                 jira_key=new_issue.key,
                                 finding=find,
                                 jira_project=jira_project)
            j_issue.jira_creation = timezone.now()
            j_issue.jira_change = timezone.now()
            j_issue.save()
            issue = jira.issue(new_issue.id)

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

            # Upload dojo finding screenshots to Jira
            for pic in find.images.all():
                jira_attachment(find, jira, issue,
                                settings.MEDIA_ROOT + pic.image_large.name)

                # if jira_project.enable_engagement_epic_mapping:
                #      epic = get_jira_issue(eng)
                #      issue_list = [j_issue.jira_id,]
                #      jira.add_jira_issues_to_epic(epic_id=epic.jira_id, issue_keys=[str(j_issue.jira_id)], ignore_epics=True)

            return True
        except JIRAError as e:
            logger.exception(e)
            logger.error("jira_meta for project: %s and url: %s meta: %s",
                         jira_project.project_key,
                         jira_project.jira_instance.url,
                         json.dumps(meta, indent=4))  # this is None safe
            log_jira_alert(e.text, find)
            return False
    else:
        log_jira_alert(
            "A Finding needs to be both Active and Verified to be pushed to JIRA.",
            find)
        logger.warning(
            "A Finding needs to be both Active and Verified to be pushed to JIRA: %s",
            find)
        return False