ElasticBeanstalk with SSL and ACM

Overview

This guide describes how to configure Elastic Beanstalk for the following:

  1. Use SSL with Amazon Certificate Manager
  2. SSL rewrite, enforces SSL
  3. ELB Health Check rewrite rules
  4. Verify Hostname Verification

 

RewriteRules

The following is written in Yaml which is my preferred method for dealing with CloudFormation and ElasticBeanstalk applications. So let's get started. The following code must go into the .ebextensions directory in the root of your application. For example, make a file within the .ebextensions/custom_apache.config. The first snippet to add looks like so:

files:
  "/etc/httpd/conf.d/ssl_rewrite.conf":
    mode: "000644"
    owner: root
    group: root
    content: |
      # More Information Here
      # https://httpd.apache.org/docs/2.4/rewrite/remapping.html
      RewriteEngine On
      If "%{HTTP_HOST} != 'michaeltrottier.com'">
      RewriteRule !/health https://michaeltrottier.com%{REQUEST_URI} [R,L]
      /If
      
      If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
      RewriteRule !/health https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
      /If

NOTE: The above If directives need to be wrapped should be <If conditional expressions></If>.

The snippet above uses the files declaration provided by Cloudformation. It sets the mode, owner and group of the file and allows you write the content in it. The content of our ssl_rewrite.conf file turns RewriteEngine on. Then it uses the If directive to first determine if the hostname is michaeltrottier.com. If not it will redirect you to the TLS version of michaeltrottier.com. This is important to avoid people using your servers IP address. Some would argue that this isn't best practice but if we can learn anything from google do a quick experiment:

[0][mike@virtual-box-home.] [20:11:55] [~]
>dig google.com +short | xargs -I {} curl {}
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

Now that we are forwarding requests based on IP to our Hostname our health checks are failing, but why?  Our ELB is checking our /health route of our webserver on port 80 using the internal IP of our EC2 Instance.  Our Apache webserver sees this and redirects to https://michaeltrottier.com which causes the ELB to recieve a 301 redirect which isn't a 200.  This would cause our Elastic Beanstalk cluster to go into a severe and start to alarm.  To fix this we need to prevent /health from being redirected to https.  Looking at our file aboe we see the !/health in our rewrite rule. This means the rule won't work on this url. Once we make this change our ELB will work successfully!

Use Amazon Certificate Manager

AWS Certificate Manager is a service that lets you easily provision, manage, and deploy Secure Sockets Layer/Transport Layer Security (SSL/TLS) certificates for use with AWS services. SSL/TLS certificates are used to secure network communications and establish the identity of websites over the Internet. AWS Certificate Manager removes the time-consuming manual process of purchasing, uploading, and renewing SSL/TLS certificates. With AWS Certificate Manager, you can quickly request a certificate, deploy it on AWS resources such as Elastic Load Balancers, Amazon CloudFront distributions, and APIs on API Gateway, and let AWS Certificate Manager handle certificate renewals. SSL/TLS certificates provisioned through AWS Certificate Manager are free. You pay only for the AWS resources you create to run your application.

As Elastic Beanstalk uses ELBs it is easy enough to configure. You can see an example below, just put this in a file in your .ebextensions directory which lies at the root directory of your application.

aws:elb:listener:443:
    SSLCertificateId: YOURCERTARN
    ListenerProtocol: HTTPS
    InstancePort: 80