【rails】S3でheroku上で画像保存しようとしたらエラー大量発生【Access denied】


##Heroku上の投稿サイトで画像が表示されない

画像を投稿するとこんな感じになります。
文字列の羅列みたいになってますね・・・
![スクリーンショット (156).png](https://qiita-image-store.s3.amazonaws.com/0/256858/b4bc5c9c-1c7a-25c0-2b6b-996e388ab6da.png)


##解決方法
ざっくりと解決方法と書きましたが、解決に至るまでにたくさんのエラーが出たため、以下にすべて記載してみました。
まずは、本番環境の保存先であるS3バケットの作成からでした。

###AWS S3でバケットを作成する
参考にしたサイト[RailsアプリをHerokuにデプロイ後、画像アップロードをAWS S3＋carriewaveで設定する方法](https://rails-school.net/heroku-aws/)

こちらのサイトがとてもわかりやすかったので、AWSでのS3のバケット作成などは、記載のとおりに進めました。


↓carrierwave.rbファイルはこちら

```rb

#carrierwave.rb

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

if Rails.env.production?
CarrierWave.configure do |config|
  config.cache_dir = "#{Rails.root}/tmp/uploads"
  config.fog_provider = 'fog/aws'
  config.fog_credentials = {
    
    provider: 'AWS',
    region:  ENV['S3_REGION'],
    aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
    
  }
  config.fog_directory  = ENV['S3_BUCKET']
end
end
```



heroku内での環境変数設定も忘れずに。以下のように設定することで、githubなどの一般公開するページに乗せた際にAWSのキーが漏洩するのを防げます。漏洩した場合、ものすごい金額の請求が来た例もあります。ネットで検索するといくつかでてきます。
なので、キーの設定は環境変数で設定しましょう。

```rb
heroku config:set AWS_ACCESS_KEY_ID=自分のアクセスキーID
heroku config:set AWS_SECRET_ACCESS_KEY=自分のシークレットアクセスキー
heroku config:set S3_BUCKET=自分のバケット
heroku config:set S3_REGION=ap-northeast-1
```

設定完了です。


##herokuにデプロイ後、「We're sorry, but something went wrong.」が発生した。

よし、herokuにデプロイし、本番環境でアプリを開き、投稿しようとすると、We're sorry, but something went wrong.が発生しました。
おなじみの画面。
![スクリーンショット (197).png](https://qiita-image-store.s3.amazonaws.com/0/256858/68a7a021-e1d3-25f1-b358-9009a02073b6.png)


##エラー１　「リージョンが違うよ」


こちら[[Ruby on Rails Tutorial]Herokuにデプロイ後Application error[H10 (App crashed)]が発生した時の対処法](https://qiita.com/masarusan24/items/77d064147a32169b5449)のサイトを参考に、原因を探ってみます。

heroku logsを実行してみる。

```rb
（略）
The authorization header is malformed; the region 'us-east-1' is wrong; expecting 'ap-northeast-1'
（略）
```

前後省略してみましたが、おそらくこれが原因っぽいですね。。。

##ユーザーを作り直してみた

[【Rails】S3へ『CarrierWave+fog』を使って画像アップロードする方法](http://vdeep.net/rubyonrails-carrierwave-s3)
とりあえず何してもだめだったので、こちらのサイトを参考にバケット、ユーザー、グループの作成を最初からやり直しました。





###気づき１　IAMユーザーでAWSにログインしていなかった
ルートーユーザーでサインインをしており、通常のコンソール上でS3バケットを作成していました。
仕組みについてはよく理解していないのですが、上記のサイトに従えば問題ないかと思います。


###気づき２（そもそもの管理リージョンが違うからおかしい？）
https://s3.console.aws.amazon.com/s3/home?region=ap-southeast-1#

southeast（シンガポール）でやっているから？

バケットはnorth（東京）でやったほうがいいよ！とほかのブログでもおすすめされているのですが、cloud9はnorth（東京）をカバーしていないはず。。。なので、ルートユーザーでは、そのままsoutheastでやり、**IAMユーザーのマネジメントコンソールは右上のリージョンがシンガポールになっていたのでそれを東京に修正しました。**
すると、同じエラーはでなくなりました。しかしさらなるエラーが…

##エラー２　「AWSキーが合わない」
やりなおしてもう一度herokuをデプロイし、画像を投稿しようとすると次はこのエラー。

```rb
#ターミナルでheroku logsを実行した結果

The request signature we calculated does not match the signature you provided. Check your key and signing method.

```

ひいい次はキーが合わないと言われている・・・
どうすりゃいいんだ・・・
とその時、気づきました・・・


###エラー２の解決法　単純にキーの入力ミス
ユーザーを作成したときに、AWSIDとシークレットキーをエクセルファイルのcsvファイルでダウンロードできるのですが、私のパソコンがなぜかソフトのライセンス認証がいろいろあってとれていなくて、ファイルダウンロードしましたが、目で確認してherokuの環境変数に入力したのですね。
それでエクセルファイルに入力したときに、小文字のlと大文字のIを区別をミスってて、キーの入力間違いがあった可能性が考えられます・・なんとも恥ずかしいミス。


##エラー３　「S3へのアクセスが拒否されました」

heroku logsをしてみると、キーが間違っているとは表示されなくなりましたが、その代わり別のエラーが・・・今回のタイトルにあるAccessdeniedです。

```rb
Excon::Error::Forbidden (Expected(200) <=> Actual(403 Forbidden)
2018-12-15T12:25:43.790917+00:00 app[web.1]: excon.error.response
2018-12-15T12:25:43.790923+00:00 app[web.1]: :body          => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>D88521220601A84D</RequestId><HostId>01z1R4aggIKUOnx2mjTE+3mqZYYhIY38Ehm2dkwl1SL5Zdf4tOQhUQLs4pWIDZc5+IUYoI17Ji0=</HostId></Error>"
```

###エラー３の解決先
[エラー<Message>Access Denied</Message> 〜Rails + Carrierwave + HerokuでAWS S3に画像を保存〜](https://qiita.com/yukiyukimiyaiwa/items/a9e0103c8342b81f6ac1)
teratailに質問を投稿したところ、この記事を参考にしましたとのコメントをいただきました。
この記事によると、私とちょうど同じ時期に全く同じエラーで悩まれていたとのこと、この方はご自分でいろいろと検索をされて解決されたとのこと。すごい！AWSがちょうどこの時期に新しい機能を追加していたのですね。。。それはいくら探してもみつからないはずだ・・・

>heroku logsで見てみると<Message>Access Denied</Message>の文字が...
ここからはS3の新機能が働いてしまっているようです。
2018/11/15に発表されたパブリックアクセス設定機能のおかげでデフォルトでは管理者しかアクセスできず、IAMユーザーのアクセスがブロックされているという結論に至りました。


そんなこんなで私も同じようにやってみます。

まずはマネジメントコンソールからS3のページにいき、作成済のバケットを選択します。私はIAMユーザーでログインしてできましたが、ルートユーザーからS3編集しても問題ないと思います。

####パブリックアクセス設定をデフォルトの状態から編集

以下のようにチェックボックスを設定してください。
![スクリーンショット (308).png](https://qiita-image-store.s3.amazonaws.com/0/256858/a3395d55-5e81-9ada-8baf-5e21f8a5bbaa.png)

結果、このように表示されます。
![スクリーンショット (309).png](https://qiita-image-store.s3.amazonaws.com/0/256858/36d18227-4fc3-d267-4ba0-066513eb4d98.png)

####バケットポリシーを編集する

![スクリーンショット (310).png](https://qiita-image-store.s3.amazonaws.com/0/256858/487b735a-84dd-7bb1-4022-539807fc4457.png)


次に上の画像のとおりにバケットポリシーをクリックし、バケットポリシーエディタを開きます。以下のように入力します。


```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "statement1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<あなたのAWS１２桁のID>:user/<あなたのIAMユーザー名>"
            },
            "Action": "*",
            "Resource": "arn:aws:s3:::<あなたのバケット名>/*"
        }
    ]
}
```

<>は入力する必要はなし。自分のIDと数字をそのまま入力します。

結果、、本番環境でできたああああ！！

![スクリーンショット (311).png](https://qiita-image-store.s3.amazonaws.com/0/256858/6ea6aa99-c161-0065-2bd8-55655a85ea7b.png)




##まとめ　S3難しい・エラーがでないためのポイントまとめ
確認することは以下の点かと思われます。

１　環境変数が誤っていないか？コマンドにheroku configと打ち入力ミスがないか確認する。
２　バケットのリージョンとIAMユーザーのリージョンが一致しているか
３　IAMユーザーにS3FullAccessのポリシーがアタッチされているか
４　S3のバケットポリシーを編集しているか

間違っていたらご指導・ご指摘よろしくお願いします。



##その他参考サイト
[Herokuで本番環境のファイルの保存先をS3に設定する手順](https://kossy-web-engineer.hatenablog.com/entry/2018/11/11/141306)