2012-06-01 5 views
42

Я пытаюсь получить django для загрузки статических файлов на S3, но istead. Я получаю запрещенную ошибку 403, и я не уверен, почему.boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden

Полный StackTrace:

Traceback (most recent call last): 
    File "manage.py", line 14, in <module> 
    execute_manager(settings) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 438, in execute_manager 
    utility.execute() 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 379, in execute 
    self.fetch_command(subcommand).run_from_argv(self.argv) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 191, in run_from_argv 
    self.execute(*args, **options.__dict__) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 220, in execute 
    output = self.handle(*args, **options) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 351, in handle 
    return self.handle_noargs(**options) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 89, in handle_noargs 
    self.copy_file(path, prefixed_path, storage, **options) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 184, in copy_file 
    if not self.delete_file(path, prefixed_path, source_storage, **options): 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 115, in delete_file 
    if self.storage.exists(prefixed_path): 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/storages/backends/s3boto.py", line 209, in exists 
    return k.exists() 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/boto/s3/key.py", line 391, in exists 
    return bool(self.bucket.lookup(self.name)) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/boto/s3/bucket.py", line 143, in lookup 
    return self.get_key(key_name, headers=headers) 
    File "/home/levi/Projects/DoneBox/.virtualenv/local/lib/python2.7/site-packages/boto/s3/bucket.py", line 208, in get_key 
    response.status, response.reason, '') 
boto.exception.S3ResponseError: S3ResponseError: 403 Forbidden 

Содержание settings.py:

import os 
DIRNAME = os.path.dirname(__file__) 
# Django settings for DoneBox project. 

DEBUG = True 
TEMPLATE_DEBUG = DEBUG 

ADMINS = (
    # ('Your Name', '[email protected]'), 
) 

MANAGERS = ADMINS 

DATABASES = { 
    'default': { 
     'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 
     'NAME': os.path.join(DIRNAME, "box.sqlite"),      # Or path to database file if using sqlite3. 
     'USER': '',      # Not used with sqlite3. 
     'PASSWORD': '',     # Not used with sqlite3. 
     'HOST': '',      # Set to empty string for localhost. Not used with sqlite3. 
     'PORT': '',      # Set to empty string for default. Not used with sqlite3. 
    } 
} 

# Local time zone for this installation. Choices can be found here: 
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 
# although not all choices may be available on all operating systems. 
# On Unix systems, a value of None will cause Django to use the same 
# timezone as the operating system. 
# If running in a Windows environment this must be set to the same as your 
# system time zone. 
TIME_ZONE = 'America/Denver' 

# Language code for this installation. All choices can be found here: 
# http://www.i18nguy.com/unicode/language-identifiers.html 
LANGUAGE_CODE = 'en-us' 

SITE_ID = 1 

# If you set this to False, Django will make some optimizations so as not 
# to load the internationalization machinery. 
USE_I18N = True 

# If you set this to False, Django will not format dates, numbers and 
# calendars according to the current locale 
USE_L10N = True 

# Absolute filesystem path to the directory that will hold user-uploaded files. 
# Example: "/home/media/media.lawrence.com/media/" 
MEDIA_ROOT = '' 

# URL that handles the media served from MEDIA_ROOT. Make sure to use a 
# trailing slash. 
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/" 
MEDIA_URL = "d1eyn4cjl5vzx0.cloudfront.net" 

# Absolute path to the directory static files should be collected to. 
# Don't put anything in this directory yourself; store your static files 
# in apps' "static/" subdirectories and in STATICFILES_DIRS. 
# Example: "/home/media/media.lawrence.com/static/" 
STATIC_ROOT = os.path.join(DIRNAME, "static") 

# URL prefix for static files. 
# Example: "http://media.lawrence.com/static/" 
STATIC_URL = "d280kzug7l5rug.cloudfront.net" 

# URL prefix for admin static files -- CSS, JavaScript and images. 
# Make sure to use a trailing slash. 
# Examples: "http://foo.com/static/admin/", "/static/admin/". 
ADMIN_MEDIA_PREFIX = '/static/admin/' 

# Additional locations of static files 
STATICFILES_DIRS = (
    # Put strings here, like "/home/html/static" or "C:/www/django/static". 
    # Always use forward slashes, even on Windows. 
    # Don't forget to use absolute paths, not relative paths. 
    os.path.join(DIRNAME, "main", "static"), 
) 

# List of finder classes that know how to find static files in 
# various locations. 
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder', 
    'django.contrib.staticfiles.finders.AppDirectoriesFinder', 
    'django.contrib.staticfiles.finders.DefaultStorageFinder', 
) 

# Make this unique, and don't share it with anybody. 
SECRET_KEY = '<snip>' 

# List of callables that know how to import templates from various sources. 
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader', 
    'django.template.loaders.app_directories.Loader', 
    'django.template.loaders.eggs.Loader', 
) 

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware', 
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware', 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    'django.contrib.messages.middleware.MessageMiddleware', 
) 

ROOT_URLCONF = 'DoneBox.urls' 

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". 
    # Always use forward slashes, even on Windows. 
    # Don't forget to use absolute paths, not relative paths. 
    os.path.join(DIRNAME, "main", "templates"), 
    os.path.join(DIRNAME, "templates"), 
    os.path.join(DIRNAME, "basic", "blog", "templates"), 
) 

INSTALLED_APPS = (
    'django.contrib.auth', 
    'django.contrib.contenttypes', 
    'django.contrib.sessions', 
    'django.contrib.sites', 
    'django.contrib.messages', 
    'django.contrib.staticfiles', 
    'django.contrib.sitemaps', 
    # Uncomment the next line to enable the admin: 
    'django.contrib.admin', 
    # Uncomment the next line to enable admin documentation: 
    'storages', 
    'django.contrib.admindocs', 
    'main', 
    'contacts', 
    'piston', 
    'registration', 
# 'contact_form', 
    'basic', 
    'basic.blog', 
) 

# A sample logging configuration. The only tangible logging 
# performed by this configuration is to send an email to 
# the site admins on every HTTP 500 error. 
# See http://docs.djangoproject.com/en/dev/topics/logging for 
# more details on how to customize your logging configuration. 
LOGGING = { 
    'version': 1, 
    'disable_existing_loggers': False, 
    'handlers': { 
     'mail_admins': { 
      'level': 'ERROR', 
      'class': 'django.utils.log.AdminEmailHandler' 
     } 
    }, 
    'loggers': { 
     'django.request': { 
      'handlers': ['mail_admins'], 
      'level': 'DEBUG', 
      'propagate': True, 
     }, 
     'django.db.backends': { 
      'handlers': ['mail_admins'], 
      'level': 'DEBUG', 
      'propagate': True, 
     } 
    } 
} 

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage' 
AWS_ACCESS_KEY_ID = '<snip>' 
AWS_SECRET_ACCESS_KEY = '<snip>' 
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage' 
AWS_STORAGE_BUCKET_NAME = "donebox-static" 
STATIC_FILES_BUCKET = "donebox-static" 
MEDIA_FILES_BUCKET = "donebox-media" 
ACCOUNT_ACTIVATION_DAYS = 7 

EMAIL_HOST = "email-smtp.us-east-1.amazonaws.com" 
EMAIL_HOST_USER = '<snip>' 
EMAIL_HOST_PASSWORD = '<snip>' 
EMAIL_PORT = 587 
EMAIL_USE_TLS = True 
TEMPLATE_CONTEXT_PROCESSORS = (
    "django.contrib.auth.context_processors.auth", 
    "django.core.context_processors.debug", 
    "django.core.context_processors.i18n", 
    "django.core.context_processors.media", 
    "django.core.context_processors.static", 
    "django.contrib.messages.context_processors.messages", 
    "DoneBox.main.context_processors_PandC", 
    ) 

Содержание из requirements.pip:

django==1.3 
django-storages==1.1.4 
django-registration==0.8 
django-piston==0.2.3 
django-tagging==0.3.1 
django-extensions==0.8 
BeautifulSoup==3.2.1 
boto==2.4.1 
mysql-python==1.2.3 
tweepy==1.9 
feedparser==5.1.2 
pycrypto==2.6 

Поиск этого исключения в google не вызывает ничего интересного. Я подозреваю, что неправильно настроил ситуацию, хотя я не уверен. Может ли кто-нибудь указать мне в правильном направлении? Спасибо за ваше время и внимание.

ответ

99

Я использую Amazon IAM для конкретного ключа ID и ключ доступа и просто врезались в тот же 403 Forbidden ... Оказывается, вам необходимо предоставить права доступа, которые нацелены на как в корень ковша и его подобъектов:

{ 
    "Statement": [ 
    { 
     "Principal": { 
      "AWS": "*" 
     }, 
     "Effect": "Allow", 
     "Action": "s3:*", 
     "Resource": ["arn:aws:s3:::bucket-name/*", "arn:aws:s3:::bucket-name"] 
    } 
    ] 
} 
+7

Есть ли способ не давать много разрешений? Я пытаюсь ограничить минимум и не нахожу достаточно информации. В частности, я хочу, чтобы разрешить «список» разрешений – KVISH

+0

Я потратил часы на поиск этого. Счастливый. –

+1

так ... где поставить это? – WeaselFox

47

Я бы рекомендовал вам протестировать ваши учетные данные AWS отдельно, чтобы проверить, действительно ли учетные данные имеют разрешение на чтение и запись данных в ведро S3. Должно работать следующее:

>>> import boto 
>>> s3 = boto.connect_s3('<access_key>', '<secret_key>') 
>>> bucket = s3.lookup('donebox-static') 
>>> key = bucket.new_key('testkey') 
>>> key.set_contents_from_string('This is a test') 
>>> key.exists() 
>>> key.delete() 

Вы должны попробовать тот же тест с другим ковшом ('donebox-media'). Если это работает, разрешения правильные, и проблема заключается в коде или конфигурации хранилища Django. Если это не удается с 403 затем:

  • access_key/secret_key строки неверны
  • access_key/secret_key являются правильными, но что учетная запись не имеет необходимых разрешений на запись в ведре

Надеюсь, что это поможет. Пожалуйста, сообщите о своих результатах.

+0

Так хорошо. Сделал меня узнать, что помимо предоставления разрешений на ведро мне также нужно было дать разрешение на его содержимое ведра/*. – Alper

+0

Спасибо. Наконец, работает. – ipeacocks

+0

AttributeError: объект «NoneType» не имеет атрибута «new_key» – itsji10dra

38

У меня была такая же проблема, и, наконец, я обнаружил, что реальной проблемой было время SERVER. Это было неправильно сконфигурировано, и AWS ответил 403 FORBIDDEN.

Использование Debian вы можете AUTOCONFIGURE с помощью NTP:

ntpdate 0.pool.ntp.org

+2

СПАСИБО. То же самое случилось со мной. Время было выключено, потому что я бегал внутри виртуальной машины, которую я приостановил, и не настроил ntp. – wjin

+1

Только что увидел это после того, как я вернулся, чтобы опубликовать то же самое. Последующий учебник по тестированию @garnaat, и когда я запустил команду 's3.get_all_buckets()' получил 403 с некоторым xml, указывающим 'RequestTimeTooSkewed Разница между временем запроса и текущим временем слишком велика. '. Жаль, что раньше я не видел этого ответа. Рады приветствовать! – Gesias

+0

Это, вероятно, не проблема с корнем, которую большинство людей приземлили здесь, но в моем случае это было - и ntpdate сохранил мой прикладом. ** Спасибо! ** – palewire

7

Это также произойдет, если настройки времени вашего станка неверны

+0

Это работа для меня. –

+0

-1, потому что кто-то уже дал этот ответ с простым и эффективным решением проблемы, за 8 месяцев до того, как вы разместили эту менее полезную информацию. –

2

В случае, если это помогает любому, я должен был добавить следующую запись конфигурации для collectstatic работать и не возвращаться 403:

AWS_DEFAULT_ACL = '' 
+0

did not работа с этим – doniyor

+0

Работал для меня. Но очень странно, что такая настройка может быть связана с ошибкой 403. Возможно, ключ доступа к комбинации и секрет доступа не имели разрешения на установку acl для загруженных файлов. Я видел, что по умолчанию boto имеет default_acl = setting ('AWS_DEFAULT_ACL', 'public-read') –

0

Другое решение, позволяющее избежать пользовательских политик и использования предопределенных политик AWS :

  • Добавить разрешения S3 для полного доступа к вашему пользователю S3.

    • IAM/Пользователи/Права доступа и Приложить политику
    • Добавить политику "AmazonS3FullAccess"
3

Также возможно, что неправильные учетные данные быть использованным. Для проверки:

import boto 
s3 = boto.connect_s3('<your access key>', '<your secret key>') 
bucket = s3.get_bucket('<your bucket>') # does this work? 
s3 = boto.connect_s3() 
s3.aws_access_key_id # is the same key being used by default? 

Если нет, посмотрите на ~/.boto, ~/.aws/config и ~/.aws/credentials.

+0

благодаря тому, что это нашло мою проблему, переменная среды не была установлена ​​правильно. – awwester

0

Это уточнение с минимальными разрешениями. Во всех случаях, как обсуждалось, elsewheres3:ListAllMyBuckets необходим для всех ковшей.

В нем по умолчанию конфигурации Джанго-хранилища будут загружать файлы на S3 с правами общественного чтения - см django-storages Amazon S3 backend

проб и ошибок выяснилось, что в конфигурации по умолчанию, только два разрешения, необходимые являются s3:PutObject загрузить файл в первое место и s3:PutObjectAcl, чтобы установить разрешения для этого объекта публично.

Никаких дополнительных действий не требуется, потому что с этой точки в любом случае чтение в прямом направлении является общедоступным.

IAM политика пользователя - общественное чтение (по умолчанию):

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
     { 
      "Effect": "Allow", 
      "Action": "s3:ListAllMyBuckets", 
      "Resource": "arn:aws:s3:::*" 
     }, 
     { 
      "Effect": "Allow", 
      "Action": [ 
       "s3:PutObject", 
       "s3:PutObjectAcl" 
      ], 
      "Resource": "arn:aws:s3:::bucketname/*" 
     } 
    ] 
} 

Это не всегда желательно иметь объекты читаемыми. Это достигается установкой соответствующего свойства в файле настроек.

Джанго settings.py:

... 
AWS_DEFAULT_ACL = "private" 
... 

И не то s3:PutObjectAcl больше не требуется, и минимальные разрешения являются:

IAM пользователя Политика - личное:

{ 
    "Version": "2012-10-17", 
    "Statement": [ 
     { 
      "Effect": "Allow", 
      "Action": "s3:ListAllMyBuckets", 
      "Resource": "arn:aws:s3:::*" 
     }, 
     { 
      "Effect": "Allow", 
      "Action": [ 
       "s3:PutObject", 
       "s3:GetObject" 
      ], 
      "Resource": "arn:aws:s3:::bucketname/*" 
     } 
    ] 
} 
0

Возможно, вы на самом деле не имеет доступа к ведру вы пытаетесь для поиска/получить/создать ..

Помните: имен ведра должны быть уникальными по всему S3 эко-системе, так что если вы пытаетесь доступ (lookup/get/create) ведро с именем «test», у вас не будет доступа к нему.