Zum Inhalt

SonarQube Code Qualität und Sicherheit Plattform Cheat Blatt

_

Im Ü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.

ZEITSCHRIFTEN Anmerkung: Sonar Qube erfordert 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 ```_

Paket Manager Installation

```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 ```_

oder Grundkonfiguration

Sonar Konfiguration des Qube Servers

```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 ```_

oder Basisnutzung

Running 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 ```_

Quality Gates

```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" ```_

Sprache-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 DevOps

```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

Individuelle 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" ```_

Branch Analysis

```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." ```_

oder Best Practices

Quality Gate Configuration

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

Häufige Fragen

```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. *