shurugiken/terraform-aws-secure-baseline
GitHub: shurugiken/terraform-aws-secure-baseline
一个可复用的 Terraform 模块,用于一键创建经过安全加固的 AWS S3 存储桶及最小权限 IAM 角色,解决因默认配置导致的数据泄露风险。
Stars: 0 | Forks: 0
# terraform-aws-secure-baseline
一个小巧、可复用的 Terraform 模块,用于配置一个**经过安全加固的 AWS S3 bucket** 以及一个仅限该 bucket 范围的**最小权限 IAM role**。这是一个默认安全存储基线的参考实现,你可以将其直接放入更大的配置中。
## 为什么需要这个模块
大多数 S3 数据泄露事件都源于默认配置:公开的 bucket、未配置加密、没有版本控制以从错误的覆盖中恢复,或者 IAM policy 中对 `*` 资源设置了 `s3:*` 权限。这个模块将那些枯燥但正确的设置集中在一处,确保它们保持一致且可供审查,而不是每次都手动点击配置。
## 创建的内容
- 一个 S3 bucket,包含:
- 静态**服务端加密**(默认为 SSE-S3 / AES256,如果传入 key ARN 则使用 SSE-KMS)
- **阻止所有公开访问**(`aws_s3_bucket_public_access_block`,四项设置均为 `true`)
- **启用版本控制**
- 一条**生命周期规则**,使非当前版本过期并中止未完成的分块上传
- 一条**拒绝非 TLS (HTTP) 请求的 bucket policy**
- 一个**最小权限的 IAM role + 内联 policy**,范围仅限于该 bucket 的 ARN(不使用跨账户/bucket 的资源通配符)
- 通过单个 `tags` 变量将**一致的标签**应用于所有可标记的资源
## 要求
| 名称 | 版本 |
| --------- | --------- |
| terraform | >= 1.5 |
| aws | ~> 5.0 |
执行 `fmt`、`init -backend=false` 或 `validate` 不需要 AWS 凭证。仅在执行 `plan`/`apply` 时才需要凭证。
## 用法
```
module "secure_bucket" {
source = "github.com/shurugiken/terraform-aws-secure-baseline"
bucket_name = "my-app-secure-bucket"
iam_role_name = "my-app-bucket-access"
# Optional: use SSE-KMS instead of SSE-S3
# kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/YOUR_KEY_ID"
tags = {
Environment = "prod"
Owner = "platform-team"
ManagedBy = "terraform"
}
}
```
完整且可直接运行 `validate` 的示例位于 [`examples/basic`](examples/basic)。
## 输入
| 名称 | 描述 | 类型 | 默认值 |
| ------------------------------------ | ------------------------------------------------------------------------ | ------------- | ------------------------------------ |
| `bucket_name` | 全局唯一、符合 DNS 规范的 bucket 名称 | `string` | 无(必填) |
| `kms_key_arn` | 用于 SSE-KMS 的 KMS key ARN;如果为 `null`,则使用 SSE-S3 (AES256) | `string` | `null` |
| `versioning_enabled` | 启用对象版本控制 | `bool` | `true` |
| `noncurrent_version_expiration_days` | 非当前版本在被删除前的天数 | `number` | `90` |
| `abort_incomplete_multipart_days` | 未完成的分块上传在中止前的天数 | `number` | `7` |
| `iam_role_name` | 最小权限 IAM role 的名称 | `string` | `"secure-baseline-bucket-access"` |
| `tags` | 应用于所有可标记资源的标签 | `map(string)` | `{ ManagedBy, Module }` |
## 输出
| 名称 | 描述 |
| -------------------- | -------------------------------------------- |
| `bucket_id` | Bucket 名称 (ID) |
| `bucket_arn` | Bucket ARN |
| `bucket_domain_name` | 区域域名 |
| `iam_role_arn` | 最小权限 IAM role 的 ARN |
| `iam_role_name` | 最小权限 IAM role 的名称 |
## 安全逻辑 — 为什么需要每一项控制
**阻止所有公开访问(`aws_s3_bucket_public_access_block`,四项均为 `true`)。**
这是价值最高的控制项。它会覆盖任何原本会授予公开访问权限的 bucket ACL 或 policy,因此后续的错误配置不会意外暴露数据。这四项设置涵盖了基于 ACL 和基于 policy 的公开授权,适用于现有和未来的授权。
**静态服务端加密。**
如果底层存储在预期路径之外被访问,加密对象可以保护数据。SSE-S3 (AES256) 是免费的,且不需要密钥管理。SSE-KMS 增加了可审计的密钥、基于密钥的访问控制以及 CloudTrail 对解密操作的可见性——代价是需要管理一个密钥。该模块默认使用 SSE-S3,并允许你通过传入 key ARN 来选择使用 KMS;对于 KMS,系统会开启 `bucket_key_enabled` 以降低 KMS 请求成本。
**拒绝非 TLS 请求(基于 `aws:SecureTransport` 的 bucket policy)。**
静态加密对通过网络传输的数据不起作用。此 policy 会拒绝任何非通过 HTTPS 发出的请求,从而弥补了传输过程中的安全漏洞,使得两项加密控制相辅相成而非存在遗漏。
**启用版本控制。**
版本控制保留了先前的对象版本,这是应对意外覆盖、意外删除和勒索软件式篡改的实用恢复机制。如果没有它,覆盖操作将是不可恢复的。
**生命周期规则(使非当前版本过期 + 中止未完成的分块上传)。**
没有生命周期管理的版本控制意味着旧版本会永远累积,并在不知不觉中增加你的账单。该规则会在可配置的时间窗口后使非当前版本过期,并中止失败的分块上传,否则这些失败的上传会留下孤立且需计费的部件,而这些部件在控制台的对象列表中是不可见的。
**最小权限 IAM(role + 限定在 bucket 范围内的 policy)。**
该 policy 仅授予典型工作负载所需的操作(对 bucket 的 `ListBucket`;对其对象的 `GetObject`/`PutObject`/`DeleteObject`),并将其范围限定为此 bucket 的 ARN——没有 `Resource: "*"`,也没有 `s3:*`。这限制了爆炸半径:使用此 role 的受损凭证无法读取或修改任何其他 bucket。信任 policy 允许 EC2 担任此 role;请更改 principal 以匹配你的实际工作负载(Lambda、ECS task 等)。
**一致的标签。**
单一的 `tags` 变量会应用于每一个可标记的资源,从而确保所有权、环境和成本分配在整个资产范围内保持一致且可查询。
## 限制
- 这是一个**参考模块**,不是开箱即用的合规包。它不配置服务器访问日志、MFA 删除策略、Object Lock / WORM、复制或专用的 CloudTrail 数据事件追踪——具体取决于你的控制要求,这些可能都是必须的。
- IAM 信任 policy 默认使用 **EC2 服务 principal**。在应用之前,请根据你的实际使用者进行调整。
- `bucket_name` 必须是**全局唯一的**;如果按原样应用,示例名称将会发生冲突。
- 这里没有配置远程 backend 或状态加密——这属于消耗该模块的根配置的职责。
## 本地验证
```
terraform fmt -check -recursive
terraform init -backend=false -input=false
terraform validate
```
## 许可证
MIT — 参见 [LICENSE](LICENSE)。
标签:AWS, DPI, ECS, IAM, S3, Terraform, 云安全配置, 安全基线, 教学环境, 漏洞利用检测