Files
cannamanage/.gitea/workflows/security.yml
T

149 lines
5.8 KiB
YAML

# ─────────────────────────────────────────────────────────────────────────────
# Aegis — Security Scan pipeline.
# Milestone M0: Trivy (SCA/IaC/secrets gate) + Gitleaks (secrets).
# This is the CANONICAL workflow; it is mirrored (copy) into target app repos
# (CannaManage first, then plate-auth / Sparkboard / InspectFlow). Repo-specific
# differences are repo-type (image vs source), not scanner config.
#
# P0 fixes applied (from docs/planning/12 + 14):
# F-05 scanner actions pinned to exact versions (never @master)
# EP-W2 timeout-minutes: 10 on every job (prevents stalled DB downloads)
# EP-W1 Trivy DefectDojo-bound run uses --scanners vuln (no secret values in JSON)
#
# Deferred to later milestones:
# M1 Semgrep (SAST) + Syft (SBOM) + Checkov (IaC) jobs
# M3 DefectDojo push steps (needs DefectDojo running — deployed in M2)
# M5 Cosign image signing + SBOM attestation
# ─────────────────────────────────────────────────────────────────────────────
name: Security Scan
on:
push:
branches: [main]
pull_request:
schedule:
- cron: '0 2 * * *' # 02:00 UTC daily — nightly deep scan
workflow_dispatch:
jobs:
# ── Trivy: SCA + IaC + secrets. GATE blocks on HIGH/CRITICAL. ──────────────
trivy:
runs-on: ubuntu-latest
timeout-minutes: 10 # EP-W2
steps:
- uses: actions/checkout@v4
# GATE — block the build on HIGH/CRITICAL findings (defense in depth).
# Human-readable table in the CI log. Suppressions: .trivyignore (CVE IDs).
- name: Trivy gate (block HIGH/CRITICAL)
uses: aquasecurity/trivy-action@0.24.0 # F-05: pinned, never @master
with:
scan-type: fs
scan-ref: .
severity: HIGH,CRITICAL
exit-code: '1'
format: table
# REPORT — full JSON for DefectDojo (M3). EP-W1: --scanners vuln SKIPS the
# secret scanner so real secret values are never written to the artifact.
# (Secret detection is Gitleaks' job below; Trivy's would leak values.)
- name: Trivy full report (vulns only — safe for DefectDojo)
if: always()
uses: aquasecurity/trivy-action@0.24.0
with:
scan-type: fs
scan-ref: .
scanners: vuln
format: json
output: trivy-report.json
- name: Upload Trivy report
if: always()
uses: actions/upload-artifact@v4
with:
name: trivy-report
path: trivy-report.json
retention-days: 30
# M3 will add: "Push to DefectDojo" step here
# (curl --fail --retry 3 --retry-delay 5 ... /api/v2/import-scan/).
# ── Gitleaks: hardcoded secrets. BLOCK on any leak (exit-code 1). ───────────
gitleaks:
runs-on: ubuntu-latest
timeout-minutes: 10 # EP-W2
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history — leaks can be in any commit
- name: Gitleaks scan
uses: gitleaks/gitleaks-action@v2 # F-05: pinned
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Gitea provides this
# Blocks (exit-code 1) on any detected secret. Suppress individual
# false positives in .gitleaksignore (rule IDs only — never real values).
# M3 will add: upload gitleaks-report + DefectDojo push.
# ── Semgrep: SAST. WARN (report only — tune rules before gating). ──────────
semgrep:
runs-on: ubuntu-latest
timeout-minutes: 10 # EP-W2
steps:
- uses: actions/checkout@v4
- name: Semgrep SAST scan
# F-01: the DefectDojo-bound run emits JSON (semgrep ci --json), NOT SARIF
# — DD's "Semgrep JSON Report" parser expects semgrep's native --json schema.
uses: returntocorp/semgrep-action@v1.80.0 # F-05: pinned (R-05)
with:
config: >-
p/owasp-top-ten p/python p/java p/typescript
scanners/semgrep-rules.yml
- name: Semgrep JSON report (for DefectDojo, M3)
if: always()
run: |
semgrep ci --json \
--output=semgrep-results.json \
--config "p/owasp-top-ten p/python p/java p/typescript scanners/semgrep-rules.yml" || true
- name: Upload Semgrep report
if: always()
uses: actions/upload-artifact@v4
with:
name: semgrep-report
path: semgrep-results.json
retention-days: 30
# ── Syft: SBOM (CycloneDX JSON). INFO (supply-chain inventory, R-09 retention). ─
sbom:
runs-on: ubuntu-latest
timeout-minutes: 10 # EP-W2
steps:
- uses: actions/checkout@v4
- name: Generate SBOM
uses: anchor/sbom-action@v0.17.0 # F-05: pinned
with:
format: cyclonedx-json
output-file: sbom.json
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom-cyclonedx
path: sbom.json
retention-days: 90 # supply-chain audit trail (R-09)
# ── Checkov: IaC scan (Dockerfiles, compose, Kubernetes, Terraform). ────────
checkov:
runs-on: ubuntu-latest
timeout-minutes: 10 # EP-W2
steps:
- uses: actions/checkout@v4
- name: Checkov IaC scan
uses: bridgecrewio/checkov-action@v12 # F-05: pinned
with:
directory: .
framework: dockerfile,terraform,kubernetes
output_format: cli,sarif
output_file_path: console,checkov-results.sarif
#soft_fail: true # M1 = WARN; flip to block once baselined