開発日報

窓際エンジニアの開発備忘。日報は嘘です。

【連載】terraform によるAWS環境構築入門 第2回 ~ 権限管理とモジュール化 ~

はじめに

この記事ではterraformを用いたIAMロール・IAMポリシーの作成方法について学びます。
また、環境の構築処理(ここではIAMの作成処理)をモジュール化し、使い回す方法についてもここで学びます。

連載記事一覧

本連載での使用技術

  • AWS
  • Docker
  • VPC
  • ECS(fargate)
  • ELB
  • IAM
  • Route53
  • RDS
  • ElastiCache
  • codexxx

1. ポリシーの作成

ポリシードキュメントの定義

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["ec2:DescribeRegions"],
      "Resource": ["*"]
    }
  ]
}

↑のポリシードキュメントをterraformで定義すると以下のようになります。

# ポリシードキュメントの定義
data "aws_iam_policy_document" "allow_describe_regions" {
  statement {
    effect    = "Allow"
    actions   = ["ec2:DescribeRegions"]
    resources = ["*"]
  }
}

IAMポリシーを作成し、ポリシードキュメントを紐付ける

ポリシードキュメントを保持するリソースが「IAM ポリシー」です。 ポリシー名と先で作成したポリシードキュメントを紐付けます。

resource "aws_iam_policy" "example" {
  name   = "example"
  policy = data.aws_iam_policy_document.allow_describe_regions.json
}

2. IAMロールの作成

信頼ポリシーの作成

信頼ポリシーを作成し、IAMロールをなんのサービスに関連付けるか定義します。

data "aws_iam_policy_document" "ec2_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

IAMロールの作成

IAMロールを定義し、先に作成した信頼ポリシーを付与します。

resource "aws_iam_role" "example" {
  name               = "example"
  assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

IAMロールとIAMポリシーの関連付け

ここまでで、IAMロールとIAMポリシーの作成ができるようになりましたので、この2つを関連付けてみましょう。

resource "aws_iam_role_policy_attachment" "example" {
  role       = aws_iam_role.example.name
  policy_arn = aws_iam_policy.example.arn
}

3. まとめ(最終成果物の作成)

以上の解説をまとめて、最終成果物を作成しましょう。
IAMロールの作成は頻繁に使うのでモジュール化しましょう。 フォルダ構成は以下の通り。

exaple
 |
 |--- iam_role (新)
 |    |___ main.tf (新)
 |
 |___ main.tf

iamのモジュール定義

「./iam_role/main.tf」にモジュールの定義を記載しましょう。
以下の3つのパラメーターを外部から渡せるようにします。

  • name - IAM ロールと IAM ポリシーの名前
  • policy - ポリシードキュメント
  • identifier - IAM ロールを紐づける AWS のサービス識別子
# ロール・ポリシーの定義を外部から渡せるようにする
variable "name" {}
variable "policy" {}
variable "identifier" {}

# 信頼ポリシーの定義 (awsの[var.identifier]サービスにロールを関連づける)
data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = [var.identifier]
    }
  }
}

# [var.name]ロールに信頼ポリシーを紐付ける
resource "aws_iam_role" "default" {
  name               = var.name
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

# [var.name]ポリシーに[var.policy]ポリシードキュメントを紐付ける
resource "aws_iam_policy" "default" {
  name   = var.name
  policy = var.policy
}

# [aws_iam_role]と[aws_iam_policy]を紐付ける
resource "aws_iam_role_policy_attachment" "default" {
  role       = aws_iam_role.default.name
  policy_arn = aws_iam_policy.default.arn
}

output "iam_role_arn" {
  value = aws_iam_role.default.arn
}

output "iam_role_name" {
  value = aws_iam_role.default.name
}

呼び出し側実装

「./main.tf」は以下のようになります。
先で作成したモジュールを呼び出してみましょう。

provider "aws" {
  region = "ap-northeast-1"
}

# ポリシードキュメントの定義
data "aws_iam_policy_document" "allow_describe_regions" {
  statement {
    effect    = "Allow"
    actions   = ["ec2:DescribeRegions"] # リージョン一覧を取得する
    resources = ["*"]
  }
}

# モジュール[iam_role]呼出
module "describe_regions_for_ec2" {
  source     = "./iam_role"
  name       = "c"
  identifier = "ec2.amazonaws.com"
  policy     = data.aws_iam_policy_document.allow_describe_regions.json
}

4. 実行

まずはinitしましょう。これをやらないと、モジュールの呼び出しができません。

$ terraform init

実行計画の確認。前回にも書きましたが、破壊的な変更が入っていないか入念に確認しましょう。

$ terraform plan

実行。実行されたら、AWSの管理画面から確認しましょう。
うまくいっていればIAMページ左上の「Search IAM」のフォームに「describe-regions-for-ec2」と入力て検索ができるはずです。

$ terraform apply