流水线参考

本文档提供 CAST DevSecOps 流水线的完整技术参考。

目录


概述

CAST DevSecOps 流水线是一个 GitHub Actions 工作流,在每次推送和向主分支发起 Pull Request 时运行六个作业。

Trigger: push / pull_request / workflow_dispatch
│
├── Job 1: secrets        (Gitleaks)       ─┐
├── Job 2: sast           (Semgrep)         │ Run in parallel
├── Job 3: sca            (pip-audit)       │
├── Job 4: container      (Trivy)          ─┘
├── Job 5: quality        (Ruff)
│
└── Job 6: gate           (Security Gate)  ← waits for 1, 2, 3, 5

作业参考

1. 密钥检测

作业 ID:secrets
运行器:ubuntu-latest
工具:Gitleaks v2

功能说明

扫描仓库的完整 Git 历史,检测硬编码的密钥、API 密钥、令牌、密码及其他凭证。Gitleaks 使用一套全面的正则表达式模式,能检测超过 150 种类型的密钥。

配置

secrets:
  name: Secrets Detection
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0   # Full history — critical for catching old commits
    - name: Gitleaks
      uses: gitleaks/gitleaks-action@v2
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

关键配置项

配置项 原因
fetch-depth: 0 完整历史 Gitleaks 扫描所有提交,而非仅扫描最新提交
GITHUB_TOKEN 自动提供 用于公开仓库的请求频率限制规避

失败行为

抑制误报

在仓库根目录添加 .gitleaks.toml

[allowlist]
  description = "Allowlist"
  regexes = [
    '''false-positive-pattern''',
  ]
  paths = [
    '''path/to/test/fixtures''',
  ]

2. SAST

作业 ID:sast
运行器:ubuntu-latest(容器化)
工具:Semgrep

功能说明

执行静态应用程序安全测试(SAST)——在不执行代码的情况下,分析源代码中的安全漏洞、不安全模式和常见编码错误。

配置

sast:
  name: SAST
  runs-on: ubuntu-latest
  container:
    image: semgrep/semgrep
  steps:
    - uses: actions/checkout@v4
    - name: Semgrep scan
      run: semgrep ci --sarif --output=semgrep.sarif || true
      env:
        SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
    - name: Upload to GitHub Security tab
      uses: github/codeql-action/upload-sarif@v3
      if: always()
      with:
        sarif_file: semgrep.sarif

关键配置项

配置项 原因
semgrep/semgrep 容器 官方镜像 确保使用正确的 Semgrep 版本
|| true 始终退出码为 0 发现结果通过 SARIF 上报,而非退出码
SEMGREP_APP_TOKEN 可选密钥 启用云端规则;未配置则回退到开源规则
上传步骤的 if: always() 始终上传 即使扫描有发现,也确保 SARIF 被上传

SARIF 集成

发现结果上传至 GitHub Security 标签页后,将以以下形式呈现:

可选:Semgrep Cloud

SEMGREP_APP_TOKEN 配置为 GitHub Actions 密钥以启用:


3. SCA

作业 ID:sca
运行器:ubuntu-latest
工具:pip-audit

功能说明

执行软件成分分析(SCA)——对照已知漏洞数据库(PyPI Advisory Database、OSV)检查您的 Python 依赖项。

配置

sca:
  name: SCA
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - uses: actions/setup-python@v5
      with:
        python-version: "3.x"
        cache: pip
    - name: pip-audit
      uses: pypa/gh-action-pip-audit@v1
      with:
        inputs: requirements*.txt

关键配置项

配置项 原因
cache: pip 已启用 加速后续运行
inputs: requirements*.txt 通配符模式 扫描所有 requirements 文件

失败行为

自定义

若要扫描 pyproject.toml 中的依赖项而非 requirements 文件:

- uses: pypa/gh-action-pip-audit@v1
  with:
    inputs: pyproject.toml

4. 容器安全

作业 ID:container
运行器:ubuntu-latest
工具:Trivy

功能说明

扫描 Docker 镜像中操作系统软件包和应用程序依赖项的已知 CVE。若仓库中不存在 Dockerfile,该作业将自动跳过

配置

container:
  name: Container Security
  runs-on: ubuntu-latest
  if: hashFiles('Dockerfile') != ''
  steps:
    - uses: actions/checkout@v4
    - name: Build image
      run: docker build -t cast-scan:${{ github.sha }} .
    - name: Trivy scan
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: cast-scan:${{ github.sha }}
        format: sarif
        output: trivy.sarif
        severity: CRITICAL,HIGH
        exit-code: "0"
    - name: Upload to GitHub Security tab
      uses: github/codeql-action/upload-sarif@v3
      if: always()
      with:
        sarif_file: trivy.sarif

关键配置项

配置项 原因
hashFiles('Dockerfile') != '' 条件判断 若无 Dockerfile 则优雅跳过
severity: CRITICAL,HIGH 过滤器 聚焦于可操作的发现
exit-code: "0" 不退出 由门禁作业处理阻断逻辑
github.sha 标签 唯一标签 防止并发运行时发生冲突

失败行为


5. 代码质量

作业 ID:quality
运行器:ubuntu-latest
工具:Ruff

功能说明

运行 Ruff——一款极速 Python 代码检查器和格式化工具——以强制执行代码风格规范并捕获常见错误。

配置

quality:
  name: Code Quality
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - uses: astral-sh/ruff-action@v1

自定义

Ruff 从 pyproject.tomlruff.toml 读取配置:

# pyproject.toml
[tool.ruff]
target-version = "py39"
line-length = 100

[tool.ruff.lint]
select = ["E", "F", "W", "I"]
ignore = ["E501"]

失败行为


6. 安全门禁

作业 ID:gate
运行器:ubuntu-latest
依赖:secretssastscaquality

功能说明

汇总所有安全作业的结果,并做出单一的通过/失败决策。GitHub 分支保护规则应以此作业为目标。

配置

gate:
  name: Security Gate
  runs-on: ubuntu-latest
  needs: [secrets, sast, sca, quality]
  if: always()
  steps:
    - name: Evaluate results
      run: |
        echo "secrets : ${{ needs.secrets.result }}"
        echo "sast    : ${{ needs.sast.result }}"
        echo "sca     : ${{ needs.sca.result }}"
        echo "quality : ${{ needs.quality.result }}"

        if [[ "${{ needs.secrets.result }}" == "failure" ||
              "${{ needs.sast.result }}"    == "failure" ||
              "${{ needs.sca.result }}"     == "failure" ]]; then
          echo "❌ Security gate failed — merge blocked"
          exit 1
        fi

        echo "✅ All checks passed — safe to merge"

门禁决策矩阵

密钥检测 SAST SCA 门禁结果
✅ 通过 ✅ 通过 ✅ 通过 ✅ 允许合并
❌ 失败 ✅ 通过 ✅ 通过 ❌ 阻止合并
✅ 通过 ❌ 失败 ✅ 通过 ❌ 阻止合并
✅ 通过 ✅ 通过 ❌ 失败 ❌ 阻止合并
任意 任意 任意 ❌ 阻止合并(以上任一失败)
注意:代码质量(Ruff)失败会被上报,但在默认配置下不会阻止合并。

通过分支保护强制执行门禁

若要将安全门禁设为 Pull Request 的强制要求:

  1. 进入 Settings → Branches → Branch protection rules
  2. main(或 master)添加规则
  3. 启用 "Require status checks to pass before merging"
  4. 搜索并添加 "Security Gate"
  5. 可选:启用 "Require branches to be up to date before merging"

权限

工作流申请最小必要权限:

permissions:
  contents: read          # checkout code
  security-events: write  # upload SARIF to Security tab
  actions: read           # read workflow status for gate

不授予对仓库内容的写入权限。


触发配置

默认触发器覆盖最常见的工作流:

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]
  workflow_dispatch:        # manual trigger from GitHub UI

仅在 Pull Request 时运行

为减少 Actions 用时,移除 push 触发器:

on:
  pull_request:
    branches: [main, master]
  workflow_dispatch:

添加定时扫描

每日运行一次完整扫描(例如,用于捕获新披露的 CVE):

on:
  schedule:
    - cron: "0 6 * * *"   # 06:00 UTC daily
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

自定义指南

修改严重性阈值

在 Trivy 作业中修改 severity 输入:

severity: CRITICAL,HIGH,MEDIUM   # report medium and above

在门禁失败时发送邮件通知

gate:
  # ... existing config ...
  steps:
    - name: Evaluate results
      # ... existing step ...
    - name: Notify on failure
      if: failure()
      uses: dawidd6/action-send-mail@v3
      with:
        server_address: smtp.example.com
        to: security-team@example.com
        subject: "CAST Security Gate Failed — ${{ github.repository }}"
        body: "Security gate failed on ${{ github.ref }}"

跳过特定路径的检查

on:
  push:
    branches: [main, master]
    paths-ignore:
      - "docs/**"
      - "*.md"

故障排查

Gitleaks 对合法测试固件报错

添加 .gitleaks.toml 允许列表(参见 密钥检测 章节)。

Semgrep SARIF 上传失败

确保 permissions 中已设置 security-events: writegithub/codeql-action/upload-sarif 操作需要此权限。

pip-audit 找不到 requirements 文件

若您仅使用 pyproject.toml,请修改 inputs 参数:

with:
  inputs: pyproject.toml

或安装您的包并审计环境:

- run: pip install -e .
- uses: pypa/gh-action-pip-audit@v1

容器作业意外被跳过

若 Dockerfile 位于子目录中,hashFiles('Dockerfile') 条件将返回空字符串。请修改条件以匹配您的路径:

if: hashFiles('**/Dockerfile') != ''