如何在AWS Elastic Beanstalk

时间:2015-05-26 06:57:42

标签: python amazon-web-services https amazon-ec2 flask

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

我试图纯粹通过HTTPS提供我的网络应用程序。

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

AWS Setup

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

我做了什么

  1. 我开始购买域名,让我们称之为example.com,通过亚马逊Route 53.最初,我设置了所有必需的DNS配置,创建适当的A记录点www .example.com到example.com,以及适当的CNAME记录,将example.com指向我的AWS Elastic Load Balancer。

  2. 接下来,我更新了Elastic Load Balancer上的安全组,以允许HTTP和HTTPS上的入站和出站流量。

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

    • 一个用于HTTP转发到实例端口80
    • 一个用于HTTPS转发到Instance端口80,指定我的SSL证书
  4. 我编写了应用程序的处理程序,已配置的端点等,并使其在本地运行。我使用的是PyCharm和AWS Elastic Beanstalk Integration For Web Languages插件。我将此部署到我的Elastic Beanstalk实例,除了在项目根目录的option_settings目录中的配置文件中指定.ebextensions之外,没有任何特殊配置。我用它来配置我的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"
    
  5. 我部署到Elastic Beanstalk。它运作良好,在访问我的网站 http ://www.example.com/时,网站呈现得很好。我可以登录,但是对SSL的需求是显而易见的(因为我通过网络以纯文本形式发送我的用户名/密码)。这验证了我的option_settings工作(因为我可以点击我的所有端点,读取所有静态文件等等。

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

  7. 最后,我尝试通过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
    
  8. 现在,在部署该配置文件后,我的网站只会超时 - 无论我是访问http还是https://www.example.com。奇怪的是,如果我部署整个<VirtualHost *:443>指令被删除,我只会得到一个空白&#34;索引/&#34;网页。

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

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

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

    提前致谢。

3 个答案:

答案 0 :(得分:0)

我认为您获取请求超时的原因是:

  • 您通过 Elastic Load Balancer(ELB)访问 HTTPS
  • ELB EC2实例执行 HTTP 请求。 (您提到过:一个用于HTTPS转发到Instance端口80,指定我的SSL证书)
  • 因此,您的 EC2实例使用重定向 ELB 回复到同一位置,但使用HTTPS(https://wiki.apache.org/httpd/RewriteHTTPToHTTPS)。
  • ELB 会将您的请求相同作为EC2回复,并重定向到 HTTPS
  • 您的浏览器会关注您的重定向信息。并回到第一点(永远循环)。

要解决此问题,请在 ELB 中,将您的ELB HTTPS 转发至实例 HTTPS (端口443)。为此,您需要指定其他.ebextensions,因为AWS Web Console中没有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]}

答案 1 :(得分:0)

您需要更新位于/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-For}i) %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
  • 将wsgireplace.config添加到.ebextensions
container_commands:   01_wsgireplace:
    command: 'cp .ebextensions/wsgi.conf /etc/httpd/conf.d/wsgi.conf'
  • ,最后是eb deploy

答案 2 :(得分:0)

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

这是我的配置: Port configuration, first setting is 80-http, 80-http, the other is 443-https and 80-http with my SSL

该资源对我来说非常有用,并且在需要时提供了更多详细信息:https://colintoh.com/blog/configure-ssl-for-aws-elastic-beanstalk