Ejemplo n.º 1
0
def new_tool_config(request):
    if request.method == 'POST':
        tform = ToolConfigForm(request.POST)
        if tform.is_valid():
            form_copy = tform.save(commit=False)
            try:
                tool_type_qs = Tool_Type.objects.filter(name='SonarQube')
                if form_copy.tool_type in tool_type_qs:
                    sq = SonarQubeAPI(form_copy)
                    project_count = sq.test_connection()  # if connection is not successful, this call raise exception
                    messages.add_message(request,
                                         messages.SUCCESS,
                                         'SonarQube connection successful. You have access to {} projects'.format(project_count),
                                         extra_tags='alert-success')
                form_copy.save()
                messages.add_message(request,
                                     messages.SUCCESS,
                                     'Tool Configuration Successfully Updated.',
                                     extra_tags='alert-success')
                return HttpResponseRedirect(reverse('tool_config', ))
            except Exception as e:
                messages.add_message(request,
                                     messages.ERROR,
                                     str(e),
                                     extra_tags='alert-danger')
    else:
        tform = ToolConfigForm()
        add_breadcrumb(title="New Tool Configuration", top_level=False, request=request)
    return render(request, 'dojo/new_tool_config.html',
                  {'tform': tform})
Ejemplo n.º 2
0
def edit_tool_config(request, ttid):
    tool_config = Tool_Configuration.objects.get(pk=ttid)
    if request.method == 'POST':
        tform = ToolConfigForm(request.POST, instance=tool_config)
        if tform.is_valid():
            form_copy = tform.save(commit=False)
            form_copy.password = dojo_crypto_encrypt(
                tform.cleaned_data['password'])
            form_copy.ssh = dojo_crypto_encrypt(tform.cleaned_data['ssh'])
            try:
                tool_type_qs_sonarqube = Tool_Type.objects.filter(
                    name='SonarQube')
                if form_copy.tool_type in tool_type_qs_sonarqube:
                    sq = SonarQubeAPI(form_copy)
                    project_count = sq.test_connection(
                    )  # if connection is not successful, this call raise exception
                    messages.add_message(
                        request,
                        messages.SUCCESS,
                        'SonarQube connection successful. You have access to {} projects'
                        .format(project_count),
                        extra_tags='alert-success')
                tool_type_qs_cobaltio = Tool_Type.objects.filter(
                    name='Cobalt.io')
                if form_copy.tool_type in tool_type_qs_cobaltio:
                    cobalt = CobaltAPI(form_copy)
                    org = cobalt.test_connection(
                    )  # if connection is not successful, this call raise exception
                    messages.add_message(
                        request,
                        messages.SUCCESS,
                        'Cobalt.io connection successful. You have access to the "{}" org'
                        .format(org["resource"]["name"]),
                        extra_tags='alert-success')
                form_copy.save()
                messages.add_message(
                    request,
                    messages.SUCCESS,
                    'Tool Configuration Successfully Updated.',
                    extra_tags='alert-success')
                return HttpResponseRedirect(reverse('tool_config', ))
            except Exception as e:
                messages.add_message(request,
                                     messages.ERROR,
                                     str(e),
                                     extra_tags='alert-danger')
    else:
        tool_config.password = prepare_for_view(tool_config.password)
        tool_config.ssh = prepare_for_view(tool_config.ssh)
        tform = ToolConfigForm(instance=tool_config)
    add_breadcrumb(title="Edit Tool Configuration",
                   top_level=False,
                   request=request)

    return render(request, 'dojo/edit_tool_config.html', {
        'tform': tform,
    })
Ejemplo n.º 3
0
    def prepare_client(test):
        product = test.engagement.product
        if test.api_scan_configuration:
            config = test.api_scan_configuration  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 7 and 8
            # Double check of config
            if config.product != product:
                raise ValidationError(
                    'Product API Scan Configuration and Product do not match.')
        else:
            sqqs = product.product_api_scan_configuration_set.filter(
                product=product,
                tool_configuration__tool_type__name='SonarQube')
            if sqqs.count(
            ) == 1:  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 4
                config = sqqs.first()
            elif sqqs.count(
            ) > 1:  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 6
                raise ValidationError(
                    'More than one Product API Scan Configuration has been configured, but none of them has been chosen. Please specify which one should be used.'
                )
            else:  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 cases no. 1-3
                config = None

        return SonarQubeAPI(
            tool_config=config.tool_configuration if config else None), config
Ejemplo n.º 4
0
    def update_sonarqube_finding(self, finding):

        sonarqube_issue = finding.sonarqube_issue
        if not sonarqube_issue:
            return

        logger.debug(
            "Checking if finding '{}' needs to be updated in SonarQube".format(
                finding))

        product = finding.test.engagement.product
        config = product.sonarqube_product_set.all().first()
        client = SonarQubeAPI(
            tool_config=config.sonarqube_tool_config if config else None)

        target_status = self.get_sonarqube_status_for(finding)

        issue = client.get_issue(sonarqube_issue.key)
        if issue.get('resolution'):
            current_status = '{} / {}'.format(issue.get('status'),
                                              issue.get('resolution'))
        else:
            current_status = issue.get('status')

        logger.debug(
            "--> SQ Current status: {}. Current target status: {}".format(
                current_status, target_status))

        transitions = self.get_sonarqube_required_transitions_for(
            current_status, target_status)
        if transitions:
            logger.info("Updating finding '{}' in SonarQube".format(finding))

            for transition in transitions:
                client.transition_issue(sonarqube_issue.key, transition)

            # Track Defect Dojo has updated the SonarQube issue
            Sonarqube_Issue_Transition.objects.create(
                sonarqube_issue=finding.sonarqube_issue,
                # not sure if this is needed, but looks like the original author decided to send display status to sonarcube
                # we changed Accepted into Risk Accepted, but we change it back to be sure we don't break the integration
                finding_status=finding.status().replace(
                    'Risk Accepted', 'Accepted')
                if finding.status() else finding.status(),
                sonarqube_status=current_status,
                transitions=','.join(transitions),
            )
Ejemplo n.º 5
0
    def update_sonarqube_finding(self, finding):

        sonarqube_issue = finding.sonarqube_issue
        if not sonarqube_issue:
            return

        logger.debug("Checking if finding '{}' needs to be updated in SonarQube".format(finding))

        product = finding.test.engagement.product
        config = product.sonarqube_product_set.all().first()
        client = SonarQubeAPI(
            tool_config=config.sonarqube_tool_config if config else None
        )

        target_status = self.get_sonarqube_status_for(finding)

        issue = client.get_issue(sonarqube_issue.key)
        if issue.get('resolution'):
            current_status = '{} / {}'.format(issue.get('status'), issue.get('resolution'))
        else:
            current_status = issue.get('status')

        logger.debug("--> SQ Current status: {}. Current target status: {}".format(current_status, target_status))

        transitions = self.get_sonarqube_required_transitions_for(current_status, target_status)
        if transitions:
            logger.info("Updating finding '{}' in SonarQube".format(finding))

            for transition in transitions:
                client.transition_issue(sonarqube_issue.key, transition)

            # Track Defect Dojo has updated the SonarQube issue
            Sonarqube_Issue_Transition.objects.create(
                sonarqube_issue=finding.sonarqube_issue,
                finding_status=finding.status(),
                sonarqube_status=current_status,
                transitions=','.join(transitions),
            )
Ejemplo n.º 6
0
    def update(self, finding):
        sonarqube_issue = finding.sonarqube_issue
        if not sonarqube_issue:
            return

        product = finding.test.engagement.product
        config = product.sonarqube_product_set.all().first()

        client = SonarQubeAPI(
            tool_config=config.sonarqube_tool_config if config else None)
        issue = client.get_issue(sonarqube_issue.key)
        if issue:  # Issue could have disappeared in SQ because a previous scan has resolved the issue as fixed
            current_status = issue.get('resolution') or issue.get('status')
            current_finding_status = self.get_sonarqube_status_for(finding)
            logger.debug(
                "--> SQ Current status: {}. Finding status: {}".format(
                    current_status, current_finding_status))

            if current_status != "OPEN" and current_finding_status != current_status:
                logger.info(
                    "Original SonarQube issue '{}' has changed. Updating DefectDojo finding '{}'..."
                    .format(sonarqube_issue, finding))
                self.update_finding_status(finding, current_status)
Ejemplo n.º 7
0
    def prepare_client(test):
        product = test.engagement.product
        if test.sonarqube_config:
            config = test.sonarqube_config  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 7 and 8
            # Double check of config
            if config.product != product:
                raise Exception(
                    'Product SonarQube Configuration and "Product" mismatch')
        else:
            sqqs = product.sonarqube_product_set.filter(product=product)
            if sqqs.count(
            ) == 1:  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 4
                config = sqqs.first()
            elif sqqs.count(
            ) > 1:  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 case no. 6
                raise Exception(
                    'It has configured more than one Product SonarQube Configuration but non of them has been choosen.\n'
                    'Please specify at Test which one should be used.')
            else:  # https://github.com/DefectDojo/django-DefectDojo/pull/4676 cases no. 1-3
                config = None

        return SonarQubeAPI(tool_config=config.
                            sonarqube_tool_config if config else None), config
Ejemplo n.º 8
0
    def import_issues(self, test):

        items = list()

        try:
            product = test.engagement.product
            config = product.sonarqube_product_set.all().first()

            client = SonarQubeAPI(
                tool_config=config.sonarqube_tool_config if config else None)

            if config and config.sonarqube_project_key:
                component = client.get_project(config.sonarqube_project_key)
            else:
                component = client.find_project(product.name)

            issues = client.find_issues(component['key'])
            logging.info('Found {} issues for component {}'.format(
                len(issues), component["key"]))

            for issue in issues:
                status = issue['status']
                from_hotspot = issue.get('fromHotspot', False)

                if self.is_closed(status) or from_hotspot:
                    continue

                type = issue['type']
                title = issue['message']
                component_key = issue['component']
                line = issue.get('line')
                rule_id = issue['rule']
                rule = client.get_rule(rule_id)
                severity = self.convert_sonar_severity(rule['severity'])
                description = self.clean_rule_description_html(
                    rule['htmlDesc'])
                cwe = self.clean_cwe(rule['htmlDesc'])
                references = self.get_references(rule['htmlDesc'])

                sonarqube_issue, _ = Sonarqube_Issue.objects.update_or_create(
                    key=issue['key'],
                    defaults={
                        'status': status,
                        'type': type,
                    })

                # Only assign the SonarQube_issue to the first finding related to the issue
                if Finding.objects.filter(
                        sonarqube_issue=sonarqube_issue).exists():
                    sonarqube_issue = None

                find = Finding(
                    title=title,
                    cwe=cwe,
                    description=description,
                    test=test,
                    severity=severity,
                    references=references,
                    file_path=component_key,
                    line=line,
                    active=True,
                    verified=self.is_confirmed(status),
                    false_p=False,
                    duplicate=False,
                    out_of_scope=False,
                    mitigated=None,
                    mitigation='No mitigation provided',
                    impact="No impact provided",
                    numerical_severity=Finding.get_numerical_severity(
                        severity),
                    static_finding=True,
                    sonarqube_issue=sonarqube_issue,
                )
                items.append(find)

        except Exception as e:
            logger.exception(e)
            create_notification(event='other',
                                title='SonarQube API import issue',
                                description=e,
                                icon='exclamation-triangle',
                                source='SonarQube API')

        return items