Zum Inhalt

SonarQube Code Qualität und Sicherheit Plattform Cheat Blatt

generieren

Überblick

SonarQube ist eine umfassende Plattform zur kontinuierlichen Überprüfung von Codequalität und Sicherheit. Es führt automatische Bewertungen mit statischer Analyse von Code, um Fehler, Codegeruch und Sicherheitslücken über 25+ Programmiersprachen zu erkennen. Sonar Qube ist in DevSecOps-Pipelines für die Einhaltung von Code-Qualitätsstandards und die Identifizierung von Sicherheitsfragen früh im Entwicklungslebenszyklus unerlässlich.

ZEIT Note: SonarQube erfordert eine richtige Konfiguration und Regelanpassung für optimale Ergebnisse. Es sollte in CI/CD-Pipelines zur kontinuierlichen Überwachung integriert werden.

Installation

Docker Installation (empfohlen)

```bash

Pull SonarQube image

docker pull sonarqube:community

Run SonarQube with PostgreSQL

docker run -d --name sonarqube \ -p 9000:9000 \ -e SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonar \ -e SONAR_JDBC_USERNAME=sonar \ -e SONAR_JDBC_PASSWORD=sonar \ sonarqube:community

Using Docker Compose

cat > docker-compose.yml << 'EOF' version: "3" services: sonarqube: image: sonarqube:community depends_on: - db environment: SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar SONAR_JDBC_USERNAME: sonar SONAR_JDBC_PASSWORD: sonar ports: - "9000:9000" volumes: - sonarqube_data:/opt/sonarqube/data - sonarqube_extensions:/opt/sonarqube/extensions - sonarqube_logs:/opt/sonarqube/logs db: image: postgres:13 environment: POSTGRES_USER: sonar POSTGRES_PASSWORD: sonar POSTGRES_DB: sonar volumes: - postgresql:/var/lib/postgresql - postgresql_data:/var/lib/postgresql/data

volumes: sonarqube_data: sonarqube_extensions: sonarqube_logs: postgresql: postgresql_data: EOF

docker-compose up -d ```_

Manuelle Installation

```bash

Download SonarQube

wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-9.9.0.65466.zip unzip sonarqube-9.9.0.65466.zip cd sonarqube-9.9.0.65466

Configure database (PostgreSQL recommended)

Edit conf/sonar.properties

cat >> conf/sonar.properties << 'EOF' sonar.jdbc.username=sonar sonar.jdbc.password=sonar sonar.jdbc.url=jdbc:postgresql://localhost/sonar EOF

Start SonarQube

bin/linux-x86-64/sonar.sh start

Check status

bin/linux-x86-64/sonar.sh status ```_

SonarScanner Installation

```bash

Download SonarScanner

wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip unzip sonar-scanner-cli-4.8.0.2856-linux.zip sudo mv sonar-scanner-4.8.0.2856-linux /opt/sonar-scanner

Add to PATH

echo 'export PATH="/opt/sonar-scanner/bin:$PATH"' >> ~/.bashrc source ~/.bashrc

Verify installation

sonar-scanner --version ```_

Installation des Paketmanagers

```bash

Ubuntu/Debian

wget -qO - https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip

macOS with Homebrew

brew install sonar-scanner

Using npm

npm install -g sonarqube-scanner ```_

Grundkonfiguration

SonarQube Server Konfiguration

```properties

conf/sonar.properties

Database configuration

sonar.jdbc.username=sonar sonar.jdbc.password=sonar sonar.jdbc.url=jdbc:postgresql://localhost/sonar

Web server configuration

sonar.web.host=0.0.0.0 sonar.web.port=9000 sonar.web.context=/sonar

Elasticsearch configuration

sonar.search.javaOpts=-Xmx512m -Xms512m -XX:MaxDirectMemorySize=256m

Security configuration

sonar.security.realm=LDAP sonar.authenticator.downcase=true

Quality gate configuration

sonar.qualitygate.wait=true ```_

Projektkonfiguration (sonar-project.properties)

```properties

sonar-project.properties

Project identification

sonar.projectKey=my-project sonar.projectName=My Project sonar.projectVersion=1.0

Source code configuration

sonar.sources=src sonar.tests=tests sonar.sourceEncoding=UTF-8

Language-specific settings

sonar.java.source=11 sonar.java.target=11 sonar.java.binaries=target/classes sonar.java.libraries=target/dependency/*.jar

Exclusions

sonar.exclusions=/test/,/*.min.js,/vendor/ sonar.test.exclusions=/test/**

Coverage reports

sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml sonar.javascript.lcov.reportPaths=coverage/lcov.info ```_

Basisnutzung

Laufender SonarScanner

```bash

Basic scan

sonar-scanner

Scan with custom properties

sonar-scanner \ -Dsonar.projectKey=my-project \ -Dsonar.sources=. \ -Dsonar.host.url=http://localhost:9000 \ -Dsonar.login=your-token

Scan specific directory

sonar-scanner -Dsonar.sources=src/main/java

Scan with exclusions

sonar-scanner \ -Dsonar.exclusions="/test/,/*.min.js" \ -Dsonar.test.exclusions="/test/**"

Debug mode

sonar-scanner -X ```_

Authentication

```bash

Generate authentication token

curl -u admin:admin -X POST "http://localhost:9000/api/user_tokens/generate?name=my-token"

Use token in scan

sonar-scanner -Dsonar.login=your-generated-token

Use username/password (not recommended)

sonar-scanner -Dsonar.login=admin -Dsonar.password=admin ```_

Qualitätstore

```bash

Check quality gate status

curl -u token: "http://localhost:9000/api/qualitygates/project_status?projectKey=my-project"

Set quality gate for project

curl -u token: -X POST "http://localhost:9000/api/qualitygates/select?projectKey=my-project&gateId;=1"

Create custom quality gate

curl -u token: -X POST "http://localhost:9000/api/qualitygates/create?name=Custom+Gate" ```_

Sprach-spezifische Konfiguration

Java Projekte

```properties

Maven integration

sonar.java.source=11 sonar.java.target=11 sonar.java.binaries=target/classes sonar.java.libraries=target/dependency/.jar sonar.java.test.binaries=target/test-classes sonar.java.test.libraries=target/dependency/.jar sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml _xml

org.sonarsource.scanner.maven sonar-maven-plugin 3.9.1.2184 _bash

Maven scan

mvn clean verify sonar:sonar \ -Dsonar.projectKey=my-project \ -Dsonar.host.url=http://localhost:9000 \ -Dsonar.login=your-token ```_

JavaScript/TypScript Projekte

```properties

JavaScript configuration

sonar.sources=src sonar.tests=test sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.typescript.lcov.reportPaths=coverage/lcov.info sonar.exclusions=node_modules/,dist/,build/** _json // package.json script \\{ "scripts": \\{ "sonar": "sonar-scanner" \\} \\} ```_

Python Projekte

```properties

Python configuration

sonar.sources=src sonar.tests=tests sonar.python.coverage.reportPaths=coverage.xml sonar.python.xunit.reportPath=test-reports/xunit.xml ```_

C# Projekte

```properties

C# configuration

sonar.cs.dotcover.reportsPaths=dotCover.html sonar.cs.nunit.reportsPaths=TestResult.xml sonar.cs.opencover.reportsPaths=opencover.xml ```_

CI/CD Integration

GitHub Aktionen

```yaml

.github/workflows/sonarqube.yml

name: SonarQube Analysis

on: push: branches: [ main, develop ] pull_request: branches: [ main ]

jobs: sonarqube: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 0

- name: Set up JDK 11
  uses: actions/setup-java@v3
  with:
    java-version: '11'
    distribution: 'temurin'

- name: Cache SonarQube packages
  uses: actions/cache@v3
  with:
    path: ~/.sonar/cache
    key: $\\\\{\\\\{ runner.os \\\\}\\\\}-sonar
    restore-keys: $\\\\{\\\\{ runner.os \\\\}\\\\}-sonar

- name: Cache Maven packages
  uses: actions/cache@v3
  with:
    path: ~/.m2
    key: $\\\\{\\\\{ runner.os \\\\}\\\\}-m2-$\\\\{\\\\{ hashFiles('**/pom.xml') \\\\}\\\\}
    restore-keys: $\\\\{\\\\{ runner.os \\\\}\\\\}-m2

- name: Build and analyze
  env:
    GITHUB_TOKEN: $\\\\{\\\\{ secrets.GITHUB_TOKEN \\\\}\\\\}
    SONAR_TOKEN: $\\\\{\\\\{ secrets.SONAR_TOKEN \\\\}\\\\}
  run: mvn clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar

```_

GitLab CI

```yaml

.gitlab-ci.yml

stages: - test - sonarqube

sonarqube-check: stage: sonarqube image: maven:3.6.3-jdk-11 variables: SONAR_USER_HOME: "$\\{CI_PROJECT_DIR\\}/.sonar" GIT_DEPTH: "0" cache: key: "$\\{CI_JOB_NAME\\}" paths: - .sonar/cache script: - mvn verify sonar:sonar allow_failure: true only: - merge_requests - master - develop ```_

Jenkins Pipeline

```groovy // Jenkinsfile pipeline \\{ agent any

tools \\\\{
    maven 'Maven-3.6.3'
    jdk 'JDK-11'
\\\\}

environment \\\\{
    SONAR_TOKEN = credentials('sonar-token')
\\\\}

stages \\\\{
    stage('Checkout') \\\\{
        steps \\\\{
            checkout scm
        \\\\}
    \\\\}

    stage('Build') \\\\{
        steps \\\\{
            sh 'mvn clean compile'
        \\\\}
    \\\\}

    stage('Test') \\\\{
        steps \\\\{
            sh 'mvn test'
        \\\\}
        post \\\\{
            always \\\\{
                junit 'target/surefire-reports/*.xml'
            \\\\}
        \\\\}
    \\\\}

    stage('SonarQube Analysis') \\\\{
        steps \\\\{
            withSonarQubeEnv('SonarQube') \\\\{
                sh 'mvn sonar:sonar'
            \\\\}
        \\\\}
    \\\\}

    stage('Quality Gate') \\\\{
        steps \\\\{
            timeout(time: 1, unit: 'HOURS') \\\\{
                waitForQualityGate abortPipeline: true
            \\\\}
        \\\\}
    \\\\}
\\\\}

\\} ```_

Azure DevOs

```yaml

azure-pipelines.yml

trigger: - main

pool: vmImage: 'ubuntu-latest'

variables: MAVEN_CACHE_FOLDER: $(Pipeline.Workspace)/.m2/repository MAVEN_OPTS: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER)'

steps: - task: Cache@2 inputs: | key: 'maven | "$(Agent.OS)" | **/pom.xml' | restoreKeys: | maven|"$(Agent.OS)" maven path: $(MAVEN_CACHE_FOLDER) displayName: Cache Maven local repo

  • task: SonarQubePrepare@4 inputs: SonarQube: 'SonarQube' scannerMode: 'Other'

  • task: Maven@3 inputs: mavenPomFile: 'pom.xml' goals: 'clean verify' options: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER)' javaHomeOption: 'JDKVersion' jdkVersionOption: '1.11'

  • task: SonarQubeAnalyze@4

  • task: SonarQubePublish@4 inputs: pollingTimeoutSec: '300' ```_

Erweiterte Konfiguration

Kundenspezifische Regeln und Qualitätsprofile

```bash

Export quality profile

curl -u token: "http://localhost:9000/api/qualityprofiles/export?qualityProfile=MyProfile&language;=java" > my-profile.xml

Import quality profile

curl -u token: -X POST -F "backup=@my-profile.xml" "http://localhost:9000/api/qualityprofiles/restore"

Create custom rule

curl -u token: -X POST \ "http://localhost:9000/api/rules/create" \ -d "custom_key=my-custom-rule" \ -d "name=My Custom Rule" \ -d "markdown_description=This is my custom rule" \ -d "severity=MAJOR" \ -d "status=READY" \ -d "template_key=java:S124" ```_

Webhooks Konfiguration

```bash

Create webhook

curl -u token: -X POST \ "http://localhost:9000/api/webhooks/create" \ -d "name=MyWebhook" \ -d "url=https://my-server.com/webhook" \ -d "project=my-project"

Test webhook

curl -u token: -X POST \ "http://localhost:9000/api/webhooks/deliveries" \ -d "webhook=webhook-id" ```_

Messtechnik

```bash

Analyze main branch

sonar-scanner \ -Dsonar.projectKey=my-project \ -Dsonar.branch.name=main

Analyze feature branch

sonar-scanner \ -Dsonar.projectKey=my-project \ -Dsonar.branch.name=feature/new-feature \ -Dsonar.branch.target=main

Analyze pull request

sonar-scanner \ -Dsonar.projectKey=my-project \ -Dsonar.pullrequest.key=123 \ -Dsonar.pullrequest.branch=feature/new-feature \ -Dsonar.pullrequest.base=main ```_

Sicherheitsanalyse

Sicherheit Hotspots

```bash

Get security hotspots

curl -u token: "http://localhost:9000/api/hotspots/search?projectKey=my-project"

Change hotspot status

curl -u token: -X POST \ "http://localhost:9000/api/hotspots/change_status" \ -d "hotspot=hotspot-key" \ -d "status=REVIEWED" \ -d "resolution=SAFE"

Add comment to hotspot

curl -u token: -X POST \ "http://localhost:9000/api/hotspots/add_comment" \ -d "hotspot=hotspot-key" \ -d "comment=This has been reviewed and is safe" ```_

Sicherheitsregeln Konfiguration

```properties

Enable security rules

sonar.security.hotspots.enabled=true sonar.security.review.enabled=true

OWASP Top 10 categories

sonar.security.owasp-a1.enabled=true sonar.security.owasp-a2.enabled=true sonar.security.owasp-a3.enabled=true sonar.security.owasp-a4.enabled=true sonar.security.owasp-a5.enabled=true sonar.security.owasp-a6.enabled=true sonar.security.owasp-a7.enabled=true sonar.security.owasp-a8.enabled=true sonar.security.owasp-a9.enabled=true sonar.security.owasp-a10.enabled=true

SANS Top 25 categories

sonar.security.sans-top25.enabled=true ```_

Automatisierung und Schrift

Automatisierte Qualität Gate Check

```python

!/usr/bin/env python3

sonar_quality_gate.py

import requests import sys import time import argparse

class SonarQubeQualityGate: def init(self, server_url, token, project_key): self.server_url = server_url.rstrip('/') self.token = token self.project_key = project_key self.session = requests.Session() self.session.auth = (token, '')

def get_project_status(self):
    """Get project quality gate status"""
    url = f"\\\\{self.server_url\\\\}/api/qualitygates/project_status"
    params = \\\\{'projectKey': self.project_key\\\\}

    try:
        response = self.session.get(url, params=params)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        print(f"Error getting project status: \\\\{e\\\\}")
        return None

def wait_for_analysis(self, timeout=300, interval=10):
    """Wait for analysis to complete"""
    start_time = time.time()

    while time.time() - start_time < timeout:
        status = self.get_project_status()

        if status and 'projectStatus' in status:
            project_status = status['projectStatus']

            if project_status.get('status') != 'IN_PROGRESS':
                return status

            print(f"Analysis in progress... waiting \\\\{interval\\\\} seconds")
            time.sleep(interval)
        else:
            print("Could not get project status")
            time.sleep(interval)

    print(f"Timeout waiting for analysis to complete (\\\\{timeout\\\\}s)")
    return None

def check_quality_gate(self):
    """Check if quality gate passes"""
    status = self.get_project_status()

    if not status:
        return False, "Could not get project status"

    project_status = status.get('projectStatus', \\\\{\\\\})
    gate_status = project_status.get('status')

    if gate_status == 'OK':
        return True, "Quality gate passed"
    elif gate_status == 'ERROR':
        conditions = project_status.get('conditions', [])
        failed_conditions = [c for c in conditions if c.get('status') == 'ERROR']

        error_msg = "Quality gate failed:\n"
        for condition in failed_conditions:
            metric = condition.get('metricKey', 'Unknown')
            actual = condition.get('actualValue', 'N/A')
            threshold = condition.get('errorThreshold', 'N/A')
            error_msg += f"  - \\\\{metric\\\\}: \\\\{actual\\\\} (threshold: \\\\{threshold\\\\})\n"

        return False, error_msg
    else:
        return False, f"Unknown quality gate status: \\\\{gate_status\\\\}"

def get_metrics(self):
    """Get project metrics"""
    url = f"\\\\{self.server_url\\\\}/api/measures/component"
    params = \\\\{
        'component': self.project_key,
        'metricKeys': 'bugs,vulnerabilities,code_smells,coverage,duplicated_lines_density'
    \\\\}

    try:
        response = self.session.get(url, params=params)
        response.raise_for_status()
        data = response.json()

        metrics = \\\\{\\\\}
        for measure in data.get('component', \\\\{\\\\}).get('measures', []):
            metrics[measure['metric']] = measure.get('value', '0')

        return metrics
    except requests.RequestException as e:
        print(f"Error getting metrics: \\\\{e\\\\}")
        return \\\\{\\\\}

def print_summary(self):
    """Print analysis summary"""
    metrics = self.get_metrics()

    print("\n=== SonarQube Analysis Summary ===")
    print(f"Project: \\\\{self.project_key\\\\}")
    print(f"Bugs: \\\\{metrics.get('bugs', 'N/A')\\\\}")
    print(f"Vulnerabilities: \\\\{metrics.get('vulnerabilities', 'N/A')\\\\}")
    print(f"Code Smells: \\\\{metrics.get('code_smells', 'N/A')\\\\}")
    print(f"Coverage: \\\\{metrics.get('coverage', 'N/A')\\\\}%")
    print(f"Duplicated Lines: \\\\{metrics.get('duplicated_lines_density', 'N/A')\\\\}%")

def main(): parser = argparse.ArgumentParser(description='SonarQube Quality Gate Checker') parser.add_argument('--server', required=True, help='SonarQube server URL') parser.add_argument('--token', required=True, help='Authentication token') parser.add_argument('--project', required=True, help='Project key') parser.add_argument('--wait', action='store_true', help='Wait for analysis to complete') parser.add_argument('--timeout', type=int, default=300, help='Timeout in seconds')

args = parser.parse_args()

qg = SonarQubeQualityGate(args.server, args.token, args.project)

if args.wait:
    print("Waiting for analysis to complete...")
    status = qg.wait_for_analysis(timeout=args.timeout)
    if not status:
        print("Analysis did not complete within timeout")
        sys.exit(1)

qg.print_summary()

passed, message = qg.check_quality_gate()
print(f"\n\\\\{message\\\\}")

sys.exit(0 if passed else 1)

if name == 'main': main() ```_

Bulk Project Management

```bash

!/bin/bash

bulk_sonar_scan.sh

Configuration

SONAR_SERVER="http://localhost:9000" SONAR_TOKEN="your-token" PROJECTS_DIR="/path/to/projects" REPORTS_DIR="/path/to/reports"

Function to scan project

scan_project() \\{ local project_path="$1" local project_name=$(basename "$project_path")

echo "Scanning $project_name..."

cd "$project_path"

# Create sonar-project.properties if it doesn't exist
if [ ! -f "sonar-project.properties" ]; then
    cat > sonar-project.properties << EOF

sonar.projectKey=$project_name sonar.projectName=$project_name sonar.projectVersion=1.0 sonar.sources=. sonar.exclusions=/node_modules/,/target/,/build/,/.git/ EOF fi

# Run scan
sonar-scanner \
    -Dsonar.host.url="$SONAR_SERVER" \
    -Dsonar.login="$SONAR_TOKEN" \
    -Dsonar.projectKey="$project_name"

# Check quality gate
python3 sonar_quality_gate.py \
    --server "$SONAR_SERVER" \
    --token "$SONAR_TOKEN" \
    --project "$project_name" \
    --wait

if [ $? -ne 0 ]; then
    echo "$project_name" >> "$REPORTS_DIR/failed_quality_gates.txt"
fi

\\}

Create reports directory

mkdir -p "$REPORTS_DIR"

Scan all projects

find "$PROJECTS_DIR" -maxdepth 1 -type d|while read -r project_dir; do if [ "$project_dir" != "$PROJECTS_DIR" ]; then scan_project "$project_dir" fi done

echo "Bulk scanning completed. Check $REPORTS_DIR for results." ```_

Best Practices

Qualität Gate Konfiguration

json \\\\{ "name": "Strict Security Gate", "conditions": [ \\\\{ "metric": "new_vulnerabilities", "op": "GT", "error": "0" \\\\}, \\\\{ "metric": "new_bugs", "op": "GT", "error": "0" \\\\}, \\\\{ "metric": "new_security_hotspots_reviewed", "op": "LT", "error": "100" \\\\}, \\\\{ "metric": "new_coverage", "op": "LT", "error": "80" \\\\}, \\\\{ "metric": "new_duplicated_lines_density", "op": "GT", "error": "3" \\\\} ] \\\\}_

Projektorganisation

```properties

Multi-module project configuration

sonar.projectKey=my-company:my-project sonar.projectName=My Project sonar.projectVersion=1.0

Module configuration

sonar.modules=module1,module2,module3

module1.sonar.projectName=Module 1 module1.sonar.sources=module1/src module1.sonar.tests=module1/test

module2.sonar.projectName=Module 2 module2.sonar.sources=module2/src module2.sonar.tests=module2/test

module3.sonar.projectName=Module 3 module3.sonar.sources=module3/src module3.sonar.tests=module3/test ```_

Leistungsoptimierung

```properties

Performance tuning

sonar.scanner.metadataFilePath=.scannerwork/report-task.txt sonar.working.directory=.scannerwork sonar.scm.disabled=false sonar.scm.provider=git

Memory settings

sonar.scanner.javaOpts=-Xmx2048m -XX:MaxPermSize=256m

Parallel processing

sonar.scanner.dumpToFile=.scannerwork/scanner-report.json ```_

Fehlerbehebung

Gemeinsame Themen

```bash

Issue: Out of memory errors

Solution: Increase memory allocation

export SONAR_SCANNER_OPTS="-Xmx2048m"

Issue: Analysis taking too long

Solution: Exclude unnecessary files

sonar-scanner -Dsonar.exclusions="/node_modules/,/target/,/build/"

Issue: Quality gate webhook not working

Solution: Check webhook configuration and network connectivity

curl -X POST https://your-webhook-url.com/webhook -d '\\{"test": "data"\\}'

Issue: Branch analysis not working

Solution: Ensure proper branch configuration

sonar-scanner -Dsonar.branch.name=feature-branch -Dsonar.branch.target=main ```_

Debug Mode

```bash

Enable debug logging

sonar-scanner -X

Check scanner logs

tail -f .scannerwork/scanner-report.log

Verify server connectivity

curl -u token: "http://localhost:9000/api/system/status" ```_

Ressourcen

--

*Dieses Betrugsblatt bietet umfassende Anleitung für die Verwendung von SonarQube, um Codequalität und Sicherheit zu erhalten. Regelmäßige Überwachung und richtige Konfiguration sind für eine effektive DevSecOps-Integration unerlässlich. *