Skip to content

S3/Cloudfront & OAC: Access denied when accessing path other than index site

0

Hi People

I am hosting a static website on S3 and serving it via Cloudfront. After doing some changes I realised that other than the index path / , everything else returns 403 Access denied. so For instance www.domainname.com/it gives me access denied, www.domainname.com/ is good.

I recently made some changes in my website.. one of them must be the responsible of my issue as everything was working fine before.

The one I believe may be the reason is that I changed the S3 policy from public to private AND MOVED TO OAI TO OAC. I did this change reading it was more secure blocking public access and also migrating to AOC. Happy if you explain me how this thing works. .

Below I am pasting some of the resources but please feel free to ask me to check anything else, as the issue may not be this.. i pushed few commits following guides.

[PS: Replacing bucket name with BUCKET_NAME in case it is a sensitive data]

resource "aws_s3_bucket_public_access_block" 
...
block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
...
}


...

resource "aws_s3_bucket_acl" "BUCKET_NAME_acl" {
  depends_on = [
    aws_s3_bucket_ownership_controls.BUCKET_NAME,
    aws_s3_bucket_public_access_block.tBUCKET_NAME_public_access_block,
  ]
  bucket = aws_s3_bucket.BUCKET_NAME_bucket.id
  acl    = "private"

STILL NOT SOLVED BUT SOME EXTRA INFO:



 if I do `domain.com/` the index.html is correctly rendered, or if I do domain.com/robot.txt, it is correctly returned.

But if I do domain.com/it (which in s3 is a folder containing index.html) gives me 403.

BUT if I write the full file path.. like domain.com/it/index.html it then works.. so looks like cloudfront is not solving correctly the sub paths?



...
resource "aws_s3_bucket_ownership_controls" "BUCKET_NAME_bucket" {
  bucket = aws_s3_bucket.BUCKET_NAME_bucket.id

  rule {
    object_ownership = "BucketOwnerPreferred"
  }
}

...

...

resource "aws_cloudfront_origin_access_control" "current" {
  name                              = "OAC ${aws_s3_bucket.BUCKET_NAME_bucket.bucket}"
  origin_access_control_origin_type = "s3"
  signing_behavior                  = "always"
  signing_protocol                  = "sigv4"
}


...

data "aws_caller_identity" "current" {}
resource "aws_s3_bucket_policy" "BUCKET_NAME_bucket_policy" {
    bucket = aws_s3_bucket.BUCKET_NAME_bucket.id

    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
          Sid       = "AllowCloudFrontAccess"
          Effect    = "Allow"
          Principal = {
            Service = "cloudfront.amazonaws.com"
          }
          Action    = "s3:GetObject"
          Resource  = "${aws_s3_bucket.BUCKET_NAME_bucket.arn}/*"
          Condition = {
            StringEquals = {
              "AWS:SourceArn" = "arn:aws:cloudfront::${data.aws_caller_identity.current.account_id}:distribution/${aws_cloudfront_distribution.BUCKET_NAME_distribution.id}"
            }
          }
        },
      ]
    })

  }
4 Answers
2

I suggest you first try setting the bucket ownership control to BucketOwnerEnforced to disable ACLs for the bucket. Otherwise, it depends on the ownership and per-object ACLs of each object, which can vary, whether the bucket policy you've configured can permit access to objects. To be clear, this isn't necessarily your problem, but it does add complexity that happens at a per-object level and can only be guessed based on the declared configuration.

Another thing to check is that the bucket is not enabled for static website hosting. It isn't present in your configuration declaration but would prevent OAC from working if it's been enabled for the bucket outside the declared configuration you included.

EXPERT

answered 2 years ago

EXPERT

reviewed 2 years ago

  • Thanks Leo, regarding the problem is there anything you can help with? happy to share more if you need

  • I suggest you change object_ownership = "BucketOwnerPreferred" in your code to object_ownership = "BucketOwnerEnforced" and verify that static website hosting option shown on the properties tab of your bucket in the AWS console is disabled.

  • About the bucket webstatic hosting, are you refering to this?

    resource "aws_s3_bucket_website_configuration" "BUCKET_NAME_website_config" { bucket = aws_s3_bucket.BUCKET_NAME_bucket.id

    index_document { suffix = "index.html" }

    error_document { key = "404.html" } }

    Also as mentioned in the question, the / path works. So if the problem was one of those I should not work at all, no?

    EDIT: Ok I will check those

  • I have done what you suggested @leo, the issue is still there, did not solve it.

    I removed

    resource "aws_s3_bucket_website_configuration" "BUCKET_NAME_website_config" {

    and changed ownership to BucketOwnerEnforced

  • Yes, you have to remove the aws_s3_bucket_website_configuration element entirely from your configuration. You won't have any need for it when using CloudFront to publish the site, but more importantly, it won't work together with OAC. You have to disable static website hosting for the S3 bucket.

0
Accepted Answer

My issue was.. as part of my migration from OAI to AOC i changed the type of s3 bucket. S3 wasn't anymore a Hosting static website s3 bucket, so it lost the ability to serve the index.html by default for the sub paths.

in order to fix this I have added a cloudfront function

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-index.html.

Thanks to Leo.K for anyway trying really to troubleshoot the issue.

answered 2 years ago

  • Okay, so the reason you were getting error messages was simply that you were requesting nonexistent objects. When requesting a URL such as https://example.com/folder/ from S3 through CloudFront without custom edge functions or a path prefix defined, the object key requested from S3 will be folder/ and not folder/index.html, which I take it you were expecting and are now appending with the custom CloudFront function.

  • Yes that's correct! I wasn't aware this function was required. In fact with the S3 bucket setting I had before migrating to AOC (the S3 was a hosting website type) it wasn't necessary !

0

When using OAI, you grant CloudFront access to your S3 bucket by associating the CloudFront distribution with an OAI. Then, the S3 bucket policy is configured to allow this OAI to retrieve objects. This method allows your S3 bucket to remain private while still serving content through CloudFront.

This is an old approach on access. More recent improvements knocked at the OAC. OAC allows CloudFront to sign requests to your S3 bucket, just like OAI, but with added security features and flexibility. It’s designed to allow CloudFront to access private S3 content without making the bucket public, and it provides more secure ways to manage requests and data encryption.

Hope this helps.

EXPERT

answered 2 years ago

  • Hi Giovanni, thank you for the general explanation. Altho this is sharing useful concepts it is not really helping me to solve the issue. Hope you can suggest me something more practical to fix it. Thanks

-1
EXPERT

answered 2 years ago

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.