web-dev-qa-db-ja.com

boto.exception.S3ResponseError:S3ResponseError:403 Forbidden

静的ファイルをS3にアップロードするためにDjangoを取得しようとしていますが、代わりに403 forbiddenエラーが表示されます。理由はわかりません。

フルスタックトレース:

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

この例外をグーグルで検索しても、興味深いものは何も見つかりません。よくわかりませんが、設定を間違えたようです。誰かが私を正しい方向に向けることができますか?あなたの時間と配慮していただきありがとうございます。

51
Levi Campbell

特定のキーIDとアクセスキーにAmazon IAMを使用していますが、同じ403 Forbiddenにぶつかりました...ターゲットbothバケットルートとそのサブオブジェクトにアクセス許可を与える必要があることがわかりました:

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

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は正しいが、そのアカウントにはバケットへの書き込みに必要な権限がない

それがお役に立てば幸いです。調査結果を報告してください。

47
garnaat

私は同じ問題を抱えていて、最終的に本当の問題はサーバー時間であることを発見しました。設定が誤っており、AWSは403 FORBIDDENで応答します。

Debianを使用すると、NTPを使用して自動構成できます。

ntpdate 0.pool.ntp.org

44
Alan Wagner

これは、マシンの時刻設定が正しくない場合にも発生します

7
altschuler

これがだれにも役立つ場合、collectstaticの次の構成エントリを追加して、403を返さないようにする必要がありました。

AWS_DEFAULT_ACL = ''
3
Danra

間違った資格情報が使用されている可能性もあります。検証します:

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

3
kat

以下は、最小限の権限を持つ改良点です。前述のとおり、すべての場合で elsewheres3:ListAllMyBucketsはすべてのバケットで必要です。

デフォルト設定では、Django-storagesはパブリック読み取りアクセス許可でファイルを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/*"
       }
   ]
}

オブジェクトをパブリックに読み取り可能にすることは常に望ましいとは限りません。これは、設定ファイルで関連するプロパティを設定することにより実現されます。

Django settings.py:

...
AWS_DEFAULT_ACL = "private"
...

そして、s3:PutObjectAclは不要になり、最小限の権限は次のとおりです。

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

カスタムポリシーを回避し、AWS定義済みポリシーを使用する別のソリューション:

  • S3ユーザーにS3フルアクセス許可を追加します。

    • [〜#〜] iam [〜#〜]/sers/PermissionsおよびAttach Policy
    • ポリシーの追加"AmazonS3FullAccess"
0
marcanuy

たぶん、ルックアップ/取得/作成しようとしているバケットに実際にアクセスできない可能性があります。

覚えておいてください:バケット名はS3エコシステム全体で一意である必要があるため、 「test」という名前のバケットにアクセス(ルックアップ/取得/作成)するには、アクセスできません。

0
eiTan LaVi