Skip to content

Commit

Permalink
Fixed #282: Always set AWS security/session token
Browse files Browse the repository at this point in the history
  • Loading branch information
alej0varas authored and jschneier committed Aug 12, 2018
1 parent 9297273 commit b13efd9
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 34 deletions.
31 changes: 14 additions & 17 deletions storages/backends/s3boto.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
from django.utils.six import BytesIO

from storages.utils import check_location, clean_name, safe_join, setting
from storages.utils import check_location, clean_name, lookup_env, safe_join, setting

try:
from boto import __version__ as boto_version
Expand Down Expand Up @@ -183,6 +183,7 @@ class S3BotoStorage(Storage):
access_key_names = ['AWS_S3_ACCESS_KEY_ID', 'AWS_ACCESS_KEY_ID']
secret_key_names = ['AWS_S3_SECRET_ACCESS_KEY', 'AWS_SECRET_ACCESS_KEY']
security_token_names = ['AWS_SESSION_TOKEN', 'AWS_SECURITY_TOKEN']
security_token = None

access_key = setting('AWS_S3_ACCESS_KEY_ID', setting('AWS_ACCESS_KEY_ID'))
secret_key = setting('AWS_S3_SECRET_ACCESS_KEY', setting('AWS_SECRET_ACCESS_KEY'))
Expand Down Expand Up @@ -245,10 +246,8 @@ def __init__(self, acl=None, bucket=None, **settings):
self._connection = None
self._loaded_meta = False

self.security_token = None
if not self.access_key and not self.secret_key:
self.access_key, self.secret_key = self._get_access_keys()
self.security_token = self._get_security_token()
self.access_key, self.secret_key = self._get_access_keys()
self.security_token = self._get_security_token()

@property
def connection(self):
Expand Down Expand Up @@ -296,24 +295,22 @@ def entries(self):
self._loaded_meta = True
return self._entries

def _lookup_env(self, names):
for name in names:
value = os.environ.get(name)
if value:
return value

def _get_access_keys(self):
"""
Gets the access keys to use when accessing S3. If none
are provided to the class in the constructor or in the
settings then get them from the environment variables.
Gets the access keys to use when accessing S3. If none is
provided in the settings then get them from the environment
variables.
"""
access_key = self.access_key or self._lookup_env(self.access_key_names)
secret_key = self.secret_key or self._lookup_env(self.secret_key_names)
access_key = self.access_key or lookup_env(S3BotoStorage.access_key_names)
secret_key = self.secret_key or lookup_env(S3BotoStorage.secret_key_names)
return access_key, secret_key

def _get_security_token(self):
security_token = self._lookup_env(self.security_token_names)
"""
Gets the security token to use when accessing S3. Get it from
the environment variables.
"""
security_token = self.security_token or lookup_env(S3BotoStorage.security_token_names)
return security_token

def _get_or_create_bucket(self, name):
Expand Down
31 changes: 14 additions & 17 deletions storages/backends/s3boto3.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.timezone import is_naive, localtime

from storages.utils import check_location, safe_join, setting
from storages.utils import check_location, lookup_env, safe_join, setting

try:
import boto3.session
Expand Down Expand Up @@ -190,6 +190,7 @@ class S3Boto3Storage(Storage):
access_key_names = ['AWS_S3_ACCESS_KEY_ID', 'AWS_ACCESS_KEY_ID']
secret_key_names = ['AWS_S3_SECRET_ACCESS_KEY', 'AWS_SECRET_ACCESS_KEY']
security_token_names = ['AWS_SESSION_TOKEN', 'AWS_SECURITY_TOKEN']
security_token = None

access_key = setting('AWS_S3_ACCESS_KEY_ID', setting('AWS_ACCESS_KEY_ID'))
secret_key = setting('AWS_S3_SECRET_ACCESS_KEY', setting('AWS_SECRET_ACCESS_KEY'))
Expand Down Expand Up @@ -262,10 +263,8 @@ def __init__(self, acl=None, bucket=None, **settings):
self._bucket = None
self._connections = threading.local()

self.security_token = None
if not self.access_key and not self.secret_key:
self.access_key, self.secret_key = self._get_access_keys()
self.security_token = self._get_security_token()
self.access_key, self.secret_key = self._get_access_keys()
self.security_token = self._get_security_token()

if not self.config:
self.config = Config(s3={'addressing_style': self.addressing_style},
Expand Down Expand Up @@ -325,24 +324,22 @@ def entries(self):
}
return self._entries

def _lookup_env(self, names):
for name in names:
value = os.environ.get(name)
if value:
return value

def _get_access_keys(self):
"""
Gets the access keys to use when accessing S3. If none
are provided to the class in the constructor or in the
settings then get them from the environment variables.
Gets the access keys to use when accessing S3. If none is
provided in the settings then get them from the environment
variables.
"""
access_key = self.access_key or self._lookup_env(self.access_key_names)
secret_key = self.secret_key or self._lookup_env(self.secret_key_names)
access_key = self.access_key or lookup_env(S3Boto3Storage.access_key_names)
secret_key = self.secret_key or lookup_env(S3Boto3Storage.secret_key_names)
return access_key, secret_key

def _get_security_token(self):
security_token = self._lookup_env(self.security_token_names)
"""
Gets the security token to use when accessing S3. Get it from
the environment variables.
"""
security_token = self.security_token or lookup_env(S3Boto3Storage.security_token_names)
return security_token

def _get_or_create_bucket(self, name):
Expand Down
12 changes: 12 additions & 0 deletions storages/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import posixpath

from django.conf import settings
Expand Down Expand Up @@ -85,3 +86,14 @@ def check_location(storage):
correct,
)
)


def lookup_env(names):
"""
Look up for names in environment. Returns the first element
found.
"""
for name in names:
value = os.environ.get(name)
if value:
return value

0 comments on commit b13efd9

Please sign in to comment.