[Fixed]-How to dynamically add EC2 ip addresses to Django ALLOWED_HOSTS

4👍

Accepted answer was working fine with IMDSv1. In 2019 AWS launched IMDSv2 which requires session token authentication. Therefore, before requesting instance meta data we first need to fetch the token:

import requests

try:
    IMDSv2_TOKEN = requests.put('http://169.254.169.254/latest/api/token', headers={
        'X-aws-ec2-metadata-token-ttl-seconds': '3600'
    }).text
    EC2_PRIVATE_IP = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4', timeout=0.01, headers={
        'X-aws-ec2-metadata-token': IMDSv2_TOKEN
    }).text
except requests.exceptions.RequestException:
    EC2_PRIVATE_IP = None


ALLOWED_HOSTS = [
    'my-app-test.eu-central-1.elasticbeanstalk.com'
]

if EC2_PRIVATE_IP:
    ALLOWED_HOSTS.append(EC2_PRIVATE_IP)

References:

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html

2👍

The snippets below will find either the Public IP address or the Elastic IP address associated with your EC2 instance and append it to ALLOWED_HOSTS.

  • Install PyCurl

    pip install pycurl
    
  • Python 3

    import pycurl
    from io import BytesIO
    
    # Determine Public IP address of EC2 instance
    buffer = BytesIO()
    c = pycurl.Curl()
    c.setopt(c.URL, 'checkip.amazonaws.com')
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    # Body is a byte string, encoded. Decode it first.
    ALLOWED_HOSTS.append(buffer.getvalue().decode('iso-8859-1').strip())
    
  • Python 2

    import pycurl
    from StringIO import StringIO
    
    buffer = StringIO()
    c = pycurl.Curl()
    c.setopt(c.URL, 'checkip.amazonaws.com')
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    # In Python 2, we can cast the return value to
    # string without knowing the exact encoding.
    ALLOWED_HOSTS.append(str(buffer.getvalue()).strip())
    

Leave a comment