문제 상황
Terraform을 이용해 인프라 상태를 원격으로 관리하기 위해 S3 + DynamoDB 백엔드(remote backend) 구성을 진행하던 중, 다음과 같은 오류가 반복적으로 발생했습니다.
Error refreshing state: AccessDenied: Access Denied
status code: 403, request id: CTSMC4XBQGZTEZEN,
host id: dbPwZnfLV1BQ4/fYHNI1X4NaWrTFGVCfT1acfI/vpqeR82ZngYlj1FJju1vfKTMJKH68qk/rTarOJnsEz/2My2iOr0eT/oV9bGMNqJV0RTs=
Bash
복사
진단 순서
1.
S3 버킷(come2us-dev-tfstate)과 DynamoDB 테이블(come2us-dev-tflock)은 정상적으로 생성되었고
2.
CLI로 접근(aws s3 ls --profile terraform)은 성공했으나
3.
Terraform에서 terraform init -backend-config=env/backend.hcl 실행 시 403 AccessDenied가 지속되었습니다.
원인 분석
S3 버킷 정책과 IAM 정책 불일치
Terraform 전용 IAM User(terraform-access)와 Role(terraform-access-role)은 생성되었으나,
버킷 정책은 Role만 허용하고 User는 제외되어 있었습니다.
이로 인해 Terraform이 backend 연결 시 사용하는 IAM User가 S3 접근 권한을 갖지 못했습니다.
"Principal": {
"AWS": "${terraform_role_arn}"
}
JSON
복사
이후 정책을 수정해 User와 Role 모두 접근할 수 있도록 했지만, S3 backend 설정 자체까지만 인식되었고, Terraform이 S3에서 상태 파일(terraform.tfstate)을 “읽거나 생성”하려고 시도하는 단계에서 403 발생
Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Error refreshing state: AccessDenied: Access Denied
status code: 403, request id: CTSMC4XBQGZTEZEN, host id: dbPwZnfLV1BQ4/fYHNI1X4NaWrTFGVCfT1acfI/vpqeR82ZngYlj1FJju1vfKTMJKH68qk/rTarOJnsEz/2My2iOr0eT/oV9bGMNqJV0RTs=
Bash
복사
Terraform backend 초기화 순서 문제
Terraform은 provider보다 backend를 먼저 초기화합니다.
terraform init -backend-config=env/backend.hcl -reconfigure
Bash
복사
즉, 아래 코드의 provider "aws" {...} 블록은 backend 연결 시점에서는 무시됩니다.
terraform {
backend "s3" {}
}
provider "aws" {
region = var.region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
assume_role {
role_arn = var.terraform_role_arn
}
}
HCL
복사
# ./env/backend.hcl
bucket = "come2us-dev-tfstate"
key = "infra/dev/terraform.tfstate"
region = "ap-northeast-2"
dynamodb_table = "come2us-dev-tflock"
HCL
복사
따라서 Terraform은 init 과정에서 provider에 정의된 키를 사용하지 못하고, 환경변수 또는 로컬 AWS CLI 프로필(default) 을 자동 탐색합니다.
Terraform이 ~/.aws/credentials의 [default] 프로필을 참조하고 있었기 때문입니다.
저의 경우 credentials 에서 여러 프로필을 사용하고 있는데, backend.hcl에 명시하지 않아 위와 같은 오류를 겪었습니다. ([default] = 개인 계정, [come2us] = 팀 계정)
해결 과정
S3 버킷 정책 수정
Terraform IAM User와 Role 모두가 접근할 수 있도록 수정했습니다.
{
"Sid": "AllowTerraformRoleAccess",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::997784788329:user/terraform-access",
"arn:aws:iam::997784788329:role/terraform-access-role"
]
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:ListBucket",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::come2us-dev-tfstate",
"arn:aws:s3:::come2us-dev-tfstate/*"
]
}
JSON
복사
IAM 정책 보완
Terraform이 DynamoDB를 사용해 state lock을 관리할 수 있도록
DescribeTable, ListTables 권한을 추가했습니다.
{
"Sid": "LockTableAccess",
"Effect": "Allow",
"Action": [
"dynamodb:PutItem",
"dynamodb:GetItem",
"dynamodb:DeleteItem",
"dynamodb:Scan",
"dynamodb:UpdateItem",
"dynamodb:DescribeTable",
"dynamodb:ListTables"
],
"Resource": "arn:aws:dynamodb:${region}:${account_id}:table/${table_name}"
}
JSON
복사
backend.hcl에 프로필 추가
Terraform backend 설정 파일(env/backend.hcl)에 프로필을 명시했습니다.
bucket = "come2us-dev-tfstate"
key = "infra/dev/terraform.tfstate"
region = "ap-northeast-2"
dynamodb_table = "come2us-dev-tflock"
profile = "terraform" # 필수!
HCL
복사
이후 명령 실행:
terraform init -backend-config=env/backend.hcl -reconfigure
Bash
복사
개선 효과
항목 | 개선 전 | 개선 후 |
Terraform init | 403 AccessDenied | |
CLI 접근 (aws s3 ls) | 가능 | 가능 |
버킷 정책 구조 | Role만 허용 | Role + User 모두 허용 |
IAM 정책 권한 | DynamoDB Describe 누락 | |
프로필 관리 방식 | default 강제 사용 | backend.hcl 명시적 지정 |
인사이트
1.
Terraform backend는 provider보다 먼저 초기화된다.
따라서 provider 블록의 credentials는 backend 연결 시 무시된다.
2.
S3 + DynamoDB backend를 사용할 때는 프로필을 backend.hcl에 명시해야 한다.
3.
IAM Role만 허용할 경우 Terraform CLI는 User 키를 사용하기 때문에 AccessDenied가 발생한다.
4.
terraform init은 profile 옵션을 지원하지 않는다.
대신 AWS_PROFILE 환경변수 또는 profile 키를 활용해야 한다.
5.
Terraform state 관리는 IAM 최소 권한 원칙(Least Privilege)을 유지하되,
S3 Get/List, DynamoDB Describe/List 권한은 필수적이다.



