[初学者向け]Terraform によるIAM ポリシー/ロール の作り方
概要
- 今回は、Terraform を使ってIAM ポリシー、IAM ロール、IAM インスタンスプロファイルを作成します。Terraform によるIAM リソースの管理は複数のパターンがありますが、つい十分理解をせず使い回すことも多いかと思います。今回は、"aws_iam_policy_document" を使いデータソースにポリシードキュメントを定義する方法、および"aws_iam_policy" リソースのpolicy属性にヒアドキュメントとしてポリシードキュメントを記述する方法の2パターンを記載しております。
- IAM ロールにIAM ポリシーを割り当てる方法は、以前失敗した経験を元に、"aws_iam_role_policy_attachment" リソースを使用するようにします。失敗談の詳細は、こちら。
- 今回モチーフとして作成するポリシーは、指定した S3バケットに対するread/write を許可します。EC2用のロールを作成し、ロールにこのポリシーを関連付けます。
Terraform によるIAM Policy の作り方
ポリシードキュメントをデータソースで定義する方法
- 先ず、S3 バケット名、IAM ポリシー名、IAM ロール名を変数として扱います。
variable "s3_bucket_name" {
type = string
}
variable "iam_policy_name" {
type = string
}
variable "iam_role_name" {
type = string
}
- 次に、"aws_iam_policy_document" のデータソースを定義します。HCLを使って、ポリシードキュメントが定義可能です。この方法は柔軟にポリシードキュメントの設定が可能となり、source_policy_documents やoverride_policy_documents の属性を利用することでポリシーを上書き、追加、更新もできます。
- “aws_iam_policy_document" の詳細は、こちらのドキュメントを参照ください。
data "aws_iam_policy_document" "allow_rw_access_s3_bucket" {
statement {
actions = ["s3:ListStorageLensConfigurations",
"s3:ListAccessPointsForObjectLambda",
"s3:GetAccessPoint",
"s3:PutAccountPublicAccessBlock",
"s3:GetAccountPublicAccessBlock",
"s3:ListAllMyBuckets",
"s3:ListAccessPoints",
"s3:PutAccessPointPublicAccessBlock",
"s3:ListJobs",
"s3:PutStorageLensConfiguration",
"s3:ListMultiRegionAccessPoints",
"s3:CreateJob"
]
resources = ["*"]
effect = "Allow"
}
statement {
actions = ["s3:*"]
resources = ["arn:aws:s3:::${var.s3_bucket_name}",
"arn:aws:s3:::${var.s3_bucket_name}/*"]
effect = "Allow"
}
}
- actionsや resources 属性は、"[ ]" で括りリスト形式で指定する必要があります。"[ ]" がない場合は、下記のエラーとなります。
Error: Incorrect attribute value type
on iam.tf line 32, in data “aws_iam_policy_document" “allow_rw_access_s3_bucket":
32: actions = “s3:*"Inappropriate value for attribute “actions": set of string required.
- 次に、"aws_iam_policy" のリソースを定義します。policy 属性に、上記で準備したポリシードキュメントを設定します。"aws_iam_policy" の詳細は、こちらのドキュメントを参照ください。
resource "aws_iam_policy" "policy_allow_rw_access_s3_bucket" {
name = var.iam_policy_name
policy = data.aws_iam_policy_document.allow_rw_access_s3_bucket.json
}
リソースのpolicy属性にヒアドキュメントとして記述する方法
- 先ず、S3 バケット名、IAM ポリシー名、IAM ロール名を変数として扱います。
variable "s3_bucket_name" {
type = string
}
variable "iam_policy_name" {
type = string
}
variable "iam_role_name" {
type = string
}
- 次に、"aws_iam_policy" のリソースを定義します。policy 属性に、複数行のヒアドキュメントを使用してポリシードキュメントを設定します。ヒアドキュメントは、シンプルなポリシーであれば便利な方法です。ポリシーが複雑な場合や他のリソースで再利用する場合は、データソースで定義する方法が良いと思います。"aws_iam_policy" の詳細は、こちらのドキュメントを参照ください。
- 以下では<<を使用していますが、<< ではなく <<- (ハイフンあり)を使用すると、インデント有りのヒアドキュメントが利用できます。
resource "aws_iam_policy" "policy_allow_rw_access_s3_bucket" {
name = var.iam_policy_name
policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListStorageLensConfigurations",
"s3:ListAccessPointsForObjectLambda",
"s3:GetAccessPoint",
"s3:PutAccountPublicAccessBlock",
"s3:GetAccountPublicAccessBlock",
"s3:ListAllMyBuckets",
"s3:ListAccessPoints",
"s3:PutAccessPointPublicAccessBlock",
"s3:ListJobs",
"s3:PutStorageLensConfiguration",
"s3:ListMultiRegionAccessPoints",
"s3:CreateJob"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::${var.s3_bucket_name}",
"arn:aws:s3:::${var.s3_bucket_name}/*"
]
}
]
}
EOT
}
- IAM リソースの作成は、下記ドキュメントが参考になります。
Terraform によるIAM Role の作り方
ポリシードキュメントをデータソースで定義する方法
- IAM ポリシーと同様に、"aws_iam_policy_document" のデータソースを定義します。HCLを使って、信頼関係のポリシードキュメントが定義可能です。以下は、EC2 の場合です。
data "aws_iam_policy_document" "ec2_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers =["ec2.amazonaws.com"]
}
}
}
- 次に、"aws_iam_role" のリソースを定義します。assume_role_policy 属性に、上記で準備した信頼関係のポリシードキュメントを設定します。"aws_iam_role" の詳細は、こちらのドキュメントを参照ください。
resource "aws_iam_role" "s3-role-for-ec2" {
name = var.iam_role_name
description = "Allows EC2 instances to call AWS services on your behalf."
assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}
- 次に、EC2 インスタンス(Elastic BeansTalk を含む)で必要となるインスタンスプロファイルを作成します。コンソールの場合は自動で作成されるため意識しませんが、AWS CLI or API を使用する場合に必要です。
- なお、インスタンスプロファイルに含めることができる IAM ロールは 1 つのみです。ただし、1 つのロールを複数のインスタンスプロファイルに含めることはできます。
resource "aws_iam_instance_profile" "instance-profile_s3-role-for-ec2" {
name = var.iam_role_name
path = "/"
role = aws_iam_role.s3-role-for-ec2.name
}
- 最後に、"aws_iam_role_policy_attachment" のリソースを定義し、IAM ロールにIAM ポリシーをアタッチします。今回は、先ほど準備したカスタマー管理のポリシーと、AWS管理ポリシー(AmazonSSMManagedInstanceCore)の2つを設定しています。
resource "aws_iam_role_policy_attachment" "role-policy-attachment_s3-role-for-ec2-attach1" {
role = aws_iam_role.s3-role-for-ec2.name
policy_arn = aws_iam_policy.policy_allow_rw_access_s3_bucket.arn
}
resource "aws_iam_role_policy_attachment" "role-policy-attachment_s3-role-for-ec2-attach2" {
role = aws_iam_role.s3-role-for-ec2.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
リソースのpolicy属性にヒアドキュメントとして記述する方法
- “aws_iam_role" のリソースを定義します。assume_role_policy 属性に、複数行のヒアドキュメントを使用してポリシードキュメントを設定します。ヒアドキュメントは、シンプルなポリシーであれば便利な方法です。ポリシーが複雑な場合や他のリソースで再利用する場合は、データソースで定義する方法が良いと思います。"aws_iam_role" の詳細は、こちらのドキュメントを参照ください。
- 以下では<<を使用していますが、<< ではなく <<- (ハイフンあり)を使用すると、インデント有りのヒアドキュメントが利用できます。
resource "aws_iam_role" "s3-role-for-ec2" {
name = var.iam_role_name
description = "Allows EC2 instances to call AWS services on your behalf."
assume_role_policy = <<EOT
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOT
}
- 次に、EC2 インスタンス(Elastic BeansTalk を含む)で必要となるインスタンスプロファイルを作成します。コンソールの場合は自動で作成されるため意識しませんが、AWS CLI or API を使用する場合に必要です。
- なお、インスタンスプロファイルに含めることができる IAM ロールは 1 つのみです。ただし、1 つのロールを複数のインスタンスプロファイルに含めることはできます。
resource "aws_iam_instance_profile" "instance-profile_s3-role-for-ec2" {
name = var.iam_role_name
path = "/"
role = aws_iam_role.s3-role-for-ec2.name
}
- 最後に、"aws_iam_role_policy_attachment" のリソースを定義し、IAM ロールにIAM ポリシーをアタッチします。今回は、先ほど準備したカスタマー管理のポリシーと、AWS管理ポリシー(AmazonSSMManagedInstanceCore)の2つを設定しています。
resource "aws_iam_role_policy_attachment" "role-policy-attachment_s3-role-for-ec2-attach1" {
role = aws_iam_role.s3-role-for-ec2.name
policy_arn = aws_iam_policy.policy_allow_rw_access_s3_bucket.arn
}
resource "aws_iam_role_policy_attachment" "role-policy-attachment_s3-role-for-ec2-attach2" {
role = aws_iam_role.s3-role-for-ec2.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}
Terraform を実行する
Terraform のtfvars を準備する
- tf ファイルに、変数を定義します。
- 今回使用する変数は、以下の3つでしたね。
s3_bucket_name = "niikawa-test"
iam_policy_name = "s3-policy-example1"
iam_role_name = "s3-role-example1"
Terraform を実行する
- tfvars ファイルを指定して、terraform を実行します。
terraform plan --var-file=terraform.tfvars
terraform apply --var-file=terraform.tfvars