web-dev-qa-db-fra.com

boto.exception.S3ResponseError: S3ResponseError: 403 interdite

J'essaie de faire en sorte que Django télécharge des fichiers statiques sur S3, mais je reçois une erreur 403 interdite, et je ne sais pas pourquoi.

Full 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

Contenu de 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",
     )

Contenu de 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

Une recherche Google pour cette exception ne révèle rien d'intéressant. Je soupçonne que j'ai mal configuré les choses, bien que je ne sois pas sûr. Quelqu'un peut-il m'indiquer la bonne direction? Merci pour votre temps et votre considération.

51
Levi Campbell

J'utilise Amazon IAM pour l'ID de clé et la clé d'accès spécifiques et vient de basculer dans le même code 403 interdit. Il s'avère que vous devez accorder des autorisations qui ciblent les deux la racine du compartiment et ses sous-objets:

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

Je vous recommande d'essayer de tester vos informations d'identification AWS séparément pour vérifier si les informations d'identification sont réellement autorisées à lire et à écrire des données dans le compartiment S3. Ce qui suit devrait fonctionner:

>>> 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()

Vous devriez essayer le même test avec l'autre compartiment ("donebox-media"). Si cela fonctionne, les autorisations sont correctes et le problème réside dans le code ou la configuration des stockages Django. Si cela échoue avec un 403, alors soit:

  • Les chaînes access_key/secret_key sont incorrectes
  • Les clés access_key/secret_key sont correctes, mais ce compte ne dispose pas des autorisations nécessaires pour écrire dans le compartiment.

J'espère que ça aide. S'il vous plaît rapporter vos conclusions.

47
garnaat

J'ai eu le même problème et j'ai finalement découvert que le vrai problème était SERVER TIME . Il était mal configuré et AWS répond par un message 403 FORBIDDEN.

En utilisant Debian, vous pouvez autoconfigurer en utilisant NTP:

ntpdate 0.pool.ntp.org

43
Alan Wagner

Cela se produira également si les paramètres horaires de votre machine sont incorrects.

7
altschuler

Il est également possible que les informations d'identification incorrectes soient utilisées. Vérifier:

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?

Sinon, jetez un coup d'œil à ~/.boto, ~/.aws/config et ~/.aws/credentials.

3
kat

Au cas où cela aiderait quelqu'un, j'ai dû ajouter l'entrée de configuration suivante pour que collectstatic fonctionne et ne retourne pas 403:

AWS_DEFAULT_ACL = ''
2
Danra

Voici un raffinement avec des autorisations minimales . Dans tous les cas, comme indiqué ci-dessus, ailleurss3:ListAllMyBuckets est nécessaire sur tous les compartiments.

Dans sa configuration par défaut, Django-storages téléchargera des fichiers sur S3 avec des autorisations de lecture publique - voir backend de Django-storages Amazon S3 } _

Des essais et des erreurs ont révélé que dans cette configuration par défaut, les deux seules autorisations requises sont s3:PutObject pour télécharger un fichier à la première place et s3:PutObjectAcl pour définir les autorisations de cet objet sur public.

Aucune action supplémentaire n'est requise car, à partir de ce moment, la lecture est désormais publique sur l'objet.

Stratégie d'utilisateur IAM - lecture publique (par défaut):

{
   "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/*"
       }
   ]
}

Il n’est pas toujours souhaitable d’avoir des objets lisibles en public. Ceci est réalisé en définissant la propriété correspondante dans le fichier de paramètres.

Django settings.py: 

...
AWS_DEFAULT_ACL = "private"
...

Et puis le s3:PutObjectAcl n'est plus requis et les autorisations minimales sont les suivantes:

Stratégie utilisateur IAM - private:

{
   "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/*"
       }
   ]
}
1
freshnewpage

Une autre solution évitant les stratégies personnalisées et utilisant les stratégies prédéfinies AWS:

  • Ajoutez des autorisations d'accès complet S3 à votre utilisateur S3.

    • IAM/ Utilisateurs / Autorisations et Attach Policy
    • Ajouter une stratégie "AmazonS3FullAccess"
0
marcanuy

Peut-être que vous n'avez pas réellement accès au seau que vous essayez de rechercher/obtenir/créer ..

Rappelez-vous:Les noms de compartiment doivent être uniques sur l’ensemble du système S3eco. Par conséquent, si vous essayez d’accéder à (rechercher/obtenir/créer) un compartiment nommé «test», vous n’y aurez pas accès . 

0
eiTan LaVi