Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

PHP Websites on AWS Elastic Beanstalk with Free SSL

Tags:
PHP Websites On AWS Elastic Beanstalk With Free SSL

Prerequisites:

  • AWS CLI
  • A PHP Elastic Beanstalk app configured to use an ELB (even if it’s a single-server instance)

With the launch of the AWS Certificate Manager (ACM), AWS users now have access to free SSL certificates for use with AWS services. These certificates are not yet directly integrated with Elastic Beanstalk, but you can still use them with it via your load balancer (ELB). Here’s how.

  1. Request and verify a certificate in Certificate Manager. Note the ARN by expanding the certificate details (screenshot here).
     
  2. Create a JSON file with the following, replacing {ARN} with your certificate’s ARN:

    [
    {
    “Namespace” : “aws:elb:healthcheck”,
    “OptionName” : “Target”,
    “Value” : “HTTP:80/status”
    },
    {
    “Namespace” : “aws:elb:listener:443”,
    “OptionName” : “ListenerProtocol”,
    “Value” : “HTTPS”
    },
    {
    “Namespace” : “aws:elb:listener:443”,
    “OptionName” : “SSLCertificateId”,
    “Value” : “{ARN}”
    },
    {
    “Namespace” : “aws:elb:listener:443”,
    “OptionName” : “InstancePort”,
    “Value” : “80”
    },
    {
    “Namespace” : “aws:elb:listener:443”,
    “OptionName” : “InstanceProtocol”,
    “Value” : “HTTP”
    },
    {
    “Namespace” : “aws:elb:listener:443”,
    “OptionName” : “ListenerEnabled”,
    “Value” : “true”
    },
    {
    “Namespace” : “aws:elb:listener:80”,
    “OptionName” : “ListenerProtocol”,
    “Value” : “HTTP”
    },
    {
    “Namespace” : “aws:elb:listener:80”,
    “OptionName” : “InstancePort”,
    “Value” : “80”
    },
    {
    “Namespace” : “aws:elb:listener:80”,
    “OptionName” : “InstanceProtocol”,
    “Value” : “HTTP”
    },
    {
    “Namespace” : “aws:elb:listener:80”,
    “OptionName” : “ListenerEnabled”,
    “Value” : “true”
    }
    ]

    Note: This is newer syntax than the Management Console uses, so you will not at this time be able to reconfigure your load balancer ports and protocols through the Console after this change. You’ll have to use the CLI to make changes. Also, I use a very basic health check in this example which looks for a blank file called status in my app root. You may need something more complex in your environment. Finally, if you get any errors, chances are your namespaces aren’t matching up with your existing environment. Run eb config in the EB CLI to confirm.

    Why is this still using port 80 and HTTP? Because we’re terminating the cert at the ELB and leaving traffic between the ELB and the instance(s), inside of AWS, unencrypted. If you need encryption all the way through, the free ACM certificates don’t yet fit your use case. Upload your own cert to IAM and your instance(s) and use that.

  3. Using the AWS CLI, run the following command, replacing {EBenv} with your Elastic Beanstalk app’s Environment Name, and {PATHtoJSON} with the path to the JSON file you just created:

    aws elasticbeanstalk update-environment --environment-name {EBenv} --option-settings file://{PATHtoJSON}

At this point your environment will update and then your website will be accessible via HTTPS on port 443 and secured over the open Internet by the AWS cert. But wouldn’t it be better to force users to use HTTPS? Let’s use Elastic Beanstalk hooks to do that. (Note: You cannot just shut down port 80 as the Elastic Beanstalk Host Manager and your ELB use it.)

  1. In your code’s root directory, add a folder named .ebextensions and create a blank file named status. If your app is not a PHP app, the location where you place this folder may need to change.
     
  2. Create an apache config (.conf) file in this new folder with the following contents (change /status to match your ELB health check if different):

    RewriteEngine On
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

    LogFormat “%h (%{X-Forwarded-For}i) %l %u %t “%r” %>s %b “%{Referer}i” “%{User-Agent}i””
    ErrorLog /var/log/httpd/elasticbeanstalk-error_log
    TransferLog /var/log/httpd/elasticbeanstalk-access_log

  3. Create another file in the folder, this time a .config, replacing {APACHEconfig} with the filename from the last step:

    container_commands:
    01_replace_apache_server:
    command: cp .ebextensions/elasticbeanstalk.conf /etc/httpd/conf.d/elasticbeanstalk.conf
    02_restart_apache:
    command: /usr/sbin/apachectl restart

    (Note: Beware spacing in this file. No tabs are allowed.)

Now Upload and Deploy your app with this new version. And voila, you’re now serving only HTTPS connections to users of your Elastic Beanstalk website.

Isn’t there a better way? Yes, ACM natively supports CloudFront, and it’s best practice that you use it. CloudFront has a setting called “Viewer Protocol Policy” with option “Redirect HTTP to HTTPS.” More info here and here.

With thanks to:
Matt Snider
Anand Capur



This post first appeared on Sean Feeney, please read the originial post: here

Share the post

PHP Websites on AWS Elastic Beanstalk with Free SSL

×