Terraform の Multiple Provider Configurationsを使ってAWSクロスアカウントの環境構築を楽ちんに

2022.08.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Terraform の Multiple Provider Configurations は 「同一プロバイダー上で複数の設定を指定できる機能」です。 alias を付けることで実現できます。

以下に示す 公式ドキュメント の例では、 AWSプロバイダーにおいて 「us-east-1 リージョンの設定(デフォルト)」 と 「us-west-2リージョンの設定( aws.west )」 の2設定を作っています。

# The default provider configuration; resources that begin with `aws_` will use
# it as the default, and it can be referenced as `aws`.
provider "aws" {
  region = "us-east-1"
}

# Additional provider configuration for west coast region; resources can
# reference this as `aws.west`.
provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

今回は、この機能を使った「 AWSのクロスアカウント環境構築 」例を紹介します。 アーキテクチャによっては、複数アカウントで「設定の行き来」が発生するものがあります。 そういったケースで、 Multiple Provider Configurations は役に立ちます。 便利です。

事前準備

今回は下図のような構築を試してみます。

img

  • AWSアカウント( 111111111111 ) の IAMユーザー認証情報を使って terraform コマンドを実行
  • AWSアカウント( 222222222222 ) の IAMロールへスイッチして、リソース構築できるようにする
  • 同様に、AWSアカウント( 333333333333 ) の IAMロールへスイッチして、リソース構築できるようにする

IAMユーザーの準備部分は割愛します。

リソース構築用の IAMロールを事前に作成しておきます。 今回のケースだと、以下のような CloudFormationテンプレートから作成できます。

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  Principals:
    Type: CommaDelimitedList
    Default: "arn:aws:iam::111111111111:user/cm-kawahara.masahiro"
Resources:
  Role:
    Type: AWS::IAM::Role
    Properties: 
      RoleName: "terraform-infra-deploy-role"
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Ref Principals
            Action:
              - sts:AssumeRole
      Description: "This role is used for infra deploy via Terraform"
      ManagedPolicyArns: 
        - "arn:aws:iam::aws:policy/AdministratorAccess"

プロバイダー設定

以下のような provider.tf を作成します。

provider.tf

provider "aws" {
  alias  = "account2222"
  region = "ap-northeast-1"
  assume_role {
    role_arn = "arn:aws:iam::222222222222:role/terraform-infra-deploy-role"
    session_name = "terraform"
  }
}

provider "aws" {
  alias  = "account3333"
  region = "ap-northeast-1"
  assume_role {
    role_arn = "arn:aws:iam::333333333333:role/terraform-infra-deploy-role"
    session_name = "terraform"
  }
}

それぞれのAWSプロバイダーに alias ( account2222account3333 ) を付与しています。 role_arn にスイッチロール先のARNを記載します。

これで最低限のクロスアカウント環境構築の準備は完了です。 リソースを作成する際には provider 値を指定します。

クロスアカウントの環境構築例

(例その1) AWS Transit Gatewayのクロスアカウント環境

img

Transit Gateway(TGW)のクロスアカウント環境を考えます。 他アカウントのVPC上にアタッチメントを作成して ネットワークを構成するには、以下の手順を踏む必要があります。

  1. TGWを作成して Resource Access Manager(RAM)で他アカウントに共有する
  2. 共有先アカウントにて VPCアタッチメントを作成する
  3. 「VPCアタッチメントのリクエスト」を承諾する (自動承諾の場合は不要)

これを Multiple Provider Configurations で構成する場合は以下のようなコードになります。 (リソースの設定値は適当です)

resource aws_vpc account3333 {
  provider = aws.account3333

  cidr_block = "10.33.0.0/16"
}

resource aws_subnet account3333 {
  provider = aws.account3333

  vpc_id     = aws_vpc.account3333.id
  cidr_block = "10.33.0.0/24"
}

##### 1. TGWを作成して Resource Access Manager(RAM)で他アカウントに共有する
# Transit Gateway
resource aws_ec2_transit_gateway this {
  provider = aws.account2222

  auto_accept_shared_attachments  = "enable"
  default_route_table_association = "disable"  
  default_route_table_propagation = "enable"
}

# Resouece Access Manager
resource aws_ram_resource_share this {
  provider = aws.account2222

  name                      = "tgw-share"
  allow_external_principals = false
}

resource aws_ram_resource_association this {
  provider = aws.account2222

  resource_arn       = aws_ec2_transit_gateway.this.arn
  resource_share_arn = aws_ram_resource_share.this.arn
}

resource aws_ram_principal_association this {
  provider = aws.account2222

  principal          = arn:aws:organizations::999999999999:ou/o-example/ou-example
  resource_share_arn = aws_ram_resource_share.this.arn
}

##### 2. 共有先アカウントにて VPCアタッチメントを作成する
# TGW/VPC Attachment
resource aws_ec2_transit_gateway_vpc_attachment account3333 {
  provider = aws.account3333

  depends_on         = [ aws_ram_principal_association.this ]
  transit_gateway_id = aws_ec2_transit_gateway.this.id
  vpc_id             = aws_vpc.account3333.id
  subnet_ids         = [ aws_subnet.account3333.id ]

  transit_gateway_default_route_table_propagation = true
  transit_gateway_default_route_table_association = false
}

##### 3. 「VPCアタッチメントのリクエスト」を承諾する (自動承諾の場合は不要)
# TGW/VPC Attachment Accepter
resource aws_ec2_transit_gateway_vpc_attachment_accepter account3333 {
  provider = aws.account2222

  transit_gateway_attachment_id = aws_ec2_transit_gateway_vpc_attachment.account3333.id
}

(例その2) Route53プライベートホストゾーンのクロスアカウント関連付け

img

Route53プライベートホストゾーンを他アカウントに関連付けるためには、 以下の手順を踏む必要があります。

  1. プライベートホストゾーン(PHZ)の作成
  2. 共有アカウントに対して、PHZの「関連付け承認」を作成する
  3. 共有アカウントにて PHZの「関連付け」を作成する

これを Multiple Provider Configurations で構成する場合は以下のようなコードになります。 (リソースの設定値は適当です)

resource aws_vpc account2222 {
  provider = aws.account2222

  cidr_block = "10.22.0.0/16"
}

resource aws_vpc account3333 {
  provider = aws.account3333

  cidr_block = "10.33.0.0/16"
}

##### 1. プライベートホストゾーン(PHZ)の作成
# Route53 Alias Record
resource aws_route53_zone this {
  provider = aws.account2222

  name = "example.com"
 
  vpc {
    vpc_id = aws_vpc.account2222.id
  }
}

##### 2. 共有アカウントに対して、PHZの「関連付け承認」を作成する
resource aws_route53_vpc_association_authorization account3333 {
  provider = aws.account2222

  zone_id = aws_route53_zone.this.zone_id
  vpc_id  = aws_vpc.account3333.id
}

##### 3. 共有アカウントにて PHZの「関連付け」を作成する
resource aws_route53_zone_association account3333 {
  provider = aws.account3333

  vpc_id  = aws_route53_vpc_association_authorization.account3333.vpc_id
  zone_id = aws_route53_vpc_association_authorization.account3333.zone_id
}

おわりに

Terraformの Multiple Provider Configurationsの活用例でした。 AWSマルチアカウントの環境構築で複数アカウントまたいだアーキテクチャを構築する際は、 この機能は便利です。おすすめです。

参考