🚔

AssumeRoleを使用したTerraformのセキュアなプロビジョニングを試す

2022/12/13に公開

これからやること


↑の「S3とか」をTerraformで構築するところまで試します。

用意するもの

  • 以下をインストール済みのWSL2
    • AWS CLI(v2以降)
    • aws-vault(v6以降)
    • Terraform(v0.15以降)
  • 以下の名前のようなAWSアカウントを2つ(Control TowerとかOrganizationsとかで用意)
    • assume-role
    • target1

1. 「assume_role_user」を作成 (これ以降、user部分を各人の名前に読み替える)


↑の赤枠部分が対象です。

①. 「assume-role」アカウントのIAMユーザー作成画面にアクセス

IAMユーザーを作成可能な権限で「assume-role」アカウントにログイン(AWS SSOなどで)。IAMユーザーの管理画面でユーザー追加ボタンをクリックします。

②. IAMユーザーの基本設定

以下のような設定にします。

  • ユーザー名:assume_role_user
  • AWS認証情報タイプを選択:アクセスキー

③. IAMユーザーのアクセス権限

「既存のポリシーを直接アタッチ」をクリックし、ポリシー作成ボタンをクリックします。

以下のようなJSON、名前は「assume_role」でポリシーを作成します。(タグや説明はお好みで追加)

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "*"
    }
}


IAMユーザーのアクセス権限設定の画面に戻り、更新ボタンを押して先ほど作成したポリシーを選択します。

④. IAMユーザーを作成しクレデンシャル情報を取得

タグなどはお好みで追加しIAMユーザーを作成します。
その後表示された画面で「assume_role_user」のクレデンシャル情報が記載されたcsvファイルをダウンロードしておきます。

⑤. MFAを有効化

IAMユーザーの管理画面で「assume_role_user」のMFAを有効化します。

名前は「user」で作成し、作成後に発行されるシリアル番号をメモしておきます。

2. 「assume_role_target1」を作成


↑の赤枠部分が対象です。

①. 「target」アカウントのIAMロール作成画面にアクセス

IAMロールを作成可能な権限で「target」アカウントにログイン(AWS SSOなどで)。IAMロールの管理画面でロール作成ボタンをクリックします。

②. IAMロールのカスタム信頼ポリシー

信頼されたエンティティは「カスタム信頼ポリシー」を選択し、以下のような設定にします。

以下が設定の詳細についてです。

  • 「1. Add actions for STS」では以下のアクションを追加
    • TagSession
    • SetSourceIdentity
  • 「2. プリンシパルを追加する」では以下を設定
    • プリンシパルタイプ:IAM users
    • ARN
      • {Account}:「assume-role」アカウントのアカウント番号
      • {UserName}:assume_role_user
  • 「3. 条件を追加する (オプション)」では以下を設定
    • 条件キー:aws:MultiFactorAuthPresent
    • 修飾子:デフォルト
    • 演算子:Bool
    • 値:true

③. IAMロールの許可ポリシー

ここでTerraformで扱いたいリソースの許可ポリシーを選択します。今回は試しにS3バケットを構築するので、「AmazonS3FullAccess」を選択します。

④. IAMロールを作成しARNを取得

名前は「assume_role_target1」でIAMロールを作成します。(タグや説明はお好みで追加)
その後、IAMロールの管理画面で「assume_role_target1」のARNをメモしておきます。

3. AssumeRoleを使用したTerraformでS3バケットをプロビジョニング


↑の赤枠部分が対象です。

①. 「assume-role-user」プロファイルを設定

ローカルPCに戻り

aws-vault add assume-role-user

といったコマンドで「assume-role-user」プロファイルを設定します。
(aws-vaultの詳しい使い方についてはこちら)
クレデンシャル情報は1-④でダウンロードした「assume_role_user」のcsvファイルを参照し設定します。

②. ~/.aws/configに設定を追記

以下コマンドの2項目を読み替えて実行し、~/.aws/configに設定を追記します。

  • {MfaSerialNumber}:1-⑤でメモしたMFAのシリアル番号
  • {AssumeRoleArn}:2-④でメモした「assume_role_target1」のARN
cat << 'EOS' >> ~/.aws/config
[profile common]
source_profile = assume-role-user
region=ap-northeast-1
output=json
mfa_serial={MfaSerialNumber}
role_session_name=user

[profile assume-role-target1]
include_profile=common
role_arn={AssumeRoleArn}

EOS

③. 「assume-role-target1」プロファイルを使用してセッションを確立する

以下コマンドを実行することで「assume-role-target1」プロファイルを使用したセッションを確立することが可能です。コマンド実行の際にはMFAコードの入力が求められます。1-⑤で設定したMFAデバイスを使用し、MFAコード入力してセッションを確立します。

aws-vault exec assume-role-target1

④. 「target」アカウントにS3バケットをプロビジョニングする

例えば以下のようなTerraformのコードを用意します。

terraform {
  required_version = "1.3.6"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.46.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
  default_tags {
    tags = {
      Name = "example"
    }
  }
}

### ==================================================

resource "aws_s3_bucket" "assume-role-target1-example" {
  bucket        = "assume-role-target1-example"
  force_destroy = true
}

あとはS3バケット名が既に使用されているものでなければ、terraform applyでプロビジョニングが実行可能となります。「target」アカウントにS3バケットが作成されているのを確認したらterraform destroyでS3バケットを削除するのを忘れないようにします。

さいごに

説明を少なくするためにIAMユーザーに直接ポリシーをアタッチしたりしましたが、実際にはIAMグループにポリシーをアタッチして、Terraformを扱う人用のユーザーをそのグループに追加していくみたいな運用がいいと思います。
また、~/.aws/configに別のAWSアカウント用プロファイルを追加する際も「common」プロファイルを継承してrole_arnだけ追記するみたいな設定でOKです。
個人的に今まで後回しにしていたAssumeRole運用の理解が出来てよかったです。これから本当にやりたかったTerragruntの導入に着手していこうと思います。

参考URL

https://developer.hashicorp.com/terraform/tutorials/aws/aws-assumerole
https://dev.classmethod.jp/articles/terraform-assumerole/

Discussion