Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS SSL with Google Domain for static website in S3

I'm trying to add HTTPS to my static website hosted in an S3 bucket with a domain bought from Google's Domains. I know that in order to set up CloudFront Distribution, I need to send the SSL Cert from AWS Certificate Manager to Google.

This is what I did:

From AWS Certificate Manager:

  • Request a certificate
  • Request a public certificate
  • Domain name: *.myweb.com and myweb.com, following this answer here.
  • Validation method: DNS validation
  • Then I have the Name, Type and Value for my CNAME.
  • I went to Google Domains, added the values I got from AWS to: DNS/Custom resource records but my AWS Cert requests are still pending. I've tried before and the requests weren't accepted so they expired.

I've looked at guide here, here, here and here without any luck.

Update 10 May:

Many thanks to @hephalump for his help. In addition to his answer, he sent to me this super helpful link from AWS.

In my case, it was slightly different from the video by Geoff:

  • After creating CloudFron Distribution, I added 2 Record Sets to AWS Route 53 Hosted Zones:
Name: mywebsite.com - Type: A - Value (ALIAS target): CloudFront Distribution (from the list).
Name: www.mywebsite.com - Type: A - Value (ALIAS target): mywebsite.com (on the bottom of the list). 

and now it works.

like image 406
Viet Avatar asked May 04 '19 19:05

Viet


People also ask

Can Amazon S3 run a static website?

You can use Amazon S3 to host a static website. On a static website, individual webpages include static content. They might also contain client-side scripts. By contrast, a dynamic website relies on server-side processing, including server-side scripts, such as PHP, JSP, or ASP.NET.

Does Google domain offer SSL certificate?

The following Google services automatically issue, install, and renew SSL/TLS certificates at no additional cost: Google Sites. Google Business Profile.


3 Answers

Since you're using AWS services, you may wish to seriously consider using Route53 for your DNS; it will make your life a lot easier.

Even if you're not using Route53 can still use the DNS validation method to validate your certificate. Alternatively, if that's not working, you can use the Email verification method which is also very reliable.

To use the DNS validation method with Google domains you would do the following:

On the AWS Certificate Manager certificate confirmation screen get something like:

NAME: _3341936be9c722351e9e3345d5118ee28.yourdomain.com.

TYPE: CNAME

VALUE: _3341936be9c722351e9e3345d5118ee28.ltfvzjuylp.acm-validations.aws.

Head over to Google domain manager and go to the Custom Resource Records section. In the first field enter _3341936be9c722351e9e3345d5118ee28. In the dropdown menu select CNAME. In the TTL enter 1H. In the data field enter _3341936be9c722351e9e3345d5118ee28.ltfvzjuylp.acm-validations.aws. Finally, click Add.

Then wait. You have to wait for the DNS record to propagate, and you have to wait for ACM to check it. It could take up to 1 hour.

EDIT: Since it seems you're using Route53 to handle your DNS this is really easy. Regardless of where your bucket is, make sure you request your certificate in the US-EAST-1 (N. Virginia) region. Follow all the request steps and on "Step 4: Validation", when the certificate is generated click on "Create record in Route 53". Wait 5 minutes and if Route53 is indeed handling your DNS then your cert will be ready to use.

Expand Image

like image 117
hephalump Avatar answered Oct 28 '22 23:10

hephalump


1. Set Up S3 Bucket

Create Bucket
  • Select “Create bucket”
  • For bucket name, it has to match your domain name including the www. So it has to be www.<your website name>.com. If it doesn’t match your domain name, pretty sure none of this is going to work.
  • Optional (this is only for testing purposes if you wanted it, change this back once you have everything working, which I instruct you through down in the Extra Steps section way down below): Uncheck Block all public access, and select “I acknowledge that the current settings might result in this bucket and the objects within becoming public”. You should definitely change this back to block once everything is connected to your domain, but for now, this will allow you to make sure that at least your S3 bucket is working.
  • You don’t have to add a tag, but for naming purposes and making it easier on yourself, make a tag. For key, call it “Name” and for Value call it <your website>-Bucket. No need to have the "www" in the Tag value, again just a name to help you.
  • Leave all other values default.
  • Select "Create Bucket"
Add Files
  • Click into your new bucket from the home page to go into the details.
  • And now upload your index.html and error.html file, along with any other additional files.
  • Select all. Make them all public by selecting "Actions" and selecting "Make public". As of Nov 2021, AWS has now changed this, and you should do this in a policy rather than here, but you now have to choose "Make public using ACL" which requires going into your bucket's Permissions -> Object Ownership and selecting "ACLS enabled".
Properties
  • In Properties down at the bottom, under "Static website hosting" select "Edit".
  • Enable static website hosting. And put in "index.html" and "error.html" for index and error document respectively.
Optional but required to complete the previous optional task (so for testing your S3 bucket out): Permissions

You will eventually only allow permission for an OAI, as mentioned earlier with blocking that you do not want people to be able to reach your S3 bucket directly, and only reach your website through your domain name that will have https when S3 buckets are http, but for testing purposes if you want to, go ahead and do the following. In Permissions, in Bucket policy, select edit and put this, again we will change this once we have an OAI:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::www.<your website name>.com/*"
        }
    ]
}
Final Notes for S3 Bucket

If you forget to enable static website hosting before connecting to your CloudFront distribution, it will result in this error when trying to view your website: enter image description here If this happens, you can try reconnecting your CloudFront distribution to your S3 bucket to re-register things so to speak. Don't know why this is.

2. Certificate Manager

Head over to certificate manager

VERY IMPORTANT: Change from your current location to US East (N. Virginia) us-east-1. The certificate must be requested from this region, no matter what. If you don’t, and instead have Northern California for example, when you move onto the next step which is Cloudfront, your ssl certificate will not show up and you will not be able to complete your HTTPS setup. Not entirely sure why this is, but to use CloudFront, the region for your certificate must be US East (N. Virginia) us-east-1.

Make a request
  • Select "Request".
  • For "Certificate Type" leave it on "Request a public certificate".
  • For "Fully qualified domain name" put both your <your website name>.com and add a second one being www.<your website name>.com.
  • Select DNS validation instead of email. As long as you have the CNAME records in your Google Domain records that will be provided after making this request, you'll never have to worry about updating the certificate again. If you go the email route, you'll have to do a yearly update and I'm not going to worry about that. Select DNS validation, and it'll be good.
  • Select make request and go to status page.
Add CNAME Records to Google Domains
  • Now on the Certificates page in AWS Certificate Manager it will show that your status is pending.
  • Click into the certificate request you just made. You should see a CNAME name and CNAME value for your www.<your website name>.com and your <your website name>.com. If the values are blank, this is a glitch that can happen, just refresh the page until they show up, they should show up right away.
  • Copy these CNAME names and CNAME values. You will put these into your Google Domains.
  • In Google Domains, go to DNS.
  • Create two CNAME records, one for your naked domain, and one for the other. So for www.<your website name>.com host name will be something like: _123a456789012b3456c7d8ef901a234b.www, Type: CNAME, DATA something like: _fe098765432dc10b987a65f43e21098d.abcdefghij.acm-validations.aws.
  • For the other record (naked domain) take the CNAME name and value associated with your name domain and do the same as in the previous record you made. Just to be clear the naked domain should have different CNAME name and value than the www.<your website name>.com.
  • Make sure you leave your domain name out since Google Domains automatically attaches this on for you, otherwise your domain name will be in the host name twice such as _123a456789012b3456c7d8ef901a234b.<your website name>.com.<your website name>.com. And this would result in error.
  • Select Save and head back over to AWS.
Waiting for Success Status

For me it took 4 minutes after routing things up in Google Domains to get my certificate issued. So sip that coffee and take a breather while you wait! It shouldn't be long.

The certificate status will change to "Issued".

3. CloudFront

Head over to CloudFront in AWS.

  • Select Create distribution.
  • Origin domain: www.<your website name>.com.s3.amazonaws.com
  • Still learning, but For Origin Path, try leaving blank, putting "index.html" or "/index.html" here broke for me. You might run into this error shown in the screenshot below as soon as you block all public access and only allow your OAI (more on the OAI later), just let me know in comments what works, and I can fix this step: enter image description here
  • Viewer protocol policy: Redirect HTTP to HTTPS Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
  • And towards the bottom, under Settings, select “Add item” for “Alternate domain name”, and put www.<your website name>.com as this should match the bucket that you are pointing to.
  • For custom SSL certificate select your new certificate. If you don’t see it, then chances are you didn’t select N. Virginia as the region when making the certificate within certificate manager.
  • Keep all else to default and select "Create distribution" to finish.

4. Route 53

Create a hosted zone
  • Select Create hosted zone.
  • Do the following: Domain name: www.<your website name>.com.
  • Leave type to "Public hosted zone"
  • Add a description and tag if you want.
  • And create.
Add a record to your Route 53 hosted zone for CloudFront

Now go to the hosted zone details if you have not already been taken there. You will now create a record to connect to our CloudFront distribution to add to the list of two records that you should already have there in your hosted zone.

  • Select Create Record
  • Turn alias on.
  • And for “Route traffic to” select “Alias to CloudFront distribution”
  • You should see your CloudFront distribution show up, something like: dd56opwkqiwae.coudfront.net. Select this.
  • Now finalize by selecting Create Record down at the bottom.

You are now done with the AWS side.

5. Google Domains

You need to create a CNAME record for www.<your website name>.com for connecting to your Cloudfront distribution, and a redirect from <your website name>.com to www.<your website name>.com so that your users can put in your naked domain name and still get to your site. If google domains supported ANAME/ALIAS records, you could do things differently, where you could also create a Cloudfront distribution for your naked domain of <your website name>.com and route <your website name>.com to it's own CloudFront distribution within Google Domains. But since Google doesn’t support ANAME/ALIAS records, you have to redirect your naked domain to your domain, and then your domain to your CloudFront. Also you would have to create an s3 bucket for your naked domain, in which you could point it to the other s3 bucket. But you don’t have to worry about that, since Google Domains doesn’t support ANAME/ALIAS records in the first place. And if it makes you feel any better, amazon.com redirects to www.amazon.com, so having a naked domain redirect to a www url is not only common but used by the big guys.

Now this is fun, the AWS docs at the time of writing this say create a Synthetic Record within Google Domains, but Google Domains recently changed their interface. It no longer calls them "Synthetic records" which was within their "DNS" page, instead you you have to:

  • Go to Google Domain's "Website" page and click "Forward Domain" enter image description here

enter image description here

  • In here, forward your naked domain of <your website name>.com to https://www.<your website name>.com. enter image description here
  • Select "Advanced Options" and select "Forward Path" and "SSL On". enter image description here
  • Then go to your DNS page and there make a CNAME record pointing your www.<your website name>.com to your CloudFront distribution.

I blocked out my info, and also put in fake sample data for you to get an idea of what your AWS records are supposed to look like in Google Domains. enter image description here

Congratulations You Successfully Have an HTTPS Website!

So when someone goes to <your website name>.com, Google Domains redirects it to www.<your website name>.com which then does a CNAME lookup and finds your CloudFront distribution url. From CloudFront which has your SSL certificate, Route 53 sees that the CloudFront distribution was reached and serves your S3 bucket static site.

Extra Steps

Now that you have it so that your users can access the S3 bucket through your domain name using https, you want to turn off the bucket from being accessed directly (which is http and not https among other reasons). So, first go to CloudFront.

1. CloudFront

  • In CloudFront, under Security, click Origin Access Identities.
  • Select "Create new origin access identity"
  • Call it whatever you'd like, but to be constant go ahead and call it <your website name>-OAI.
  • Go to CloudFront distributions.
  • Click your distribution.
  • Select "Origins"
  • Select your origin displayed in the list there.
  • Select "Edit"
  • Under S3 bucket access, select Yes use OAI (bucket can restrict access to only CloudFront)
  • From the Origin Access Identity drop down menu that appears, select your new OAI you just made.
  • Select "Yes, update the bucket policy". You will still have to go to S3 and delete the previous allow policy that we put in way back in the beginning of this tutorial, which was only optional since it was for testing purposes.
  • Select "Save Changes" down in the bottom, and you now have your OAI connected up.

2. S3

  • Now head over to S3.
  • Select your bucket.
  • Only your OAI needs access, so you should block all public access now. So in Permissions, under Block public access (bucket settings), go ahead and block all access now. And under Bucket policy you should have the following:

JSON for OAI, which should have been set if you selected "Yes, update the bucket policy" in the previous step. I added "s3:PutObject" in list of actions as shown below

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <your OAI ID>"
           },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
           "Resource": "[resource_name]"
        }
    ]
}

And now users should only be able to enter your static website via CloudFront and not directly through your S3 bucket.

like image 25
Adam Avatar answered Oct 28 '22 22:10

Adam


I was trying the same, by adding CNAMEs using Google domain DNS manager. For me the issue was, instead of adding just the alphanumerical part, I was adding the entire string including the domain. Once I removed that, I believe, it might have taken less than an hour. Go through the below link and pay special attention to the one under 'important' section. https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-validate-dns.html

From the above link.

The CNAME information that you need does not include the name of your domain. If you include your domain name in the DNS database CNAME record, validation fails. For example, the displayed Name may resemble the following:

_a79865eb4cd1a6ab990a45779b4e0b96.yourdomain.com However, the required CNAME information only includes the following:

_a79865eb4cd1a6ab990a45779b4e0b96

like image 31
Anoop Isaac Avatar answered Oct 28 '22 21:10

Anoop Isaac