Skip to content

fix(sonarqube): handle missing service_key_1 in test_product_connection#14412

Open
samiat4911 wants to merge 2 commits intoDefectDojo:devfrom
samiat4911:fix/sonarqube-optional-service-key
Open

fix(sonarqube): handle missing service_key_1 in test_product_connection#14412
samiat4911 wants to merge 2 commits intoDefectDojo:devfrom
samiat4911:fix/sonarqube-optional-service-key

Conversation

@samiat4911
Copy link

Description

This PR addresses a severe defect in the SonarQube API client where the connection test sequence crashes under specific UI configurations.

The Issue (Bug):
When a user attempts to configure a SonarQube API scan via the UI, the "Service key 1" parameter is presented as optional. However, if this field is left blank (passing None to the backend), the test_product_connection method within api_client.py blindly passes this None value to the SonarQube API's get_project method. Because the SonarQube API strictly requires the
component parameter for connection tests, it responds with a fatal 400 Bad Request error:
{"errors":[{"msg":"The 'component' parameter is missing"}]}

image

Root Cause & Architecture:
Upon reviewing the broader api_sonarqube module, it became evident that the data ingestion methods (import_issues and import_hotspots in importer.py) were architected correctly to handle this edge case. They implement a robust validation check: if service_key_1 is absent, they gracefully fall back to utilizing find_project(product.name). The test_product_connection method lacked parity with this design pattern, causing the failure during the initial configuration test sequence.

The Solution:
I have refactored the test_product_connection method to mirror the established fallback architecture found in the importer logic. The connection test now evaluates the presence of service_key_1; if present, it strictly queries by that key via get_project(). If absent, it safely falls back to a broad search utilizing find_project(product.name), completely resolving the 400 Bad Request condition.

Visual Evidence (Code Changes)

Before / After in api_client.py:

# -> BEFORE: Blindly passing the optional key
    def test_product_connection(self, api_scan_configuration):
        organization = api_scan_configuration.service_key_2 or None
        project = self.get_project(
            api_scan_configuration.service_key_1, organization=organization,
        )
        
# -> AFTER: Implementing robust validation and fallback pattern
    def test_product_connection(self, api_scan_configuration):
        organization = api_scan_configuration.service_key_2 or None
        if api_scan_configuration.service_key_1:
            project = self.get_project(
                api_scan_configuration.service_key_1, organization=organization,
            )
        else:
            project = self.find_project(
                api_scan_configuration.product.name, organization=organization,
            )

Test results

  • Static Analysis: Verified the refactored code block is fully compliant with flake8 and passes all local ruff linting processes.
  • Dynamic Verification (Standalone Test Suite): Constructed an isolated test sequence executing 11 edge-condition scenarios to guarantee the integrity of the fallback logic:
    • Validated proper resolution through get_project() when service_key_1 is fully hydrated.
    • Asserted flawless routing to find_project(product.name) when service_key_1 evaluates to None.
    • Asserted flawless routing to find_project(product.name) when service_key_1 resolves to an empty string ("").
    • Confirmed the organization parameter (service_key_2) is faithfully appended to the outbound request in all routing conditions.

Documentation

No documentation updates are necessary. This commit implements a behavioral patch to existing infrastructure without altering public interfaces or introducing novel capabilities.

Checklist

This checklist is for your information.

  • Make sure to rebase your PR against the very latest dev.
  • Features/Changes should be submitted against the dev.
  • Bugfixes should be submitted against the bugfix branch.
  • Give a meaningful name to your PR, as it may end up being used in the release notes.
  • Your code is flake8 compliant.
  • Your code is python 3.13 compliant.
  • If this is a new feature and not a bug fix, you've included the proper documentation in the docs at https://github.com/DefectDojo/django-DefectDojo/tree/dev/docs as part of this PR.
  • Model changes must include the necessary migrations in the dojo/db_migrations folder.
  • Add applicable tests to the unit tests.
  • Add the proper label to categorize your PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants