S3互換ストレージでアップロードが失敗するときの対処法
起きたこと
AWS CLI v2でmdxのオブジェクトストレージにファイルをアップロードしようとしたところ、以下のエラーが発生しました。
An error occurred (InvalidArgument) when calling the PutObject operation:
x-amz-content-sha256 must be UNSIGNED-PAYLOAD,
STREAMING-AWS4-HMAC-SHA256-PAYLOAD, or a valid sha256 value.
小さいファイルでも大きいファイルでも同様に失敗します。
原因
AWS CLI v2は、アップロード時にファイルの内容からSHA256ハッシュを計算し、x-amz-content-sha256 というリクエストヘッダーに含めて送信します。これはデータの改ざん検知のための仕組みです。
【AWS本家のS3】
AWS CLI → 「x-amz-content-sha256: abc123def456...」 → OK(受け付ける)
【S3互換ストレージ(一部の実装)】
AWS CLI → 「x-amz-content-sha256: abc123def456...」 → エラー(拒否される)
S3互換ストレージの中には、このヘッダーの値として UNSIGNED-PAYLOAD や STREAMING-AWS4-HMAC-SHA256-PAYLOAD といった定数のみを受け付け、実際のハッシュ値を受け付けない実装があります。
これはS3の仕様上はどちらも正しい動作ですが、互換性のギャップがエラーを引き起こしています。
対処法
環境変数を2つ設定するだけで解決します。
export AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
export AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED
この設定により、AWS CLIはチェックサムの計算と検証を「必須の場合のみ」に制限します。結果として、S3互換ストレージが受け付けない形式のハッシュ値が送信されなくなります。
使用例
# 環境変数を設定してアップロード
AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED \
AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED \
aws s3 cp ./myfile.tif s3://my-bucket/path/to/myfile.tif \
--endpoint-url https://s3ds.mdx.jp
恒久的に設定する場合
~/.aws/config に以下を追加します。
[default]
request_checksum_calculation = when_required
response_checksum_validation = when_required
ただし、AWS本家のS3も使う場合はプロファイルを分けることをお勧めします。
[default]
# AWS本家用(デフォルト)
[profile mdx]
request_checksum_calculation = when_required
response_checksum_validation = when_required
# プロファイルを指定して使う
aws s3 cp ./myfile.tif s3://my-bucket/path/ \
--endpoint-url https://s3ds.mdx.jp \
--profile mdx
補足:マルチパートアップロードでも同じ問題が起きる
大きなファイル(デフォルトで8MB以上)をアップロードすると、AWS CLIは自動的にマルチパートアップロードに切り替えます。この場合、各パートごとに x-amz-content-sha256 が送信されるため、UploadPart のタイミングでも同じエラーが発生します。
multipart_threshold を大きく設定してマルチパートを回避する方法もありますが、根本原因はチェックサムの形式なので、上記の環境変数による対処が最もシンプルです。
影響を受けるストレージ
今回はmdxのオブジェクトストレージ(s3ds.mdx.jp)で発生しましたが、S3互換を謳うストレージ全般で起こりえます。以下は一例です。
- mdxのオブジェクトストレージ
- 一部バージョンのMinIO
- Ceph Object Gateway(RGW)の設定による
AWS本家のS3では発生しません。