S3互換Objest Storageを使っている場合、SDK for Java 2.xを2.30.0以上にversion upする時は要注意
TL;DR
S3には次のようなData Integrity Protectionsの仕組みがあります。
この仕組みが、SDK for Java 2.xの2.30.0
より自動で有効化されるようになりました。
もしも使っているS3互換Object Storageがコレに対応していない場合、Object Storageへのリクエストがエラーとなる可能性があります。
(testをちゃんと書いていれば気付けると思いますが、少し注意してversion upするといいでしょう)
遭遇した場合は次のような設定をしましょう。
// sync clientの場合
S3Client
.builder()
// ...
.requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) // これ
.responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED) // これ
// ...
.build()
// async clientの場合
S3AsyncClient
.builder()
// ...
.requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) // これ
.responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED) // これ
// ...
.build()
きっかけ
software.amazon.awssdk:s3
を2.30.0
以上にあげたところ、社内で使用しているS3互換Object Storageで以下のようなエラーが発生するようになりました。
(Service: S3, Status Code: 400, Request ID: MASKED...)
software.amazon.awssdk.services.s3.model.S3Exception: (Service: S3, Status Code: 400, Request ID: MASKED...)
at software.amazon.awssdk.protocols.xml.internal.unmarshall.AwsXmlPredicatedResponseHandler.handleErrorResponse(AwsXmlPredicatedResponseHandler.java:155)
...
原因
S3には次のようなData Integrity Protectionsの仕組みがあります。
ざっくりという仕組みを解説すると、
- S3へuploadするときにコンテンツのchecksumを計算し、コンテンツと一緒にchecksumもuploadします
- S3 server側にて送信されたコンテンツのchecksum検証をします
- S3からコンテンツをdownloadするときに、コンテンツと一緒にchecksumもdownloadします
- SDK側で受信したコンテンツのchecksum検証をします
(もともと、upload時にContent-MD5ヘッダーを指定することでデータ完全性の確認をする機能もありましたが、これの上位互換的なものでしょうか。downloadでもデータ完全性の確認ができるようになったのは便利ですね)
この仕組みが、2.30.0より自動で有効化されるようになりました。
が、自分が使っているS3互換Object Storageでは対応されていなかったため、エラーが発生するようになってしまったというわけです。
自分の場合はtestですぐに気付けていたのですが、マイナーバージョンしか変わっていないため、油断してしまう人も多いのかなと思います。
各S3互換Object Storageの対応状況
ちゃんと調べたかったけど、諦めました!
雑にo1 pro mode & Deep Searchに調べさせた結果だと、MinIOは対応しているが、他のものは対応していないそう。
この仕組みが導入されたのが2022年2月と比較的新しい(といっても3年前)ため、あまり対応はされていないでしょうね。
余談
SDK for Java 1.xでは未だにこの機能に対応していないため、こういった問題には遭遇しません。が、今年中にEOLを迎えるので、まだ2.x系に移行できていない人はあげておきましょう。
Discussion