Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Source code being exposed by AWS Elastic Beanstalk

I've tried using the AWS forums to get help but, oh boy, it's hard to get anything over there. In any case, the original post is still there.

Here's the same question.

I deployed a Python (Flask) app using Elastic Beanstalk and the Python container. The directory structure is more or less this (simplified to get to the point):

[app root]
  - application.py
  - requirements.txt
  /.ebextensions
      - python-container.config 
  /secrets
      - keys.py
      - secret_logic.py
  /myapp
      - __init__.py
      /static
         - image1.png
         - some-other-file.js
      /services
         - __init__.py
         - some-app-logic.py

I found that any file in my app can be retrieved by browsing as in the following URLs:

  • http://myapp-env-blablabla.elasticbeanstalk.com/static/requirements.txt
  • http://myapp-env-blablabla.elasticbeanstalk.com/static/secrets/keys.py
  • http://myapp-env-blablabla.elasticbeanstalk.com/static/myapp/services/some-app-logic.py
  • etc

I poked around and found that this is caused by this config in the file /etc/httpd/conf.d/wsgi.conf:

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

Basically this allows read access to my entire app (deployed at /opt/python/current/app/) through the /static virtual path.

At this point someone might suggest that it's a simple matter of overriding the default Python container staticFiles option (what a terrible default value, by the way) using a .config ebextension file. Well, if you look at my directory structure, you'll see python-container.config, which has:

"aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": "app/myapp/static/"

But this file is completely ignored when the Apache configuration files are generated. To (I think) prove that, look at the AWS EB scripts at these files (just the important lines):

/opt/elasticbeanstalk/hooks/configdeploy/pre/01generate.py:

configuration = config.SimplifiedConfigLoader().load_config()
config.generate_apache_config(
    configuration, os.path.join(config.ON_DECK_DIR, 'wsgi.conf'))

/opt/elasticbeanstalk/hooks/appdeploy/pre/04configen.py:

configuration = config.SimplifiedConfigLoader().load_config()
config.generate_apache_config(
    configuration, os.path.join(config.ON_DECK_DIR, 'wsgi.conf'))

/opt/elasticbeanstalk/hooks/config.py:

def _generate_static_file_config(mapping):
    contents = []
    for key, value in mapping.items():
        contents.append('Alias %s %s' % (key, os.path.join(APP_DIR, value)))
        contents.append('<Directory %s>' % os.path.join(APP_DIR, value))
        contents.append('Order allow,deny')
        contents.append('Allow from all')
        contents.append('</Directory>')
        contents.append('')
    return '\n'.join(contents)

class SimplifiedConfigLoader(ContainerConfigLoader):
    def load_config(self):
        parsed = json.loads("path/to/containerconfiguration")
        python_section = parsed['python']
        converted = {}
        #..snip...
        static_files = {}
        for keyval in python_section['static_files']:
            key, value = keyval.split('=', 1)
            static_files[key] = value
        converted['static_files'] = static_files
        #...
        return converted

/opt/elasticbeanstalk/deploy/configuration/containerconfiguration:

{
    "python": {
        //...
        "static_files": [
            "/static="
        ], 
        //...
}

I apologize for dumping so much code, but the gist of it is that when _generate_static_file_config is called to produce that part of wsgi.config, it never uses any of the values specified in those ebextension config files. SimplifiedConfigLoader only uses the fixed file containerconfiguration, which has the evil default value for the /static mapping.

I hope I'm missing something because I can't find a way to prevent this without resorting to a custom AMI.

like image 818
sergiopereira Avatar asked Oct 14 '13 15:10

sergiopereira


People also ask

When should you not use Elastic Beanstalk?

Elastic Beanstalk is a bad choice if you need worker processes. The whole point of a worker process is to perform a task in the background without slowing down your main web app. But Elastic Beanstalk doesn't support this option in a scalable way.

What format can source files be in for Amazon Elastic Beanstalk?

Your source bundle must meet the following requirements: Consist of a single ZIP file or WAR file (you can include multiple WAR files inside your ZIP file) Not exceed 512 MB. Not include a parent folder or top-level directory (subdirectories are fine)

How does AWS Elastic Beanstalk work?

Elastic Beanstalk reduces management complexity without restricting choice or control. You simply upload your application, and Elastic Beanstalk automatically handles the details of capacity provisioning, load balancing, scaling, and application health monitoring.


1 Answers

I ended up opening a paid case with AWS support and they confirmed it was a bug in the Python container code.

As a result of this problem, they have just released (10/25/2013) a new version of the container and any new environments will contain the fix. To fix any of your existing environments... well, you can't. You'll have to create a new environment from the ground up (don't even use saved configurations) and then switch over from the old one.

Hope this helps the next poor soul.

Update 2017-01-10: Back when I answered it wasn't possible to upgrade the container to newer versions. Since then AWS added that feature. You can even let it auto-update with the Managed Platform Updates feature.

like image 174
sergiopereira Avatar answered Oct 24 '22 05:10

sergiopereira