Search
🔐

[TroubleShooting] S3 + DynamoDB 백엔드 접근 오류 (403 AccessDenied)

Date
2025/11/10
Category
Devops
Tag
TroubleShooting
AWS
IaC

문제 상황

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) 을 자동 탐색합니다.
CLI로는 접근이 가능한데 Terraform은 실패한 이유가 바로 이것입니다.
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
복사
결과: S3 접근은 AWS CLI와 콘솔 모두에서 정상 동작 확인

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
복사
결과: backend가 올바른 프로필(terraform)을 사용하여 S3/DynamoDB 접근 성공

개선 효과

항목
개선 전
개선 후
Terraform init
403 AccessDenied
정상 연결
CLI 접근 (aws s3 ls)
가능
가능
버킷 정책 구조
Role만 허용
Role + User 모두 허용
IAM 정책 권한
DynamoDB Describe 누락
Describe/List 추가
프로필 관리 방식
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 initprofile 옵션을 지원하지 않는다.
대신 AWS_PROFILE 환경변수 또는 profile 키를 활용해야 한다.
5.
Terraform state 관리는 IAM 최소 권한 원칙(Least Privilege)을 유지하되,
S3 Get/List, DynamoDB Describe/List 권한은 필수적이다.

참고자료