How to force https on elastic beanstalk?

2019-01-04 06:49发布

I can't seem to force https on the free usage tier of elastic beanstalk.

I have tried the following suggestion at How to force https on amazon elastic beanstalk without failing the health check

Using this Apache rewrite rule

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

When I try that, http requests do not get redirected to https as I would like. Instead, the http page loads normally. I've also tried to use the X-Forwarded-Port header with the same result.

I've also tried the following rewrite rule

RewriteCond %{SERVER_PORT} 80
RewriteRule . https://%{SERVER_NAME}%{REQUEST_URI} [L,R]

And this rule causes a redirect loop. So it would seem that the apache rewrite rules don't pick up the Elastic Load Balancer headers X-Forwarded-Port and X-Forwarded-Proto, but also a redirect loop isn't what I am going for either.

Please help. I am new to AWS, Elastic Beanstalk, and not very familiar with Apache rules. I am not too sure where to go from here. Thanks.

19条回答
放我归山
2楼-- · 2019-01-04 07:27

I am trying to redirect an elastic beanstalk with loadbalancer in 2018. None of the above answers works in my environment. Several issues I encoutered:

  1. I was trying the most voted answer, but my tomcat is version 2.7. It does not support .

  2. I was using container_commands and copy the 00_applications setting. AWS simply ignores it.

So finally I got it working by reading this: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/java-tomcat-proxy.html

Here is what I do:

I recreated the folder structure:

.ebextensions 
 - httpd
  -conf.d
   -ssl.conf

And then this is the content of ssl.conf

<VirtualHost *:80>
  RewriteEngine on
  RewriteCond %{HTTP:X-Forwarded-Proto} =http
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
  <Proxy *>
    Order Allow,Deny
    Allow from all
  </Proxy>
  ProxyPass / http://localhost:8080/ retry=0
  ProxyPassReverse / http://localhost:8080/
  ProxyPreserveHost on

  ErrorLog /var/log/httpd/elasticbeanstalk-error_log
</VirtualHost>

Hope this will help.

查看更多
The star\"
3楼-- · 2019-01-04 07:27

I had a difficult time figuring this out so after I came up with a solution I wrote a detailed explanation of my solution to hopefully help someone else. This is specific to Tomcat 8, Apache2, and Spring Boot app. There are really useful ebextension examples in the AWS labs github.

Summary of what worked for me:

  1. Create a file at /src/main/webapp/.ebextensions/httpd/conf.d/elasticbeanstalk.conf
  2. Add rewrite conds/rules being careful to include "LoadModule rewrite_module modules/mod_rewrite.so"
  3. Deploy to AWS EBS

Here is an example Spring Boot app.

查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-04 07:27

I have following configurations for elastic beanstalk (64bit Amazon Linux 2016.09 v2.3.1 running Tomcat 8 Java 8). I created a directory .ebextensions and added a .config YAML file with the rewrite conditions

Zagas solution described above (which is very complex) doesn't work for me.

  1. Because "If" condition is unknown
  2. Because of Apache 2.2 I don't have mod_rewrite.so included in my httpd.conf file

This solution make more sense for me, but also this doesn't work. Nothing happens, and I cannot see file "ssl_rewrite.conf" under "conf.d" directory.

Third tried solution was to add "run.config" and "ssl_rewrite.conf" files under ".ebextendsion" directory.

run_config contains

container_commands:
copy-config:
command: "cp .ebextensions/ssl_rewrite.conf /etc/httpd/conf.d"

ssl_rewrite.conf contains

LoadModule rewrite_module modules/mod_rewrite.so
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule . https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

ssl_rewrite.conf is created under "conf.d" direcotry but redirect from http to https doesn't work.

The only worked solution for me was to add the following lines in "/etc/httpd/conf.d/elasticbeanstalk/00_application.conf"

<VirtualHost *:80>
......
RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
......
</VirtualHost>

but this is a temporary solution and if a machine is replaced my https redirection is gone.

查看更多
家丑人穷心不美
5楼-- · 2019-01-04 07:30

This answer assumes you have already enabled https in the load balancer security group, added the SSL certificate to the load balancer, added 443 to the ports forwarded by the load balancer, and pointed your domain name at the Elastic Beanstalk environment with Route 53 (or equivalent DNS service).

NOTE: This answer is for Elastic Beanstalk environments that use Apache. It also may not work for a docker-based deployment.

All you need to do is add the following to one of your .config files in the .ebextensions directory of your project:

files:
    "/etc/httpd/conf.d/ssl_rewrite.conf":
        mode: "000644"
        owner: root
        group: root
        content: |
            RewriteEngine On
            <If "-n '%{HTTP:X-Forwarded-Proto}' && %{HTTP:X-Forwarded-Proto} != 'https'">
            RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
            </If>

Explanation

This is moderately straight forward outside of Elastic Beanstalk. One usually adds an Apache rewrite rule like the following:

RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Or, if behind a load balancer, like we are in this case:

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

However, these configurations only work within a <VirtualHost> block. Changing the RewriteCond to an <If> block allows it to work properly outside of a <VirtualHost> block, allowing us to put in in a standalone Apache config file. Note that standard Apache setup on CentOS (including the setup on ElasticBeanstalk) inculdes all files matching /etc/httpd/conf.d/*.conf, which matches the file path where we are storing this file.

The -n '%{HTTP:X-Forwarded-Proto}' part of the condition prevents it from redirecting if you are not behind a load balancer, allowing you to have shared configuration between a production evironment with a load balancer and https, and a staging environment that is single instance and does not have https. This is not necessary if you are using load balancers and https on all of your environments, but it doesn't hurt to have it.

Bad solutions I have seen

I have seen a lot of bad solutions to this problem, and it is worth going through them to understand why this solution is necessary.

  1. Use Cloudfront: Some people suggest using non-cached Cloudfront setup in front of Elastic Beanstalk to do the HTTP to HTTPS redirect. This adds a whole new service (thus adding complexity) that isn't exactly appropriate (Cloudfront is a CDN; it's not the right tool for forcing HTTPS on inherantly dynamic content). Apache config is the normal solution to this problem and Elastic Beanstalk uses Apache, so that's the way we should go.

  2. SSH into the server and...: This is completely antithetical to the point of Elastic Beanstalk and has so many problems. Any new instances created by autoscaling won't have the modified configuration. Any cloned environments won't have the configuration. Any number of a reasonable set of environment changes will wipe out the configuration. This is just such a bad idea.

  3. Overwrite the Apache config with a new file: This is getting into the right realm of solution but leaves you with a maintenance nightmare if Elastic Beanstalk changes aspects of the server setup (which they very well may do). Also see the problems in the next item.

  4. Dynamically edit the Apache config file to add a few lines: This is a decent idea. The problems with this is that it won't work if Elastic Beanstalk ever changes the name of their default Apache config file, and that this file can get overwritten when you least expect: https://forums.aws.amazon.com/thread.jspa?threadID=163369

查看更多
祖国的老花朵
6楼-- · 2019-01-04 07:30

EDIT: While I love this answer, it is now very old. AWS has come up with new services (like Certificate Manager) that make part of this answer obsolete. Additionally, using the .ebextensions folder with Apache is a cleaner way to handle this redirect as explained above.

If you are hosting your website on S3, parts of this answer may still be useful to you.


This worked for me:

  1. Upload the certificate to AWS using the aws console command. The command structure is:

    aws iam upload-server-certificate --server-certificate-name CERTIFICATE_NAME --certificate-body "file://PATH_TO_CERTIFICATE.crt" --private-key "file://YOUR_PRIVATE_KEY.pem" --certificate-chain "file://YOUR_CERTIFICATE_CHAIN.ca-bundle" --path /cloudfront/
    
  2. In your Elastic Beanstalk application, go to Configuration -> Network Tier -> Load Balancing and click the gear icon.

  3. Select Secure listener port as 443. Select Protocol as HTTPS. Select the CERTIFICATE_NAME from step 2 for SSL certificate ID. Save the configuration.

  4. Go to your Console. Click EC2 Instances. Click Load Balancers. Click through the load balancers. Click Instances and scroll down to see the EC2 instances assigned to that load balancer. If the EC2 instance has the same name as your Application URL (or something close), take note of the DNS Name for the load balancer. It should be in the format awseb-e-...

  5. Go back to your Console. Click CloudFront. Click Create Distribution. Select a Web distribution.

  6. Set up the distribution. Set your Origin Domain Name to the load balancer DNS name you found in step 5. Set the Viewer Protocol Policy to Redirect HTTP to HTTPS. Set Forward Query Strings to Yes. Set Alternate Domain Names (CNAMEs) to the URL(s) you want to use for your application. Set SSL Certificate to the CERTIFICATE_NAME you uploaded in step 2. Create your distribution.

  7. Click on your distribution name in CloudFront. Click Origins, select your origin, and click Edit. Ensure your Origin Protocol Policy is Match Viewer. Go back. Click Behaviors, select your origin, and click Edit. Change Forward Headers to Whitelist and add Host. Save.

Note: I wrote a longer guide as well.

查看更多
兄弟一词,经得起流年.
7楼-- · 2019-01-04 07:30

The most upvoted doesn't work for me.. the <If> directive only works with Apache 2.4+, but ElasticBeanstalk has version 2.2.x.

So, following the same advice as above. Create a file called .ebextensions/https_rewrite.config with the following content

files:
    "/etc/httpd/conf.d/ssl_rewrite.conf":
        mode: "000644"
        owner: root
        group: root
        content: |
            LoadModule rewrite_module modules/mod_rewrite.so
            RewriteEngine On
            # This will enable the Rewrite capabilities
            RewriteCond %{HTTPS} !=on
            # This checks to make sure the connection is not already HTTPS
            RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]

This seems to work for me.

On how to build this file into your WAR file, see this answer

查看更多
登录 后发表回答