AbdelazezMohamedAzez/secure-devsecops-starter
GitHub: AbdelazezMohamedAzez/secure-devsecops-starter
该项目通过一个加固的 Python Flask 应用,演示了如何在整个 CI/CD 流水线及多云部署中实现自动化安全门禁与 DevSecOps 最佳实践。
Stars: 1 | Forks: 0
# 安全 DevSecOps 入门项目
这是一个实操性的 Python Flask API 项目,用于练习和展示 DevSecOps 基础、安全的 CI/CD pipeline、自动化安全门禁、容器加固、左移安全、运行时 DAST 以及实践性的多云安全部署证据。
## 项目概述
该项目最初只是一个简单的 Flask API,后来逐渐升级为一个经过加固的 DevSecOps 入门 pipeline。
其主要目标是演示如何在代码合并、部署或暴露到云环境之前,将安全检查集成到软件交付生命周期中。
该 pipeline 不仅会生成安全报告,还会在检测到高风险问题时强制执行阻断性安全门禁。
该仓库还包含了跨 AWS 和 GCP 的实际云部署证据,展示了基于 VM 的部署模型和托管式 serverless 容器部署模型。
## 项目包含内容
- Python Flask API
- Docker 化的应用
- GitHub Actions CI pipeline
- 最小权限的 GitHub Actions 权限配置
- 基于分支的 PR 工作流
- 使用 Gitleaks 进行 secret 扫描
- 使用 Semgrep 进行 SAST 扫描
- 使用 CodeQL 进行代码扫描
- 使用 pip-audit 进行 Python 依赖项漏洞扫描
- 使用 Trivy 进行容器漏洞扫描
- 使用 OWASP ZAP Baseline Scan 进行 DAST 扫描
- 使用 Dependabot 自动化依赖项更新
- 本地 pre-commit 安全检查
- Docker 非 root 用户加固
- 基础的 Flask 安全响应头
- 作为 GitHub Actions artifacts 上传的安全扫描报告
- AWS EC2 实际部署证据
- GCP Cloud Run 实际部署证据
- Artifact Registry 镜像部署证据
- 运行时 Trivy 扫描证据
- 针对已部署云 endpoint 的 OWASP ZAP DAST 证据
- CI 与运行时容器扫描对比调查
- 临时云资源清理文档
## 技术栈
| 领域 | 工具 / 服务 |
|---|---|
| 应用程序 | Python Flask |
| Web 服务器 | Gunicorn |
| 容器化 | Docker |
| CI/CD | GitHub Actions |
| Secret 扫描 | Gitleaks |
| SAST | Semgrep |
| 代码扫描 | CodeQL |
| 依赖项扫描 | pip-audit |
| 容器扫描 | Trivy |
| DAST | OWASP ZAP Baseline Scan |
| 依赖自动化 | Dependabot |
| 本地安全检查 | pre-commit |
| 云运行时 - AWS | EC2 |
| 云运行时 - GCP | Cloud Run |
| GCP 容器镜像仓库 | Artifact Registry |
| GCP 构建 | Cloud Build |
| GCP 日志 | Cloud Logging |
| IaC 安全相关项目 | Terraform + Checkov |
## 每周进展与文档索引
本节是仓库的主要路线图。每周总结了已完成的安全工作,并链接到相关文档或证据文件。
| 周次 | 重点领域 | 完成内容 | 文档 / 证据 |
|---|---|---|---|
| 第 1 周 | DevSecOps 基础 | 构建 Flask API,对应用进行 Docker 化,添加 GitHub Actions CI、Gitleaks、Semgrep、pip-audit、Trivy,并修复了早期发现的问题。 | 主 README 部分:[CI/CD Pipeline](#cicd-pipeline)、[Security Gates](#security-gates)、[Security Reports and Observability](#security-reports-and-observability) |
| 第 2 周 | CI/CD 加固 | 添加了基于分支的 PR 工作流、最小权限的 GitHub Actions 权限、工作流并发控制、阻断性安全门禁、CodeQL、Dependabot、pre-commit hooks 以及 Docker 非 root 加固。 | [GitHub Actions Hardening](#github-actions-hardening)、[CodeQL Code Scanning](#codeql-code-scanning)、[Dependabot Automation](#dependabot-automation)、[Shift-Left Security with pre-commit](#shift-left-security-with-pre-commit) |
| 第 6 周 | OWASP ZAP DAST | 添加了针对正在运行的 Flask 容器的 OWASP ZAP Baseline Scan,生成了 HTML/Markdown/JSON 报告,上传了 artifacts,并添加了安全响应头以减少被动发现。 | [docs/week-6-dast-report.md](docs/week-6-dast-report.md) |
| 第 7 周 | 容器安全 | 通过添加非 root 用户、所有权安全的拷贝行为以及容器运行时安全文档,加固了 Docker 的执行。 | [Security Finding and Remediation: Docker Running as Root](#security-finding-and-remediation-docker-running-as-root) |
| 第 8 周 | 多云 IaC 安全 | 在单独的仓库中完成:针对 AWS 和 GCP 的 Terraform 安全基线、Checkov 扫描、CI 门禁以及修复证据。 | [Multi-Cloud IaC Security Scanning](https://github.com/AbdelazezMohamedAzez/multi-cloud-iac-security-scanning) |
| 第 9 周 | 多云安全部署 | 添加了 AWS/GCP 安全部署规划、AWS EC2 实际部署、GCP Cloud Run 实际部署、运行时 Trivy 扫描、针对云 endpoint 的 ZAP 扫描、CI 与运行时扫描对比调查以及清理证据。 | [docs/week-9-multicloud-secure-deployment.md](docs/week-9-multicloud-secure-deployment.md)、[AWS Practical Evidence](docs/evidence/practical/aws-practical-deployment-evidence.md)、[GCP Practical Evidence](docs/evidence/practical/gcp-practical-deployment-evidence.md) |
## 文档导航
`docs/` 文件夹包含了每周总结背后的详细证据。
| 文件 | 用途 |
|---|---|
| [docs/week-6-dast-report.md](docs/week-6-dast-report.md) | 第 6 周 OWASP ZAP DAST 报告及运行时 Web 安全测试笔记 |
| [docs/week-9-multicloud-secure-deployment.md](docs/week-9-multicloud-secure-deployment.md) | 第 9 周多云安全部署概述 |
| [docs/evidence/aws-secure-deployment-evidence.md](docs/evidence/aws-secure-deployment-evidence.md) | AWS 安全部署规划证据 |
| [docs/evidence/gcp-secure-deployment-plan.md](docs/evidence/gcp-secure-deployment-plan.md) | GCP 安全部署规划证据 |
| [docs/evidence/aws-vs-gcp-security-comparison.md](docs/evidence/aws-vs-gcp-security-comparison.md) | AWS 与 GCP 安全性对比 |
| [docs/evidence/week-9-final-evidence-checklist.md](docs/evidence/week-9-final-evidence-checklist.md) | 第 9 周最终证据核对清单 |
| [docs/evidence/practical/aws-practical-deployment-evidence.md](docs/evidence/practical/aws-practical-deployment-evidence.md) | AWS EC2 + Docker 实际部署证据 |
| [docs/evidence/practical/gcp-practical-deployment-evidence.md](docs/evidence/practical/gcp-practical-deployment-evidence.md) | GCP Cloud Run + Artifact Registry 实际部署证据 |
## 实际证据报告
第 9 周的实际报告存储在以下位置:
```
docs/evidence/practical/reports/
```
预期报告:
```
docs/evidence/practical/reports/
├── trivy-week9-aws.txt
├── zap-week9-aws.html
├── zap-week9-aws.json
├── zap-week9-gcp.html
└── zap-week9-gcp.json
```
报告用途:
| 报告 | 用途 |
|---|---|
| `trivy-week9-aws.txt` | 来自 AWS EC2 部署的运行时容器漏洞扫描 |
| `zap-week9-aws.html` | 针对 AWS endpoint 的 OWASP ZAP HTML 报告 |
| `zap-week9-aws.json` | 针对 AWS endpoint 的 OWASP ZAP JSON 报告 |
| `zap-week9-gcp.html` | 针对 GCP Cloud Run endpoint 的 OWASP ZAP HTML 报告 |
| `zap-week9-gcp.json` | 针对 GCP Cloud Run endpoint 的 OWASP ZAP JSON 报告 |
## 仓库结构
```
.
├── .github/
│ └── workflows/
│ ├── security-ci.yml
│ ├── codeql.yml
│ └── zap-dast.yml
├── docs/
│ ├── week-6-dast-report.md
│ ├── week-9-multicloud-secure-deployment.md
│ └── evidence/
│ ├── aws-secure-deployment-evidence.md
│ ├── gcp-secure-deployment-plan.md
│ ├── aws-vs-gcp-security-comparison.md
│ ├── week-9-final-evidence-checklist.md
│ └── practical/
│ ├── aws-practical-deployment-evidence.md
│ ├── gcp-practical-deployment-evidence.md
│ └── reports/
│ ├── trivy-week9-aws.txt
│ ├── zap-week9-aws.html
│ ├── zap-week9-aws.json
│ ├── zap-week9-gcp.html
│ └── zap-week9-gcp.json
├── app.py
├── Dockerfile
├── requirements.txt
├── README.md
└── .pre-commit-config.yaml
```
## 本地运行
安装依赖项:
```
pip install -r requirements.txt
```
运行应用程序:
```
python app.py
```
然后打开:
```
http://localhost:5000
```
## 使用 Docker 运行
构建 Docker 镜像:
```
docker build -t secure-devsecops-starter .
```
运行容器:
```
docker run -p 5000:5000 secure-devsecops-starter
```
然后打开:
```
http://localhost:5000
```
## CI/CD 流水线
GitHub Actions pipeline 会在 push 和针对受保护分支的 pull request 时运行。
当前的工作流触发器:
```
push → main, develop
pull_request → main, develop
manual workflow_dispatch
```
主要安全 pipeline 阶段:
1. 检出源代码
2. 准备安全报告目录
3. 运行 Gitleaks secret 扫描
4. 运行 Semgrep SAST 扫描
5. 使用 pip-audit 进行 Python 依赖项审计
6. 构建 Docker 镜像
7. 运行 Trivy 容器镜像扫描
8. 将安全报告作为 artifacts 上传
9. 编写安全摘要
10. 强制执行最终安全门禁
OWASP ZAP DAST 工作流阶段:
1. 检出源代码
2. 构建 Docker 镜像
3. 运行 Flask 应用程序容器
4. 等待 `/health` endpoint
5. 针对正在运行的应用程序执行 OWASP ZAP Baseline Scan
6. 将 ZAP 报告作为 GitHub Actions artifacts 上传
7. 停止并移除应用程序容器
DAST 工作流在运行时验证应用程序,而不是仅仅扫描源文件或依赖项。
## GitHub Actions 加固
工作流使用最小权限进行了加固:
```
permissions:
contents: read
pull-requests: read
security-events: write
actions: read
```
还添加了并发控制,以防止在同一分支上重复运行工作流:
```
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
```
这改善了 pipeline 控制,减少了嘈杂的运行,并遵循了更像生产环境的 GitHub Actions 设置。
## 安全门禁
该 pipeline 使用安全门禁在合并前阻止不安全的更改。
| 门禁 | 工具 | 阻断条件 |
|---|---|---|
| Secrets 门禁 | Gitleaks | 检测到 secret 或凭据 |
| SAST 门禁 | Semgrep | 检测到 ERROR 级别的 SAST 发现 |
| 依赖项门禁 | pip-audit | 检测到有漏洞的 Python 依赖项 |
| 容器门禁 | Trivy | 检测到 HIGH 或 CRITICAL 漏洞 |
| 构建门禁 | Docker | Docker 镜像构建失败 |
| 运行时门禁 | ZAP 设置 | 应用程序容器无法启动 |
最后的强制执行步骤会检查每个安全阶段的结果,如果有任何阻断性门禁失败,则 pipeline 会失败。
OWASP ZAP Baseline Scan 目前用作 DAST 证据和分类步骤。它将报告作为 artifacts 上传,以便对发现的问题进行审查和修复。
## 安全报告与可观测性
安全报告将生成并作为 GitHub Actions artifacts 上传。
生成的 CI 报告包括:
```
reports/
├── semgrep.json
├── pip-audit.json
└── trivy.txt
zap-reports/
├── zap-report.html
├── zap-report.md
└── zap-report.json
```
这些报告为以下方面提供了证据:
- 安全审查
- 调试失败的 pipeline
- 漏洞分类
- DAST 发现审查
- 运行时验证
- 云部署证据
- 面试演示
- 作品集文档
## 安全发现与修复:Flask 开发服务器
Semgrep 检测到 Flask 开发服务器正在使用:
```
app.run(host="0.0.0.0", port=5000)
```
这可能会将开发服务器公开暴露。
该问题通过将其更改为以下内容得到了修复:
```
app.run(host="127.0.0.1", port=5000, debug=False)
```
修复后,GitHub Actions pipeline 成功通过。
## 安全发现与修复:Docker 以 Root 身份运行
在 pipeline 加固期间,Semgrep 检测到 Docker 容器没有指定非 root 用户。
发现:
```
dockerfile.security.missing-user.missing-user
```
风险:
如果攻击者攻破了应用程序进程,以 root 身份运行容器会增加容器环境内部的破坏影响。
已应用的修复:
```
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
COPY --chown=appuser:appgroup . .
USER appuser
```
修复后,pipeline 成功通过。
## Secret 扫描测试
使用自定义的演示规则对 Gitleaks 进行了测试。
在一个单独的测试分支上故意提交了一个演示 secret,以验证 secret 扫描是否有效。
结果:
- Gitleaks 检测到了演示 secret
- pipeline 按预期失败
- 演示 secret 已被移除
- 修复后 pipeline 再次通过
这证实了 secret 扫描正作为阻断性 CI 门禁发挥作用。
## 使用 pip-audit 进行依赖项扫描
添加了 pip-audit 以扫描 `requirements.txt` 中的 Python 依赖项。
它检测到了 Flask 3.0.3 中的一个漏洞,并建议升级 Flask。
该问题通过将 Flask 更新到 3.1.3 版本得到了修复:
```
Flask==3.1.3
gunicorn==22.0.0
```
升级后,GitHub Actions pipeline 成功通过。
## 使用 Trivy 进行容器扫描
添加了 Trivy 以扫描 Docker 镜像中的 HIGH 和 CRITICAL 漏洞。
该 pipeline 会构建 Docker 镜像并在认为 CI 成功之前对其进行扫描。
当前 Trivy CI 行为:
- 扫描构建好的 Docker 镜像
- 检查 HIGH 和 CRITICAL 漏洞
- 忽略未修复的漏洞
- 当检测到阻断性漏洞时使 pipeline 失败
第 9 周增加了一个重要的运行时验证教训:
- GitHub Actions 通过了,因为 Trivy CI 扫描配置了 `ignore-unfixed: true`。
- AWS 运行时扫描在没有 `--ignore-unfixed` 的情况下执行了。
- 运行时 Trivy 扫描识别出了在 CI 结果中不可见的基础镜像漏洞。
- 这些发现与 Debian 基础镜像包有关,而不是 Python 应用程序依赖项。
- 在 AWS 运行时 Trivy 报告中,Python 包显示 `0` 个漏洞。
这表明扫描配置会影响可见性,并且通过的 CI 应该有运行时验证和证据审查作为支撑。
## 使用 OWASP ZAP 进行动态应用程序安全测试
添加了 OWASP ZAP Baseline Scan 以动态测试正在运行的 Flask 应用程序。
ZAP 工作流:
1. 构建 Docker 镜像
2. 运行应用程序容器
3. 等待 `/health` endpoint
4. 针对 `http://127.0.0.1:5000` 运行 OWASP ZAP Baseline Scan
5. 生成 HTML、Markdown 和 JSON 报告
6. 将报告作为 GitHub Actions artifacts 上传
这为项目增加了运行时 Web 安全测试。
该扫描未经身份验证且侧重于被动检查,这使其适合作为早期的 CI/CD DAST 检查。
第 6 周报告:
```
docs/week-6-dast-report.md
```
第 9 周实际的云 ZAP 报告:
```
docs/evidence/practical/reports/zap-week9-aws.html
docs/evidence/practical/reports/zap-week9-aws.json
docs/evidence/practical/reports/zap-week9-gcp.html
docs/evidence/practical/reports/zap-week9-gcp.json
```
## CodeQL 代码扫描
添加了 CodeQL 作为额外的静态代码分析层。
CodeQL 提供了更深入的代码扫描,并与 GitHub Security 功能集成。
当前 CodeQL 设置:
- 在 pull request 时运行
- 在 push 到受保护分支时运行
- 扫描 Python 代码
- 使用 security-extended 和 security-and-quality 查询
结果出现在:
```
GitHub → Security → Code scanning
```
## Dependabot 自动化
添加了 Dependabot 以自动化依赖项和工作流更新检查。
已配置的生态系统:
| 生态系统 | 用途 |
|---|---|
| pip | 监控 Python 依赖项 |
| github-actions | 监控 GitHub Actions 版本 |
| docker | 监控 Docker 基础镜像更新 |
Dependabot 通过开启自动更新的 pull request 来帮助保持项目最新,并降低供应链风险。
## 使用 pre-commit 实现左移安全
添加了本地 pre-commit 层,以便在代码到达 GitHub 之前发现问题。
当前 pre-commit hooks:
| Hook | 用途 |
|---|---|
| detect-private-key | 防止提交私钥 |
| check-yaml | 验证 YAML 文件 |
| check-json | 验证 JSON 文件 |
| end-of-file-fixer | 确保文件正确结尾 |
| trailing-whitespace | 删除不必要的空格 |
| Gitleaks | 在本地检测硬编码的 secret |
手动运行所有 hooks:
```
pre-commit run --all-files
```
在本地安装 hooks:
```
pre-commit install
```
这在 CI/CD 之前增加了一个本地安全层。
## 第 9 周:多云实际安全部署
第 9 周将项目从 CI/CD 安全扩展到了实际的云部署证据。
目标不是让生产基础设施保持运行。目标是进行临时部署,验证安全控制,收集证据,并清理所有资源。
### AWS 实际部署
AWS 使用了基于 VM 的部署模型:
```
EC2 → Docker → Flask container
```
已完成的 AWS 工作:
- 创建了临时的 EC2 实例
- 将 Security Group 访问限制为我的 IP
- 在 EC2 上安装了 Docker
- 构建了 Docker 镜像
- 在端口 `5000` 上运行 Flask 容器
- 在浏览器中和使用 curl 验证了应用程序
- 在 EC2 主机上安装并运行了 Trivy
- 保存了 Trivy 运行时扫描报告
- 针对 AWS endpoint 运行了 OWASP ZAP baseline scan
- 保存了 ZAP HTML 和 JSON 报告
- 调查了为什么 GitHub Actions 没有显示相同的 Trivy 发现
- 停止并移除了容器
- 终止了 EC2 实例
- 测试后移除了临时的 AWS 资源
AWS 证据:
```
docs/evidence/practical/aws-practical-deployment-evidence.md
docs/evidence/practical/reports/trivy-week9-aws.txt
docs/evidence/practical/reports/zap-week9-aws.html
docs/evidence/practical/reports/zap-week9-aws.json
```
### GCP 实际部署
GCP 使用了托管式 serverless 容器部署模型:
```
Artifact Registry → Cloud Run → HTTPS endpoint
```
已完成的 GCP 工作:
- 启用了所需的 GCP API
- 创建了 Artifact Registry Docker 仓库
- 使用 Cloud Shell / Cloud Build 构建并推送了镜像
- 将镜像部署到 Cloud Run
- 暂时允许了公开访问以进行测试
- 使用了基于请求的计费
- 将最小实例数设置为 `0`
- 将最大实例数设置为 `1`
- 打开并验证了 Cloud Run URL
- 查看了 Cloud Run 日志
- 针对 GCP endpoint 运行了 OWASP ZAP baseline scan
- 保存了 ZAP HTML 和 JSON 报告
- 删除了 Cloud Run 服务
- 删除了 Artifact Registry 仓库
- 确认完成了 GCP 清理
GCP 证据:
```
docs/evidence/practical/gcp-practical-deployment-evidence.md
docs/evidence/practical/reports/zap-week9-gcp.html
docs/evidence/practical/reports/zap-week9-gcp.json
```
### AWS 与 GCP 部署模型对比
| 领域 | AWS 实际 | GCP 实际 |
|---|---|---|
| 运行时 | EC2 VM | Cloud Run |
| 容器执行 | 安装在 VM 上的 Docker | 托管式容器运行时 |
| 镜像存储 | 在 EC2 上本地构建 | Artifact Registry |
| 网络暴露 | Security Group 规则 | Cloud Run 公开访问设置 |
| DAST | 针对 EC2 endpoint 的 ZAP | 针对 Cloud Run URL 的 ZAP |
| 日志 | 运行时和 EC2 验证 | Cloud Logging |
| 清理 | 终止 EC2 并移除临时资源 | 删除 Cloud Run 服务和 Artifact Registry 仓库 |
这演示了传统的基于 VM 的部署和托管式 serverless 容器部署。
## 当前状态
该项目目前具有:
- 在本地运行的 Flask 应用
- 正常工作的 Docker 构建
- 使用非 root 用户的加固 Dockerfile
- 配置了基础的 Flask 安全响应头
- 正常工作的 GitHub Actions CI pipeline
- 配置了最小权限的工作流权限
- 已配置并测试的 Gitleaks
- 已配置并测试的 Semgrep
- 已配置并测试的 pip-audit
- 已配置并测试的 Trivy
- 已配置并通过的 CodeQL
- 已配置的 Dependabot
- 已配置并在本地测试的 pre-commit
- 添加了 OWASP ZAP DAST 工作流
- 作为 artifacts 上传的安全报告
- 作为 artifacts 上传的 ZAP DAST 报告
- 修复了真实的 Semgrep 发现
- 修复了真实的依赖项漏洞
- 修复了真实的容器加固发现
- 通过的安全门禁
- 完成了 AWS 实际安全部署证据
- 完成了 GCP 实际 Cloud Run 部署证据
- 记录了运行时 Trivy 扫描证据
- 记录了 CI 与运行时扫描行为
- 收集了 AWS 和 GCP ZAP 报告
- 清理了 AWS 和 GCP 临时资源
## 我学到了什么
- 如何使用最小权限来加固 GitHub Actions
- 如何将安全工具从被动的报告转化为阻断性的 CI 门禁
- 如何分析和修复真实的 SAST 发现
- 如何防止容器以 root 身份运行
- 如何将安全扫描报告作为 pipeline artifacts 上传
- 如何使用 CodeQL 进行 GitHub 原生代码扫描
- 如何使用 Dependabot 自动化依赖项更新
- 如何使用 pre-commit hooks 实现左移安全
- 如何针对实时的容器化应用程序运行 OWASP ZAP DAST
- 如何在运行时安全扫描之前使用 `/health` 检查
- 如何将安全发现和修复记录为作品集证据
- 如何在 AWS EC2 上部署 Docker 化的应用程序
- 如何在 GCP Cloud Run 上部署 Docker 化的应用程序
- 如何使用 Artifact Registry 进行容器镜像存储
- 如何比较基于 VM 的和托管式容器部署模型
- 扫描器配置如何隐藏或揭示漏洞发现
- 如何记录测试后的临时云资源清理
## 后续改进
计划的后续步骤:
- 使用 Syft 添加 SBOM 生成
- 使用 Cosign 添加容器镜像签名
- 添加基于 OIDC 的云部署
- 使用轻量级的本地或托管集群添加 Kubernetes 安全实验
- 添加云审计日志截图和检测笔记
- 为常见的云发现添加事件响应 runbook
- 添加 CSPM 式的云错误配置审查清单
- 添加带有安全回滚文档的自动化部署
## 相关安全项目
- [Multi-Cloud IaC Security Scanning](https://github.com/AbdelazezMohamedAzez/multi-cloud-iac-security-scanning)
## 作品集价值
该仓库展示了实用的 DevSecOps 和云安全工程师技能:
- 安全的 CI/CD pipeline 设计
- 安全门禁和自动化
- SAST、SCA、secret 扫描、容器扫描和 DAST
- Docker 加固
- 运行时漏洞调查
- AWS 安全部署证据
- GCP Cloud Run 部署证据
- 云清理规范
- 专业的安全文档
标签:DevSecOps, Docker, Python Flask, Web安全, 上游代理, 安全防御评估, 蓝队分析, 请求拦截, 逆向工具