grepstrength/CICDefense

GitHub: grepstrength/CICDefense

这是一个使用 Terraform 在 Azure 上自动构建 CI/CD 与软件供应链安全测试实验室的项目。

Stars: 0 | Forks: 0

![替代文本](https://static.pigsec.cn/wp-content/uploads/repos/cas/8e/8e17063b3a09286eecfbe1b2bab9fac11e9e6a01d522c56619bb82856a561cff.png) # CI/CD defense **通过 CI/CDefense 实践软件供应链安全!** 如果你在过去几年关注过网络安全公告,就会知道软件供应链在相当长的一段时间内一直持续受到攻击。因为我觉得学习如何防御自己的 CI/CD pipeline 是至关重要的,所以我启动了这个项目。 借此,你可以构建自己的 Azure 实验室,用于 CI/CD pipeline 和软件供应链安全测试。 ## 实验室架构 它在私有网络上拥有三台 VM,只能通过托管的堡垒机进行访问。没有任何 VM 使用公共 IP。 - **Ubuntu (最新 LTS)**:主要 CI 运行器,相当于自托管的 GitLab Runner 或 GitHub Actions runner - **Windows Server 2022 Datacenter**:用于 Windows 二进制文件和 .NET 构建的辅助运行器 - **notkali**:基于 Ubuntu 的对抗/DAST 节点,预装了用于模拟供应链攻击和扫描暴露 secret 的攻击性工具 网络态势: - VM 之间可以互相访问 - VM 可以访问互联网(允许流出以拉取 package 和模型) - 互联网上的任何设备都无法访问 VM(无流入) - 操作员访问通过 Azure Bastion 进行(**注意:**选择 Standard SKU 是一个*有意的*决定。如果你希望通过 Azure 门户中的 RDP 直接连接到 Linux 主机,则必须使用此项!) ## 构建内容 Azure(17 个资源): - 资源组、虚拟网络、工作负载子网、AzureBastionSubnet - 采用最小权限规则的安全组,以及子网关联 - Azure Bastion 主机及其静态公共 IP - 3 个网络接口,无公共 IP - 3 台虚拟机(除 Windows 运行器外,均为 Ubuntu 24.04) - 3 个用于安装桌面环境和工具的 VM 扩展 ## 前置条件 - Terraform CLI 1.9 或更高版本 - Azure CLI - 启用了计费的 Azure 订阅 - Git ### 可选但推荐 **注意:**这些必须手动创建/配置。 - 带有 HashiCorp Terraform 扩展的 VS Code - 多个虚拟账户 - GitHub - Azure - CircleCI ## 已验证的实验室 ### notkali(对抗 / DAST 节点) ![notkali 已验证](https://static.pigsec.cn/wp-content/uploads/repos/cas/4e/4ed78b8be7435e52f147f9a0ed483dfd6d28969b3ca648fe8b6bdb96541dc290.png) 确认项:`labmin` 登录,`notkali-dast` 主机名,私有 IP `10.0.2.6`(无公共 IP),通过 Bastion (RDP) 连接的 XFCE 桌面,已安装 ZAP,并且攻击性工具链可在 PATH 中解析(nmap、sqlmap、nikto、gobuster、ffuf、trufflehog、gitleaks、amass)。 ### Ubuntu(CI 运行器) ![ubuntu 已验证](https://raw.githubusercontent.com/grepstrength/CICDefense/main/screenshots/ubuntu-validated.png) 确认项:`ubuntu-runner`,私有 IP `10.0.2.4`,通过 Bastion (RDP) 连接的 XFCE 桌面。后台的 systemd 安装已完成 — Docker(注意正在运行的 `docker0` 网桥)、Syft、Grype、Trivy、.NET、Go、Rust 和 osquery 均可在 PATH 中解析,证明延迟安装模式有效。 ### Windows(辅助运行器) ![windows 已验证](https://static.pigsec.cn/wp-content/uploads/repos/cas/88/8897679b3b603f45943801a84b0c9ffd2c92450a085d4ea325a9c4cb1e1dcfa7.png) 确认项:`win-runner`,私有 IP `10.0.2.5`,以及 Sysmon 正在通过 SwiftOnSecurity 配置主动将 Process Create (Event ID 1) 事件记录到操作日志中。 ## 快速开始 ### 1. 认证 ``` az login az account show --query id --output tsv ``` 复制打印出的订阅 GUID。 ### 2. 创建变量文件 `terraform.tfvars` 已被 gitignore,不在此 repo 中。从模板创建它: ``` copy terraform.tfvars.example terraform.tfvars ``` 然后填写: - `subscription_id` — 步骤 1 中的 GUID - `location` — 默认为 `centralus` - `admin_username` — 不能是 admin、administrator、root、guest、user 或 test - `admin_password` — 12 个字符以上,包含大小写字母、数字、符号 为了防止密码留在磁盘上,请将其设置为环境变量并从文件中省略: ``` $env:TF_VAR_admin_password = "your-password-here" ``` ### 3. 部署 ``` terraform init terraform validate terraform plan terraform apply ``` 预计需要 20 到 40 分钟。仅 Bastion 本身就需要 5 到 10 分钟,而且 notkali 扩展会安装大量攻击性工具集。 ### 4. 连接 ``` terraform output ``` 在 Azure 门户中,转到资源组,选择一台 VM,然后依次选择连接、Bastion。使用你的管理员用户名和密码登录。 所有三台 VM 均支持 RDP。Linux 节点上安装了 xrdp,因此它们提供图形化桌面,而不是纯 shell。对于 Linux VM,在 Bastion 连接窗格中选择协议:RDP,端口 3389(由 Standard SKU 启用)。通过 az network bastion tunnel + mstsc 进行的原生客户端隧道也可使用。 ### 通过原生 RDP 客户端连接 门户中的 Bastion 连接窗格适用于 Windows (RDP) 和 Linux(通过 Standard SKU 协议选项的 RDP)。如果你更愿意使用本地 RDP 客户端 — 用于剪贴板共享、文件传输或多显示器 — 请从 PowerShell 打开 Bastion 隧道并从中进行连接。 需要 Bastion **Standard** SKU 且 `tunneling_enabled = true`(两者均 在 `bastion.tf` 中设置)。 打开到 VM 的隧道。保持此窗口运行 — 它用于维持隧道打开: ``` az network bastion tunnel ` --name cicdefense-bastion ` --resource-group cicdefense-rg ` --target-resource-id "" ` --resource-port 3389 ` --port 13389 ``` 使用以下命令获取 VM 的资源 ID: ``` az vm show --resource-group cicdefense-rg --name cicdefense-ubuntu --query id --output tsv ``` 然后,在第二个窗口中,针对本地隧道端口启动远程桌面: ``` mstsc /v:localhost:13389 ``` 使用你的 `admin_username` 和 `admin_password` 登录。对于第二台 VM,请在不同的本地端口上打开另一个 隧道(例如 `--port 13390`),以便两者可以同时运行。 ### 5. 销毁 ``` terraform destroy ``` 在每次会话结束时执行此操作。 ## 已安装的工具 配置脚本位于 `scripts/` 中,并通过 VM 扩展自动运行。 在 Ubuntu 运行器上,较重的工具链和扫描器会在首次启动后通过 systemd 一次性单元在后台安装,因此部署会很快完成。如果在你连接后工具没有立即出现,说明它仍在安装中;请检查 `/var/log/cicdefense-detection-install.log`。 所有节点: - git - VS Code - Ollama Ubuntu(主要 CI 运行器): - XFCE 桌面和 xrdp - 构建工具链:build-essential (gcc/g++/make)、Python (pip、venv) - 后台工具链:Docker CE、Node.js/npm、JDK + Maven、.NET SDK 8.0、Go、Rust - 检测:auditd(带规则集)、osquery、Wireshark、mitmproxy - SBOM 和漏洞扫描:Syft、Grype、Trivy Windows Server 2022(用于 Windows 特定测试用例的辅助运行器,通过直接下载安装,无包管理器): - git、VS Code、Ollama - .NET SDK 8.0、Node.js - 检测:Sysmon(带 SwiftOnSecurity 配置)、Procmon、Autoruns、Regshot - IE 增强的安全配置已禁用 - C++ 构建工具 (MSVC) **未**进行配置 — Visual Studio Build Tools 的安装体积大且速度慢。如有需要,请手动安装:`winget install Microsoft.VisualStudio.2022.BuildTools` notkali(对抗 / DAST 节点): - XFCE 桌面和 xrdp - 侦察和 OSINT:nmap、masscan、dnsrecon、amass(通过 snap)、whatweb、theHarvester - Web 应用测试:sqlmap、nikto、gobuster、ffuf、wfuzz、OWASP ZAP - Secrets 扫描:trufflehog、gitleaks - 流量:Wireshark、mitmproxy - Burp Suite Community 已下载到 Downloads 文件夹,但尚未安装。如果你需要使用它,必须自行安装 ### 语言模型 Ollama 已安装,但在配置期间未拉取模型,因为下载量很大,可能会导致扩展超时。在首次登录后拉取它们: ``` ollama pull gemma4:e4b ollama pull R4C3R/minicpm5-1b-fable5-heretic ``` 我选择这些是因为它们符合我的预期用例,但当然你可以为这个实验室选择任何你想要的模型。 默认的 `Standard_D2s_v5` 规格(2 个 vCPU,8 GB RAM)可以轻松运行小型模型。如需更多空间,请在 `terraform.tfvars` 中调大 `vm_size`。 ## 成本 此实验室按小时计费。为了你的理智,在不使用时请将其销毁。 在 centralus 地区大约每小时 0.55 到 0.65 美元,细分为: - 3 台 D2s_v5 VM,每台约 $0.10/小时(取决于地区) - Azure Bastion Standard SKU,约 $0.29 - OS 磁盘(Linux 节点上的 64 GB StandardSSD),每小时几美分 - 静态公共 IP,约 $0.005 免费:资源组、虚拟网络、子网和网络安全组 请针对你所在的地区和订阅通过 Azure 定价计算器进行验证。 注意: - 无论你是否通过 Bastion 连接,它仅仅因为存在就会计费 - 即使 VM 已停止,OS 磁盘也会计费;停止并不等同于销毁 - `terraform destroy` 会删除所有内容,包括磁盘 四个小时的会话花费几美元。被遗忘一周的耗费大约为 100 美元。 ## 安全说明 请记住这是一个实验室。我刻意在几件事情上选择了便利性而非强化安全性: - Windows 配置脚本在部署时从公共 GitHub 原始 URL (raw.githubusercontent.com/.../win-setup.ps1) 获取并执行。它固定在一个分支而不是 commit 上,因此相同的配置随着时间的推移可能会拉取不同的脚本。这正是本实验室研究的远程获取供应链风险的生动实例。 - Linux VM 上已启用密码身份验证。SSH 密钥是普遍接受的安全做法。这之所以是可辩护的,仅仅是因为 VM 没有公共 IP,并且只能通过 Bastion 访问。如果要切换,请将 `disable_password_authentication = false` 替换为 `admin_ssh_key` 块。 - Terraform state 包含明文形式的 secret。将变量标记为 sensitive 只会将其从控制台输出中隐藏。State 文件已被 gitignore,但生产设置将使用带有静态加密和 state 锁定的远程 backend。 - 配置脚本使用了通过管道传递给 shell 的 curl。Ollama 安装程序执行了未经审查的远程脚本。这是标准的安装路径,坦白说,也是本实验室旨在研究的那类问题的生动实例,与本节中的其他配置一样。 - notkali 上的几个攻击性工具是从供应商安装脚本和 GitHub 发行版二进制文件安装的,而不是已签名的发行版 package。这既方便又常见,也正是本实验室旨在研究的未经核实的供应链步骤。 - 镜像版本设置为 `latest` 而非固定版本。这仅仅是为了方便。最终结果是,相同的配置随着时间的推移会产生不同的镜像。如果你想要完全可复现的构建,请固定你想要的精确版本。 - 出口不受限制。向 NSG 添加出站拒绝规则是顺理成章的下一步强化练习,这也是能够阻止受到破坏的运行器泄露 secret 的控制措施。 切勿提交 `terraform.tfvars` 或 `.tfstate` 文件。两者均在 repo 根目录下被 gitignore。 ## 故障排除 **terraform plan 提示输入变量。** 某个必需的变量没有值。请检查 `terraform.tfvars` 是否存在并已填写完整。 **Azure CLI 不知道订阅 ID。** `terraform.tfvars` 中的 GUID 与你登录的会话不匹配。运行 `az account list --all --output table` 并进行比较。同时确认你登录的是正确的账户,特别是当你有多个账户时。 **SkuNotAvailable 或 NotAvailableForSubscription。** 你的区域 vCPU 配额可能为零或太低,或者该 VM 规格系列未向你所在地区的订阅提供。使用 `az vm list-usage --location --output table` 检查并查看 Limit 列。通过请求增加配额(在门户中搜索 Quotas、Compute)或选择你的订阅可用的区域或规格来解决此问题。 **Marketplace 套餐已移除,无法用于新购买。** 该镜像已从 Marketplace 撤回(这就是为什么对抗节点使用原生的 Ubuntu 加上工具,而不是官方的 Kali 镜像)。请使用原生镜像并通过配置脚本安装工具。 **PlatformImageNotFound。** Marketplace 镜像引用发生了偏移。请使用以下命令进行验证: ``` az vm image list --publisher --offer --location centralus --all --output table ``` **Bastion 连接窗格仅显示 Linux VM 的 SSH。** RDP 协议选项需要 Bastion **Standard** SKU(或更高版本)。在 SKU 上,门户仅为 Linux VM 提供 SSH,因此你获得的是一个终端而不是 XFCE 桌面。在 `azurerm_bastion_host` 资源上设置 `sku = "Standard"` 并重新应用。SKU 可以就地升级(无需重新构建)。 **`az network bastion tunnel` 失败:“Bastion Host SKU must be Standard or Premium and Native Client must be enabled.”** 根本原因与上述相同。原生客户端隧道需要 Standard(或 Premium)SKU **并且**在 `azurerm_bastion_host` 资源上设置 `tunneling_enabled = true`。同时设置两者并重新应用,然后重新运行隧道命令。 **扩展失败并显示“VM has reported a failure”。** Terraform 无法查看脚本内部。通过 Bastion 连接并阅读日志。在 Linux 上,查看 `/var/log/azure/custom-script/handler.log`。在 Windows 上,阅读 `C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\*\Downloads\` 下的 stderr。 **通过 RDP 连接到 Linux VM 后出现空白的灰屏。** `.xsession` 文件丢失或所有者错误。检查安装脚本是否为正确的用户编写了该文件。 **templatefile 错误:“vars map does not contain key ...”。** 配置脚本使用了带有花括号语法 (`${VAR}`) 的 bash 变量,这与 Terraform 的 `templatefile()` 插值发生冲突。请将其转义为 `$${VAR}`,以便 Terraform 将其传递给 bash。只有 `${admin_username}` 应该保留单美元符号(该项旨在由 Terraform 注入)。 **notkali 上缺少 OWASP ZAP。** ZAP 通过 snap 安装,而 snapd 在首次启动配置期间有时尚未就绪,因此安装可能会静默失败(根据设计,这不是致命错误)。如果 ZAP 不存在,请在连接后重新运行 `sudo snap install zaproxy --classic`。 **Windows 扩展失败并显示 404 / “failed to download the blob”。** Windows 扩展在部署时从公共 GitHub 原始 URL 获取 `scripts/win-setup.ps1`。如果你编辑了脚本但未推送,或者 `extensions.tf` 中的文件名(`fileUris` + `-File`)与实际文件不匹配,下载将返回 404。在应用之前,确认原始 URL 可在浏览器中解析,并确保文件、`fileUris` URL 和 `commandToExecute -File` 参数全都写明 `win-setup.ps1`。 **其他方法均无效。** 开启调试日志: ``` $env:TF_LOG = "DEBUG" terraform plan $env:TF_LOG = "" ``` ## 路线图 - [x] 检测和日志层:Windows 上的 Sysmon;运行器上的 auditd 和 osquery;使用 Syft、Grype 和 Trivy 进行 SBOM 和漏洞扫描 - [ ] 用于攻击场景的预置漏洞 pipeline(这就是 CircleCI/GitHub 虚拟账户的用武之地) - [ ] 带有锁定的远程 state backend - [ ] 出口过滤练习 - [ ] 固定的镜像版本以实现可复现的构建 - [ ] 集中日志聚合,以便将来自所有三台 VM 的检测事件发送到同一个地方 ## 许可证 完全免费,即 MIT。
标签:AI风险缓解, Azure, ECS, Terraform, 基础架构即代码, 安全实验环境, 安全测试, 攻击性安全, 请求拦截