Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/02-security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,53 @@ jobs:
base: ${{ github.event.pull_request.base.sha }}
head: ${{ github.event.pull_request.head.sha }}
extra_args: --only-verified # Only flag verified secrets

# πŸš€ CI/CD OPTIMIZATION: Trivy filesystem scans (NO Docker build required!)
# This replaces slow Docker builds on PRs while maintaining security coverage
trivy-backend:
name: πŸ” Trivy - Backend Dependencies
runs-on: ubuntu-latest
steps:
- name: πŸ“₯ Checkout code
uses: actions/checkout@v4

- name: πŸ” Scan Python dependencies (pyproject.toml, poetry.lock)
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: 'backend/'
format: 'sarif'
output: 'trivy-backend-deps.sarif'
severity: 'CRITICAL,HIGH'
scanners: 'vuln' # Only vulnerabilities, not misconfigurations

- name: πŸ“€ Upload Trivy Backend SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: trivy-backend-deps.sarif
category: trivy-backend-deps

trivy-frontend:
name: πŸ” Trivy - Frontend Dependencies
runs-on: ubuntu-latest
steps:
- name: πŸ“₯ Checkout code
uses: actions/checkout@v4

- name: πŸ” Scan Node dependencies (package.json, package-lock.json)
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: 'frontend/'
format: 'sarif'
output: 'trivy-frontend-deps.sarif'
severity: 'CRITICAL,HIGH'
scanners: 'vuln'

- name: πŸ“€ Upload Trivy Frontend SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: trivy-frontend-deps.sarif
category: trivy-frontend-deps
70 changes: 56 additions & 14 deletions .github/workflows/03-build-secure.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
name: Secure Docker Build & Scan

# πŸš€ CI/CD OPTIMIZATION: Docker builds moved to post-merge only
# ================================================================
# WHY: PR feedback time reduced from 18-22 min to 3-4 min (85% faster)
# SECURITY: Dependency scanning still runs on PRs via Trivy filesystem scans (02-security.yml)
# WHEN: Builds run after merge to main, weekly scans, or manual trigger
# REF: docs/development/CI_CD_OPTIMIZATION_ANALYSIS.md
on:
pull_request:
branches: [main]
paths:
# Only run on PR if Dockerfiles or dependencies change
# NOTE: Do NOT include workflow file itself to avoid expensive builds on CI/CD changes
- 'backend/Dockerfile.backend'
- 'backend/pyproject.toml'
- 'backend/poetry.lock'
- 'frontend/Dockerfile.frontend'
- 'frontend/package*.json'
- 'docker-compose*.yml'
push:
branches: [main]
# Always scan on merge to main
# Always build and scan on merge to main
schedule:
# Weekly CVE scan every Tuesday at 6:17 PM UTC
- cron: '17 18 * * 2'
Expand Down Expand Up @@ -104,6 +99,15 @@
category: hadolint-${{ matrix.service }}

# ===== STAGE 2: Build Docker Image with Optimizations =====
- name: πŸ”„ Restore BuildKit Cache
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ matrix.service }}-${{ hashFiles(format('{0}/poetry.lock', matrix.context), format('{0}/package-lock.json', matrix.context)) }}

Check warning on line 106 in .github/workflows/03-build-secure.yml

View workflow job for this annotation

GitHub Actions / YAML Lint

106:121 [line-length] line too long (169 > 120 characters)
restore-keys: |
${{ runner.os }}-buildx-${{ matrix.service }}-
${{ runner.os }}-buildx-

- name: πŸ—οΈ Build Docker Image
uses: docker/build-push-action@v5
with:
Expand All @@ -112,11 +116,18 @@
push: false
load: true
tags: ${{ matrix.image_name }}:${{ github.sha }}
# No external cache to avoid slow export - rely on BuildKit's internal cache
# BuildKit cache mounts in Dockerfile are sufficient for speed
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
build-args: |
BUILDKIT_INLINE_CACHE=1

# Move cache to optimize for next run (temp workaround for actions/cache#828)
- name: πŸ’Ύ Save BuildKit Cache
if: always()
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache || true

# Clean up build cache immediately to free space
- name: 🧹 Clean Build Cache
if: always()
Expand Down Expand Up @@ -194,6 +205,37 @@
exit-code: '0' # Don't fail the build, just report
ignore-unfixed: true

# ===== STAGE 4.5: Grype Vulnerability Scan (Backup Scanner) =====
# IBM uses both Trivy + Grype for comprehensive coverage
# Grype provides better fix recommendations and broader CVE database
- name: πŸ“₯ Install Grype CLI
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

- name: πŸ” Grype - Vulnerability Scan
continue-on-error: true
run: |
grype ${{ matrix.image_name }}:${{ github.sha }} \
--scope all-layers \
--only-fixed \
--output table

- name: πŸ“„ Grype - Generate SARIF Report
continue-on-error: true
run: |
grype ${{ matrix.image_name }}:${{ github.sha }} \
--scope all-layers \
--output sarif \
--file grype-${{ matrix.service }}.sarif

- name: πŸ“€ Upload Grype SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
continue-on-error: true
with:
sarif_file: grype-${{ matrix.service }}.sarif
category: grype-${{ matrix.service }}

# ===== STAGE 5: SBOM Generation (Syft) =====
- name: πŸ“‹ Syft - Generate SBOM
id: syft
Expand Down
Loading
Loading