Can’t seem to create route53 record for s3

Hi,

We have an internal application that is being deprecated very soon. The current address for the site is x.company.io. The site is changing to y.company.io. Instead of doing a redirect from the old address the new, management wants a little page that tells application users that it has moved and update their bookmarks. I guess this makes sense, as they’ll just keep going to the old URL and when I eventually delete the record they’ll be confused.

Anyway, I figured the easiest way to do this was to make a simple HTML document and host it on S3 as a website. The HTML page works just fine if I go to the website endpoint: http://bucket_id.s3-website.us-east-2.amazonaws.com. Cool.

The front end of the application is on Amplify. When it’s time to switch it over (they’re both running parallel right now), I’ll need to point the old URL (x.company.io) to this S3 bucket. The new version of the application is already pointing to y.company.io and working.

Right now I’m just doing some testing so I know this will work when the cutoff happens. I’m using just a bogus record name for now. When I try to go to this temporary testing URL via the Route 53 record, I get a 404 from my browser and curl.

404 Not Found

    Code: NoSuchBucket
    Message: The specified bucket does not exist
    BucketName: temp-redirect.company.io
    RequestId: 1WVMY8RF1ES2ANTA
    HostId: xVYYn8bIa/6/yp2+9bjyTzdq6+ZG+dOrVaryYqmp2Vc1TzYvugO10H8GR5pY862BMaggprLPo5M=

If I do a nslookup of the s3 bucket website domain and the route53 record, the Non-authoritative answer addresses are both different. Which confuses me even more.

The BucketName in the error is the Route53 record I’m trying to create, not the bucket I’m trying to point to. I can’t seem to figure out where in my code is causing that. My Terraform code is essentially identical to the Terraform AWS Provider Version 4 Upgrade Guide

This error made me think that if I change the alias name to aws_s3_bucket.redirect.id to the bucket ID, it would make it work. But that resulted in an error:

Error: [ERR]: Error building changeset: InvalidChangeBatch: [Tried to create an alias that targets BUCKET_ID., type A in zone XXXXXXXXXXX, but the alias target name does not lie within the target zone]
│ 	status code: 400, request id: fc3a53af-79eb-4d4d-b61e-b9a1773c0dea

If I try to change the alias name to aws_s3_bucket_website_configuration.redirect.website_endpoint, I got timeouts using the route53 record. So I changed back to aws_s3_bucket_website_configuration.redirect.website_domain.

S3 website hosting is a bit of a mystery to me. I use it sparingly for very simple tasks when I’m too lazy to make a real sever. I’ve never used route 53 with it.

I was wondering if it is just not possible to create a route53 record name that doesn’t match the bucket name. However, the docs seem to show someone making a www route53 record name pointing to some random bucket. So, I made a new route53 record that has the same name as the bucket_id (if that worked would make a CNAME to that record) and am essentially getting the same 404. What am I missing?

If I can’t get this figured out, I’ll just make a tiny EC2 running httpd for a bit…

Here is my code:

################################################################################
# Terraform
################################################################################
terraform {
  required_version = ">= 1.2.2"

  backend "s3" {
    bucket = "bucket"
    key    = "redirect.tfstate"
    region = "us-east-2"
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~>4.0"
    }
  }
}

provider "aws" {
  region = "us-east-2"
}

################################################################################
# Data Sources
################################################################################
data "aws_caller_identity" "current" {}

data "aws_region" "current" {}

################################################################################
# S3
################################################################################
// Data Sources
data "aws_s3_bucket" "access_logs" {
  bucket = lower("${data.aws_caller_identity.current.account_id}-${data.aws_region.current.name}-s3-logs")
}

// Old Redirect Page
resource "aws_s3_bucket_policy" "redirect" {
  bucket = aws_s3_bucket.redirect.id
  policy = data.aws_iam_policy_document.redirect.json
}

data "aws_iam_policy_document" "redirect" {
  statement {
    principals {
      type        = "*"
      identifiers = ["*"]
    }

    actions = [
      "s3:GetObject",
      "s3:ListBucket",
    ]

    resources = [
      aws_s3_bucket.redirect.arn,
      "${aws_s3_bucket.redirect.arn}/*",
    ]
    effect = "Allow"
  }
}

resource "aws_s3_bucket" "redirect" {
  bucket        = lower("${var.company}-old-${var.service}-redirect")
  force_destroy = true

  tags = merge(local.common_tags, tomap({ "Name" = lower("${var.company}-old-${var.service}-redirect") }))
}

resource "aws_s3_bucket_acl" "redirect" {
  bucket = aws_s3_bucket.redirect.id
  acl    = "private"
}

resource "aws_s3_bucket_versioning" "redirect" {
  bucket = aws_s3_bucket.redirect.id

  versioning_configuration {
    status = "Suspended"
  }
}

resource "aws_s3_bucket_public_access_block" "redirect" {
  bucket = aws_s3_bucket.redirect.id

  block_public_acls       = false
  ignore_public_acls      = false
  block_public_policy     = false
  restrict_public_buckets = false
}

resource "aws_s3_bucket_logging" "redirect" {
  bucket = aws_s3_bucket.redirect.id

  target_bucket = data.aws_s3_bucket.access_logs.id
  target_prefix = "${aws_s3_bucket.redirect.id}/"
}

resource "aws_s3_bucket_server_side_encryption_configuration" "redirect" {
  bucket = aws_s3_bucket.redirect.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_website_configuration" "redirect" {
  bucket = aws_s3_bucket.redirect.id

  index_document {
    suffix = "index.html"
  }
}

resource "aws_s3_object" "redirect_index" {
  key                    = "index.html"
  bucket                 = aws_s3_bucket.redirect.id
  server_side_encryption = "AES256"
  content_type           = "text/html"
  content                = file("${path.cwd}/Assets/index.html")
}

################################################################################
# Route 53
################################################################################
data "aws_route53_zone" "public" {
  name         = lower("${var.company}.io")
  private_zone = false
}

resource "aws_route53_record" "redirect" {
  allow_overwrite = true
  zone_id         = data.aws_route53_zone.public.zone_id
  name            = "temp-redirect"
  type            = "A"

  alias {
    evaluate_target_health = true
    name                   = aws_s3_bucket_website_configuration.redirect.website_domain
    zone_id                = aws_s3_bucket.redirect.hosted_zone_id
  }
}