IAM policy resource/data diff

說明 Terraform 中 aws_iam_policy resource 與 aws_iam_policy_document data source 的差異及拆分的好處。

發佈 ~1 分鐘 #IAM

為啥 terraform 中已經有 aws_iam_policy resource 了,還會需要有 aws_iam_policy_document data source?

Resource 和 Data Source 本質上的差異

  • Resource 會對資源進行新增、刪除、修改
  • Data Source 並不會建立新資源,而是生成或查詢現有的資料。因此 aws_iam_policy_document data source 只是幫我們組裝出一個 json 文件,並不會新增資源

為什麼要這樣設計?

在 AWS 中,IAM Policy 本質上是一段 JSON。直接手寫 JSON 的缺點是:

  • 可讀性差
  • 容易出錯(特別是 ARN 拼錯或 JSON 格式錯誤)
  • 難以模組化(尤其在多環境、多專案共用時)

因此 Terraform 提供 aws_iam_policy_document data source,用 HCL 語法來描述,最後會輸出一個 JSON 字串給其他資源引用。

data "aws_iam_policy_document" "example" {
  statement {
    actions   = ["s3:ListBucket"]
    resources = ["arn:aws:s3:::my-bucket"]
  }
}

這段只是在 Terraform 執行期 生成 JSON,通常會再丟給 aws_iam_policy (resource) 或 aws_iam_role_policy 等去使用。

resource "aws_iam_policy" "example" {
  name   = "example"
  policy = data.aws_iam_policy_document.example.json
}

這個才是真正的 AWS IAM Policy 資源。它需要一段 JSON 作為 policy 參數,所以可以選擇:

  • 手動寫 JSON(容易出錯)
  • 用 aws_iam_policy_document 生成 JSON(更乾淨、安全)

這樣的拆分有幾個好處:

  1. 單一職責:生成 JSON 與操作 API 分開,邏輯更清晰
  2. 可重複利用:一份 policy document 可以被不同資源引用,而不必重複手寫 JSON
  3. 抽象化:開發者不用直接面對易錯的 JSON,而是用 HCL block 描述規則
  4. 靈活性:有些情況不需要獨立的 policy 資源,而是 inline policy(例如 aws_iam_role_policy),此時還是能透過 aws_iam_policy_document 來產生 JSON