Rails アプリを Heroku にデプロイし、画像アップロードを AWS S3 で行おうとした際に、以下の2つのエラーに悩まされました。
① SSL 認証エラー(CA 情報が無くて弾かれる)
② S3 に画像をアップロードできないエラー
本記事では、実際に遭遇したエラー内容と、その原因・解決方法をまとめます。
同じ問題でつまづいた方の助けになれば幸いです。
1. SSL 認証エラー(CA 情報がない)
● 発生したエラー
Heroku 上で Rails アプリから S3 へアクセスしようとした際、以下のような SSL 認証エラーが発生。
SSL_connect returned=1 errno=0 state=error: certificate verify failed
● 原因
Heroku 上の Ruby(もしくは AWS SDK)が 正しい CA 情報(認証局情報)を参照できていなかった ことが原因でした。
S3 と HTTPS 通信を行う時は、
「このサーバーは本物の AWS ですよ」
と証明するための CA 証明書 が必要です。
しかし、SDK の設定に必要な情報が足りなかったため、SSL 検証で弾かれていました。
● 解決方法
aws-sdk-s3 の設定に 明示的に証明書情報を指定 することで解決。
例(config/initializers/aws.rb 等):
Aws.config.update(
region: 'ap-northeast-1',
credentials: Aws::Credentials.new(
ENV['AWS_ACCESS_KEY_ID'],
ENV['AWS_SECRET_ACCESS_KEY']
)
)
必要な情報を正しく設定することで、S3 への HTTPS 接続が正常に通るようになりました。
2 画像アップロードができない(S3 側のアクセス権エラー)
Heroku ではアプリ内にファイル保存できないため、Active Storage を使って S3 にアップロードします。
しかし、画像をアップロードしようとすると 500 エラー になり、ログに次のような権限エラーが出ました。
Access Denied
● 原因
AWS S3 の ブロックパブリックアクセス設定が強すぎる 状態になっていました。
S3 の初期設定ではセキュリティのため、バケットポリシーでの公開をほとんど拒否しています。
そのため、Rails アプリが署名付き URL を使ってアップロードしようとしても弾かれていました。
● 解決方法(合計 2 ステップ)
① S3 のパブリックアクセス設定を変更
以下の項目を OFF にしました:
「新規のパブリックバケットポリシーをブロック」
(必要に応じて)「パブリックアクセスをブロック(バケット設定)」の一部
これでバケットポリシーが適用できるようになります。
② バケットポリシーを適切に設定
以下の JSON を適用することで、Rails(IAM ユーザー)からのアップロードが許可されました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "statement1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<あなたのAWS12桁のID>:user/<あなたのIAMユーザー名>"
},
"Action": "*",
"Resource": "arn:aws:s3:::<あなたのバケット名>/*"
}
]
}
これにより、IAM ユーザー(Rails アプリからアクセスするためのユーザー)に
S3 バケット内のファイル操作権限が与えられ、画像アップロードが成功しました。
まとめ
今回のトラブルは次の2点が原因でした。
エラー 原因 解決方法
SSL 認証エラー CA 情報が不足し、HTTPS 検証で失敗 AWS SDK の設定を正しく行い、証明書を認識させる
S3 アップロード不可 パブリックアクセス設定が厳しすぎる/ポリシーが適用されない S3 のブロック設定を調整し、適切なバケットポリシーを設定
同じように Heroku × Rails × S3 でハマっている方の参考になれば嬉しいです。
参考サイト