如何在弹性beanstalk上强制https?

我似乎无法强制https在弹性beanstalk的免费使用层。

我已经尝试了如何强制https在亚马逊弹性beanstalk没有失败健康检查以下build议

使用这个Apache重写规则

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] 

当我尝试,http请求不会被redirect到https,因为我想。 相反,http页面正常加载。 我也试着用相同的结果使用X-Forwarded-Port头。

我也尝试了以下重写规则

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

而这个规则会导致redirect循环。 所以看起来,Apache重写规则不拾起Elastic Load Balancer头X-Forwarded-Port和X-Forwarded-Proto,但redirect循环也不是我所要做的。

请帮忙。 我是AWS的新手,Elastic Beanstalk,并不熟悉Apache规则。 我不太确定该从哪里出发。 谢谢。

此答案假定您已在负载平衡器安全组中启用https,将SSL证书添加到负载平衡器,将443添加到由负载平衡器转发的端口,并在Elastic Beanstalk环境中将您的域名用Route 53(或等效的DNS服务)。

注意:此答案适用于使用Apache的Elastic Beanstalk环境。 它也可能不适用于基于docker的部署。

您只需将以下内容添加到项目的.ebextensions目录中的一个.config文件中 :

 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> 

说明

这是Elastic Beanstalk以外的中等直线。 通常会添加一个Apache重写规则,如下所示:

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

或者,如果在负载均衡器后面,就像我们在这种情况下那样:

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

但是,这些configuration只能在<VirtualHost>块中使用。 将RewriteCond更改为<If>块可以使其在<VirtualHost>块之外正常工作,从而允许我们将其放入独立的Apacheconfiguration文件中。 请注意,CentOS上的标准Apache设置(包括ElasticBeanstalk上的设置)包含了所有匹配/etc/httpd/conf.d/*.conf的文件,该文件与我们存储此文件的文件path相匹配。

如果您不在负载平衡器的后面,则条件中的-n '%{HTTP:X-Forwarded-Proto}'部分将阻止其redirect,从而允许您在具有负载平衡器和https的生产环境之间共享configuration,以及一个单一实例,没有https的登台环境。 如果您在所有环境中使用负载均衡器和https,则这不是必需的,但是这并不会造成影响。

我看到了不好的解决scheme

我已经看到了这个问题的很多不好的解决scheme,值得通过他们来理解为什么这个解决scheme是必要的。

  1. 使用Cloudfront:有人build议在Elastic Beanstalk之前使用非caching的Cloudfront设置来执行HTTP到HTTPS的redirect。 这增加了一个全新的服务(因此增加了复杂性),这是不恰当的(Cloudfront是一个CDN;它不是在dynamic内容上强制HTTPS的正确工具)。 Apacheconfiguration是这个问题的正常解决scheme,Elastic Beanstalk使用Apache,所以这是我们应该去的方式。

  2. SSH到服务器和…:这是Elastic Beanstalk点完全相反,有这么多的问题。 任何通过自动缩放创build的新实例都不会有修改后的configuration。 任何克隆的环境都不会有configuration。 任何数量的一组合理的环境变化都将消除configuration。 这是一个坏主意。

  3. 用新文件覆盖Apacheconfiguration:这正在进入正确的解决scheme领域,但如果Elastic Beanstalk更改服务器设置的某些方面(他们可能会这样做),则会给您带来维护的噩梦。 另请参阅下一项中的问题。

  4. dynamic编辑Apacheconfiguration文件添加几行:这是一个体面的想法。 这个问题是,如果Elastic Beanstalk改变了默认的Apacheconfiguration文件的名称,那么这个文件就不能工作,而且当你最不期待的时候这个文件会被覆盖: https : //forums.aws.amazon.com/thread .jspa?线程ID = 163369

编辑:虽然我喜欢这个答案,现在是非常古老的 AWS已经提出了新的服务(如证书pipe理器 ),使得这个答案的一部分已经过时。 另外, .ebextensions ,在Apache中使用.ebextensions文件夹是处理此redirect的一种更.ebextensions方式。

如果您在S3上托pipe您的网站,这个答案的部分内容可能对您仍然有用。


这对我工作:

  1. 使用aws console命令将证书上传到AWS。 命令结构是:

     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. 在您的Elastic Beanstalk应用程序中,转至configuration – > networking层 – > 负载平衡 ,然后单击齿轮图标

  3. select安全侦听器端口443 。 selectProtocol作为HTTPS 。 从步骤2中selectCERTIFICATE_NAME以获取SSL证书ID 。 保存configuration。

  4. 转到您的控制台 。 点击EC2实例 。 点击负载平衡器 。 点击负载平衡器。 单击实例,然后向下滚动以查看分配给该负载均衡器的EC2实例。 如果EC2实例的名称与您的应用程序URL(或closures的)相同,请记下负载均衡器的DNS名称 。 它应该是格式awseb-e-...

  5. 回到你的控制台 。 点击CloudFront 。 点击创build分配 。 select一个Web分配。

  6. 设置分配。 将您的源域名设置为您在步骤5中find的负载均衡器DNS名称。 将查看器协议策略设置为将HTTPredirect到HTTPS 。 将转发查询string设置为 。 将备用域名(CNAME)设置为要用于应用程序的URL。 将SSL证书设置为您在步骤2中上传的CERTIFICATE_NAME 。 创build你的发行版。

  7. 在CloudFront中点击您的分配名称。 点击来源,select您的来源,然后点击编辑 。 确保您的Origin协议策略匹配查看器 。 回去。 点击行为 ,select您的来源,然后点击编辑 。 将转发标题更改为白名单并添加主机 。 保存。

注意: 我也写了一个更长的指南 。

这对下一个命令是适合我的:

 RewriteCond %{HTTP:X-Forwarded-Port} !=443 

没有https检查:

 RewriteCond %{HTTP:X-Forwarded-Proto} !https 

看起来ELB将X-Forwarded-Proto的值更改为http(即使在TCP协议上)。

编辑: Zags的解决scheme是更一般和正确的。 我推荐它在我的(这是特定于Python的环境)

我提出了一个干净而快速的解决scheme,可以避免黑客攻击wsgi.conf或使用CloudFront

在你的.ebextensions / some_file.config中:

 # Redirect HTTP to HTTPS "/etc/httpd/conf.d/https_redirect.conf": mode: "000644" owner: root group: root content: | <Directory /opt/python/current/app/> RewriteEngine on RewriteCond %{HTTP:X-Forwarded-Proto} ^http$ RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] </Directory> 

我觉得这很容易,但似乎工作正常。

另外请注意,我明确redirectHTTP而不是“不HTTPS”。

最有价值的不适用于我.. <If>指令只适用于Apache 2.4 +,但ElasticBeanstalk具有2.2.x版本。

所以,遵循上面的同样的build议。 使用以下内容创build一个名为.ebextensions / https_rewrite.config的文件

 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] 

这似乎为我工作。

有关如何将此文件构build到WAR文件中,请参阅此答案

我有以下弹性beanstalk(运行Tomcat 8 Java 8的64位Amazon Linux 2016.09 v2.3.1)的configuration。 我创build了一个目录.ebextensions并添加了一个带有重写条件的.config YAML文件

上面描述的Zagas 解决scheme (这非常复杂)不适用于我。

  1. 因为“如果”条件是未知的
  2. 由于Apache 2.2,我没有在我的httpd.conf文件中包含mod_rewrite.so

这个解决scheme对我来说更有意义,但这也行不通。 什么也没有发生,我看不到“conf.d”目录下的“ssl_rewrite.conf”文件。

第三个尝试的解决scheme是在“.ebextendsion”目录下添加“run.config”和“ssl_rewrite.conf”文件。

run_config包含

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

包含ssl_rewrite.conf

 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在“conf.d”目录下创build,但是从httpredirect到https不起作用。

唯一有效的解决scheme是在“/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> 

但这是一个临时的解决scheme,如果一台机器被取代,我的httpsredirect已经消失。

上述答案都没有为我工作,但一些帮助我找出对我有效的答案我还发现了下面的url帮助http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/java-tomcat -platform.html

我创build了上述url中提到的文件结构来更改2个文件httpd.conf 00_application.conf

从您的实例中复制整个httpd.conf,并将其放在上面链接提到的文件夹结构下的.ebextention下的代码中。 然后,只需将下面一行添加到项目中的该文件即可

 LoadModule rewrite_module modules/mod_rewrite.so 

对00_application.conf做同样的事情,把它从你的实例拷贝到你的代码库中,放在httpd / conf.d / elasticbeanstalk / 00_application.conf下的.ebextention下。现在编辑这个文件,在VirtualHost

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

现在部署你的代码它应该工作。

在弹性beanstalk上,您可以直接添加configuration,以便AWS覆盖它,这将允许您覆盖Web服务器configuration并提交您自己的configuration。

只需在path下添加以下文件:.ebextensions \ httpd \ conf.d

文件内容:

 <VirtualHost *:80> LoadModule rewrite_module modules/mod_rewrite.so RewriteEngine On RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteCond %{HTTP_USER_AGENT} !ELB-HealthChecker RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} <Proxy *> Order deny,allow Allow from all </Proxy> ProxyPass / http://localhost:8080/ retry=0 ProxyPassReverse / http://localhost:8080/ ProxyPreserveHost on ErrorLog /var/log/httpd/elasticbeanstalk-error_log </VirtualHost> 

'.ebextensions'是AWS中的标准configuration文件夹,剩下的就是指向你想要覆盖的文件和文件夹。 如果文件或文件夹不存在,简单地创build它们。

我很困惑,所以在提出解决scheme之后,我详细解释了我的解决scheme ,希望可以帮助别人。 这是特定于Tomcat 8,Apache2和Spring Boot应用程序。 AWS labs github中有非常有用的ebextension示例 。

什么为我工作的总结:

  1. 在/src/main/webapp/.ebextensions/httpd/conf.d/elasticbeanstalk.conf创build一个文件
  2. 添加重写conds /规则要小心包括“LoadModule rewrite_module modules / mod_rewrite.so”
  3. 部署到AWS EBS

这是一个Spring Boot应用程序的例子 。

为什么不简单地把一个.htaccess文件放在根文件夹中? 这样你可以简单地testing和debugging它。 如果将其包含在.zip中,它将自动再次部署到所有实例上。

只需使用.htaccess

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

请注意,现在投票最多的答案已经有点老了。 保罗的答案实际上是正确的答案。 他的答案中提供的链接是由AWS提供的(因此,在Elastic Beanstalk上运行应用程序时,推荐的方法是覆盖Apacheconfiguration,以便从HTTPredirect到HTTPS)。

有一件非常重要的事情需要注意。 如果您正在部署多个Web应用程序,则在您的一个Web应用程序内添加.ebextensions文件夹将不起作用。 您将会注意到您指定的configuration的Non被写入或创build。 如果要在Elastic Beanstalk环境中部署多个Web应用程序,则需要阅读AWS Java Tomcat的这篇文章。 在Elastic Beanstalk上部署多个WAR文件

通常,在发出eb命令来部署WAR文件之前,需要具有以下结构:

 MyApplication.zip ├── .ebextensions ├── foo.war ├── bar.war └── ROOT.war 

如果.ebextentions文件夹存在于每个WAR文件中,那么您会注意到它完全被忽略,不会执行任何configuration更改。

希望这可以帮助别人。

如果您使用Load Balanced环境,则可以按照AWS Elastic Beanstalk环境的HTTPSconfiguration说明进行操作 ,最后禁用HTTP端口。

请注意,目前AWS免费使用套件包含与EC2微型实例相同的Elastic Load Balancing(ELB)小时数。

这是一个简单的解决scheme

  1. ssh进入你的EC2实例
  2. 将/etc/httpd/conf.d/wsgi.conf的内容复制到一个名为wsgi.conf的本地文件中,该文件将被放置在应用程序的基本文件夹中
  3. 编辑wsgi.conf的本地版本,并在<VirtualHost> </ VirtualHost>标签中添加以下redirect规则

     RewriteEngine On RewriteCond %{HTTP:X-Forwarded-Proto} !https RewriteRule !/status https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301] 
  4. “/ status”更改为您用作健康检查页面的任何页面。

  5. 保存文件
  6. 编辑你的<app> .conf文件。 ebextensions目录添加一个容器命令,将这个版本的wsgi.conf复制到Amazon的版本上

     container_commands: 01_syncdb: command: "django-admin.py syncdb --noinput" leader_only: true 02_collectstatic: command: "django-admin.py collectstatic --noinput" 03_wsgireplace: command: 'cp wsgi.conf ../wsgi.conf' ... 
  7. 部署代码。

  8. /etc/httd/conf.d/wsgi.conf中部署的wsg.conf版本现在将包含必要的redirect规则。

它应该工作,文件将被正确地更新为每个部署。 唯一值得注意的是,如果亚马逊在未来改变其基础wsgi.conf文件内容,那么你的副本可能不再工作。

作者rickchristianson