Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Set Up HTTPS on AWS Elastic Beanstalk

I'm new to AWS, Elastic Beanstalk, Apache, and Flask.

I'm trying to serve my web app purely over HTTPS.

I'm providing every detail as to what I've done in the hope that someone can find what I've missed or done wrong.


AWS Setup

I'm using AWS Elastic Beanstalk, using the Amazon Linux AMI, and written my app using Flask and Flask-Security (to handle users/sessions) in the latest Python container (Python 3.4).

What I Did

  1. I started off by purchasing a domain, let's call it example.com, through Amazon Route 53. Initially, I set up all of the required DNS config, creating A records where appropriate to point www.example.com to example.com, and CNAME records where appropriate to point example.com to my AWS Elastic Load Balancer.

  2. Next, I updated the security group on my Elastic Load Balancer to allow traffic both Inbound and Outbound on both HTTP and HTTPS.

  3. I then purchased an SSL certificate from a popular provider. There are plenty of solid procedures on the web that show how to do this so I've omitted it from here. I configured two listeners on my Elastic Load Balancer:

    • one for HTTP forwarding to Instance port 80
    • one for HTTPS forwarding to Instance port 80, specifying my SSL certificate
  4. I wrote my app's handlers, configured endpoints, etc, and got it working locally. I was using PyCharm and the AWS Elastic Beanstalk Integration For Web Languages Plugin. I deployed this to my Elastic Beanstalk instance with no special configuration other than specifying option_settings in my config file in the .ebextensions directory in the project root. I used this to configure my WSGIPath (where I exposed my application callable) and static files:

    option_settings:
      "aws:elasticbeanstalk:container:python":
        WSGIPath: my_app.wsgi
      "aws:elasticbeanstalk:container:python:staticfiles":
        "/static/": "my_app/static/"
        "/favicon.ico": "my_app/static/img/favicon.ico"
    
  5. I deployed to Elastic Beanstalk. It worked, and upon visiting my site at http://www.example.com/, the site rendered fine. I could log in, however the need for SSL was apparent (as I was sending my username/password over the wire in plain text). This verified that my option_settings worked (as I could hit all of my endpoints, read all of my static files, etc.

  6. It also worked when trying https://www.example.com, but only when I manually typed https:// at the front of my URL. Ideally I would like for a user to type www.example.com and find themselves at https://www.example.com. Another interesting behaviour I found was that when I hit https://www.example.com, and logged in, I would be sent to the main page where it was just HTTP, not HTTPS.

  7. Lastly, I tried adding custom configuration via the .ebextensions mechanism provided by AWS. I added a RewriteRule for all traffic that wasn't coming in on https, to redirect over https. I also added a new VirtualHost for port 443 and added all of my original mappings (from above, just translated into Apache config). My SSL config file is as follows:

    files:
      "/etc/httpd/conf.d/ssl.conf":
      mode: "000644"
      owner: root
      group: root
      content: |
        <VirtualHost *:80>
            LogLevel debug
            RewriteEngine On
            RewriteCond %{HTTP:X-Forwarded-Proto} !https
            RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
        </VirtualHost>
    
        <VirtualHost *:443>
            LogLevel debug
            Alias /favicon.ico /opt/python/current/app/my_app/static/img/favicon.ico
            <Directory /opt/python/current/app/my_app/static/img/favicon.ico>
            Order allow,deny
            Allow from all
            </Directory>
    
            Alias /static/ /opt/python/current/app/my_app/static/
            <Directory /opt/python/current/app/my_app/static/>
            Order allow,deny
            Allow from all
            </Directory>
    
            WSGIScriptAlias / /opt/python/current/app/my_app.wsgi
    
            <Directory /opt/python/current/app/>
              Require all granted
            </Directory>
        </VirtualHost>
    
    container_commands:
        restart_apache:
        command: /sbin/service httpd restart
    
  8. Now, after deploying that config file, my website only times out - regardless of whether I visit http or https://www.example.com. Strangely, if I deploy with the entire <VirtualHost *:443> Directive removed, I only get a blank "Index Of /" webpage.


I would like to have my entire site served over HTTPS. Many SO articles and other websites point out how to configure Elastic Load Balancer to accept HTTPS and forward to port 80 (HTTP) on the EC2 instance, however I must be missing something - it seems as though my Apache server is not sending Outbound traffic over HTTPS.

So I looked up Apache configuration and noted the RewriteRule Directive, which redirects port 80 traffic to port 443, but many websites that suggested using a RewriteRule also forgot to mention I might need a new VirtualHost setup for port 443.

Again I'm not sure if I'm missing something critical (obviously there is a gap in my understanding) - but I just can't seem to find a way to get my entire site running over HTTPS.

Thanks in advance.

like image 389
TheBaker Avatar asked Nov 10 '22 12:11

TheBaker


1 Answers

My issue was in how I was configuring the ports. Once you have your certificate, you can configure your ports in Configuration > Load Balancer > Modify.

Here is my configuration: Port configuration, first setting is 80-http, 80-http, the other is 443-https and 80-http with my SSL

This resource was super useful for me and gives more detail if you need it: https://colintoh.com/blog/configure-ssl-for-aws-elastic-beanstalk

like image 144
Joshua Wolff Avatar answered Nov 14 '22 22:11

Joshua Wolff