Я почесал голову над этим в течение нескольких дней. В настоящее время работаю над главой 13 (пользовательские микросообщения) Rails Tutorial , и хотя мое приложение отлично работает в процессе разработки, я не могу загрузить изображения на AWS S3, работающие в производстве (подробности здесь, в учебник ). Приложение использует ASW S3 корзины для хранения и CarrierWave / Fog gems для загрузки файлов.
Когда я открываю свое производственное приложение heroku, все работает нормально, кроме загрузки изображений. Когда я пытаюсь загрузить изображение на новый микросообщение, я получаю общее выражение «Извините, но что-то пошло не так». ошибка в браузере. Журналы Heroku показывают: ошибка состояния 403 «Запрещено» при попытке добраться до корзины (подробные журналы приведены ниже).
У других, похоже, были похожие проблемы. В большинстве случаев кажется, что решение состоит в том, чтобы установить правильные разрешения пользователя IAM или установить политику сегмента S3 , но я вполне уверен, что они настроены правильно по двум причинам:
- Я могу использовать веб-интерфейс этой учетной записи пользователя для загрузки и управления файлами в корзине, поэтому я знаю, что у него есть доступ.
- Я установил инструмент командной строки aws, настроил его на тот же ключ доступа пользователя и секретный ключ, которые использовались в моем веб-приложении, и я могу иметь возможность загружать и извлекать информацию из корзины через CLI.
Тем не менее, я попробовал несколько политик и разрешений пользователей, включая разрешение на полный доступ к Amazon S3 (я считаю, что оно является наиболее общим), и несколько более конкретных версий (см. Последнюю версию ниже).
Другие вещи, которые я пробовал, похоже, работают для других:
Будучи новым разработчиком, я чувствую, что у меня пока нет технических знаний для диагностики этого, и, честно говоря, это немного обескураживает, поэтому я надеюсь на помощь. Вот некоторые вопросы, которые у меня есть, и возможные направления для изучения, которые я хотел бы изучить подробнее:
- Вопрос: Если я смогу получить доступ к ведру с помощью aws-cli, я не смогу ли я также использовать героку с несущей / туманом, используя те же учетные данные, или я что-то недопонимаю о том, как герою достает S3 ведро?
- Возможная проблема: Carrierwave или ImageMagick создают временный файл при загрузке изображения. В некоторых случаях кажется, что это может помешать загрузке. Кто-то дал расплывчатый ответ об этом здесь , но я не понимаю, какие действия могут помочь избавиться от этой проблемы.
- Возможная проблема: У кого-то, похоже, были проблемы с Rails strong params при этом. Я не мог понять, как отладить это ... Когда я использую byebug, чтобы открыть интерактивную консоль на сервере в месте ошибки (в моем методе micropost_controller #create), сразу после загрузки файла изображение находится в параметрах хэш, но ключ
:picture
переменной экземпляра @micropost
равен nil (в то же время ключ :content
не равен nil, он содержит любой текст, который я отправил с изображением, как и должно быть).
Ссылка на остальную часть кода на GitHub , если это поможет.
Извините за скучность. Любое руководство будет с благодарностью.
Ошибка:
2019-01-07T08:11:37.684069+00:00 app[web.1]: F, [2019-01-07T08:11:37.683926 #22] FATAL -- : [363c5115-f872-43b4-857a-10d1d7d11737] Excon::Error::Forbidden (Expected(200) <=> Actual(403 Forbidden)
2019-01-07T08:11:37.684074+00:00 app[web.1]: excon.error.response
2019-01-07T08:11:37.684077+00:00 app[web.1]: :body => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>***</RequestId><HostId>***=</HostId></Error>"
2019-01-07T08:11:37.684079+00:00 app[web.1]: :cookies => [
2019-01-07T08:11:37.684081+00:00 app[web.1]: ]
2019-01-07T08:11:37.684082+00:00 app[web.1]: :headers => {
2019-01-07T08:11:37.684085+00:00 app[web.1]: "Connection" => "close"
2019-01-07T08:11:37.684086+00:00 app[web.1]: "Content-Type" => "application/xml"
2019-01-07T08:11:37.684088+00:00 app[web.1]: "Date" => "Mon, 07 Jan 2019 08:11:36 GMT"
2019-01-07T08:11:37.684090+00:00 app[web.1]: "Server" => "AmazonS3"
2019-01-07T08:11:37.684092+00:00 app[web.1]: "x-amz-id-2" => "***"
2019-01-07T08:11:37.684094+00:00 app[web.1]: "x-amz-request-id" => "***"
2019-01-07T08:11:37.684096+00:00 app[web.1]: }
2019-01-07T08:11:37.684098+00:00 app[web.1]: :host => "bucket-name.s3-us-west-1.amazonaws.com"
2019-01-07T08:11:37.684099+00:00 app[web.1]: :local_address => "*********"
2019-01-07T08:11:37.684101+00:00 app[web.1]: :local_port => ******
2019-01-07T08:11:37.684103+00:00 app[web.1]: :path => "/uploads/micropost/picture/306/ocean2.jpeg"
2019-01-07T08:11:37.684104+00:00 app[web.1]: :port => 443
2019-01-07T08:11:37.684106+00:00 app[web.1]: :reason_phrase => "Forbidden"
2019-01-07T08:11:37.684108+00:00 app[web.1]: :remote_ip => "*******"
2019-01-07T08:11:37.684110+00:00 app[web.1]: :status => 403
2019-01-07T08:11:37.684111+00:00 app[web.1]: :status_line => "HTTP/1.1 403 Forbidden\r\n"
2019-01-07T08:11:37.684113+00:00 app[web.1]: ):
2019-01-07T08:11:37.684217+00:00 app[web.1]: F, [2019-01-07T08:11:37.684147 #22] FATAL -- : [363c5115-f872-43b4-857a-10d1d7d11737]
2019-01-07T08:11:37.684392+00:00 app[web.1]: F, [2019-01-07T08:11:37.684328 #22] FATAL -- : [363c5115-f872-43b4-857a-10d1d7d11737] app/controllers/microposts_controller.rb:7:in `create'
Политика использования ковша:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::***********:user/user-name"
},
"Action": [
"s3:AbortMultipartUpload",
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:DeleteObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::bucket-name/*",
"arn:aws:s3:::bucket-name"
]
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::*******:user/user-name"
},
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::bucket-name",
"Condition": {}
}
]
}
CORS:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Текущий инициализатор: carrier_wave.rb
if Rails.env.production?
CarrierWave.configure do |config|
config.fog_credentials = {
# Configuration for Amazon S3
:provider => 'AWS',
:aws_access_key_id => ENV['S3_ACCESS_KEY'],
:aws_secret_access_key => ENV['S3_SECRET_KEY'],
:region => ENV['S3_REGION']
}
config.fog_directory = ENV['S3_BUCKET']
end
end
picture_uploader.rb
class PictureUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
process resize_to_limit: [400, 400]
if Rails.env.production?
storage :fog
else
storage :file
end
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Add a white list of extensions which are allowed to be uploaded.
def extension_whitelist
%w(jpg jpeg gif png)
end
end