def add_non_finding(issue, options):
    """
    Adds a non-finding.
    """
    title = validate_report.capitalize(issue.title.strip())
    print_status('{0} - {1} - {2}'.format(issue.state, issue.labels, title),
                 options)
    non_finding_id = '{0}-{1}'.format(issue.iid, valid_filename(title))
    filename = 'non-findings/{0}.xml'.format(non_finding_id)
    non_finding = collections.OrderedDict()
    non_finding['title'] = title
    non_finding['p'] = unicode.replace(issue.description, '\r\n', '\n')
    for note in [x for x in issue.notes.list() if not x.system]:
        non_finding['p'] += unicode.replace(note.body, '\r\n', '\n')
    non_finding_xml = jxmlease.XMLDictNode(non_finding,
                                           tag='non-finding',
                                           xml_attrs={'id': non_finding_id})
    if options['dry_run']:
        print_line('[+] {0}'.format(filename))
        print(non_finding_xml.emit_xml())
    else:
        if os.path.isfile(filename) and not options['overwrite']:
            print_line(
                'Non-finding {0} already exists (use --overwrite to overwrite)'
                .format(filename))
        else:
            if options['y'] or ask_permission('Create file ' + filename):
                with open(filename, 'w') as xmlfile:
                    xmlfile.write(non_finding_xml.emit_xml().encode('utf-8'))
                print_line('[+] Created {0}'.format(filename))
def from_issue(issue):
    """Parse gitlab issue and return Finding, NonFinding or None."""
    if 'finding' in [x.lower() for x in issue.labels]:
        item = Finding()
        item.description = convert_text(issue.description)
        for note in [x for x in reversed(issue.notes.list()) if not x.system]:
            if len(note.body.splitlines()):
                if 'impact' in note.body.split()[0].lower():
                    item.impact = convert_text(''.join(
                        note.body.splitlines(True)[1:]))
                elif 'recommendation' in note.body.split()[0].lower():
                    item.recommendation = convert_text(''.join(
                        note.body.splitlines(True)[1:]))
                else:
                    item.technicaldescription += u'{0}\n'.format(
                        convert_text(note.body))
    elif 'non-finding' in [x.lower() for x in issue.labels]:
        item = NonFinding()
        item.content = convert_text(issue.description)
        for note in [x for x in reversed(issue.notes.list()) if not x.system]:
            item.content += convert_text(note.body) + '\n'
    else:
        return None
    item.title = validate_report.capitalize(issue.title.strip())
    item.identifier = 'f{0:02}-{1}'.format(issue.iid,
                                           valid_filename(item.title))
    return item
def add_finding(issue, options):
    """
    Writes issue as XML finding to file.
    """
    title = validate_report.capitalize(issue.title.strip())
    print_status('{0} - {1} - {2}'.format(issue.state, issue.labels, title),
                 options)
    threat_level = 'Moderate'
    finding_type = 'TODO'
    finding_id = '{0}-{1}'.format(issue.iid, valid_filename(title))
    filename = 'findings/{0}.xml'.format(finding_id)
    finding = collections.OrderedDict()
    finding['title'] = title
    finding['description'] = unicode.replace(issue.description, '\r\n', '\n')
    finding['technicaldescription'] = ''
    for note in [x for x in issue.notes.list() if not x.system]:
        finding['technicaldescription'] += unicode.replace(
            note.body, '\r\n', '\n')
    finding['impact'] = {}
    finding['impact']['p'] = 'TODO'
    finding['recommendation'] = {}
    finding['recommendation']['ul'] = {}
    finding['recommendation']['ul']['li'] = 'TODO'
    finding_xml = jxmlease.XMLDictNode(finding,
                                       tag='finding',
                                       xml_attrs={
                                           'id': finding_id,
                                           'threatLevel': threat_level,
                                           'type': finding_type
                                       })
    if options['dry_run']:
        print_line('[+] {0}'.format(filename))
        print(finding_xml.emit_xml())
    else:
        if os.path.isfile(filename) and not options['overwrite']:
            print_line(
                'Finding {0} already exists (use --overwrite to overwrite)'.
                format(filename))
        else:
            if options['y'] or ask_permission('Create file ' + filename):
                with open(filename, 'w') as xmlfile:
                    xmlfile.write(finding_xml.emit_xml().encode('utf-8'))
                print_line('[+] Created {0}'.format(filename))
def from_issue(issue):
    """Parse gitlab issue and return Finding, NonFinding or None."""
    if 'finding' in [x.lower() for x in issue.labels]:
        item = Finding()
        item.description = convert_text(issue.description)
        for note in [x for x in reversed(issue.notes.list()) if not x.system]:
            if len(note.body.splitlines()):
                if 'impact' in note.body.split()[0].lower():
                    item.impact = convert_text(''.join(note.body.splitlines(True)[1:]))
                elif 'recommendation' in note.body.split()[0].lower():
                    item.recommendation = convert_text(''.join(note.body.splitlines(True)[1:]))
                else:
                    item.technicaldescription += u'{0}\n'.format(convert_text(note.body))
    elif 'non-finding' in [x.lower() for x in issue.labels]:
        item = NonFinding()
        item.content = convert_text(issue.description)
        for note in [x for x in reversed(issue.notes.list()) if not x.system]:
            item.content += convert_text(note.body) + '\n'
    else:
        return None
    item.title = validate_report.capitalize(issue.title.strip())
    item.identifier = 'f{0:02}-{1}'.format(issue.iid, valid_filename(item.title))
    return item