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-PAYLOADSTREAMING-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では発生しません。