S3
carrierwave
Rails4

[Rails4] CarrierWave 経由で AWS S3 に pdf をアップロード(ACCESS DENIED の対処)


対象者


  • いろんな記事を見て回って試しているけど、S3からACCESS DENIED がずっと返って来る。

  • 諦めたい

そんな人の助けになれば幸いです...!><


使ったもの


Gemfile

gem 'rails', '4.2.3'

# CarrierWave
gem 'carrierwave'
gem 'fog-aws'


Gemfile.lock

carrierwave (1.3.1)

...
fog-aws (3.4.0)

でした。


概要

ACCESS DENIED を解決するために行ったAWS S3設定画像を貼っているだけです←本当にこれだけ

ACCESS DENIED を解決するための方法として、AWS S3の設定をいじるのはやめました。

(推奨)マークがついているものは全てチェックを維持したままでも、CarrierWave側のconfigに1行追加すれば ACCESS DENIED を回避できました。

AWSの設定、S3の作成、carrierewaveの設定については、いろんな記事があって私が解説する必要もないので、私が使用した記事を掲載するにとどめます。


やり方


AWSの準備、S3バケットの作成

エラーAccess Denied 〜Rails + Carrierwave + HerokuでAWS S3に画像を保存〜


Railsコードの記述、CarrierWaveの設定

【Rails5】Carrierwave + Fog で AWS S3 に画像をアップロードする


参考(エラーの対処と、CarrierWaveの設定項目の解説)

【Rails】AWS S3へ画像のアップロードが出来た♪


実際に行った設定


config/initializers/carrierWave.rb

require 'carrierwave/storage/abstract'

require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
if Rails.env.production? || Rails.env.development? # 開発中もs3使う
config.storage :fog
config.fog_provider = 'fog/aws'
config.fog_directory = 'バケット名'
config.asset_host = 'https://s3.amazonaws.com/バケット名'
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: 'AWS_ACCESS_KEY_ID',
aws_secret_access_key: 'AWS_SECRET_ACCESS_KEY',
region: 'us-east-2',
# path_style: true
}
else
config.storage :file
config.enable_processing = false if Rails.env.test?
end
end



app/uploaders/hoge_uploders.rb

class HogeUploader < CarrierWave::Uploader::Base

storage :fog
def store_dir
"carrierwave-test-siruku6/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end


発生したエラー


log

Completed 500 Internal Server Error in 6490ms (ActiveRecord: 5.4ms)

Excon::Error::Forbidden (Expected(200) <=> Actual(403 Forbidden)
excon.error.response
:body => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>xxxxxxxx</RequestId><HostId>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</HostId></Error>"
:cookies => [
]
:headers => {
"Connection" => "close"
"Content-Type" => "application/xml"
"Date" => "Sat, 16 Mar 2019 17:05:27 GMT"
"Server" => "AmazonS3"
"x-amz-id-2" => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
"x-amz-request-id" => "xxxxxxxxxxxxxxxx"
}
:host => "バケット名.s3.us-east-2.amazonaws.com"
:local_address => "xxx.xxx.xxx.xxx"
:local_port => 44250
:path => "/xxxxxxxxxxxxxxx/uploads/xxxxxxxx/xxxxxxxxx/1/fx%E6%90%8D%E7%9B%8A.pdf"
:port => 443
:reason_phrase => "Forbidden"
:remote_ip => "xxx.xxx.xxx.xxx"
:status => 403
:status_line => "HTTP/1.1 403 Forbidden\r\n"
):
app/controllers/hoge_controller.rb:14:in `upload'


むぐぐ


やむを得ず行った変更(AWS S3)

image.png

1つチェックを外して設定を保存した

セキュリティが落ちるので、チェックを外すのはやめました。


代替策(設定変更)


config/initializers/carrierWave.rb

require 'carrierwave/storage/abstract'

require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
if Rails.env.production? || Rails.env.development? # 開発中もs3使う
config.storage :fog
config.fog_provider = 'fog/aws'
config.fog_directory = 'バケット名'
config.asset_host = 'https://s3.amazonaws.com/バケット名'
# NOTE: AWS側の設定を変えなくても、この1行の設定でアップロードできた
config.fog_public = false # ←コレ
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: 'AWS_ACCESS_KEY_ID',
aws_secret_access_key: 'AWS_SECRET_ACCESS_KEY',
region: 'us-east-2',
# path_style: true
}
else
config.storage :file
config.enable_processing = false if Rails.env.test?
end
end


これでアップロードできた!


参考にしたサイト

【Ruby on Rails】carrierwave-awsを使ってAWSのS3に画像をアップロードするときにAws::S3::Errors::AccessDeniedのエラー対処法

この人はチェック3つ外してるけど、一番上の1つだけでも動いたよ。


その他

stackoverflowにはこんなこと書かれてるけど、これは試してないです

Excon::Errors::Forbidden (Expected(200) <=> Actual(403 Forbidden)


考えたこと


  • 「パブリックオブジェクトのアップロードをブロックする」という設定が有効

  • config.fog_public = true または config.fog_public を設定していない

この2つの条件を両方満たすと、403エラーになるようだ。

fog_publicというのは、パブリックオブジェクトとしてアップロードするかどうかの設定だったみたい。