Why does my CloudFront distribution give access denied when I have any path or query params in the URL?

0

For example www.example.com loads fine but on load if the URL changes to www.example.com/upload and then I click reload in the browser I get an access denied. The same behaviour occurs when I have query parameters in the URL, I will admit I haven't read the docs thoroughly, but would be grateful if someone just directs my in the right direction. Thanks. Enter image description here
Enter image description here

More details:

  • My bucket is private
  • SSE-KMS is disabled
  • I use an OAC policy to access the contents
  • I have alternative aliases configured to point to my Route53 domain name
  • I have this specified in my S3 bucket policy: "Action": "s3:GetObject", "Resource": "arn:aws:s3:::staging-filtering-bucket/*",
  • I have this in my CORS S3 config: [ { "AllowedHeaders": [], "AllowedMethods": [ "GET" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [], "MaxAgeSeconds": 0 } ]

This is my Terraform configuration for my CloudFront distribution:

resource "aws_cloudfront_origin_access_control" "frontend_oac" {
  count                             = var.create_resources ? 1 : 0
  name                              = aws_s3_bucket.frontend_bucket[0].bucket_regional_domain_name
  description                       = "Origin Access Control policy for frontends"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}

resource "aws_cloudfront_distribution" "s3_distribution" {
  count = var.create_resources ? 1 : 0
  origin {
    domain_name              = aws_s3_bucket.frontend_bucket[0].bucket_regional_domain_name
    origin_access_control_id = aws_cloudfront_origin_access_control.frontend_oac[0].id
    origin_id                = var.s3_origin_id

    origin_shield {
      enabled = true
      origin_shield_region = "eu-west-2"
    }
  }

  enabled = true

  is_ipv6_enabled     = var.is_ipv6_enabled
  comment             = "Cloudfront for the frontend application."
  default_root_object = var.default_root_object
	
  logging_config {
    include_cookies = false
    bucket          = module.log_bucket[0].s3_bucket_bucket_domain_name
    prefix          = "${var.environment}-${var.name}"
  }

  aliases = var.aliases

  default_cache_behavior {
    allowed_methods  = var.default_cache_allowed_methods
    cached_methods   = var.default_cached_methods
    target_origin_id = var.s3_origin_id

    forwarded_values {
      query_string = true

      cookies {
        forward = "none"
      }
    }

    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
    compress               = var.compress
    viewer_protocol_policy = var.viewer_protocol_policy
  }
  
  price_class = var.price_class

  restrictions {
    geo_restriction {
      restriction_type = var.restriction_type
      locations        = var.geo_locations
    }
  }

  viewer_certificate {
    acm_certificate_arn      = aws_acm_certificate_validation.cert_validation[0].certificate_arn
    minimum_protocol_version = "TLSv1.2_2021"
    ssl_support_method       = "sni-only"
  }

  depends_on = [
    aws_s3_bucket.frontend_bucket
  ]
}
taxmann
asked 7 months ago281 views
1 Answer
1
Accepted Answer

This isn't about query parameters, it's about finding the "root" object in a "folder".

First: S3 doesn't have folders. That we use the "/" character to separate objects names in S3 and we treat them like folders is merely a way for humans to deal with things easily.

Second: In CloudFront you will have set the default object somewhere - perhaps it is index.html. So www.example.com means CloudFront will get index.html from S3. But when you request www.example.com/something/ CloudFront wants to find something/ from S3 which doesn't exist.

But there is a solution: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/

profile pictureAWS
EXPERT
answered 7 months ago
profile picture
EXPERT
reviewed 6 months ago
  • Thank you for your response, the S3 bucket keys make a lot of sense.

    Since I'm hosting an SPA vue.js application after two days of battling with this issue the solution seems to be to create a custom error response in CloudFront in the 'Error Pages' tab - select the '403:Forbidden' HTTP Error code and configure the Response page path to be '/index.html' with a HTTP response code to 200:OK.

    Writing this comment here for anyone else struggling with this issue, hope you don't have to fight with this for 2 days like I had to.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions