SonarQube Integration
Relevant source files
The following files were used as context for generating this wiki page:
The SonarQube integration feature in huskyCI is designed to format the results of various security scans into a single JSON file. This file adheres to the SonarQube Generic Issue Data format, allowing security vulnerabilities identified by huskyCI to be imported and displayed directly within a SonarQube dashboard. This provides development teams with a centralized view of security issues alongside their other code quality metrics.
This functionality is handled by the huskyCI client application after a security analysis is completed. The client processes the full analysis results, transforms them, and writes the output to a local file, typically huskyCI/sonarqube.json.
Sources: client/cmd/main.go:82-86, README.md
Client Execution Flow
The SonarQube report generation is one of the final steps in the huskyCI client's execution workflow. It occurs after the analysis has been monitored and the standard command-line output has been printed.
The following diagram illustrates the sequence of events in the main function of the client.
This diagram shows that sonarqube.GenerateOutputFile is called after the main analysis results are fetched and printed.
Sources: client/cmd/main.go:37-86
Report Generation Process
The core of the integration is the GenerateOutputFile function. This function is responsible for aggregating all vulnerabilities from different tools and converting them into the SonarQube format.
Sources: client/integration/sonarqube/sonarqube.go:21-120
Data Aggregation and Transformation
The process follows these steps:
- Aggregate Vulnerabilities: It collects all detected vulnerabilities (low, medium, and high severity) from every security tool's result set (e.g.,
gosec,bandit,safety,npmaudit) into a single slice oftypes.HuskyCIVulnerability. - Iterate and Transform: The function iterates through the aggregated list of vulnerabilities. Each
HuskyCIVulnerabilityis transformed into aSonarIssuestruct. - Map Data: During the transformation, huskyCI-specific fields are mapped to SonarQube-compatible fields. This includes severity levels, vulnerability details, and location information.
- Generate JSON: The final list of
SonarIssueobjects is marshaled into a JSON string. - Write to File: The resulting JSON is written to the specified output file.
The data flow is visualized below:
Severity Mapping
huskyCI severity levels are translated into SonarQube severities according to a fixed mapping.
| huskyCI Severity | SonarQube Severity |
|---|---|
high | BLOCKER |
medium | MAJOR |
low | MINOR |
| (any other) | INFO |
This mapping is implemented in a switch statement:
// client/integration/sonarqube/sonarqube.go:90-99
switch strings.ToLower(vuln.Severity) {
case `low`:
issue.Severity = "MINOR"
case `medium`:
issue.Severity = "MAJOR"
case `high`:
issue.Severity = "BLOCKER"
default:
issue.Severity = "INFO"
}
Sources: client/integration/sonarqube/sonarqube.go:90-99
File Path Handling
The system includes special logic for handling file paths:
- Go Projects: For vulnerabilities found by
gosec, the container's internal path prefix (/go/src/code/) is removed to ensure the file path is relative to the project root. - Dependency Vulnerabilities: For vulnerabilities that are not tied to a specific source file (e.g., vulnerable dependencies found by
safetyornpmaudit), a placeholder file is created.- File Name:
huskyCI_Placeholder_File - Path: The file is created in the specified
outputPath(e.g.,./huskyCI/). - Content: The file contains a standard message explaining that the vulnerability is not associated with a specific file.
- File Name:
// client/integration/sonarqube/sonarqube.go:101-107
if vuln.File == "" {
err := util.CreateFile([]byte(placeholderFileText), outputPath, placeholderFileName)
if err != nil {
return err
}
issue.PrimaryLocation.FilePath = filepath.Join(outputPath, placeholderFileName)
} else {
Sources: client/integration/sonarqube/sonarqube.go:101-115, client/integration/sonarqube/testdata/sonarqube/vulnerable_js_output.json:1
Data Structures
The SonarQube report format is defined by a set of Go structs in client/integration/sonarqube/types.go. These structs are designed to be marshaled into the JSON format expected by SonarQube.
The diagram above shows the relationship between the main data structures for the SonarQube output.
Sources: client/integration/sonarqube/types.go:9-32
Key Data Structures
| Struct | Field | Type | Description |
|---|---|---|---|
HuskyCISonarOutput | Issues | []SonarIssue | A slice containing all the vulnerability issues to be reported. |
SonarIssue | EngineID | string | Hardcoded to "huskyCI". Identifies the tool that raised the issue. |
RuleID | string | A unique identifier for the rule, constructed as Language - SecurityTool (e.g., "Python - Bandit"). | |
PrimaryLocation | SonarLocation | The primary location of the issue. | |
Type | string | Hardcoded to "VULNERABILITY". | |
Severity | string | The mapped severity (BLOCKER, MAJOR, MINOR, INFO). | |
SonarLocation | Message | string | The vulnerability details message. |
FilePath | string | The path to the affected file. | |
TextRange | SonarTextRange | Specifies the line number where the issue was found. | |
SonarTextRange | StartLine | int | The line number of the issue. Defaults to 1 if not available. |
Sources: client/integration/sonarqube/types.go:9-32, client/integration/sonarqube/sonarqube.go:86-119
Summary
The SonarQube integration provides a crucial link between huskyCI's security analysis capabilities and the widely-used SonarQube platform. By translating diverse vulnerability data into a standardized generic issue format, it enables teams to manage security findings within their existing code quality workflows, promoting better visibility and faster remediation of security risks. The process is fully automated within the huskyCI client, running after each analysis and producing a ready-to-import sonarqube.json file.
Sources: client/cmd/main.go:82-86, client/integration/sonarqube/sonarqube.go