Vulnerability Scan #74
Workflow file for this run
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: Vulnerability Scan | |
| on: | |
| workflow_dispatch: # Allows manual triggering | |
| schedule: | |
| - cron: "0 2 * * 1" # Run weekly at 2 AM on Monday | |
| pull_request: | |
| paths: | |
| - 'Dockerfile' | |
| - '.github/workflows/security.yaml' | |
| permissions: | |
| contents: write | |
| packages: write | |
| issues: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-image: | |
| name: Build Docker Image | |
| runs-on: ubuntu-latest | |
| outputs: | |
| image_name: ${{ steps.meta.outputs.tags }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Log in to the GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata for Docker | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/${{ github.repository }} | |
| tags: type=sha,prefix=scan- | |
| - name: Build and push Docker image | |
| id: build | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| - name: Save image to a tar file | |
| run: docker save ${{ steps.meta.outputs.tags }} -o image.tar | |
| - name: Upload image artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: image-tar | |
| path: image.tar | |
| retention-days: 1 | |
| scan-and-report: | |
| name: Vulnerability Scan | |
| needs: build-image | |
| runs-on: [self-hosted, self-hosted-linux-amd64-jammy-private-endpoint-medium] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Download image artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: image-tar | |
| - name: Install secscan client | |
| run: | | |
| sudo snap install canonical-secscan-client | |
| sudo snap connect canonical-secscan-client:home system:home | |
| - name: Run security scan | |
| continue-on-error: true | |
| id: scan | |
| run: | | |
| secscan-client --batch submit \ | |
| --ssdlc-product-name 'landscape-ui' \ | |
| --ssdlc-cycle '25.10' \ | |
| --ssdlc-product-version '1.17.0' \ | |
| --ssdlc-product-channel 'edge' \ | |
| --scanner trivy \ | |
| --type container-image \ | |
| --format oci \ | |
| image.tar \ | |
| --wait-and-print > secscan-results.txt | |
| - name: Analyze Scan Results and Determine Job Status | |
| if: always() | |
| id: analysis | |
| run: | | |
| EXIT_CODE=${{ steps.scan.exit_code }} | |
| echo "Scan step exited with code: $EXIT_CODE" | |
| # Exit code 0 means a clean scan | |
| if [ "$EXIT_CODE" == "0" ]; then | |
| echo "Success: Scan completed and no vulnerabilities were found." | |
| exit 0 | |
| fi | |
| # Exit codes 100-199 mean CVEs were found | |
| if [ "$EXIT_CODE" -ge 100 ] && [ "$EXIT_CODE" -lt 200 ]; then | |
| echo "::error::Vulnerabilities were detected by the scan." | |
| if grep -q -E 'CRITICAL|HIGH' secscan-results.txt; then | |
| echo "::error::High or Critical vulnerabilities found." | |
| else | |
| echo "::warning::Medium or Low vulnerabilities found." | |
| fi | |
| exit 1 # Fail the job | |
| fi | |
| # Any other non-zero exit code is a processing error | |
| echo "::error::The security scan failed to run properly. Exit code: $EXIT_CODE" | |
| if [ -f secscan-results.txt ] && grep -q -i 'Scan has failed' secscan-results.txt; then | |
| echo "::error::The secscan tool reported a failure in its output. See results for details." | |
| fi | |
| exit 1 | |
| - name: Upload Scan Results on Success | |
| if: success() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: secscan-results | |
| path: secscan-results.txt | |
| - name: Create Issue on Failure | |
| if: failure() | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| echo "Vulnerability scan found high/critical issues or failed to run." > issue-body.txt | |
| echo "" >> issue-body.txt | |
| echo "Please check the workflow run logs for the 'Run security scan' step for details." >> issue-body.txt | |
| echo "" >> issue-body.txt | |
| echo "### Scan Output" >> issue-body.txt | |
| echo '```' >> issue-body.txt | |
| if [ -f secscan-results.txt ]; then | |
| cat secscan-results.txt | |
| else | |
| echo "Scan results file not found." | |
| fi >> issue-body.txt | |
| echo '```' >> issue-body.txt | |
| gh issue create --title "High/Critical Vulnerabilities Detected in Landscape UI" --body-file issue-body.txt --label "security,bug" | |
| generate-and-submit-sbom: | |
| name: Generate and Submit SBOM | |
| needs: build-image | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Log in to the GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Run Trivy to generate SBOM and submit to Dependency Graph | |
| uses: aquasecurity/trivy-action@0.33.1 | |
| with: | |
| image-ref: ${{ needs.build-image.outputs.image_name }} | |
| format: 'spdx-json' | |
| output: 'dependency-results.sbom.json' | |
| github-pat: ${{ secrets.GITHUB_TOKEN }} | |
| severity: "HIGH,CRITICAL" | |
| scanners: "vuln" | |
| - name: Upload SBOM as an Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sbom-report-json | |
| path: 'dependency-results.sbom.json' | |
| retention-days: 30 |