私が個人開発で開発しているJavaアプリでは、S3からファイルをダウンロードする処理があります。
その処理がある日いきなりAWSの認証が通らずにエラーになり始めました。
問題は解決できたんですが、正直なところ、原因はよく分かっていません。
エンジニア失格や……。
ただ、学びが色々あったので共有です。
エラーは以下です。
バケットポリシーか、IAMユーザの許可ポリシーらへんでDENYが指定されていてアクセスできていないっぽい感じのエラー内容です。
改めてAWSの設定を見直してみましたがそんな設定はしていません。
てか、それまでは普通にアクセスできていましたし、設定の変更はしていません。
うーん…。なんだろう
結論から言うと、IAMユーザを作成し直したら認証が通るようになりました。
元々使用していたユーザと同じく、IAMユーザの許可ポリシーは同じもの(AmazonS3FullAccess)を指定していますし、なんで認証が通るようになったのか謎です。
一応、元々使用していたユーザでアクセスキーを再生成してみたり、バケットポリシーをより明示的に許可するように修正したり、CloudFront経由でアクセスしてるのでそのキャッシュを削除して見たり、色々考え付くことはすべて試したんですが、全部無意味で、なんかユーザ再作成でいけちゃいました。
これはAWSを本腰入れて学習すれば原因が分かるものなのだろうか?
AWS SDK for javaのMaven依存関係のバージョンを上げてSpring Bootを起動させたら、以下のログが出ていました。
1.x系はもう古いのかよ!!
2.xで実装し直しました。
Mavenは以下です。パッケージも変わっています。
https://mvnrepository.com/artifact/software.amazon.awssdk/s3/2.28.19
以下のURLを参考に書けば結構いけます。
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
https://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/java_s3_code_examples.html
Objectを扱うRequestにはkey()というメソッドがありますが、ここにはS3上の”パス”を指定するようです。
(ディレクトリの概念がありそうでないS3の場合、パスという表現は不適切なんだろうけど、まぁこっちの方が伝わるだろう…。)
PutObjectRequest putObj = PutObjectRequest.builder() .bucket(bucketName) .key(objectKey) // バケット上のファイルまでの"パス"を指定 .build();
トークン修正してコミットしようとしたときGit君に
「え…君、シークレットアクセストークンコミットしようとしてる?それは流石にやばいて。やろうとしてることの意味理解しとるん???」
と言われて気が付きました。
プロジェクトを非公開にしていたとはいえ、GitHub上でシークレットアクセストークンを管理するのはやばい…。
個人開発かつprivateとはいえ流石に良くない。
Springのapplication.ymlに環境変数のキー名を書き、シークレットアクセストークンは環境変数で管理するように修正しました。
多分これが一番分かりやすいパターン。