概要

  • 今回は、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 リソースの作成は、下記ドキュメントが参考になります。
Use Terraform to apply policy permissions to IAM user and S3 bucket resources. Refactor your policy with the IAM policy document data source to automatically format your JSON policies for reuse.

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

参考資料

概要 Terraformハンズオンの第一弾です。今回は、AWS環境にVPC/EC2 のリソースを作成します。 なお、今回は、Terraform Registry のModule を使用して構築を行います。このハンズオンのポイントは、Terraform Registry のサンプルをできるだけ組み合わせて作成できる...
Use Terraform to apply policy permissions to IAM user and S3 bucket resources. Refactor your policy with the IAM policy document data source to automatically format your JSON policies for reuse.
String literals and template sequences interpolate values and manipulate text. Learn about both quoted and heredoc string syntax.

元記事はこちら

https://oji-cloud.net/2022/03/25/post-6984/
著者:新川貴章


アイレットなら、AWS で稼働するサーバーを対象とした監視・運用・保守における煩わしい作業をすべて一括して対応し、経験豊富なプロフェッショナルが最適なシステム環境を実現いたします。AWS プレミアコンサルティングパートナーであるアイレットに、ぜひお任せください。

AWS 運用・保守サービスページ:
https://cloudpack.jp/service/aws/maintenance.html

その他のサービスについてのお問合せ、お見積り依頼は下記フォームよりお気軽にご相談ください。
https://cloudpack.jp/contact/form/