如何在 AWS Elastic Beanstalk 上设置 HTTPS

Posted

技术标签:

【中文标题】如何在 AWS Elastic Beanstalk 上设置 HTTPS【英文标题】:How To Set Up HTTPS on AWS Elastic Beanstalk 【发布时间】:2015-08-07 17:07:57 【问题描述】:

我是 AWS、Elastic Beanstalk、Apache 和 Flask 的新手。

我正在尝试完全通过 HTTPS 提供我的网络应用程序。

我提供了我所做的每一个细节,希望有人能找到我遗漏或做错的事情。


AWS 设置

我正在使用 AWS Elastic Beanstalk,使用 Amazon Linux AMI,并在最新的 Python 容器 (Python 3.4) 中使用 Flask 和 Flask-Security(用于处理用户/会话)编写了我的应用程序。

我做了什么

    我首先通过 Amazon Route 53 购买了一个域,我们称之为 example.com。最初,我设置了所有必需的 DNS 配置,在适当的地方创建指向 www.example.com 的 A 记录到 example.com,CNAME 记录在适当的地方将 example.com 指向我的 AWS Elastic Load Balancer。

    接下来,我更新了弹性负载均衡器上的安全组,以允许 HTTP 和 HTTPS 上的入站和出站流量。

    然后,我从一家受欢迎的提供商处购买了 SSL 证书。网上有很多可靠的程序展示了如何做到这一点,所以我从这里省略了它。我在 Elastic Load Balancer 上配置了两个监听器:

    一个用于将 HTTP 转发到实例端口 80 一个用于 HTTPS 转发到实例端口 80,指定我的 SSL 证书

    我编写了我的应用程序的处理程序、配置的端点等,并让它在本地工作。我使用的是 PyCharm 和 AWS Elastic Beanstalk Integration For Web Languages 插件。我将它部署到我的 Elastic Beanstalk 实例,除了在项目根目录的 .ebextensions 目录中的配置文件中指定 option_settings 之外,没有进行任何特殊配置。我用它来配置我的 WSGIPath(我在其中暴露了我的 application 可调用文件)和静态文件:

    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"
    

    我已部署到 Elastic Beanstalk。它起作用了,在访问我的网站 http://www.example.com/ 后,该网站呈现正常。我可以登录,但是显然需要 SSL(因为我通过网络以纯文本形式发送我的用户名/密码)。这验证了我的 option_settings 有效(因为我可以访问所有端点、读取所有静态文件等。

    在尝试 https://www.example.com 时它也有效,但当我在我的前面手动键入 https:// 时网址。理想情况下,我希望用户键入 www.example.com 并在 https://www.example.com 找到自己。我发现的另一个有趣的行为是,当我点击 https://www.example.com 并登录时,我会被发送到只有 HTTP 而不是 HTTPS 的主页。

    最后,我尝试通过 AWS 提供的 .ebextensions 机制添加自定义配置。我为所有未通过 https 进入的流量添加了 RewriteRule,以通过 https 重定向。我还为端口 443 添加了一个新的 VirtualHost,并添加了我所有的原始映射(从上面,刚刚翻译成 Apache 配置)。我的 SSL 配置文件如下:

    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
    

    现在,在部署该配置文件后,我的网站只会超时 - 无论我访问的是 http 还是 https://www.example.com。奇怪的是,如果我在删除整个 &lt;VirtualHost *:443&gt; 指令的情况下进行部署,我只会得到一个空白的“Index Of /”网页。


我希望我的整个网站都通过 HTTPS 提供服务。许多 SO 文章和其他网站指出如何配置 Elastic Load Balancer 以接受 HTTPS 并转发到 EC2 实例上的端口 80 (HTTP),但是我必须遗漏一些东西 - 好像我的 Apache 服务器没有发送 通过 HTTPS 的出站 流量。

所以我查看了 Apache 配置并注意到 RewriteRule 指令,它将端口 80 的流量重定向到端口 443,但是许多建议使用 RewriteRule 的网站也忘记提到我可能需要为端口 443 设置新的 VirtualHost。

再次,我不确定我是否遗漏了一些关键的东西(显然我的理解存在差距) - 但我似乎无法找到让我的整个网站通过 HTTPS 运行的方法。

提前致谢。

【问题讨论】:

【参考方案1】:

我的问题在于我是如何配置端口的。获得证书后,您可以在配置 > 负载均衡器 > 修改中配置端口。

这是我的配置:

这个资源对我非常有用,如果你需要它会提供更多细节:https://colintoh.com/blog/configure-ssl-for-aws-elastic-beanstalk

【讨论】:

【参考方案2】:

我认为您收到请求超时的问题是:

您通过弹性负载均衡器 (ELB) 访问了 HTTPSELBEC2 实例 发出 HTTP 请求。 (您提到:一个用于 HTTPS 转发到实例端口 80,指定我的 SSL 证书) 所以,您的 EC2 实例 回复 ELB 并使用 HTTP 重定向 到同一位置但 HTTPS (https://wiki.apache.org/httpd/RewriteHTTPToHTTPS)。 ELB 将回复您的请求 same 作为 EC2,重定向到 HTTPS。 您的浏览器将跟随您的重定向信息。然后回到第一点(永远循环)。

要解决此问题,请在您的 ELB 中,将您的 ELB HTTPS 转发到实例 HTTPS(端口 443)。为此,您需要指定额外的 .ebextensions,因为 AWS Web 控制台中没有 HTTPS 到 HTTPS 配置。

这是我的.ebextensions 文件配置:

Resources:
  AWSEBSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Allow SSH, HTTP, and HTTPS"
      SecurityGroupIngress:
        - IpProtocol: "tcp", FromPort: 22, ToPort: 22, CidrIp: "0.0.0.0/0"
        - IpProtocol: "tcp", FromPort: 80, ToPort: 80, CidrIp: "0.0.0.0/0"
        - IpProtocol: "tcp", FromPort: 443, ToPort: 443, CidrIp: "0.0.0.0/0"
  AWSEBLoadBalancerSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      GroupDescription: "Allow HTTP and HTTPS"
      SecurityGroupIngress:
        - IpProtocol: "tcp", FromPort: 80, ToPort: 80, CidrIp: "0.0.0.0/0"
        - IpProtocol: "tcp", FromPort: 443, ToPort: 443, CidrIp: "0.0.0.0/0"
      SecurityGroupEgress:
        - IpProtocol: "tcp", FromPort: 80, ToPort: 80, CidrIp: "0.0.0.0/0"
        - IpProtocol: "tcp", FromPort: 443, ToPort: 443, CidrIp: "0.0.0.0/0"
  AWSEBLoadBalancer:
    Type: "AWS::ElasticLoadBalancing::LoadBalancer"
    Properties:
      Listeners:
        - LoadBalancerPort: 80, Protocol: "HTTP", InstancePort: 80, InstanceProtocol: "HTTP"
        - LoadBalancerPort: 443, Protocol: "HTTPS", InstancePort: 443, InstanceProtocol: "HTTPS", SSLCertificateId: "arn:aws:iam::123456789012:server-certificate/YourSSLCertificate"
      SecurityGroups:
        - "Fn::GetAtt" : [AWSEBLoadBalancerSecurityGroup, GroupId]

【讨论】:

【参考方案3】:

您需要更新位于 /etc/httpd/conf.d/wsgi.conf 的 wsgi.conf 文件

将 wsgi.conf 文件添加到 .ebextensions
LoadModule wsgi_module modules/mod_wsgi.so
WSGIPythonHome /opt/python/run/baselinenv
WSGISocketPrefix run/wsgi
WSGIRestrictEmbedded On

<VirtualHost *:80>


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

Alias /static/ /opt/python/current/app/mindbliss/static/
<Directory /opt/python/current/app/mindbliss/static/>
Order allow,deny
Allow from all
</Directory>


WSGIScriptAlias / /opt/python/current/app/application.py


<Directory /opt/python/current/app/>
  Require all granted
</Directory>

WSGIDaemonProcess wsgi processes=3 threads=20 display-name=%GROUP \
  python-path=/opt/python/current/app:/opt/python/run/venv/lib64/python2.7/site-packages:/opt/python/run/venv/lib/python2.7/site-packages user=wsgi group=wsgi \
  home=/opt/python/current/app
WSGIProcessGroup wsgi
</VirtualHost>

LogFormat "%h (%X-Forwarded-Fori) %l %u %t \"%r\" %>s %b \"%Refereri\" \"%User-Agenti\"" combined
将 wsgireplace.config 添加到 .ebextensions
container_commands:   01_wsgireplace:
    command: 'cp .ebextensions/wsgi.conf /etc/httpd/conf.d/wsgi.conf'
最后是eb deploy

【讨论】:

以上是关于如何在 AWS Elastic Beanstalk 上设置 HTTPS的主要内容,如果未能解决你的问题,请参考以下文章

如何在 AWS Elastic Beanstalk 上修改 Nginx 配置

如何在 AWS Elastic Beanstalk 上设置 HTTPS

如何在 AWS Elastic Beanstalk 上设置 HTTPS

如何在 AWS Elastic Beanstalk 中更改数据库配置

如何在 AWS Elastic Beanstalk 中选择特定平台?

如何使用 Elastic beanstalk 和 Dockerrun.aws.json 正确部署到 AWS?