TacoRocket/terraform-labs-for-azurefox
GitHub: TacoRocket/terraform-labs-for-azurefox
一个基于 OpenTofu 的 Azure 靶场,托管可销毁资源以供 AzureFox 进行端到端验证与取证。
Stars: 1 | Forks: 0
# AzureFox OpenTofu 证明实验室
```
OpenTofu 也会使用 Azure CLI 会话,除非您通过环境变量覆盖身份验证。
`tofu apply` 在部署历史记录盖章期间会使用本地的 `tofu`、`az` 和 `python3` 可执行文件。OpenTofu 会自动将所需值传递给辅助脚本,因此您无需手动设置额外环境变量。
以下示例使用 Bash(如有不同,PowerShell 等效命令会另行显示)。
## 配置
复制示例变量文件并替换 SSH 公钥:
```
cp tofu.tfvars.example terraform.tfvars
```
```
Copy-Item tofu.tfvars.example terraform.tfvars
```
编辑 `terraform.tfvars` 并设置:
- `ssh_public_key` 使用 RSA 公钥
- `name_prefix` 如需不同的全局唯一存储名称前缀
- 如需要,可覆盖 VM 规格
当前经过测试的备用默认值:
- `location = "centralus"`
- `vm_size = "Standard_D2s_v3"`
- `vmss_sku = "Standard_D2s_v3"`
选择这些默认值的原因:
- 较小的 B 系列及其他低成本 SKU 可能被新订阅或近期升级的订阅阻止(显示 `NotAvailableForSubscription`)
- `Standard_D2s_v3` 在 `centralus` 已验证可用,且使用的系列在此订阅中具有非零默认配额
- 这是面向 POC 的备用配置,并非长期理想的成本配置
生成兼容的密钥对:
```
ssh-keygen -t rsa -b 4096 -f ~/.ssh/azurefox_lab_rsa -C "azurefox-lab" -N ""
cat ~/.ssh/azurefox_lab_rsa.pub
```
```
ssh-keygen -t rsa -b 4096 -f $HOME/.ssh/azurefox_lab_rsa -C "azurefox-lab" -N ""
Get-Content $HOME/.ssh/azurefox_lab_rsa.pub
```
## 部署
```
tofu init
tofu plan
tofu apply
```
`tofu apply` 也会在链接模板工件存在后,通过一个小的 Azure CLI 辅助程序盖章 Phase 2 ARM 部署历史对象。它会创建一个成功的订阅级部署、一个成功的资源组部署和一个失败的资源组部署,以便 AzureFox 验证部署历史记录的覆盖情况。
应用后的有用输出:
```
tofu output subscription_id
tofu output -json role_trusts_manifest
tofu output -json validation_manifest
```
如果更改了 `outputs.tf` 或清单期望,在重新运行验证之前,请刷新 OpenTofu 状态,以避免 `validation_manifest` 与当前分支不匹配:
```
tofu apply -refresh-only
```
## 验证 AzureFox 对应的实验室
在首选环境中安装 AzureFox 包依赖项,然后运行:
```
python3 scripts/validate_azurefox_lab.py
```
默认情况下,验证器会:
- 读取 `tofu output -json validation_manifest`
- 从 `--azurefox-dir` 执行 AzureFox
- 以 `--mode full` 运行,执行当前发布门槛下的独立 AzureFox 命令集
- 将默认 `--mode full` 视为管理员证明路径
- 在每个 AzureFox 步骤前后打印进度行,包括耗时和输出目录
- 记录每个命令的 UTC 开始和结束时间戳及持续时间到 `command-timeline.json`
- 将证明工件存储在 `proof-artifacts/latest`
现提供支持视角感知的验证:
- `admin` 保持当前的发布门槛,应看到最完整的实验室真实情况
- `dev` 使用受限的工作负载 `Contributor` 服务主体,仍应返回有用的面向工作负载的输出,而无需订阅范围的真实情况
- `lower-privilege` 使用工作负载 `Reader` 服务主体,应返回诚实的部分可见性,而非误导性的空结果
缩减视角会故意运行更小的命令路径:
- `whoami`
- `principals`
- `permissions`
- `managed-identities`
- `workloads`
- `functions`
这些缩减路径用于证明在更窄立足点下的诚实行为,而不是替代管理员发布门槛。
若要获取更丰富的 `devops` 证明,请在运行验证器之前将 AzureFox 指向真实的 Azure DevOps 组织:
```
export AZUREFOX_DEVOPS_ORG=
```
可选标志:
```
python3 scripts/validate_azurefox_lab.py \
--azurefox-dir /path/to/azurefox \
--artifacts-dir ./proof-artifacts/run-01
```
有用的范围限定重新运行:
```
python3 scripts/validate_azurefox_lab.py --mode commands-only
python3 scripts/validate_azurefox_lab.py --mode full
python3 scripts/validate_azurefox_lab.py --mode full --skip-command role-trusts
python3 scripts/validate_azurefox_lab.py --mode commands-only --viewpoint dev
python3 scripts/validate_azurefox_lab.py --mode commands-only --viewpoint lower-privilege
python3 scripts/validate_azurefox_lab.py --viewpoint all
```
运行时说明:
- 使用 `--mode full` 作为端到端单次验证运行
- `commands-only` 现在是 `full` 命令系列的显式独立重新运行别名
- `--viewpoint admin` 是默认值,保持现有的发布门槛工件布局
- `--viewpoint dev` 和 `--viewpoint lower-privilege` 需要 `--mode commands-only`;它们使用敏感的 OpenTofu 输出以及隔离的 `AZURE_CONFIG_DIR` 会话,因此验证器不会覆盖操作员的主要 Azure CLI 登录
- `--viewpoint all` 会同时运行管理员路径和两个缩减路径,并将缩减路径工件存储在 `proof-artifacts/latest/viewpoints/`
- 如果实验室已就绪且仅更改了输出或验证器期望,请在重新运行验证之前刷新
OpenTofu 状态,以避免因过时的 `validation_manifest` 数据导致误报不匹配
- 使用 `--mode commands-only` 当您只需要单个命令输出而不需要编排通过
- `role-trusts` 可能耗时较长,因为 Azure API 路径较慢;验证器现在会在该步骤期间输出周期性等待信息,而非显示挂起
- 在 `role-trusts` 首次验证后,重新运行可使用 `--skip-command role-trusts`,除非您更改了该切片或遇到指向它的阻塞问题
- Key Vault 替换在 `tofu apply` 期间可能耗时数分钟进入 Azure 软删除状态,然后重新创建完成;请将其视为已知缓慢路径,而非意外挂起
- 更一般地,请不要默认重新运行已知缓慢的验证路径;仅在确实需要时再执行
- 当变更的切片触及它、存在实时阻塞点,或团队明确需要额外证明时,才执行
- 使用 [docs/live-run-strategy.md](/Users/cfarley/Documents/Terraform Labs for AzureFox/docs/live-run-strategy.md) 作为完整运行与快速重新运行的策略规范
工件包括:
- 每个 AzureFox 命令的一个 JSON 有效负载
- AzureFox 输出的副本(loot 文件)
- `command-timeline.json`
- `summary.json`
- `summary.txt`
- 当同时运行多个视角时,每个视角一个子文件夹,以及 `viewpoint-summary.json` 和 `viewpoint-summary.txt`
- `azurefox-mismatch-report.md`
- `identity-mismatch-report.md`
可选的 SOC/检测工件流程:
- `command-timeline.json` 现在为每个 AzureFox 验证命令记录 UTC 开始和结束标记以及持续时间,以便分析师可将这些标记与 Azure 控制平面活动相关联
- 此时间戳工件仅覆盖验证器命令路径;请在需要时单独记录 `apply` 和 `destroy` 时间戳以获取完整实验室窗口
- 使用 [docs/activity-log-bundles.md](/Users/cfarley/Documents/Terraform Labs for AzureFox/docs/activity-log-bundles.md) 从本地提取 Azure 活动日志到整个实验室窗口,并与阶段标记和验证器命令标记一起打包
- 打包脚本为 [export_activity_log_bundle.py](/Users/cfarley/Documents/Terraform Labs for AzureFox/scripts/export_activity_log_bundle.py)
## 证据边界
本实验室用于验证 AzureFox 输出与实际 Azure 对象。它不是工具本身中清晰表述或基于证据的发现的替代。
AzureFox 可直接通过只读控制平面和 Graph 数据验证的内容:
- 应用注册、服务主体、所有者边、联合凭证、应用角色分配或可读取 API 中的授权策略行是否存在
- 资源或身份是否可见,以及 AzureFox 如何对其进行汇总
- 当 Graph 返回权限或可见性错误时,策略表面是否部分不可读
- Key Vault 网络立场、私有端点存在与清除保护立场是否存在于管理元数据中
- 部署历史记录是否记录了输出、链接模板或参数 URI 以及失败状态元数据
- 应用服务与函数应用设置是否暴露了明文或 Vault 托管的配置路径
- 托管标识令牌表面是否在 Web 工作负载、VM 和部署历史记录中相关联
- Azure 托管的应用服务与函数应用主机名是否为可见控制平面端点路径,而非证明实时入口
- NIC 支持的公共入口证据是否来自可见的 NSG 允许规则,而非推测的可达性
- 存储、VMSS、自动化、API Management、AKS、ACR 和 Azure SQL 的深度是否保持基于证据,且仅凭管理元数据可见
- 当前 DNS 边界是否停留在区域库存和私有端点支持的命名空间使用上,而非记录导出或实时解析证明
- `lighthouse`、`cross-tenant` 和 `devops` 是否诚实地处理外部前提条件、租户形态或部分读取边界
仅实验室可确认的内容(一旦基础设施存在且验证器已运行):
- RBAC 可见性是否足以让 AzureFox 提取预期的服务主体进入 `role-trusts`
- 信任边是否在部署后存活并在实时租户中按预期显示
- AzureFox 表述是否偏离元数据实际证明的内容
- `tokens-credentials` 是否仍包含 Web 工作负载的身份标识(当该工作负载没有环境变量行时)
- 组合的 `resource-trusts` 路径是否与存储和 Key Vault 的实时对象保持一致
- Key Vault 清除保护发现是否不包含在 `resource-trusts` 中
本阶段不测试的内容:
- 来自外部颁发方的实时联邦令牌交换
- 通过真实登录流程执行的委托 OAuth 同意路径
- 租户范围的身份验证策略强制执行结果(如 Conditional Access 登录时的行为)
- 通过运行工作负载实际检索 Key Vault 机密
- 工作负载本身的实时 IMDS 或托管标识令牌交换
- 私有端点从虚拟网络内的可访问性
- 记录内容、记录目标分析或实时 DNS 解析行为
## 销毁
拆除实验室:
```
tofu destroy
```
不要将本地 `tofu destroy` 退出视为最终真相。请先通过 Azure 确认已删除标记的实验室足迹,然后再宣布拆除完成:
```
az group list --query "[?tags.project=='azurefox-proof-lab'].{name:name,location:location,provisioningState:properties.provisioningState}" -o json
az resource list --tag project=azurefox-proof-lab --query "[].{name:name,type:type,group:resourceGroup,location:location}" -o json
```
如果任一查询仍返回实验室组或资源,请认为拆除不完整,并重试或
在关闭运行前清理剩余阻塞项。
## Terraform 用户说明
如果您更习惯使用 Terraform,本实验室应该仍然熟悉:
- 配置文件仍位于常规的 `.tf` 文件中
- 提供者配置使用 `hashicorp/azurerm`
- 本地状态仍为 `terraform.tfstate`
- 锁定文件仍为 `.terraform.lock.hcl`
需要注意的实际差异:
- 运行 `tofu` 而非 `terraform`
- 在 `tofu init` 后检查 `.terraform.lock.hcl` 变更
- 避免在相同状态上交替使用 `terraform` 和 `tofu`,除非团队明确支持该工作流
- 大多数 Azure 示例都基于 Terraform 风格,因此请仔细转换命令
## 已知 OpenTofu 注意事项
- 工具链和 CI 作业需要调用 `tofu`,而非 `terraform`
- 锁定文件名称仍为 `.terraform.lock.hcl`,熟悉但容易在审查时忽略
- 本地状态仍使用 `terraform.tfstate`,因此混合工具使用可能导致贡献者混淆(若未记录工作流)
- 本 v1 实验室避免使用 OpenTofu 专属语言特性,以减少对 Terraform 用户的意外
- 如果实验室后续采用远程状态,请在与团队协商后端行为和工作流程后再标准化
## 成本与容量说明
- 长期实验室形态倾向于在许可允许的情况下使用更低成本的 VM SKU
- 某些新或近期升级的 Azure 订阅会返回 `NotAvailableForSubscription`,即使跨多个区域,小型 VM 系列也可能不可用
- 当前仓库默认使用 `Standard_D2s_v3`(位于 `centralus`),因为该组合已验证在此订阅中可部署
- 对于公开发布,请重新评估配额/SKU 访问权限,并在可能时改用更小的默认值
## 发布准备
发布准备说明位于:
- `VERSION`
- `CHANGELOG.md`
- `docs/release-process.md`
- `docs/release-readiness-checklist.md`
使用这些文档保持可重复的发布决策。在此仓库中,发布准备主要关注
可部署性、验证质量、工件质量以及明确的配额或成本指导。发布标签
应镜像 AzureFox 的确切版本号。
## 许可证
本仓库使用与主 AzureFox 项目相同的 MIT 许可证。请参见 [LICENSE](LICENSE)。
标签:ACR, AKS, API 管理, Azure, AzureFox, Azure 部署, CLI, DNS, EC2, ECS, IaC, Lighthouse, OpenTofu, PoC, RBAC, SEO: AzureFox 验证, SEO: Azure 实验室, SEO: OpenTofu 示例, SEO: 一次性订阅部署, Terraform, VMSS, WiFi技术, 一次性订阅, 代码分析, 凭证管理, 函数, 反取证, 取证, 可重复部署, 存储, 安全评估, 实验室环境, 密钥保管库, 应用服务, 快照与磁盘, 指标共享, 数据库, 暴力破解, 权限, 演示环境, 生成式AI安全, 网络, 网络调试, 自动化, 蓝军, 虚拟机, 覆盖范围, 角色信任, 资源发现, 跨租户, 逆向工具, 验证, 验证运行