15. 使用 Terraform 为 DynamoDB 访问附加 IAM 策略
Source: Dev.to
实验信息
DevOps 团队的任务是创建一个安全的 DynamoDB 表,并使用 IAM 强制细粒度访问控制。此设置将仅允许受信任的 AWS 服务安全且受限地访问该表。
作为 Nautilus DevOps Team 的成员,您的任务是使用 Terraform 完成以下操作:
- 创建 DynamoDB 表 – 一个名为
datacenter-table的表,使用最小配置。 - 创建 IAM 角色 – 一个名为
datacenter-role的角色,允许访问该表。 - 创建 IAM 策略 – 一个名为
datacenter-readonly-policy的策略,授予对特定 DynamoDB 表的 只读 访问(GetItem、Scan、Query),并将其附加到角色。 - 创建
main.tf文件(不要创建单独的.tf文件),用于配置表、角色和策略。 - 创建
variables.tf文件,包含以下变量:KKE_TABLE_NAME– DynamoDB 表的名称KKE_ROLE_NAME– IAM 角色的名称KKE_POLICY_NAME– IAM 策略的名称
- 创建
outputs.tf文件,包含以下输出:kke_dynamodb_table– DynamoDB 表的名称kke_iam_role_name– IAM 角色的名称kke_iam_policy_name– IAM 策略的名称
- 在
terraform.tfvars文件中定义这些变量的实际值。 - 确保 IAM 策略仅允许读取访问,并限制在已创建的特定 DynamoDB 表上。
实验室解决方案
variables.tf
variable "KKE_TABLE_NAME" {
type = string
}
variable "KKE_ROLE_NAME" {
type = string
}
variable "KKE_POLICY_NAME" {
type = string
}
terraform.tfvars
KKE_TABLE_NAME = "datacenter-table"
KKE_ROLE_NAME = "datacenter-role"
KKE_POLICY_NAME = "datacenter-readonly-policy"
main.tf
# DynamoDB table (minimal configuration)
resource "aws_dynamodb_table" "datacenter_table" {
name = var.KKE_TABLE_NAME
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
}
# IAM Role
resource "aws_iam_role" "datacenter_role" {
name = var.KKE_ROLE_NAME
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
Action = "sts:AssumeRole"
}]
})
}
# IAM Policy (read‑only access to specific DynamoDB table)
resource "aws_iam_policy" "datacenter_policy" {
name = var.KKE_POLICY_NAME
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = [
"dynamodb:GetItem",
"dynamodb:Scan",
"dynamodb:Query"
]
Resource = aws_dynamodb_table.datacenter_table.arn
}]
})
}
# Attach policy to role
resource "aws_iam_role_policy_attachment" "attach_policy" {
role = aws_iam_role.datacenter_role.name
policy_arn = aws_iam_policy.datacenter_policy.arn
}
outputs.tf
output "kke_dynamodb_table" {
value = aws_dynamodb_table.datacenter_table.name
}
output "kke_iam_role_name" {
value = aws_iam_role.datacenter_role.name
}
output "kke_iam_policy_name" {
value = aws_iam_policy.datacenter_policy.name
}
Terraform 命令(按顺序运行)
terraform init
terraform validate
terraform apply
# Type "yes" when prompted
bob@iac-server ~/terraform via 💠 default ➜ terraform apply
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_dynamodb_table.datacenter_table will be created
+ resource "aws_dynamodb_table" "datacenter_table" {
+ arn = (known after apply)
+ billing_mode = "PAY_PER_REQUEST"
+ hash_key = "id"
+ id = (known after apply)
+ name = "datacenter-table"
+ read_capacity = (known after apply)
+ stream_arn = (known after apply)
+ stream_label = (known after apply)
+ stream_view_type = (known after apply)
+ tags_all = (known after apply)
+ write_capacity = (known after apply)
+ attribute {
+ name = "id"
+ type = "S"
}
+ point_in_time_recovery (known after apply)
+ server_side_encryption (known after apply)
+ ttl (known after apply)
}
# aws_iam_policy.datacenter_policy will be created
+ resource "aws_iam_policy" "datacenter_policy" {
+ arn = (known after apply)
+ attachment_count = (known after apply)
+ id = (known after apply)
+ name = "datacenter-readonly-policy"
+ name_prefix = (known after apply)
+ path = "/"
+ policy = (known after apply)
+ policy_id = (known after apply)
+ tags_all = (known after apply)
}
# aws_iam_role.datacenter_role will be created
+ resource "aws_iam_role" "datacenter_role" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
+ Statement = [
+ {
+ Action = "sts:AssumeRole"
+ Effect = "Allow"
+ Principal = {
+ Service = "ec2.amazonaws.com"
}
},
]
+ Version = "2012-10-17"
}
)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ managed_policy_arns = (known after apply)
+ name = "datacenter-role"
+ path = "/"
+ tags_all = (known after apply)
}
# aws_iam_role_policy_attachment.attach_policy will be created
+ resource "aws_iam_role_policy_attachment" "attach_policy" {
+ id = (known after apply)
+ policy_arn = aws_iam_policy.datacenter_policy.arn
+ role = aws_iam_role.datacenter_role.name
}
Plan: 4 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_dynamodb_table.datacenter_table: Creating...
aws_iam_role.datacenter_role: Creating...
aws_iam_policy.datacenter_policy: Creating...
aws_dynamodb_table.datacenter_table: Creation complete after 2s [id=datacenter-table]
aws_iam_role.datacenter_role: Creation complete after 1s [id=datacenter-role]
aws_iam_policy.datacenter_policy: Creation complete after 1s [id=arn:aws:iam::123456789012:policy/datacenter-readonly-policy]
aws_iam_role_policy_attachment.attach_policy: Creating...
aws_iam_role_policy_attachment.attach_policy: Creation complete after 0s [id=datacenter-role-arn:aws:iam::123456789012:policy/datacenter-readonly-policy]
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
kke_dynamodb_table = "datacenter-table"
kke_iam_role_name = "datacenter-role"
kke_iam_policy_name = "datacenter-readonly-policy"
Terraform 应用输出
aws_iam_role.datacenter_role will be created
+ arn = (known after apply)
+ assume_role_policy = (known after apply)
+ create_date = (known after apply)
+ description = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ inline_policy = (known after apply)
+ max_session_duration = 3600
+ name = "datacenter-role"
+ name_prefix = (known after apply)
+ path = "/"
+ tags_all = (known after apply)
+ unique_id = (known after apply)
aws_dynamodb_table.datacenter_table will be created
+ arn = (known after apply)
+ billing_mode = "PAY_PER_REQUEST"
+ hash_key = "id"
+ id = (known after apply)
+ name = "datacenter-table"
+ read_capacity = (known after apply)
+ stream_arn = (known after apply)
+ stream_enabled = false
+ stream_view_type = (known after apply)
+ ttl = (known after apply)
+ write_capacity = (known after apply)
aws_iam_policy.datacenter_policy will be created
+ arn = (known after apply)
+ description = (known after apply)
+ id = (known after apply)
+ name = "datacenter-readonly-policy"
+ path = "/"
+ policy = (known after apply)
+ policy_id = (known after apply)
aws_iam_role_policy_attachment.attach_policy will be created
+ id = (known after apply)
+ policy_arn = (known after apply)
+ role = "datacenter-role"
Plan: 4 to add, 0 to change, 0 to destroy.
计划:新增 4 项,修改 0 项,销毁 0 项。
输出的更改
kke_dynamodb_table= “datacenter-table”kke_iam_policy_name= “datacenter-readonly-policy”kke_iam_role_name= “datacenter-role”
您是否想执行这些操作?
Terraform 将执行上述描述的操作。
仅接受 yes 进行批准。
输入值: yes
aws_iam_role.datacenter_role:正在创建… aws_dynamodb_table.datacenter_table:正在创建… aws_iam_role.datacenter_role:创建完成,耗时 0 秒 [id=datacenter-role] aws_dynamodb_table.datacenter_table:创建完成,耗时 3 秒 [id=datacenter-table] aws_iam_policy.datacenter_policy:正在创建… aws_iam_policy.datacenter_policy:创建完成,耗时 0 秒 [id=arn:aws:iam::000000000000:policy/datacenter-readonly-policy] aws_iam_role_policy_attachment.attach_policy:正在创建… aws_iam_role_policy_attachment.attach_policy:创建完成,耗时 0 秒 [id=datacenter-role-20260129134119333700000001]
应用完成!资源:新增 4 项,修改 0 项,销毁 0 项。
输出
kke_dynamodb_table= “datacenter-table”kke_iam_policy_name= “datacenter-readonly-policy”kke_iam_role_name= “datacenter-role”
Step‑by‑Step Explanation (Simple & Clear)
Why PAY_PER_REQUEST for DynamoDB?
- billing_mode = “PAY_PER_REQUEST”
- 无需容量规划
- 配置最少
- 对实验和轻负载来说最便宜、最简单
Why does DynamoDB need a hash key?
- 每个 DynamoDB 表必须至少有一个主键。
- 我们使用
hash_key = "id"来保持表结构最小且合法。
IAM Role vs. IAM Policy (very important)
| 组件 | 符号 | 含义 |
|---|---|---|
| IAM Policy | 📜 | 允许的操作 |
| IAM Role | 🪪 | 谁获得这些权限 |
| Attachment | 🔗 | 将策略连接到角色 |
Why only these DynamoDB actions?
dynamodb:GetItemdynamodb:Scandynamodb:Query
这些都是 只读 操作(没有写入、删除或表结构修改)——最小权限原则。
Why restrict the policy to one table?
resource = aws_dynamodb_table.datacenter_table.arn
- 角色只能访问 datacenter-table。
- 不能读取其他 DynamoDB 表,提供了强安全边界。
What happens during terraform apply?
- Terraform 创建 DynamoDB 表。
- Terraform 创建 IAM 角色。
- Terraform 创建 IAM 策略。
- Terraform 将策略附加到角色。
- AWS 强制只读访问。
- Terraform 输出资源名称。
Easy Memory Model
- DynamoDB table = 📦 数据存储
- IAM role = 👤 身份
- IAM policy = 🔑 权限
- Attachment = 🔗 连接
- Read‑only = 👀 安全访问
Common Mistakes to Avoid
- ❌ 为 DynamoDB 资源 ARN 使用
*。 - ❌ 授予写入权限。
- ❌ 忘记哈希键。
- ❌ 硬编码名称(使用变量或
name_prefix)。 - ❌ 输出名称不匹配。