Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix AWS security/session token not being set #514

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 clean_name, safe_join, setting
from storages.utils import 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 @@ -247,10 +248,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 @@ -298,24 +297,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 @@ -16,7 +16,7 @@
from django.utils.six.moves.urllib import parse as urlparse
from django.utils.timezone import is_naive, localtime

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

try:
import boto3.session
Expand Down Expand Up @@ -187,6 +187,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 @@ -248,10 +249,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 @@ -300,24 +299,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 @@ -80,3 +81,14 @@ def safe_join(base, *paths):
' component')

return final_path.lstrip('/')


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