LoginSignup
9
2

More than 3 years have passed since last update.

iamポリシーのjsonをHCLで書き直すパズル集

Posted at

はじめに。aws_iam_policy_documentは便利だが、、、

terraformでIAMのポリシーを書く時に、いくつか選択肢がありますが、そのうちの一つで aws_iam_policy_document を使うという手段があります。

Terraformでテンプレートを使ってポリシーを定義する - Qiita

HCLのシンタックスハイライトを使ってポリシーを書ける
plan 実行時にある程度の構文チェックができる
書くものが減りすこしスッキリする(テンプレートの方式だと、 json ファイル、 data ソース、 aws_iam_policy リソースを用意しないといけない)

ということで基本的にすごく便利なのですが、JSONで書かれた各種サンプルをHCLに変換して書き直さないといけない(コピペできない)というデメリットがあります。

というわけで、いくつか例を挙げながら、JSONのポリシーをaws_iam_policy_documentで書き換えてみます。

初級編

お題はこちら。
ビルドプロジェクトに関する情報の取得をユーザーに許可する


{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "codebuild:BatchGetProjects",
      "Resource": "arn:aws:codebuild:us-east-2:123456789012:project/my*"      
    }
  ]
}

一番シンプルなパターンです。

正解はこう。

data "aws_iam_policy_document" "sample" {
  version = "2012-10-17"
  statement {
    sid = ""
    actions = [
      "codebuild:BatchGetProjects",
    ]
    effect = "Allow"
    resources = [
      "arn:aws:codebuild:us-east-2:123456789012:project/my*"
    ]
  }
}
// 確認用
output "sample" {
  value = data.aws_iam_policy_document.sample.json
}

JSONと1:1の構造になっているのでわかりやすいですね。terraform plan を実行すると、内容が同じで有ることが確認できます。

  + sample = jsonencode(
        {
          + Statement = [
              + {
                  + Action   = "codebuild:BatchGetProjects"
                  + Effect   = "Allow"
                  + Resource = "arn:aws:codebuild:us-east-2:123456789012:project/my*"
                  + Sid      = ""
                },
            ]
          + Version   = "2012-10-17"
        }
    )

初級編②

次はこちら。
AWS CodeBuild のアイデンティティベースのポリシーの使用 - AWS CodeBuild

Statementが複数です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "codebuild:CreateProject",
      "Resource": "arn:aws:codebuild:us-east-2:123456789012:project/*"      
    },
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam:123456789012:role/CodeBuildServiceRole"
    }
  ]
}

正解はこう。

data "aws_iam_policy_document" "sample" {
  version = "2012-10-17"
  statement {
    sid = ""
    actions = [
      "codebuild:codebuild:CreateProject",
    ]
    effect = "Allow"
    resources = [
      "arn:aws:codebuild:us-east-2:123456789012:project/*"
    ]
  }

  statement {
    sid = ""
    actions = [
      "iam:PassRole",
    ]
    effect = "Allow"
    resources = [
      "arn:aws:iam:123456789012:role/CodeBuildServiceRole"
    ]
  }
}

シンプルにstatementを複数書いてあげればOKです。

中級編

お題はこちら。

数値条件演算子

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "s3:ListBucket",
    "Resource": "arn:aws:s3:::example_bucket",
    "Condition": {"NumericLessThanEquals": {"s3:max-keys": "10"}}
  }
}

conditionという複雑そうなものがありますが、正解はこう。


data "aws_iam_policy_document" "sample" {
  version = "2012-10-17"

  statement {
    sid = ""
    actions = [
      "s3:ListBucket",
    ]
    effect = "Allow"
    resources = [
      "arn:aws:s3:::example_bucket"
    ]

    condition {
      test = "NumericLessThanEquals"
      values = ["10"]
      variable = "s3:max-keys"
    }
  }
}

書き方がjsonと比べて直感的ではないですが、aws_iam_policy_document にも同じように conditionが書けます。

上級編

お題はこちら。

VPC ネットワークインターフェイスを作成するために必要な AWS のサービスへのアクセスを CodeBuild に許可する

今までの組み合わせ + Condition が複雑なパターンです。一番伝えたかったのはこれ。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow", 
            "Action": [
                "ec2:CreateNetworkInterface",
                "ec2:DescribeDhcpOptions",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeVpcs"
            ], 
            "Resource": "*" 
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:CreateNetworkInterfacePermission"
            ],
            "Resource": "arn:aws:ec2:region:account-id:network-interface/*",
            "Condition": {
                "StringEquals": {
                    "ec2:Subnet": [
                        "arn:aws:ec2:region:account-id:subnet/subnet-id-1",
                        "arn:aws:ec2:region:account-id:subnet/subnet-id-2"
                    ],
                    "ec2:AuthorizedService": "codebuild.amazonaws.com"
                }
            }
        }
    ]
}

正解はこう

data "aws_iam_policy_document" "sample" {
  version = "2012-10-17"

  statement {
    sid = ""
    actions = [
      "ec2:CreateNetworkInterface",
      "ec2:DescribeDhcpOptions",
      "ec2:DescribeNetworkInterfaces",
      "ec2:DeleteNetworkInterface",
      "ec2:DescribeSubnets",
      "ec2:DescribeSecurityGroups",
      "ec2:DescribeVpcs"
    ]
    effect = "Allow"
    resources = [
      "*"
    ]
  }

  statement {
    sid = ""
    actions = [
      "ec2:CreateNetworkInterfacePermission"
    ]
    effect = "Allow"
    resources = [
      "arn:aws:ec2:region:account-id:network-interface/*"
    ]
    condition {
      test = "StringEquals"
      values = [
        "arn:aws:ec2:region:account-id:subnet/subnet-id-1",
        "arn:aws:ec2:region:account-id:subnet/subnet-id-2"
      ]
      variable = "ec2:Subnet"
    }

    condition {
      test = "StringEquals"
      values = [
        "codebuild.amazonaws.com"
      ]
      variable = "ec2:AuthorizedService"
    }
  }
}

conditionを複数書くのが、元のjsonと構造が変わっているのが難しいですね。
terraform planを実行すると同様で有ることが確認できます。


 + sample = jsonencode(
        {
          + Statement = [
              + {
                  + Action   = [
                      + "ec2:DescribeVpcs",
                      + "ec2:DescribeSubnets",
                      + "ec2:DescribeSecurityGroups",
                      + "ec2:DescribeNetworkInterfaces",
                      + "ec2:DescribeDhcpOptions",
                      + "ec2:DeleteNetworkInterface",
                      + "ec2:CreateNetworkInterface",
                    ]
                  + Effect   = "Allow"
                  + Resource = "*"
                  + Sid      = ""
                },
              + {
                  + Action    = "ec2:CreateNetworkInterfacePermission"
                  + Condition = {
                      + StringEquals = {
                          + ec2:AuthorizedService = "codebuild.amazonaws.com"
                          + ec2:Subnet            = [
                              + "arn:aws:ec2:region:account-id:subnet/subnet-id-2",
                              + "arn:aws:ec2:region:account-id:subnet/subnet-id-1",
                            ]
                        }
                    }
                  + Effect    = "Allow"
                  + Resource  = "arn:aws:ec2:region:account-id:network-interface/*"
                  + Sid       = ""
                },
            ]
          + Version   = "2012-10-17"
        }
    )

おわりに

いくつか具体例を上げてみましたが参考になりましたでしょうか。

このパターンの方がもっと難しい!という題材を見つけた方は教えていただけるとうれしいです。

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2