I have a terraform code which deploys S3, S3 policy, VPC Endpoint, VPC endpoint policy.
resource "aws_security_group" "S3_vpc_endpoint" {
name = "s3_endpoint-sg"
vpc_id = data.aws_vpc.selected.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"] }
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"] }
tags = var.tags
}
# Create S3 bucket
resource "aws_s3_bucket" "databucket" {
bucket = "test"
force_destroy = true
tags = var.tags
}
# Resource to attach a bucket policy to a bucket resource
"aws_s3_bucket_policy" "access_through_vpc_endpoint" {
bucket = aws_s3_bucket.databucket.id
policy = <<EOF {
"Version":"2012-10-17",
"Id":"Policy1415115909152",
"Statement":[
{
"Sid":"Access-to-specific-VPCE-only",
"Principal":"*",
"Action":"s3:*",
"Effect":"Deny",
"Resource":[
"arn:aws:s3:::${aws_s3_bucket.databucket.bucket}",
"arn:aws:s3:::${aws_s3_bucket.databucket.bucket}/*"
],
"Condition":{
"StringNotEquals":{
"aws:sourceVpce":"${aws_vpc_endpoint.s3.id}"
}
}
} ] } EOF
depends_on = [aws_vpc_endpoint.s3]
}
resource "aws_s3_bucket_ownership_controls" "databucket" {
bucket = aws_s3_bucket.databucket.id
rule {
object_ownership = "BucketOwnerPreferred" } }
resource "aws_s3_bucket_public_access_block" "databucket" {
bucket = aws_s3_bucket.databucket.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_vpc_endpoint" "s3" {
vpc_id = data.aws_vpc.selected.id
service_name = "com.amazonaws.us-east-1.s3"
subnet_ids = data.aws_subnets.test_subnets.ids
security_group_ids = [aws_security_group.S3_vpc_endpoint.id]
vpc_endpoint_type = "Interface"
private_dns_enabled = true
tags = var.tags }
resource "aws_vpc_endpoint_policy" "s3" {
vpc_endpoint_id = aws_vpc_endpoint.s3.id
policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
"Sid" : "AccessToSpecificBucket",
"Effect" : "Allow",
"Principal" : "*",
"Action" : [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject"
],
"Resource" : [
"arn:aws:s3:::${aws_s3_bucket.databucket.bucket}",
"arn:aws:s3:::${aws_s3_bucket.databucket.bucket}/*"
]
}
] }) }
After deploying this resources I can access S3 through vpc endpoint by running this aws cli command:
- aws s3 ls s3://my-bucket/ --region us-east-1 --endpoint-url https://bucket.vpce-1a2b3c4d-5e6f.s3.us-east-1.vpce.amazonaws.com
To force terraform to use private endpoint I added below block to provider:
provider "aws" {
region = var.aws_region
endpoints {
s3 = "https://bucket.vpce-1a2b3c4d-5e6f.s3.us-east-1.vpce.amazonaws.com"
}
}
I created EC2 instance in the same VPC with full access role and tried to plan terraform\terragrunt code but it took long time to plan and after gives me an error:
│ Error: getting S3 bucket (test-63891963011907) policy:
AccessDenied: Access Denied │ status code: 403, request id:
3EN8P99ZDY5R8W45, host id:
tg+K3zhErNLy8VgN5v3KmYv8GiDw5amn8GDLZfBvpBGHowYxPWJfdvveWL7tToXU9dDKFFTU+3E=
│ │ with aws_s3_bucket.databucket, │ on main.tf line 108, in
resource "aws_s3_bucket" "databucket": │ 108: resource
"aws_s3_bucket" "databucket" {
Do anybody implemented such case with terraform ?
Howcan I tell terraform to use private endpoint for S3. Because by default it requests public endpoints.
Regards