0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[AWS][IAM][Terraform] ロール切替方式の権限設定一式を作成する

Posted at

以下の記事の続き。

マルチアカウントにおけるユーザ管理を考える
https://qiita.com/batatch/items/425661dbffece3b981bf

概要

ここでは、ロール切替におけるグループ、ロール、ポリシーなど権限一式を実装していきます。
権限設定の全体像は下図のとおり。

fig-switch-role-all-1.png

マスターアカウント、ターゲットアカウントに対して、それぞれ以下の項目を設定します。

ターゲットアカウントへの設定項目

IAM ロール ロール名 信頼関係のポリシー IAM ポリシー
Administrator 管理者 1111-1111-1111 からの AssumeRole 許可 AdministratorAccess など (*)
Maintainer 作業者 1111-1111-1111 からの AssumeRole 許可 PowerUserAccess など (*)
Viewer 閲覧者 1111-1111-1111 からの AssumeRole 許可 ViewOnlyAccess など (*)
: : : :

(*) 実際には独自に権限を整理してポリシーを定義しますが、ここでは AWS デフォルトの職務機能のポリシーを使って例示していきます。

マスターアカウントへの設定項目

IAM ユーザ IAM グループ IAM ポリシー 説明
user001 a2_AdministratorGroup a2_AdministratorPolicy 2222-2222-2222 の管理者へのロール切替
a2_MaintainerGroup a2_MaintainerPolicy 2222-2222-2222 の作業者へのロール切替
user001
user002
a2_ViewerGroup a2_ViewerPolicy 2222-2222-2222 の閲覧者へのロール切替
a3_AdministratorGroup a3_AdministratorPolicy 3333-3333-3333 の管理者へのロール切替
a3_MaintainerGroup a3_MaintainerPolicy 3333-3333-3333 の作業者へのロール切替
user002
user003
a3_ViewerGroup a3_ViewerPolicy 3333-3333-3333 の閲覧者へのロール切替

ロール切替グループを作成し、ユーザへマッピングします。
グループは、対象のアカウント x ロール数の組み合わせ だけ用意します。

ターゲットアカウントへの設定項目

ターゲットアカウントへの設定項目を実装します。
以下、Terraform スクリプトとして記述していきます。

IAM ロールへ付与する信頼関係ポリシー定義

スクリプト

data "aws_iam_policy_document" "assume_from" {
  statement {
    actions = ["sts:AssumeRole"]
    principals {
      type = "AWS"
      identifiers = [
        format("arn:aws:iam::%s:root", var.master_account_id)    # マスターアカウントID を指定
      ]
    }
  }
}

IAM ロール本体の定義

上記で作成した信頼関係ポリシーを割り当てます。

入力情報

- role_name: Administrator
    ...
- role_name: Maintainer
    ...
- role_name: Viewer
    ...

スクリプト

resource "aws_iam_role" "this" {
  name               = var.role_name                                    # ロール名
  path               = var.path                                         # パス (デフォルトで "/")
  description        = var.desc                                         # ロール説明 (英数字のみ)
  assume_role_policy = data.aws_iam_policy_document.assume_from.json    # 信頼関係ポリシー (上記で定義)
}

IAM ポリシーの独自定義

独自に権限設定を定義する場合は、IAM ポリシー定義を作成します。

スクリプト

resource "aws_iam_policy" "this" {
  name        = var.name                                         # ポリシー名
  path        = var.path                                         # パス (デフォルトで "/")
  description = var.desc                                         # ポリシー説明 (英数字のみ)
  policy      = file(format("policy_defs/%s.json", var.name))    # ポリシー定義の本文、例は外部から "ポリシー名.json" ファイルを読み込み
}

IAM ロールへの IAM ポリシー割当

IAM ロールへ権限本体の IAM ポリシーを割り当てます。
以下の例では var.policies として IAM ポリシーの ARN の配列を渡して、for_each のループで設定させています。

入力情報

- role_name: Administrator
  policies:
    - arn:aws:iam::aws:policy/AdministratorAccess
- role_name: Maintainer
  policies:
    - arn:aws:iam::aws:policy/PowerUserAccess
- role_name: Viewer    
  policies:
    - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess

スクリプト

resource "aws_iam_role_policy_attachment" "this" {
  for_each = toset(var.policies)

  role       = aws_iam_role.this.name    # ロール名
  policy_arn = each.key                  # 割り当てるポリシーの ARN
}

マスターアカウントへの設定項目

マスターアカウントへの設定項目を実装します。
以下、Terraform スクリプトとして記述していきます。

ロール切替用の IAM ポリシー定義

ロール切替用のポリシー定義を作成します。
ターゲットアカウントの ID、ロール名がパラメータとなるので、テンプレート変換にすると便利です。

入力情報

- target_name: a2
  target_id: 222222222222
  roles:
    - Administrator  #=> a2_AdministratorPolicy
    - Maintainer     #=> a2_MaintainerPolicy
    - Viewer         #=> a2_ViewerPolicy

スクリプト

resource "aws_iam_policy" "this" {
  for_each = toset(var.roles)

  name        = format("%s_%sPolicy", var.target_name, each.key)    # ポリシー名
  path        = var.path                                            # パス (デフォルトで "/")
  description = var.desc                                            # ポリシー説明 (英数字のみ)

  policy = templatefile("policy_defs/assume_to.tpl.json", {         # ポリシー定義の本文 (テンプレートをファイルから読み込み)
    target_account_id = var.target_id,                              # ターゲットアカウント ID を指定
    path              = var.path,                                   # パス (デフォルトで "/")
    role_name         = format("%s", each.key)                      # ターゲットアカウント上のロール名
  })
}

テンプレートファイル(JSON)

policy_defs/assume_to.tpl.json
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::${target_account_id}:role${path}${role_name}"
    }
}

ロール切替用の IAM グループ作成

ロール切替用のグループを作成し、上記で作成したポリシーを割り当てます。

入力情報

- target_name: a2
  roles:
    - Administrator  #=> a2_AdministratorGroup
    - Maintainer     #=> a2_MaintainerGroup
    - Viewer         #=> a2_ViewerGroup

スクリプト

resource "aws_iam_group" "this" {
  for_each = toset(var.roles)

  name = format("%s_%sGroup", var.target_name, each.key)    # グループ名
  path = var.path                                           # パス (デフォルトで "/")
}

resource "aws_iam_group_policy_attachment" "this" {
  for_each = aws_iam_group.this

  group      = each.value.name                              # グループ名
  policy_arn = aws_iam_policy.this[each.key].arn            # 割り当てるポリシーの ARN
}

Terraform の構成

今回は以下のようにディレクトリを整理します。

versions.tf
components/
  account-master/
    main.tf
    outputs.tf
    versions.tf -> ../../versions.tf
  account-target/
    main.tf
    outputs.tf
    versions.tf -> ../../versions.tf
  policy_defs/
    assume_to.tpl.json
modules/
  group_assume_role/
    main.tf
    outputs.tf
    variables.tf
  policy/
    main.tf
    outputs.tf
    variables.tf
  role/
    main.tf
    outputs.tf
    variables.tf

ターゲットアカウントでは以下のようにコマンドを実行します。

$ cd components/account-target/
$ terraform init
$ terraform plan
$ terraform apply

マスターアカウントではこうなります。

$ cd components/account-master/
$ terraform init
$ terraform plan
$ terraform apply

module を使う/使わないなど、ベストプラクティスがいろいろあるようです。

作業者の役割によって、インフラ寄りだったり、アプリケーションの環境構築だったりと観点も異なるので、状況に合わせてよい形を見つけていくことが大事だと思います。
ディレクトリも適当な範囲で区切って、あまり大きくまとめない方がよさそうです。

個人としては、module を引き込む components 内の処理の記述が分かりやすくしたいです。
module は汎用性を高めるのではなく、components の記述がシンプルに仕様を表現できるように処理をまとめられるようにします。

ターゲットアカウントの設定スクリプトのイメージ

components/account-target/main.tf
locals {
  master_account_id = "111111111111"                         # マスターアカウント ID

  policy_defs = {                                            # 個別に定義するポリシー設定
    SamplePolicy = "Policy of Sample"
  }

  assumed_role_defs = {                                      # 切替先となるロールと割り当てるポリシー設定
    "Administrator" = {
      policies = [
        "arn:aws:iam::aws:policy/AdministratorAccess"
      ]
    },
    "Maintainer" = {
      policies = [
        "arn:aws:iam::aws:policy/PowerUserAccess"
      ]
    },
    "Viewer" = {
      policies = [
        "arn:aws:iam::aws:policy/job-function/ViewOnlyAccess"
      ]
    }
  }
}

module "target_policy" {                                     # 個別ポリシーを定義する
  source = "../../modules/policy"

  for_each = local.policy_defs

  name = each.key                                            # ポリシー名
  path = "/"
  desc = each.value                                          # ポリシー説明
  body = file(format("../policy_defs/%s.json", each.key))    # ポリシー定義の本文をファイルから読み込み
}

module "target_role" {                                       # ロールを定義する
  source = "../../modules/role"

  for_each = local.assumed_role_defs

  master_account_id = local.master_account_id                # マスターアカウント ID

  name     = each.key                                        # ロール名
  path     = "/"
  policies = each.value.policies                             # ロールに割りてるポリシーの一覧(ARN)
}

マスターアカウントの設定スクリプトのイメージ

components/account-master/main.tf
locals {
  target_defs = {                                            # 切替先ターゲットアカウントとロールの対応設定
    "a2" = {
      account_id = "222222222222",
      roles = [
        "Administrator",
        "Maintainer",
        "Viewer"
      ]
    },
    "a3" = {
      account_id = "333333333333",
      roles = [
        "Administrator",
        "Maintainer",
        "Viewer"
      ]
    }
  }
}

module "master_group_assume_role" {                          # ロール切替用のグループ、ポリシーを定義
  source = "../../modules/group_assume_role"

  for_each = local.target_defs

  assume_policy_template_file = "../policy_defs/assume_to.tpl.json"
                                                             # ロール切替用のポリシーのテンプレート定義ファイル
  target_name = each.key                                     # ターゲットアカウント名
  target_id   = each.value.account_id                        # ターゲットアカウント ID
  path        = "/"
  roles       = each.value.roles                             # ロール一覧
}

このように必要な情報だけに整理すると、仕様の見通しがよくなります。
例では設定内容は locals に集約されています。

あとは、先に説明した resource 定義をそれぞれ参照されている module に当てはめていくことになります。

今回はここまで。

// EOF

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?