DevSecOps test #19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: DevSecOps Pipeline | ||
| on: | ||
| push: | ||
| branches: [ main ] | ||
| pull_request: | ||
| branches: [ main ] | ||
| workflow_dispatch: | ||
| # Required permissions for code scanning API and committing reports | ||
| permissions: | ||
| security-events: write | ||
| actions: read | ||
| contents: write # Upgraded from 'read' to 'write' to allow committing files | ||
| jobs: | ||
| secrets-scanning: | ||
| name: Secrets Scanning | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| # Create docs/reports directory if it doesn't exist | ||
| - name: Ensure docs/reports directory exists | ||
| run: mkdir -p ./docs/reports | ||
| - name: TruffleHog OSS | ||
| uses: trufflesecurity/trufflehog@main | ||
| with: | ||
| extra_args: --debug --json | ||
| # Generate TruffleHog report in docs/reports | ||
| - name: Generate TruffleHog report | ||
| run: | | ||
| echo "Running TruffleHog scan manually to save report" | ||
| docker run --rm -v $(pwd):/pwd trufflesecurity/trufflehog:latest github --repo file:///pwd --json > ./docs/reports/trufflehog-results.json || true | ||
| # Upload TruffleHog results as artifact | ||
| - name: Upload TruffleHog results | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: trufflehog-results | ||
| path: ./docs/reports/trufflehog-results.json | ||
| sast-scanning: | ||
| name: Static Application Security Testing (CodeQL) | ||
| runs-on: ubuntu-latest | ||
| needs: secrets-scanning | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| token: ${{ github.token }} | ||
| # Create docs/reports directory | ||
| - name: Ensure docs/reports directory exists | ||
| run: mkdir -p ./docs/reports | ||
| # Initialize CodeQL | ||
| - name: Initialize CodeQL | ||
| uses: github/codeql-action/init@v3 | ||
| with: | ||
| languages: javascript | ||
| queries: security-and-quality | ||
| # Autobuild (attempts to automatically build any compiled languages) | ||
| - name: Autobuild | ||
| uses: github/codeql-action/autobuild@v3 | ||
| # Run CodeQL Analysis - analyzes and produces SARIF file(s) | ||
| - name: Perform CodeQL Analysis | ||
| uses: github/codeql-action/analyze@v3 | ||
| with: | ||
| category: "javascript-analysis" | ||
| output: ./docs/reports | ||
| # Copy and consolidate results to docs/reports directory | ||
| - name: Process CodeQL SARIF results | ||
| run: | | ||
| echo "Listing CodeQL SARIF files in ./docs/reports:" | ||
| find ./docs/reports -type f -name "*.sarif" | sort | ||
| # Check if any SARIF files were generated | ||
| if [ -n "$(find ./docs/reports -type f -name '*.sarif')" ]; then | ||
| # Create a consolidated sarif file for DefectDojo | ||
| echo "Creating consolidated SARIF file for DefectDojo" | ||
| # Find the first SARIF file and make a copy for DefectDojo | ||
| FIRST_FILE=$(find ./docs/reports -type f -name "*.sarif" | head -1) | ||
| echo "Using file: $FIRST_FILE for consolidated results" | ||
| # Make sure the file exists and is not a directory | ||
| if [ -f "$FIRST_FILE" ]; then | ||
| cp "$FIRST_FILE" ./docs/reports/codeql-results.sarif | ||
| # Display info about the consolidated file | ||
| echo "Consolidated SARIF file created at ./docs/reports/codeql-results.sarif" | ||
| ls -la ./docs/reports/codeql-results.sarif | ||
| echo "First 20 lines of consolidated SARIF file:" | ||
| head -n 20 ./docs/reports/codeql-results.sarif | ||
| else | ||
| echo "Warning: Selected file is not a regular file. Creating placeholder instead." | ||
| echo '{ | ||
| "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", | ||
| "version": "2.1.0", | ||
| "runs": [ | ||
| { | ||
| "tool": { | ||
| "driver": { | ||
| "name": "CodeQL", | ||
| "version": "placeholder", | ||
| "rules": [] | ||
| } | ||
| }, | ||
| "results": [] | ||
| } | ||
| ] | ||
| }' > ./docs/reports/codeql-results.sarif | ||
| fi | ||
| else | ||
| echo "No CodeQL SARIF files found, creating placeholder" | ||
| echo '{ | ||
| "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", | ||
| "version": "2.1.0", | ||
| "runs": [ | ||
| { | ||
| "tool": { | ||
| "driver": { | ||
| "name": "CodeQL", | ||
| "version": "placeholder", | ||
| "rules": [] | ||
| } | ||
| }, | ||
| "results": [] | ||
| } | ||
| ] | ||
| }' > ./docs/reports/codeql-results.sarif | ||
| fi | ||
| # CodeQL automatically uploads results, so we don't need this step. | ||
| # We're only keeping the artifact upload for DefectDojo integration | ||
| # Save SARIF as artifact | ||
| - name: Upload SARIF as artifact | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: codeql-results | ||
| path: ./docs/reports/codeql-results.sarif | ||
| sca-scanning: | ||
| name: Software Composition Analysis | ||
| runs-on: ubuntu-latest | ||
| needs: sast-scanning | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| token: ${{ github.token }} | ||
| - name: Create reports directory | ||
| run: mkdir -p ./docs/reports | ||
| - name: OWASP Dependency-Check Scan - Backend | ||
| uses: dependency-check/Dependency-Check_Action@main | ||
| with: | ||
| project: 'Angular-XSS-Backend' | ||
| path: './xss/api' | ||
| format: 'SARIF' | ||
| out: './docs/reports' | ||
| args: >- | ||
| --suppression ./dependency-check-suppressions.xml | ||
| --failOnCVSS 11 | ||
| - name: OWASP Dependency-Check Scan - Frontend | ||
| uses: dependency-check/Dependency-Check_Action@main | ||
| with: | ||
| project: 'Angular-XSS-Frontend' | ||
| path: './xss/frontend' | ||
| format: 'SARIF' | ||
| out: './docs/reports' | ||
| args: >- | ||
| --suppression ./dependency-check-suppressions.xml | ||
| --failOnCVSS 11 | ||
| - name: Check SARIF files | ||
| run: | | ||
| echo "Checking if SARIF files exist in docs/reports directory" | ||
| if [ -d "./docs/reports" ]; then | ||
| ls -la ./docs/reports/ | ||
| echo "Found files in docs/reports directory" | ||
| sarifCount=$(find ./docs/reports -name "*.sarif" | wc -l) | ||
| if [ "$sarifCount" -gt 0 ]; then | ||
| find ./docs/reports -name "*.sarif" | while read file; do | ||
| echo "Found SARIF file: $file" | ||
| echo "File contents (first 20 lines):" | ||
| head -n 20 "$file" | ||
| done | ||
| else | ||
| echo "No SARIF files found in docs/reports directory. Creating placeholder." | ||
| echo '{ | ||
| "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", | ||
| "version": "2.1.0", | ||
| "runs": [ | ||
| { | ||
| "tool": { | ||
| "driver": { | ||
| "name": "OWASP Dependency-Check", | ||
| "version": "placeholder", | ||
| "rules": [] | ||
| } | ||
| }, | ||
| "results": [] | ||
| } | ||
| ] | ||
| }' > ./docs/reports/dependency-check-placeholder.sarif | ||
| fi | ||
| else | ||
| echo "Reports directory does not exist!" | ||
| mkdir -p ./docs/reports | ||
| echo '{ | ||
| "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", | ||
| "version": "2.1.0", | ||
| "runs": [ | ||
| { | ||
| "tool": { | ||
| "driver": { | ||
| "name": "OWASP Dependency-Check", | ||
| "version": "placeholder", | ||
| "rules": [] | ||
| } | ||
| }, | ||
| "results": [] | ||
| } | ||
| ] | ||
| }' > ./docs/reports/dependency-check-placeholder.sarif | ||
| fi | ||
| - name: Find SARIF files | ||
| id: find-sarif | ||
| run: | | ||
| # Find all SARIF files | ||
| echo "Finding SARIF files in ./docs/reports directory" | ||
| find ./docs/reports -name "*.sarif" -type f | ||
| # Check if we have any SARIF files | ||
| SARIF_COUNT=$(find ./docs/reports -name "*.sarif" -type f | wc -l) | ||
| if [ "$SARIF_COUNT" -eq 0 ]; then | ||
| echo "No SARIF files found, creating placeholder" | ||
| echo '{ | ||
| "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", | ||
| "version": "2.1.0", | ||
| "runs": [ | ||
| { | ||
| "tool": { | ||
| "driver": { | ||
| "name": "OWASP Dependency-Check", | ||
| "version": "placeholder", | ||
| "rules": [] | ||
| } | ||
| }, | ||
| "results": [] | ||
| } | ||
| ] | ||
| }' > ./docs/reports/dependency-check-placeholder.sarif | ||
| echo "primary_sarif=./docs/reports/dependency-check-placeholder.sarif" >> $GITHUB_OUTPUT | ||
| else | ||
| # Get the first SARIF file for primary upload | ||
| PRIMARY_SARIF=$(find ./docs/reports -name "*.sarif" -type f | head -1) | ||
| echo "Found primary SARIF file: $PRIMARY_SARIF" | ||
| echo "primary_sarif=$PRIMARY_SARIF" >> $GITHUB_OUTPUT | ||
| fi | ||
| # Upload primary SARIF file | ||
| - name: Upload primary SARIF file | ||
| uses: github/codeql-action/upload-sarif@v3 | ||
| if: always() | ||
| with: | ||
| sarif_file: ${{ steps.find-sarif.outputs.primary_sarif }} | ||
| category: dependency-check | ||
| # Upload any additional SARIF files individually | ||
| - name: Upload additional SARIF files | ||
| run: | | ||
| # Skip the first file as it was already uploaded | ||
| COUNT=0 | ||
| for sarif_file in $(find ./docs/reports -name "*.sarif" -type f); do | ||
| if [ $COUNT -gt 0 ]; then | ||
| echo "Uploading additional SARIF file: $sarif_file" | ||
| # Use the GitHub API to upload the SARIF file | ||
| UPLOAD_URL="https://api.github.com/repos/$GITHUB_REPOSITORY/code-scanning/sarifs" | ||
| curl -X POST \ | ||
| -H "Authorization: Bearer ${{ github.token }}" \ | ||
| -H "Accept: application/vnd.github.v3+json" \ | ||
| -H "Content-Type: application/json" \ | ||
| -d "{\"commit_sha\":\"$GITHUB_SHA\",\"ref\":\"$GITHUB_REF\",\"sarif\":\"$(base64 -w 0 $sarif_file)\",\"tool_name\":\"OWASP Dependency-Check (Additional)\"}" \ | ||
| $UPLOAD_URL || echo "Failed to upload additional SARIF file: $sarif_file" | ||
| fi | ||
| COUNT=$((COUNT + 1)) | ||
| done | ||
| continue-on-error: true | ||
| # Copy SARIF to artifact directory for persistent storage | ||
| - name: Upload SCA Results as Artifact | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: sca-results | ||
| path: ./docs/reports/ | ||
| sbom-generation: | ||
| name: Software Bill of Materials | ||
| runs-on: ubuntu-latest | ||
| needs: sca-scanning | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| # Create docs/reports directory if it doesn't exist | ||
| - name: Ensure docs/reports directory exists | ||
| run: mkdir -p ./docs/reports | ||
| - name: Generate SBOM with CycloneDX | ||
| uses: CycloneDX/gh-node-module-generatebom@master | ||
| with: | ||
| path: './xss' | ||
| output: './docs/reports/angular-xss-sbom.json' | ||
| - name: Upload SBOM as artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: angular-xss-sbom | ||
| path: './docs/reports/angular-xss-sbom.json' | ||
| dast-scanning: | ||
| name: Dynamic Application Security Testing | ||
| runs-on: ubuntu-latest | ||
| needs: sbom-generation | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| # Install necessary dependencies for ZAP scanning | ||
| - name: Install dependencies for ZAP | ||
| run: | | ||
| # Check if curl is installed | ||
| if ! command -v curl &> /dev/null; then | ||
| echo "Installing curl" | ||
| apt-get update && apt-get install -y curl | ||
| fi | ||
| # Install Docker Compose plugin if needed | ||
| - name: Set up Docker Compose | ||
| run: | | ||
| # Check if docker-compose is available | ||
| if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then | ||
| echo "Installing Docker Compose plugin" | ||
| # Install Docker Compose V2 | ||
| DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} | ||
| mkdir -p $DOCKER_CONFIG/cli-plugins | ||
| curl -SL https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose | ||
| chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose | ||
| fi | ||
| # Verify Docker and Docker Compose are installed | ||
| echo "Docker version:" | ||
| docker --version | ||
| echo "Docker Compose version:" | ||
| docker compose version || docker-compose --version || echo "Docker Compose not installed properly" | ||
| - name: Start Angular XSS application with Docker Compose | ||
| run: | | ||
| cd ./xss | ||
| # Try using docker compose command (v2) first, if it fails try docker-compose (v1) | ||
| echo "Starting containers with docker compose..." | ||
| docker compose build || docker-compose build || (echo "Docker Compose build failed" && exit 1) | ||
| docker compose up -d || docker-compose up -d || (echo "Docker Compose up failed" && exit 1) | ||
| # Wait for application to be ready | ||
| echo "Waiting for application to become available..." | ||
| sleep 60 | ||
| # Create docs/reports directory if it doesn't exist | ||
| - name: Ensure docs/reports directory exists | ||
| run: mkdir -p ./docs/reports | ||
| # Create and verify ZAP rules file for scanning | ||
| - name: Set up ZAP rules file | ||
| run: | | ||
| # Check if zap-rules.tsv exists in the repo | ||
| echo "Checking for ZAP rules files..." | ||
| echo "Current directory: $(pwd)" | ||
| ls -la | ||
| if [ -f "zap-rules.tsv" ]; then | ||
| echo "ZAP rules file already exists in the root directory" | ||
| elif [ -f "./angular-xss/zap-rules.tsv" ]; then | ||
| echo "Found ZAP rules in angular-xss directory, copying to root" | ||
| cp ./angular-xss/zap-rules.tsv ./ | ||
| else | ||
| echo "ZAP rules file not found, creating a basic one" | ||
| echo '10016 IGNORE http://localhost:4200 (IGNORE: A technology has been identified)' > zap-rules.tsv | ||
| echo '10020 IGNORE http://localhost:4200 (IGNORE: X-Frame-Options Header Not Set)' >> zap-rules.tsv | ||
| echo '10021 IGNORE http://localhost:4200 (IGNORE: X-Content-Type-Options Header Missing)' >> zap-rules.tsv | ||
| echo '10038 IGNORE http://localhost:4200 (IGNORE: Content Security Policy (CSP) Header Not Set)' >> zap-rules.tsv | ||
| echo '10049 IGNORE http://localhost:4200 (IGNORE: Non-Storable Content)' >> zap-rules.tsv | ||
| echo '40012 FAIL http://localhost:4200 (FAIL: Cross Site Scripting (Reflected))' >> zap-rules.tsv | ||
| fi | ||
| # Verify the rules file exists and show content | ||
| echo "Verifying ZAP rules file location and content:" | ||
| ls -la zap-rules.tsv | ||
| cat zap-rules.tsv | ||
| # Create a temporary directory with proper permissions for ZAP to write reports | ||
| - name: Create writable temp directory for ZAP | ||
| run: | | ||
| mkdir -p /tmp/zap-output | ||
| chmod 777 /tmp/zap-output | ||
| echo "Created writable directory for ZAP reports at /tmp/zap-output" | ||
| ls -la /tmp/zap-output | ||
| - name: ZAP Baseline Scan | ||
| uses: zaproxy/action-baseline@v0.11.0 | ||
| continue-on-error: true | ||
| with: | ||
| target: 'http://localhost:4200' | ||
| allow_issue_writing: true | ||
| # Use Docker's /tmp directory which should be writable | ||
| cmd_options: '-a -j -T 10 -w /tmp/zap-output/zap-baseline-report.md' | ||
| rules_file_name: 'zap-rules.tsv' | ||
| issue_title: 'ZAP Baseline Scan Report' | ||
| artifact_name: 'zap-baseline-report' | ||
| docker_name: 'ghcr.io/zaproxy/zaproxy:stable' | ||
| - name: ZAP Full Scan | ||
| uses: zaproxy/action-full-scan@v0.8.0 | ||
| continue-on-error: true | ||
| with: | ||
| target: 'http://localhost:4200' | ||
| allow_issue_writing: true | ||
| # Use Docker's /tmp directory which should be writable | ||
| cmd_options: '-a -j -T 10 -w /tmp/zap-output/zap-full-scan-report.md' | ||
| rules_file_name: 'zap-rules.tsv' | ||
| issue_title: 'ZAP Full Scan Report' | ||
| docker_name: 'ghcr.io/zaproxy/zaproxy:stable' | ||
| # Copy ZAP reports to docs/reports directory | ||
| - name: Copy ZAP reports to docs/reports | ||
| run: | | ||
| echo "Looking for ZAP report files in various locations..." | ||
| # Check in /tmp/zap-output where we directed ZAP to write reports | ||
| echo "Checking in /tmp/zap-output:" | ||
| ls -la /tmp/zap-output || echo "Directory not found" | ||
| # Check in current directory | ||
| echo "Checking in current directory:" | ||
| find . -maxdepth 2 -name "*report*.md" -o -name "*report*.html" -o -name "*report*.json" | ||
| # Try to copy from our specific ZAP output directory first | ||
| if [ -d "/tmp/zap-output" ]; then | ||
| echo "Copying reports from /tmp/zap-output:" | ||
| cp -v /tmp/zap-output/*.* ./docs/reports/ 2>/dev/null || echo "No files to copy from /tmp/zap-output" | ||
| fi | ||
| # Then try multiple possible filenames and locations for the reports | ||
| for report in \ | ||
| ./zap-baseline-report.md \ | ||
| ./zap-full-scan-report.md \ | ||
| ./baseline-report.md \ | ||
| ./full-scan-report.md \ | ||
| ./report_md.md \ | ||
| /tmp/zap-baseline-report.md \ | ||
| /tmp/zap-full-scan-report.md \ | ||
| /zap/wrk/zap-baseline-report.md \ | ||
| /zap/wrk/zap-full-scan-report.md; do | ||
| if [ -f "$report" ]; then | ||
| echo "Found report: $report" | ||
| cp -v "$report" ./docs/reports/ | ||
| fi | ||
| done | ||
| # If no reports were found, create placeholders | ||
| if [ ! -f "./docs/reports/zap-baseline-report.md" ] && [ ! -f "./docs/reports/baseline-report.md" ]; then | ||
| echo "Creating placeholder for ZAP baseline report" | ||
| echo "# ZAP Baseline Scan Report (Placeholder) | ||
| This is a placeholder for the ZAP baseline scan report. | ||
| The actual scan may have failed to generate a report file due to permissions issues. | ||
| " > ./docs/reports/zap-baseline-report.md | ||
| fi | ||
| if [ ! -f "./docs/reports/zap-full-scan-report.md" ] && [ ! -f "./docs/reports/full-scan-report.md" ]; then | ||
| echo "Creating placeholder for ZAP full scan report" | ||
| echo "# ZAP Full Scan Report (Placeholder) | ||
| This is a placeholder for the ZAP full scan report. | ||
| The actual scan may have failed to generate a report file due to permissions issues. | ||
| " > ./docs/reports/zap-full-scan-report.md | ||
| fi | ||
| # Check if any reports were copied or created | ||
| echo "Contents of docs/reports directory:" | ||
| ls -la ./docs/reports/ | ||
| - name: Upload ZAP Report | ||
| uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: zap-reports | ||
| path: ./docs/reports/ | ||
| - name: Stop Docker Containers | ||
| if: always() | ||
| run: | | ||
| cd ./xss | ||
| # Try both docker compose (v2) and docker-compose (v1) commands | ||
| docker compose down || docker-compose down || true | ||
| # Verify containers are stopped | ||
| echo "Checking for running containers:" | ||
| docker ps | ||
| save-reports: | ||
| name: Save Scan Reports | ||
| runs-on: ubuntu-latest | ||
| needs: [secrets-scanning, sast-scanning, sca-scanning, sbom-generation, dast-scanning] | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| token: ${{ github.token }} # Use GitHub token for authentication | ||
| fetch-depth: 0 # Full history for proper commits | ||
| - name: Download all artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| - name: Ensure reports directory exists | ||
| run: mkdir -p ./docs/reports | ||
| - name: Save all scan reports to docs/reports | ||
| run: | | ||
| # Create comprehensive report index file | ||
| echo "# DevSecOps Scan Reports" > ./docs/reports/README.md | ||
| echo "Generated on $(date)" >> ./docs/reports/README.md | ||
| echo "" >> ./docs/reports/README.md | ||
| echo "## Available Reports" >> ./docs/reports/README.md | ||
| # Process all artifacts and copy to docs/reports | ||
| for artifact_dir in ./artifacts/*; do | ||
| if [ -d "$artifact_dir" ]; then | ||
| artifact_name=$(basename "$artifact_dir") | ||
| echo "Processing artifact: $artifact_name" | ||
| # Copy all files from the artifact directory to docs/reports | ||
| cp -v $artifact_dir/* ./docs/reports/ 2>/dev/null || echo "No files to copy from $artifact_name" | ||
| # Add entry to the report index | ||
| echo "- **$artifact_name**" >> ./docs/reports/README.md | ||
| for file in $artifact_dir/*; do | ||
| if [ -f "$file" ]; then | ||
| filename=$(basename "$file") | ||
| echo " - [$filename](./$filename)" >> ./docs/reports/README.md | ||
| fi | ||
| done | ||
| fi | ||
| done | ||
| # Check if any reports were saved | ||
| echo "Saved reports in docs/reports directory:" | ||
| ls -la ./docs/reports/ | ||
| # Commit and push the reports to the repository | ||
| - name: Commit and push reports to the repository | ||
| run: | | ||
| # Configure git | ||
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | ||
| git config --local user.name "github-actions[bot]" | ||
| # Check for changes in remote and pull if needed | ||
| echo "Checking for updates from remote..." | ||
| git pull origin ${GITHUB_REF_NAME} --no-rebase || echo "Failed to pull, proceeding anyway" | ||
| # Ensure docs/reports directory exists | ||
| mkdir -p ./docs/reports/ | ||
| # Stage the changes | ||
| echo "Adding report files to git..." | ||
| git add ./docs/reports/ | ||
| # Verify changes were staged | ||
| git status | ||
| # Check if there are changes to commit | ||
| if git diff --staged --quiet; then | ||
| echo "No changes to commit" | ||
| else | ||
| # Commit the changes | ||
| echo "Committing report files..." | ||
| git commit -m "Add security scan reports [skip ci]" | ||
| # Push to the repository | ||
| echo "Pushing changes to the repository..." | ||
| git push origin ${GITHUB_REF_NAME} | ||
| echo "Reports have been committed and pushed to the repository." | ||
| echo "View them at: https://github.com/${GITHUB_REPOSITORY}/tree/${GITHUB_REF_NAME}/docs/reports" | ||
| fi | ||
| continue-on-error: true # Continue workflow even if push fails | ||
| defectdojo-import: | ||
| name: Import Results to DefectDojo | ||
| runs-on: ubuntu-latest | ||
| needs: [save-reports] | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
| - name: Download all artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| # Copy artifacts to docs/reports for local usage | ||
| - name: Copy artifacts to docs/reports | ||
| run: | | ||
| mkdir -p ./docs/reports | ||
| echo "Copying all artifacts to docs/reports directory..." | ||
| # TruffleHog results | ||
| if [ -d "./artifacts/trufflehog-results" ]; then | ||
| echo "Found TruffleHog results" | ||
| cp ./artifacts/trufflehog-results/* ./docs/reports/ || echo "No TruffleHog files to copy" | ||
| else | ||
| echo "No TruffleHog results directory found" | ||
| fi | ||
| # CodeQL results | ||
| if [ -d "./artifacts/codeql-results" ]; then | ||
| echo "Found CodeQL results" | ||
| cp ./artifacts/codeql-results/* ./docs/reports/ || echo "No CodeQL files to copy" | ||
| else | ||
| echo "No CodeQL results directory found" | ||
| fi | ||
| # SCA results | ||
| if [ -d "./artifacts/sca-results" ]; then | ||
| echo "Found SCA results" | ||
| cp ./artifacts/sca-results/* ./docs/reports/ || echo "No SCA files to copy" | ||
| else | ||
| echo "No SCA results directory found" | ||
| fi | ||
| # SBOM results | ||
| if [ -d "./artifacts/angular-xss-sbom" ]; then | ||
| echo "Found SBOM results" | ||
| cp ./artifacts/angular-xss-sbom/* ./docs/reports/ || echo "No SBOM files to copy" | ||
| else | ||
| echo "No SBOM results directory found" | ||
| fi | ||
| # ZAP results | ||
| if [ -d "./artifacts/zap-reports" ]; then | ||
| echo "Found ZAP results" | ||
| cp ./artifacts/zap-reports/* ./docs/reports/ || echo "No ZAP files to copy" | ||
| else | ||
| echo "No ZAP results directory found" | ||
| fi | ||
| # Verify copied files | ||
| echo "Files in docs/reports directory after copying artifacts:" | ||
| ls -la ./docs/reports/ | ||
| # Run verification script to check for required reports | ||
| echo "Running verification script..." | ||
| chmod +x ./verify-reports.sh | ||
| ./verify-reports.sh | ||