Creating and Destroying AWS S3 Buckets in two Regions with Terraform

January 03, 2017

terraform

I ran across an issue with Terraform where I couldn't destroy an Amazon S3 bucket created in a region other than the one provided at the prompt.

To get around this I had to configure an AWS provider for each region I wanted to add a bucket to, and use the alias property to reference the provider from the s3 resource.

Without the region based providers security errors were showing up when trying to manipulate the bucket in different regions.

For example, Create two buckets in different regions:

resource "aws_s3_bucket" "s3_bucket_1" { bucket = "com-ginocoates-testbucket1" region = "us-east-1" } resource "aws_s3_bucket" "s3_bucket_2" { bucket = "com-ginocoates-testbucket2" region = "us-east-2" }

Plan and apply them...

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform plan provider.aws.region The region where AWS operations will take place. Examples are us-east-1, us-west-2, etc. Default: us-east-1 Enter a value: + aws_s3_bucket.s3_bucket_1 acceleration_status: "<computed>" acl: "private" arn: "<computed>" bucket: "com-ginocoates-testbucket1" force_destroy: "false" hosted_zone_id: "<computed>" region: "us-east-1" request_payer: "<computed>" versioning.#: "<computed>" website_domain: "<computed>" website_endpoint: "<computed>" + aws_s3_bucket.s3_bucket_2 acceleration_status: "<computed>" acl: "private" arn: "<computed>" bucket: "com-ginocoates-testbucket2" force_destroy: "false" hosted_zone_id: "<computed>" region: "us-east-2" request_payer: "<computed>" versioning.#: "<computed>" website_domain: "<computed>" website_endpoint: "<computed>" Plan: 2 to add, 0 to change, 0 to destroy. gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform apply provider.aws.region The region where AWS operations will take place. Examples are us-east-1, us-west-2, etc. Default: us-east-1 Enter a value: aws_s3_bucket.s3_bucket_2: Creating... acceleration_status: "" => "<computed>" acl: "" => "private" arn: "" => "<computed>" bucket: "" => "com-ginocoates-testbucket2" force_destroy: "" => "false" hosted_zone_id: "" => "<computed>" region: "" => "us-east-2" request_payer: "" => "<computed>" versioning.#: "" => "<computed>" website_domain: "" => "<computed>" website_endpoint: "" => "<computed>" aws_s3_bucket.s3_bucket_1: Creating... acceleration_status: "" => "<computed>" acl: "" => "private" arn: "" => "<computed>" bucket: "" => "com-ginocoates-testbucket1" force_destroy: "" => "false" hosted_zone_id: "" => "<computed>" region: "" => "us-east-1" request_payer: "" => "<computed>" versioning.#: "" => "<computed>" website_domain: "" => "<computed>" website_endpoint: "" => "<computed>" aws_s3_bucket.s3_bucket_1: Still creating... (10s elapsed) aws_s3_bucket.s3_bucket_1: Creation complete Error applying plan: 1 error(s) occurred: * aws_s3_bucket.s3_bucket_2: Error putting S3 ACL: TemporaryRedirect: Please re-send this request to the specified temporary endpoint. Continue to use the original request endpoint for future requests. status code: 307, request id: 9D4A2839B33A45F4

We get an error, however, the two buckets were created successfully. We can query s3 to verify...

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ aws s3 ls | grep bucket 2017-01-03 14:16:01 com-ginocoates-testbucket1 2017-01-03 14:15:59 com-ginocoates-testbucket2

Lets try to destroy the buckets...

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform destroy Do you really want to destroy? Terraform will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes provider.aws.region The region where AWS operations will take place. Examples are us-east-1, us-west-2, etc. Default: us-east-1 Enter a value: aws_s3_bucket.s3_bucket_2: Refreshing state... (ID: com-ginocoates-testbucket2) aws_s3_bucket.s3_bucket_1: Refreshing state... (ID: com-ginocoates-testbucket1) Error refreshing state: 1 error(s) occurred: * aws_s3_bucket.s3_bucket_2: error reading S3 bucket "com-ginocoates-testbucket2": Forbidden: Forbidden status code: 403, request id: E081D8D9A009E943

Forbidden error, since the AWS provider is initialized with us-east-1, we can't delete the s3 bucket that was created in us-east-2. What I think this means is that the default provider is locked in to the region it was initialized with and can't call the s3 API in another region to refresh the state of bucket 2.

Lets try to fix it. Configure the AWS provider so we can create buckets in different regions. We can do this with alias properties.

provider "aws" { alias = "us-east-1" region = "us-east-1" } provider "aws" { alias = "us-east-2" region = "us-east-2" } resource "aws_s3_bucket" "s3_bucket_1" { bucket = "com-ginocoates-testbucket1" region = "us-east-1" provider = "aws.us-east-1" } resource "aws_s3_bucket" "s3_bucket_2" { bucket = "com-ginocoates-testbucket2" region = "us-east-2" provider = "aws.us-east-2" }

Lets plan these changes...

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform plan aws_s3_bucket.s3_bucket_1: Refreshing state... (ID: com-ginocoates-testbucket1) aws_s3_bucket.s3_bucket_2: Refreshing state... (ID: com-ginocoates-testbucket2) No changes. Infrastructure is up-to-date. This means that Terraform could not detect any differences between your configuration and the real physical resources that exist. As a result, Terraform doesn't need to do anything.'

So TF now sees the state as correct. Can we now destroy the s3 buckets successfully in each region?

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform destroy gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform destroy Do you really want to destroy? Terraform will delete all your managed infrastructure. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes aws_s3_bucket.s3_bucket_2: Refreshing state... (ID: com-ginocoates-testbucket2) aws_s3_bucket.s3_bucket_1: Refreshing state... (ID: com-ginocoates-testbucket1) aws_s3_bucket.s3_bucket_1: Destroying... aws_s3_bucket.s3_bucket_2: Destroying... aws_s3_bucket.s3_bucket_2: Destruction complete aws_s3_bucket.s3_bucket_1: Destruction complete Destroy complete! Resources: 2 destroyed.

Yes! Now is it possible to move bucket2 to us-east-1? Lets first recreate them.

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform apply aws_s3_bucket.s3_bucket_1: Creating... acceleration_status: "" => "<computed>" acl: "" => "private" arn: "" => "<computed>" bucket: "" => "com-ginocoates-testbucket1" force_destroy: "" => "false" hosted_zone_id: "" => "<computed>" region: "" => "us-east-1" request_payer: "" => "<computed>" versioning.#: "" => "<computed>" website_domain: "" => "<computed>" website_endpoint: "" => "<computed>" aws_s3_bucket.s3_bucket_2: Creating... acceleration_status: "" => "<computed>" acl: "" => "private" arn: "" => "<computed>" bucket: "" => "com-ginocoates-testbucket2" force_destroy: "" => "false" hosted_zone_id: "" => "<computed>" region: "" => "us-east-2" request_payer: "" => "<computed>" versioning.#: "" => "<computed>" website_domain: "" => "<computed>" website_endpoint: "" => "<computed>" aws_s3_bucket.s3_bucket_1: Still creating... (10s elapsed) aws_s3_bucket.s3_bucket_2: Still creating... (10s elapsed) aws_s3_bucket.s3_bucket_1: Creation complete aws_s3_bucket.s3_bucket_2: Creation complete Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Lets use change testbucket to to use the provider us-east-1. In theory this should destroy the bucket and create a new one in the desired region. Fingers crossed....

provider "aws" { alias = "us-east-1" region = "us-east-1" } provider "aws" { alias = "us-east-2" region = "us-east-2" } resource "aws_s3_bucket" "s3_bucket_1" { bucket = "com-ginocoates-testbucket1" region = "us-east-1" provider = "aws.us-east-1" } resource "aws_s3_bucket" "s3_bucket_2" { bucket = "com-ginocoates-testbucket2" region = "us-east-1" provider = "aws.us-east-1" }

Plan the changes...

gino@gino-MacBookPro:~/sourcecode/s3-multiregion$ terraform plan aws_s3_bucket.s3_bucket_1: Refreshing state... (ID: com-ginocoates-testbucket1) aws_s3_bucket.s3_bucket_2: Refreshing state... (ID: com-ginocoates-testbucket2) Error refreshing state: 1 error(s) occurred: * aws_s3_bucket.s3_bucket_2: error reading S3 bucket "com-ginocoates-testbucket2": Forbidden: Forbidden status code: 403, request id: 83855B6D6780B04D

Oops, error. The state has the bucket in us-east-2, but the tf files reference us-east-1. So the provider is initialized with the us-east-1 endpoint when we run terraform plan. But it can't refresh the state of the bucket in us-east-2 as its configured to use a different AWS endpoint. Kinda makes sense.

So, with TF we can't destroy a bucket in one region and recreate it in another with this setup. Something to watch out for!

To achieve the move we'd have to remove bucket2 from our tf files, apply to allow TF to destroy it, then add it back with the desired region, and apply these changes.

Learn Terraform Here....

Sharing is caring

Stay In Touch

Connect with Me

© 2021, Created by me using Gatsby