Skip to content

Instantly share code, notes, and snippets.

@joshua-quek-sonarsource
Created June 26, 2024 02:35
Show Gist options
  • Save joshua-quek-sonarsource/e1c3f8635876bd78fd8c22637ec52e1e to your computer and use it in GitHub Desktop.
Save joshua-quek-sonarsource/e1c3f8635876bd78fd8c22637ec52e1e to your computer and use it in GitHub Desktop.
Docker Scan & Results into SonarQube
#!/bin/bash
# Ensure that NodeJS is installed!
# remove some files if they exist
rm -rf .container_scan/trivy_scan_results.json
rm -rf .container_scan/sonarqube_import.json
# Build the Docker image
docker build -t my_docker_image .
# Run the Trivy scan on the Docker image
docker run --rm -v $(pwd):/app -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy --format json image my_docker_image > .container_scan/trivy_scan_results.json
# Run the jq command to convert the Trivy scan results to SonarQube format
node $(pwd)/scripts/sonar/trivy_transform.js
const fs = require('fs')
const path = require('path')
// Load the Trivy scan results JSON
const inputFilePath = path.join(__dirname, './../../.container_scan/trivy_scan_results.json')
const outputFilePath = path.join(__dirname, './../../.container_scan/sonarqube_import.json')
const rawData = fs.readFileSync(inputFilePath, 'utf8')
const trivyData = JSON.parse(rawData)
// Function to handle optional fields safely
function getNested (obj, ...args) {
return args.reduce((obj, level) => obj && obj[level], obj) || 'N/A'
}
// Ensure the references array exists and is correctly formatted or provide a fallback
function formatReferences (refs) {
return Array.isArray(refs) ? refs.join('\n') : 'No references available'
}
// Transform function to convert Trivy data to SonarQube format
function transformTrivyToSonarQube (data) {
const rules = data.Results[0].Vulnerabilities.map(vul => ({
id: `${vul.VulnerabilityID}-${vul.PkgID}`,
name: vul.Title || 'No title available',
description: `${vul.Description}\n\nCVSS Details:\n- CVSS V2 Vector: ${getNested(vul, 'CVSS', 'nvd', 'V2Vector')}\n- CVSS V3 Vector: ${getNested(vul, 'CVSS', 'nvd', 'V3Vector')}\n- NVD V2 Score: ${getNested(vul, 'CVSS', 'nvd', 'V2Score')}\n- NVD V3 Score: ${getNested(vul, 'CVSS', 'nvd', 'V3Score')}\n\nReferences:\n${formatReferences(vul.References)} - NVD URL: ${vul.PrimaryURL}`,
engineId: 'Trivy',
cleanCodeAttribute: 'CONVENTIONAL',
impacts: [{
softwareQuality: 'SECURITY',
severity: (() => {
switch (vul.Severity.toUpperCase()) {
case 'CRITICAL':
case 'BLOCKER':
case 'HIGH':
return 'HIGH'
case 'MEDIUM':
case 'LOW':
return 'MEDIUM'
default:
return 'MEDIUM'
}
})()
}]
}))
const issues = data.Results[0].Vulnerabilities.map(vul => ({
ruleId: `${vul.VulnerabilityID}-${vul.PkgID}`,
effortMinutes: 60,
primaryLocation: {
message: `${vul.Title} - NVD URL: ${vul.PrimaryURL}`,
// filePath: `Affected component: ${vul.PkgName} version ${vul.InstalledVersion}`,
filePath: 'server/start.js',
textRange: {
startLine: 1
}
},
secondaryLocations: [{
message: `NVD URL: ${vul.PrimaryURL}`,
// filePath: 'Refer to NVD for more information',
filePath: 'server/start.js',
textRange: {
startLine: 1
}
}]
}))
return {
rules,
issues
}
}
// Ensure the input data has a valid structure
const validTrivyData = Array.isArray(trivyData.Results) && trivyData.Results.length > 0
? trivyData
: {
Results: [{
Vulnerabilities: []
}]
}
// Process the data
const sonarQubeData = transformTrivyToSonarQube(validTrivyData)
// Save the transformed data to a file
fs.writeFileSync(outputFilePath, JSON.stringify(sonarQubeData, null, 2), 'utf8')
console.log('Transformation complete. Data saved to:', outputFilePath)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment