この記事では、Terraform で IAM Policy の管理をより効率的に行うためのテクニックをいくつか紹介します。Terraform は v1.7.5、AWS Provider は v5.46.0 で動作確認しました。
目次
jsonencode 関数を使う
IAM Role を書く時の例。assume_role_policy
や inline_policy
に HCL で IAM Policy を書いて、jsonencode
関数で JSON に変換します。IAM Role を書くときは以下のパターンを一番よく使います。
resource "aws_iam_role" "example" {
name = "my_role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "ec2.amazonaws.com"
}
},
]
})
inline_policy {
name = "my_inline_policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = ["ec2:Describe*"]
Effect = "Allow"
Resource = "*"
},
]
})
}
}
jsonencode
関数の良いところは以下の通り。
- オブジェクトの後ろにカンマがあっても大丈夫
- ダブルクォーテーションの量が減る
terraform fmt
コマンドで整形される- HCL ではなく、間違って JSON を書いても JSON に変換してくれる
参考ドキュメント
- aws_iam_role | Resources | hashicorp/aws | Terraform | Terraform Registry
- jsonencode - Functions - Configuration Language | Terraform | HashiCorp Developer
ヒアドキュメントを使う
上記の IAM Role の例を heredoc にしたのが以下のコード。IAM Policy がすでにドキュメントに載っていて、それをコピーして利用する場合は heredoc を使います。heredoc は通常 <<
と書きますが、<<-
のようにハイフンをつけることでインデントに対応させて、可読性を上げることができます。
resource "aws_iam_role" "example" {
name = "my_role"
assume_role_policy = <<-EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole"
"Effect": "Allow"
"Sid": ""
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
]
}
EOT
inline_policy {
name = "my_inline_policy"
policy = <<-EOT
{
"Version": "2012-10-17"
"Statement": [
{
"Action": ["ec2:Describe*"]
"Effect": "Allow"
"Resource": "*"
}
]
}
EOT
}
}
通常のヒアドキュメント<<
の場合は、以下のようにインデントがずれて見づらくなります。
resource "aws_iam_role" "example" {
name = "my_role"
assume_role_policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole"
"Effect": "Allow"
"Sid": ""
"Principal": {
"Service": "ec2.amazonaws.com"
}
}
]
}
EOT
inline_policy {
name = "my_inline_policy"
policy = <<EOT
{
"Version": "2012-10-17"
"Statement": [
{
"Action": ["ec2:Describe*"]
"Effect": "Allow"
"Resource": "*"
}
]
}
EOT
}
}
参考ドキュメント
IAM Policy を再利用する
assume_role_policy
は、同じ文字列が何度も出てくることがあります。このようなときは data "aws_iam_policy_document"
を使って再利用できるようにします。
data "aws_iam_policy_document" "instance_assume_role_policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "example" {
name = "my_role"
assume_role_policy = data.aws_iam_policy_document.instance_assume_role_policy.json
}
IAM Policy をファイルから読み込む
IAM Policy の記述量が多い場合は、全体の見通しを良くするために、templatefile
関数を使って外部ファイルに定義された IAM Policy を読み込むことがあります。ファイルには Terraform コードから値を渡すことができます。
resource "aws_iam_role" "example" {
name = "my_role"
inline_policy {
name = "my_inline_policy
policy = templatefile("./iam_role_policy.tftpl", {
region = data.aws_region.current.name
account_id = data.aws_caller_identity.current.account_id
instance_id = "i-0123456789abcdef0"
})
}
}
iam_role_policy.tftpl
{
"Version": "2012-10-17"
"Statement": [
{
"Action": ["ec2:Describe*"]
"Effect": "Allow"
"Resource": "arn:aws:ec2:${region}:${account_id}:instance/${instance_id}"
}
]
}
実は、私はこの方法をあまり使いません。IAM Policy の量が多い場合はエディタの機能で折りたたみます。IAM Policy だけファイルが分かれることで、可読性を下げてしまうこともあります。
参考ドキュメント