1

Here is the application directory structure.

  • app/__init_.py
  • app/static/
  • app/models/
  • app/views/
  • application.py
  • requirements.txt
  • .elasticbeanstalk/config
  • .elasticbeanstalk/optionsettings.application_name
  • .ebextensions/python.config
  • .ebextensions/https.config

Here are the snippets of files inside .elasticbeanstalk

#config
EnvironmentTier=WebServer::Standard::1.0
EnvironmentType=SingleInstance
Region=us-west-1
ServiceEndpoint=https://elasticbeanstalk.us-west-1.amazonaws.com
SolutionStack=64bit Amazon Linux 2014.03 v1.0.3 running Python

#optionsettings.application_name
[aws:elasticbeanstalk:container:python]
NumProcesses=1
NumThreads=15
StaticFiles=/static/=app/static/
WSGIPath=application.py

[aws:elasticbeanstalk:container:python:staticfiles]
/static/=app/static/

Here is the steps I took to create SSL certificate from CheapSSL

  • openssl genrsa 2048 > privatekey.pem
  • openssl req -new -key privatekey.pem -out csr.pem
  • Made SSL certificate request to Comodo and received three files
    • Root CA Certificate - AddTrustExternalCARoot.crt
    • Intermediate CA Certificate - PositiveSSLCA2.crt
    • Your PositiveSSL Certificate - server.crt

Note: I specified the server to be Apache/OpenSSL

Lastly, here are the snippets of files inside .ebextensions

#https.config
Resources:
  sslSecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupName: {Ref : AWSEBSecurityGroup}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      CidrIp: 0.0.0.0/0

packages:
  yum:
    mod24_ssl : []

files:
  /etc/httpd/conf.d/ssl.conf:
    mode: 000777
    owner: ec2-user
    group: ec2-user
    content: |
      LoadModule ssl_module modules/mod_ssl.so
      Listen 443
      <VirtualHost *:443>
        <Proxy *>
          Order deny,allow
          Allow from all
        </Proxy>
        SSLEngine on
        SSLCertificateFile "/etc/pki/tls/certs/server.crt"
        SSLCertificateKeyFile "/etc/pki/tls/certs/server.key"

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

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

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

        WSGIDaemonProcess wsgi-ssl processes=1 threads=15 display-name=%{GROUP} \
          python-path=/opt/python/current/app:/opt/python/run/venv/lib/python2.6/site-packages user=wsgi group=wsgi \
          home=/opt/python/current/app
        WSGIProcessGroup wsgi
      </VirtualHost>

  /etc/pki/tls/certs/server.crt:
    mode: 000777
    owner: ec2-user
    group: ec2-user
    content: |
      -----BEGIN CERTIFICATE-----
      #contents from server.crt
      -----END CERTIFICATE-----


  /etc/pki/tls/certs/server.key:
    mode: 000777
    owner: ec2-user
    group: ec2-user
    content: |
      -----BEGIN RSA PRIVATE KEY-----
      #contents from privatekey.pem
      -----END RSA PRIVATE KEY-----

This config is a snippet from AWS Elastic Beanstalk documentation with small changes. http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/SSLPython.SingleInstance.html

  • mod_ssl -> mod24_ssl due to yum install error. I was lucky to find this fix from Github
  • 01killhttpd excluded. After going through deploying application multiple times, killing httpd left permanent damage to the application.

The symptom is the following.

  • Can access to http:
  • Gives 403 Forbidden You don't have permission to access / on this server. for https:

I will disclose the site address if necessary.

I have taken every step specified in AWS Documentation but still failed to achieve a single goal; hooking my site with https. There aren't enough posts available online to help me figure this out. I stayed away from Load Balancer because I purchased domain using GoDaddy and it's too complicated to set up domain for lb (That's another story).

Here is the link to the snapshot of Elastic Beanstalk Log.

https://dl.dropboxusercontent.com/u/23288606/Log.txt

Thanks in advance.

Update:

Someone read the logs and pointed out an error message stating this.

[ssl:warn] [pid 1989] AH01909: [ec2-address].compute.amazonaws.com:443:0 server certificate does NOT include an ID which matches the server name

So yeah, SSL certificate refers to my custom domain while the server still thinks of it as ec2's default Public DNS (I think).

FYI, the custom domain is purchased from Godaddy. I made it so that A Record points to my ec2 ip address.

In short, how do I make it so that when my ec2 server sets up ssl, it knows its fqdn is my custom domain, not the one provided by ec2?

lustdante
  • 483
  • 4
  • 14

2 Answers2

2

WARNING: I'm a developer, not a sys admin and I have no idea what I am doing.

This week I had the exact same problems. Including the domain one. Here is a configuration that worked for me. Feedback is welcomed since I just hacked this togheter.

Resources:
  sslSecurityGroupIngress: 
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupName: {Ref : AWSEBSecurityGroup}
      IpProtocol: tcp
      ToPort: 443
      FromPort: 443
      CidrIp: 0.0.0.0/0

packages:
  yum:
    mod24_ssl : []

files:
  /etc/httpd/conf.d/ssl.conf:
    mode: "000755"
    owner: root
    group: root
    content: |
      LoadModule ssl_module modules/mod_ssl.so
      Listen 443
      <VirtualHost *:443>
        <Proxy *>
        Require all granted
        </Proxy>
        SSLEngine on
        SSLCertificateFile "/etc/pki/tls/certs/server.crt"
        SSLCertificateChainFile "/etc/pki/tls/certs/inter.crt"
        SSLCertificateKeyFile "/etc/pki/tls/certs/server.key"

        Alias /static /opt/python/current/app/printwithme/static
        <Directory /opt/python/current/app/>
        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-ssl processes=1 threads=15 display-name=%{GROUP} \
          python-path=/opt/python/current/app:/opt/python/run/venv/lib/python2.6/site-packages user=wsgi group=wsgi \
          home=/opt/python/current/app
        WSGIProcessGroup wsgi-ssl
      </VirtualHost>

  /etc/pki/tls/certs/server.crt:
    mode: "000400"
    owner: root
    group: root
    content: |
      -----BEGIN CERTIFICATE-----

      -----END CERTIFICATE-----

  /etc/pki/tls/certs/server.key:
    mode: "000400"
    owner: root
    group: root
    content: |
      -----BEGIN RSA PRIVATE KEY-----

      -----END RSA PRIVATE KEY-----

  /etc/pki/tls/certs/inter.crt:
    mode: "000400"
    owner: root
    group: root
    content: |
      -----BEGIN CERTIFICATE-----

      -----END CERTIFICATE-----

container_commands:
  01killhttpd:
    command: "killall httpd"
  02waitforhttpddeath:
    command: "sleep 3"

Add first I thought the forbidden problems had to do with file permissions. Which I think is why OP has his permissions set to 777. In my case it had to do with Apache versions. Amazon uses Apache 2.2 in their example but have 2.4 in the servers. Confirm that by running httpd -v. If this is true then see this link. Which gave me my changes in <Proxy *> and <Directory /opt/python/current/app/>. I don't know the difference between Order deny,allow and Order allow,deny, which I now know are called access controls. If I changed them wrong please let me know. Then I received 404 errors.

After changing that I had to change:

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

to

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

This should point to the file where you create your application object. Your's might be different.

Then had to change:

Alias /static /opt/python/current/app/

to

Alias /static /opt/python/current/app/my-app-name/static

because in my app the static files are in nested folder. This should point to the directory with your. Notice my-app-name is a variable to be changed by you if needed.

Lastly I added a chain file. This was given to me by the SSL people with my certificate. You might need to add it too. In my understanding it might be optional but not really.

Sorry if I missed anything.

Update

I had issues with the file modes. I had to quote them: mode: "000755" mode: "000400"

I will update the configuration to reflect these changes.

Wilberto
  • 520
  • 1
  • 4
  • 10
  • I'd like to give this a go immediately but I have discarded eb for good at the moment. Regardless this answer addresses my concern more directly! – lustdante Sep 22 '14 at 02:22
0

These don't match:

    WSGIDaemonProcess wsgi-ssl processes=1 threads=15 display-name=%{GROUP} \
      python-path=/opt/python/current/app:/opt/python/run/venv/lib/python2.6/site-packages user=wsgi group=wsgi \
      home=/opt/python/current/app
    WSGIProcessGroup wsgi

You possibly should have:

    WSGIProcessGroup wsgi-ssl

for that directive.

Graham Dumpleton
  • 57,726
  • 6
  • 119
  • 134
  • Fix applied but the issue persists. Probably due to my lack of knowledge with Apache but should user=wsgi group=wsgi in the code snippet be affected as well? – lustdante Aug 23 '14 at 15:19
  • Using user=wsgi group=wsgi is not probably what you want as it means you would have to have a UNIX user and group on the system called that, which you will not. Generall those options should be left out unless you know what you are doing. It is a common mistake in instructions to try and set them to the Apache user which isn't even needed. Arbitrarily setting them to something else where there is no corresponding UNIX user or group is worse. – Graham Dumpleton Aug 24 '14 at 07:57
  • I'm a bit lost here. So, do I keep WSGIDaemonProcess? – lustdante Aug 24 '14 at 11:09
  • The wsgi settings might be flawed in the eyes of the expert, but as far as the log is concerned, I believe ssl setting is to be questioned first as specified in the updated portion of the question. – lustdante Aug 24 '14 at 11:21
  • 2
    Your SSL certificate message is a different issue. If you solve that, mod_wsgi will then fail because of what I am pointing out. The first argument to the WSGIProcessGroup directive must match the first argument to a WSGIDaemonProcess which you have defined. Right now that isn't the case, so if a request ever gets to mod_wsgi it will error saying that you are trying to select a daemon process group that doesn't exist. To avoid that, you need to change the argument of the WSGIProcessGroup directive to be wsgi-ssl to match what WSGIDaemonProcess directive uses as first argument. – Graham Dumpleton Aug 24 '14 at 11:54
  • Good point. I will definitely apply your suggestion as soon as I come in terms with certificate issue. Thank you so much for your patience. – lustdante Aug 24 '14 at 12:10