Search code examples
amazon-web-servicesamazon-s3cloudhostingserverless

Is there any way to host a static wesbite on AWS S3 without giving public access?


I wish to host a static website on Amazon S3 without actually giving the public access to the bucket. I am using a client AWS account in which all the buckets have public accessed blocked, when I try to configure my bucket as public, it redirects me to a page where I have to grant public access to all the buckets.


Solution

  • Yes it is possible, All you need to do is serve s3 through cloudfront. Client -> Route53 -> Cloudfront -> S3 (blocked public access)

    In Cloudfront

    • Create cloudfront function (from left menu), this will redirect any request with index.html appended. For ex: example.com/home to example.com/home/index.html

      'use strict';
      function handler(event) {
       var request = event.request;
       var uri = request.uri;
      
       // Check whether the URI is missing a file name.
       if (uri.endsWith('/')) {
           request.uri += 'index.html';
       } 
       // Check whether the URI is missing a file extension.
       else if (!uri.includes('.')) {
           request.uri += '/index.html';
       }
        return request;
      }
      
    • Create the origin access (from left menu), this will be used in distribution's origin

    • In Distributions

      • In origin tab

        • Create origin as S3 type, by choosing the s3 bucket

        • Click on origin access control settings that create at first step

      • Edit general settings and put index.html in default root object.

      • Edit Behaviours, In Function associations, select cloudfront function in viewer request. Don’t need to go with lambda function

    In S3

    • In properties, disable static s3 website hosting

    • In permissions

      • Block all public access

      • Edit the bucket policy with below:

        {
           "Version": "2008-10-17",
           "Id": "PolicyForCloudFrontPrivateContent",
           "Statement": [
            {
                "Sid": "AllowCloudFrontServicePrincipal",
                "Effect": "Allow",
                "Principal": {
                    "Service": "cloudfront.amazonaws.com"
                },
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::BUCKET_NAME/*",
                "Condition": {
                    "StringEquals": {
                        "AWS:SourceArn": "arn:aws:cloudfront::ACC_NUMBER:distribution/DISTRIBUTION_ID"
                    }
                }
            }
           ]
        }
        
        
        
        

    In Route53

    • Create A record by selecting cloudfront distribution