kingsrule50/azure-static-website-lab

GitHub: kingsrule50/azure-static-website-lab

一个演示如何在 Azure 上通过 Terraform、GitHub Actions 和 OIDC 联邦身份认证实现零密钥安全交付静态网站的实验项目。

Stars: 0 | Forks: 0

# Azure 上的安全静态网站托管 — Terraform + GitHub Actions (OIDC) 我构建了这个实验来演示一个在尽可能小的足迹上运行的、完整的、生产级的交付工作流:Azure Blob Storage 上的静态网站。重点不在于网站本身,而在于流水线。Terraform 负责配置和强化基础设施;GitHub Actions 在每次推送到 `main` 分支时自动部署内容,并通过**不存储任何密钥的 OIDC 联邦身份验证**向 Azure 进行身份验证。 ## 架构 ``` Developer GitHub Azure ───────── ────── ───── git push main ──────▶ Actions workflow ──OIDC token──▶ Entra ID (federated credential) │ │ issues short-lived token │ ▼ └──── az storage blob ────▶ Storage Account (LRS) upload-batch └─ $web container │ Recruiter's browser ◀───── HTTPS / TLS 1.2 ──┘ (static website endpoint) ``` *(替换为渲染后的图表:`docs/architecture.png`)* ## 我的设计思路与原因 - **由 Terraform 管理的基础设施。** 资源组、存储帐户和静态网站配置全部在代码中声明,远程状态存储在我的中央 Terraform 状态存储帐户(`static-website.tfstate`)中——这是我在整个实验系列中使用的相同状态管理模式。 - **默认进行安全强化。** 仅限 HTTPS 流量、最低 TLS 1.2 以及完全禁用匿名 blob 访问——静态网站通过专用的 Web endpoint 提供服务,因此永远不需要公共 blob 访问。 - **零存储凭证。** GitHub Actions 流水线通过 Entra ID 应用注册进行身份验证,该应用注册具有作用域限定于此存储库 `main` 分支的**联合凭证**。没有会泄露、需要轮换或过期的客户端密钥。Azure 在工作流运行时颁发短期 token。 - **最小权限 RBAC。** 流水线身份仅持有 `Storage Blob Data Contributor` 和实验室资源组的 `Reader` 角色——它无法创建、修改或删除基础设施。 - **关注点分离。** Terraform 拥有基础设施生命周期;CI/CD 流水线仅拥有内容。两者都不能执行对方的任务。 ## 仓库结构 ``` ├── terraform/ # Infrastructure as Code (azurerm ~> 4.0) │ ├── providers.tf # provider + remote state backend │ ├── main.tf # RG, hardened storage account, static website │ ├── variables.tf │ └── outputs.tf # site URL + storage account name ├── site/ # Website content — deployed by CI/CD, not Terraform │ ├── index.html │ └── 404.html ├── .github/workflows/ │ └── deploy.yml # OIDC login → upload-batch to $web ├── scripts/ │ └── setup-oidc.sh # one-time app registration + federated credential + RBAC └── docs/screenshots/ # validation evidence ``` ## 部署演练 **1. 配置基础设施** ``` cd terraform terraform init terraform plan terraform apply terraform output website_url ``` **2. 一次性 OIDC 联邦设置** ``` az login bash scripts/setup-oidc.sh ``` 然后将其输出的四个值添加为 GitHub Actions **变量**(不是 secrets——它们都不敏感): `AZURE_CLIENT_ID`、`AZURE_TENANT_ID`、`AZURE_SUBSCRIPTION_ID`、`STORAGE_ACCOUNT`。 **3. 部署内容** ``` git add site/ && git commit -m "Update site" && git push ``` ## 验证证据 *(截图目标——在录制会话期间捕获)* 1. `terraform apply` 输出,显示已创建的资源 + `website_url` 输出 2. Azure Portal — 存储帐户 **Configuration** 边栏选项卡,显示 *Secure transfer required: Enabled* 和 *Minimum TLS: 1.2* 3. Azure Portal — **Static website** 边栏选项卡,显示已启用状态和主要 endpoint 4. GitHub Actions — 成功的工作流运行,其中 OIDC 登录步骤已展开 5. Entra ID — 应用注册 **Certificates & secrets** 边栏选项卡,显示联合凭证和 **零客户端密钥** 6. 资源组上的 IAM 边栏选项卡,仅显示两个最小权限角色分配 7. 浏览器中的实时站点,可见挂锁/HTTPS 标志 8. 针对直接 blob URL 的失败匿名访问尝试(证明公共访问已被禁用) ## 成本 包含两个 HTML 文件的标准 LRS 存储几乎没有成本(每月不到一美分)。与基于 VM 的实验不同,这个实验会永久运行——上面的实时 URL 始终可用。 ## 核心要点 - OIDC 工作负载身份联邦消除了最常见的 CI/CD 安全故障:流水线 secrets 中泄露的长期有效云凭证。 - Blob Storage 上的静态网站托管可以在完全禁用匿名 blob 访问的情况下工作——`$web` 容器通过专用 endpoint 提供服务,这是许多指南都弄错的一个细节。 - 在 azurerm provider v4.x 中,静态网站配置从内联块移到了独立的 `azurerm_storage_account_static_website` 资源。 - 将内容部署排除在 Terraform 之外(没有 `azurerm_storage_blob` 资源)意味着内容更改永远不会触及基础设施状态。 *我的企业 Azure 基础设施自动化作品集中的实验 · [github.com/kingsrule50](https://github.com/kingsrule50)*
标签:Azure, ECS, OIDC, Terraform, 后端开发, 基础设施自动化, 应用安全, 静态网站托管