Here is the scenario that we are going to deal with:
- You have created a website which is running on Elastic Beanstalk. In my particular case it is a java webapp running on Tomcat running on Elastic Beanstalk, but this post will apply to any other app hosted on Beanstalk.
- The domain on which you want to run the webapp is registered with an external registrar eg.Godaddy, NetworkSolutions etc.
- You have an SSL certificate for the domain (or you are going to buy one) and want the final deployment to run as https://mydomain.com as well as http://mydomain.com
WHAT ROUTE53 IS DOING
What we are doing here is use Amazon Route 53 to handle the DNS processing for your domain, but not transfer the ownership of the domain from your existing registrar. Though if you want to transfer the ownership of the domain to Route53 that is possible, but I am not going to go into that part in this post. So your existing domain registrar continues to be the domain registrar but transfers the domain handling to Route 53. You can always reverse this back by deleting the DNS entries from Route 53 and setting the default nameservers back in your domain registrar.
One of the fundamental requirements for running a domain under SSL for Beanstalk applications is that you have to run it under a Load Balancer rather than a Single Instance. If you are running it under a Single Instance then most likely you would been assigned an Elastic IP which is a static IP. Your webapp can then run on this IP directly eg. http://x.x.x.x . In your external DNS setup, you would simply point the A record of your domain to this IP and then http://yourdomain.com would work. Even in Single Instance deployment, you can actually setup your SSL directly in your EC2 instance using .ebextensions but I can assure you that path is very messy and error-prone . Amazon themselves recommended going the VPS way as it fits into the rest of the their architecture.
So in your Elastic Beanstalk->Configuration screen, change Environment Type to Load Balanced, keep everything else the same and click Apply.
So now when you go to the AWS Dashboard and click on EC2, in our EC2 Console you should see zero Elastic IPs and one Load Balancer.
ROUTE 53 SETUP
Now we will setup Route 53. Go to the AWS Dashboard and click on Route 53 under Network Services.
Click on the Get Started Now button under DNS Management.
Click on Create Hosted Zone button. On the right hand side of the screen, fill in the form with your domain details and click Create.
Once this is done, Route 53 will create some default DNS entries for your domain, namely the Nameservers (NS) records and the Start of Authority record (SOA).
EXPORTING DNS DATA TO ROUTE53
We will now export the domain DNS data from your registrar to Route53. I am going to assume Godaddy here but the steps are applicable to any other registrar. The screenshots will be different but the process is the same.
Go to your Godaddy account and go to My Domains. From the list of domains pick your domain and click on Manage
In the Domain Settings scroll down till you see the heading Additional Settings and click on Manage DNS
In the next page scroll down to Advanced Features section and click on the link which says Export Zone File (Unix)
A file called yourdomain.txt will be downloaded to your computer. Open the file in any text-editor and keep it open.
Next go back to your Route53 page with the Hosted Zone selected. Click on the Import Zone File button at the top. In the form space which opens, copy the contents of the file yourdomain.txt which is open in your text editor and paste the contents into the form. Click on the Import button.
At this stage all the DNS entries from your registrar should have been copied into the Route 53 Hosted Zone. If you dont see the new entries just refresh the browser.
We need to now go change the nameservers in your domain registrar. Which means the 4 DNS servers for the NS entry above have to be put as nameservers in your domain registrar. In Godaddy , you will find the section called Nameservers above Advanced Features. Click on the Change button in front of Using Default Nameservers line. Select Custom from the dropdown and then add the four nameservers from Route 53 and click on Save.
Back in Route53, we will now make new A entries for the domain. Important: If you have setup an IP address as the A record, please delete it first. To do that just click on the DNS entry in Route 53 and click on Delete Record Set button at the top. What we are doing now is to make the webapp run on http://mydomain.com as well as http://www.mydomain.com
Click on Create Record Set button at the top. This will be the A record for http://mydomain.com. In the form which comes up in the right hand side leave the Name field empty. Keep Type as A – IPv4 Address. Select Alias as Yes. In the Alias Target dropdown select the URL which comes up for your Elastic BeanStalk environment (not your Classic Load Balancer URL). Click on Create button. When you click on the newly added A entry, something like this should show up on the right:
Again click on Create Record Set button at the top. This will be the A record for http://www.mydomain.com. In the form which comes up in the right hand side put www in the Name field . Keep Type as A – IPv4 Address. Select Alias as Yes. In the Alias Target dropdown select the URL which comes up for your Elastic BeanStalk environment (not your Classic Load Balancer URL). Click on Create button. When you click on the newly added second A entry, something like this should show up on the right:
So now , after a few minutes your webapp should run as both http://mydomain.com and http://mydomain.com . Sometimes it might take a few hours for the DNS changes to propagate throughout the internet but mostly it takes a few minutes. Route 53 provides a handly tool to see if the DNS entry is resolving correctly. Select your A record from the DNS list and click on Test Record Set button at the top:
In the next screen, under the Simulate Sending DNS Request section, change the Resolver IP to 188.8.131.52 from the default DNS server which AWS has prefilled it with. 184.108.40.206 is the DNS server for Google. So if Google is able to resolve the DNS correctly that means its working fine. When you click on Get Response button, the output on the right side for DNS Response Code should show as NOERROR.
We will now configure the website to run under SSL. I am assuming you have already purchased SSL for your domain. I am not covering the process of purchasing SSL in this post. What we will do now is download the certificate files and put them into AWS. A website SSL has two types of keys. One are the public keys which are downloadable many times after the certificate has been generated. The other is the private key which is only generated once and is installed in the server where the website is hosted. That means the public keys are available in one place and the private key is available in another place. We will first download the public keys.
In Godaddy, in the My Products page, click on SSL Certificates. Click on the Manage button in front of the domain SSL.
Click on the Download icon at the top.
In the next page, select the Server Type from the dropdown. In my case it was Tomcat, but perhaps in your case it will be Apache.
A zip file will be downloaded eg.yourdomain.zip . In this zip file you will find crt file(s) and a pem file. If you have multiple crt files then one of them is the root certificate and the other is your intermediate certificate. In order to differentiate between which is the root and which is the intermediate certificate file, open each of the files in a text editor. The one which has only one —BEGIN CERTIFICATE– and one —END CERTIFICATE— entry is the root certificate. The file which has multiple of these entries is the intermediate certificate.
Go back to the AWS Dashboard and look for Certificate Manager under Security, Identity and Compliance section. In the Certificate Manager page click on Import Certificate button at the top.
You will get an empty form as below:
For Certificate Body, take the root certificate contents and paste them. In case you have an intermediate certificate file, paste the contents into Certificate Chain field. Now we come to the Certificate private key part. As mentioned earlier, you will not be able to download this from your SSL provider. This will be automatically installed in the server where your site is hosted. Hopefully you would have saved a copy of it somewhere. Otherwise you will have to download it from your hosted site. The file will be most likely called yourdomain.key or yourdomain.pem . The way to identify a private key is to open it in a text editor and make sure that it has the two entries:
-----BEGIN RSA PRIVATE KEY----- and
-----END RSA PRIVATE KEY-----
Anything else is not a private key. Once you have the private key contents paste in the Certificate Private key field. Click on Import button. If all goes well the key will be added to AWS and you will your domain entry listed something similar to this:
ADDING SSL TO VPC
We now need to add the SSL to your Elastic Beanstalk Load Balancer. Go to the AWS Dashboard ->Elastic BeanStalk . Click on your Beanstalk app. Then go to Configuration page. Click on the Modify button in the Load Balancer section.
You will find there is already an entry for running your app on http on port 80.
We will now create a listener for SSL. Click on the Add Listener button. In the popup form which comes up, choose 443 as the Listener Port, HTTPS as Listener Protocol, 80 as Instance Port, HTTP as Instance Protocol. Select your SSL certificate from the dropdown and click on Add.
Now your Load Balancer should be listening to both http and https ports.
OPENING PORTS IN SECURITY GROUP
Most likely, your Elastic Beanstalk Security group would have already been updated to allow Inbound Access on port 443 for SSL. In case you do not see it, you can add it manually. Go to AWS Dashboard and click on EC2. Under Resources click on Security Groups link.
Out of the several Security Groups you will find one which says SecurityGroup for Elastic Beanstalk environment. Click on that. At the bottom of the page click on Inbound tab. Click on the Edit button. Click Add Rule. Choose Type as HTTPS. Protocol as TCP, Port Range as 443 , Source as Custom, CIDR as 0.0.0.0/0 . Click on Save.
This allows https requests to come to your webapp.
At this stage, your website should run on all the four types of URLS: