AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

managed_policy_arns と aws_iam_role_policy_attachment を利用すると apply 毎にアタッチとデタッチを繰り返す

タイトルがすべてシリーズ。

とりあえず

僕の用途では、aws_iam_role_policy_attachment に全部そろえよう、となった。

解説

先人が全部かいてくれていた。

qiita.com

oji-cloud.net

問題の出ていた記述

自分で作成した IAM role に、 AWS のマネジメントなポリシーをアタッチしたくて以下のような使い方をしていた。

resource "aws_iam_role" "ecs_task_execution_role" {
  name = "ecs_task_execution_role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = { Service = "ecs-tasks.amazonaws.com" }
        Action    = "sts:AssumeRole"
      }
    ]
  })
  managed_policy_arns = [
    "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
    "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
  ]
}

# ECS: ECS exec 用ポリシー
resource "aws_iam_policy" "ssmmessages" {
  name_prefix = "${var.prefix}_ssmmessages"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        "Effect": "Allow",
        "Action": [
          "ssmmessages:CreateControlChannel",
          "ssmmessages:CreateDataChannel",
          "ssmmessages:OpenControlChannel",
          "ssmmessages:OpenDataChannel"
        ],
        "Resource": [
          "*"
        ]
      }
    ]
  })
}

# ECS execssmmessages ポリシーのアタッチ
resource "aws_iam_role_policy_attachment" "ssmmessages" {
  role       = aws_iam_role.ecs_task_execution_role.name
  policy_arn = aws_iam_policy.ssmmessages.arn
}
  1. aws_iam_role.ecs_task_execution_role を自作
    1. に対して AWS マネージドな AmazonECSTaskExecutionRolePolicy, AmazonSSMReadOnlyAccess を managed_policy_arns でアタッチ
    1. に対して、更に自作した aws_iam_policy.ssmmessagesaws_iam_role_policy_attachment でアタッチ
  2. terraform (apply|destroy) すると、実行毎にアタッチ→デタッチ、を繰り返す

どうした

全部 aws_iam_role_policy_attachment に揃えた。

resource "aws_iam_role" "ecs_task_execution_role" {
  name = "ecs_task_execution_role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = { Service = "ecs-tasks.amazonaws.com" }
        Action    = "sts:AssumeRole"
      }
    ]
  })
  #managed_policy_arns = [
  #  "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
  #  "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
  #]
}

# ECS: ECS exec 用ポリシー
resource "aws_iam_policy" "ssmmessages" {
  name_prefix = "${var.prefix}_ssmmessages"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        "Effect": "Allow",
        "Action": [
          "ssmmessages:CreateControlChannel",
          "ssmmessages:CreateDataChannel",
          "ssmmessages:OpenControlChannel",
          "ssmmessages:OpenDataChannel"
        ],
        "Resource": [
          "*"
        ]
      }
    ]
  })
}

# ECS execssmmessages ポリシーのアタッチ
resource "aws_iam_role_policy_attachment" "ssmmessages" {
  role       = aws_iam_role.ecs_task_execution_role.name
  policy_arn = aws_iam_policy.ssmmessages.arn
}

# マネージドポリシー AmazonECSTaskExecutionRolePolicy のアタッチ
data "aws_iam_policy" "AmazonECSTaskExecutionRolePolicy" {
    arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

resource "aws_iam_role_policy_attachment" "AmazonECSTaskExecutionRolePolicy" {
  role       = aws_iam_role.ecs_task_execution_role.name
  policy_arn = data.aws_iam_policy.AmazonECSTaskExecutionRolePolicy.arn
}

# マネージドポリシー AmazonSSMReadOnlyAccess のアタッチ
data "aws_iam_policy" "AmazonSSMReadOnlyAccess" {
    arn = "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
}

resource "aws_iam_role_policy_attachment" "AmazonSSMReadOnlyAccess" {
  role       = aws_iam_role.ecs_task_execution_role.name
  policy_arn = data.aws_iam_policy.AmazonSSMReadOnlyAccess.arn
}

言い訳

とくに Qiita 兄貴が書いてくれていたのですが、

この2つの管理方法を併用することは推奨されておりませんので、本番環境等では利用しないでください。 https://qiita.com/hmdsg/items/7862213637fc4c3d9a3f#%E4%B8%A1%E6%96%B9%E3%81%A7%E7%AE%A1%E7%90%86%E3%81%97%E3%81%9F%E5%A0%B4%E5%90%88

ギョワー! 単純に僕の考慮漏れというか知識不足ですねこれは。

ちなみに

aws_iam_role_policy_attachment に揃えた後、マネジメントなリソースは data で state に追加していますが、これは省略して直接 arn を指定してもオッケーです。

ただし Terraform 的なお作法だと、自身が作成しなかった (マネージドな) リソースは data で一回読み出すべきっぽいので、冗長でもその様に扱った方がよさそう。

urotasm.hatenablog.com