15. 使用 Terraform 为 DynamoDB 访问附加 IAM 策略

发布: (2026年2月8日 GMT+8 17:11)
9 分钟阅读
原文: Dev.to

Source: Dev.to

实验信息

DevOps 团队的任务是创建一个安全的 DynamoDB 表,并使用 IAM 强制细粒度访问控制。此设置将仅允许受信任的 AWS 服务安全且受限地访问该表。

作为 Nautilus DevOps Team 的成员,您的任务是使用 Terraform 完成以下操作:

  1. 创建 DynamoDB 表 – 一个名为 datacenter-table 的表,使用最小配置。
  2. 创建 IAM 角色 – 一个名为 datacenter-role 的角色,允许访问该表。
  3. 创建 IAM 策略 – 一个名为 datacenter-readonly-policy 的策略,授予对特定 DynamoDB 表的 只读 访问(GetItemScanQuery),并将其附加到角色。
  4. 创建 main.tf 文件不要创建单独的 .tf 文件),用于配置表、角色和策略。
  5. 创建 variables.tf 文件,包含以下变量:
    • KKE_TABLE_NAME – DynamoDB 表的名称
    • KKE_ROLE_NAME – IAM 角色的名称
    • KKE_POLICY_NAME – IAM 策略的名称
  6. 创建 outputs.tf 文件,包含以下输出:
    • kke_dynamodb_table – DynamoDB 表的名称
    • kke_iam_role_name – IAM 角色的名称
    • kke_iam_policy_name – IAM 策略的名称
  7. terraform.tfvars 文件中定义这些变量的实际值
  8. 确保 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:GetItem
  • dynamodb:Scan
  • dynamodb:Query

这些都是 只读 操作(没有写入、删除或表结构修改)——最小权限原则。

Why restrict the policy to one table?

resource = aws_dynamodb_table.datacenter_table.arn
  • 角色只能访问 datacenter-table
  • 不能读取其他 DynamoDB 表,提供了强安全边界。

What happens during terraform apply?

  1. Terraform 创建 DynamoDB 表。
  2. Terraform 创建 IAM 角色。
  3. Terraform 创建 IAM 策略。
  4. Terraform 将策略附加到角色。
  5. AWS 强制只读访问。
  6. Terraform 输出资源名称。

Easy Memory Model

  • DynamoDB table = 📦 数据存储
  • IAM role = 👤 身份
  • IAM policy = 🔑 权限
  • Attachment = 🔗 连接
  • Read‑only = 👀 安全访问

Common Mistakes to Avoid

  • ❌ 为 DynamoDB 资源 ARN 使用 *
  • ❌ 授予写入权限。
  • ❌ 忘记哈希键。
  • ❌ 硬编码名称(使用变量或 name_prefix)。
  • ❌ 输出名称不匹配。
0 浏览
Back to Blog

相关文章

阅读更多 »