Terraformでstateファイルの格納先を分離したいときのTips


はじめに

Terraformを使用してAWSリソースを構築する際に、コンプライアンス上の理由により、実際にAWSリソースを作成する対象となるAWSアカウントと、stateファイルを保管する対象になるS3バケットを分離したい、なんていう要件が発生することがよくあります。

実際に業務でそういった要件が発生し、どうしたものかとちょっと悩んだのですが、意外と簡単に解決することができたので、Tipsとして書き残しておきます。

環境

実装している環境は以下の通りです。

  • Terraform: 1.7.3
  • AWS Provider: 5.36.0
  • クライアントのOS: macOS Sonoma 14.3.1

Profileの設定

Profileの設定は、他のTerraform実行環境と同様に、macOSであれば ~/.aws/config に記述しますが、今回はAWS IAM Identity Center (AWS SSO)を使用してAWSアカウントに対してアクセスを行っているので、Profileは以下のように記述しています。

# IAM Identity CenterにSSOでアクセスするためのProfileを記述
[sso-session vlayusuke]
sso_start_url = https://vlayusuke.awsapps.com/start#
sso_region = ap-northeast-1
sso_registration_scopes = sso:account:access

# stateファイルを格納する対象となるAWSアカウントの情報
[profile vlayusuke-state-account]
sso_session = vlayusuke
sso_account_id = ************
sso_role_name = vlayusuke-S3Control
region = ap-northeast-1
output = json

# AWSリソースを構築する対象となるAWSアカウントの情報
[profile vlayusuke-resource-account]
sso_session = vlayusuke
sso_account_id = ************
sso_role_name = vlayusuke-ResourceAccess
region = ap-northeast-1
output = json

vlayusuke と定義したsso-sessionを利用して、stateファイルを格納する対象となるAWSアカウント( vlayusuke-state-account )と、実際にAWSリソースを構築するAWSアカウント( vlayusuke-resource-account )とを定義しています。

AWS IAM Identity Centerを使用していない場合でも、stateファイルを格納したいAWSアカウントのProfile情報と、AWSリソースを構築する対象のAWSアカウントのProfile情報を記述しておけば問題ないと思います。

terraform.tfの実装と実行

その上で、 terraform.tf には以下のように実装をします。

ポイントとなるのは、S3 Backendを定義するブロックと、Providerを定義するブロックに、それぞれProfileで定義したそれぞれのProfile情報を profile で設定してあげればOKです。

terraform {
  required_version = "1.7.3"

  backend "s3" {
    bucket  = "vlayusuke-state-bucket"
    key     = "state/production.terraform.tfstate"
    region  = "ap-northeast-1"
    profile = "vlayusuke-state-account"
  }

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

data "aws_caller_identity" "current" {}
data "aws_elb_service_account" "main" {}

provider "aws" {
  region  = "ap-northeast-1"
  profile = "vlayusuke-resource-account"

  default_tags {
    tags = {
      Managed     = "terraform"
      Identifier  = local.identifier
      Project     = local.project
      Environment = local.env
      Repository  = local.repository
    }
  }
}

実行時には、以下の順序でコマンドを実行してあげれば確実です。先にstateファイルを保管するProfile情報を使用して aws sso login を実行してログインを行い、次に実際にAWSリソースを構築するProfile情報を使用して aws sso login をすることで、最後に実行したProfile情報に記述したAWSアカウント上で、Terraformを実行することが可能になります。

% aws sso login --profile vlayusuke-state-account

(WebブラウザでAWS IAM Identity Centerから認証を求める画面が表示されるので、認証を行います)

% aws sso login --profile vlayusuke-resource-account

(WebブラウザでAWS IAM Identity Centerから認証を求める画面が表示されるので、認証を行います)

% terraform init

実際に設定のコツさえわかってしまえば、構成管理のためにもかなり有用な方法なので、もしもこのような要件が出てきた場合にはぜひ試してみてください。

カテゴリー: AWS, Work タグ: , パーマリンク