Terraform で S3 を Backend に指定してステートファイルを管理したい。これを達成するため .tf
ファイルに次のような記述をするとしよう。
terraform {
...
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.23.0"
}
...
}
backend "s3" {
bucket = "my-bucket-for-tfstate"
key = "terraform.tfstate"
region = "ap-northeast-1"
}
}
provider "aws" {
region = var.region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
assume_role {
role_arn = var.aws_role_arn
}
}
次に S3
に my-buekct-for-tfstate
バケットを作成して terraform init
をするとしよう。次のようなエラーが表示されるだろう。
$ terraform init
Initializing modules...
Initializing the backend...
Error: Error loading state:
AccessDenied: Access Denied
status code: 403, request id: xxxxxxxxxxxxxxxx, host id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Terraform failed to load the default state from the "s3" backend.
State migration cannot occur unless the state can be loaded. Backend
modification and state migration has been aborted. The state in both the
source and the destination remain unmodified. Please resolve the
above error and try again.
何が問題なのか? ここでは .tf
ファイルで aws
プロバイダに設定している assume_role
が問題を起こしている。この例では、ある AWS アカウントに対して、あるロール (var.aws_role_arn
で指定されているもの) を assume してプロビジョンしているので、S3 には assume する前のユーザーがバケットにアクセスする権限が付与されていなければならない。
具体的にはプロビジョンする対象の AWS アカウントに作る my-bucket-for-tfstate
に次のような記述をする必要がある。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::012345678901:user/aws-terraform@example.com"
},
"Action": [
"s3:DeleteObject",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::my-bucket-for-tfstate",
"arn:aws:s3:::my-bucket-for-tfstate/*"
]
}
]
}
ここで "arn:aws:iam::012345678901:user/aws-terraform@example.com"
は AWS アカウント ID “012345678901” における IAM ユーザー “aws-terraform@example.com” の ARN であり、これが assume role 前のユーザーである。
この設定をすることで、最初の 403 エラーは解消できる。