S3のKMSキーを別のキーに変更する、UpdateObjectEncryptionでコピー不要になった

  • AWS
  • S3
  • KMS

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

S3にSSE-KMSで保存済みのオブジェクトを、別のKMSキーに切り替える必要があって調べた。結論から言うと、今は2つのやり方がある。

前提: 既存オブジェクトの暗号化キーは後から自動で変わらない

バケットのデフォルト暗号化設定を変更しても、既にアップロード済みのオブジェクトには影響しない。これは以前から変わっていない。新しいキーで暗号化し直したいなら、既存オブジェクト1つ1つに対して明示的な操作が必要になる。

方法1: aws s3 cp で自分自身に上書きコピーする(従来方式)

同じパスに対して cp を実行し、暗号化オプションだけ新しいキーを指定するとS3側で再暗号化される。

ターミナル
aws s3 cp s3://example-bucket/example-prefix/ s3://example-bucket/example-prefix/ \
--recursive \
--sse aws:kms \
--sse-kms-key-id arn:aws:kms:ap-northeast-1:111122223333:key/xxxxxxxx

ポイント:

  • --recursive はプレフィックス(フォルダ)配下をまとめて処理するためのオプション。単一オブジェクトだけ対象にするなら不要。
  • 実体としては「新しいオブジェクトとしてコピーし直す」動作なので、S3のリクエスト課金(コピー分)が発生する。バージョニング有効なバケットだと新しいバージョンが積み増しされる。
  • オブジェクト数が多いと単純に時間がかかる。数百万〜数十億単位なら S3 Batch Operations でジョブ化するのが現実的(S3 Inventoryからマニフェストを作って渡す)。

これは今でも使える方法だけど、「コピー」である以上データが動く。Glacierに入ってるオブジェクトだと復元(リストア)が絡んでくるし、Intelligent-Tieringだとティア移動が発生することもある。

方法2: UpdateObjectEncryption API(2026年2月〜)

2026年2月5日に UpdateObjectEncryption operationが追加された。データを動かさずに暗号化タイプ・KMSキーだけをその場で更新できる。

ターミナル
aws s3api update-object-encryption \
--bucket example-bucket \
--key example-object.png \
--object-encryption '{"SSEKMS": { "KMSKeyArn": "arn:aws:kms:ap-northeast-1:111122223333:key/yyyyyyyy", "BucketKeyEnabled": true }}'

cp 方式との違い:

  • データはコピーされない。Glacier Flexible Retrieval / Deep Archiveのオブジェクトでもリストア不要、Intelligent-Tieringのティアも動かない。
  • storage class、作成日時、ETag、チェックサムなどのメタデータプロパティはそのまま保持される。
  • 完了はミリ秒単位。オブジェクトサイズやストレージクラスに関係なく速い。
  • 課金はPUT/COPY/POST/LIST相当(リクエスト単価)で、常にS3 Standardクラスのリクエストとして課金される。

用途としては公式に「カスタマー管理KMSキーのローテーション対応」が明記されているので、まさに今回みたいなキー変更のためのAPIという位置づけ。SSE-S3 → SSE-KMSへの変更や、S3 Bucket Keyの後付け適用にも使える。

制限

  • 未暗号化オブジェクト、DSSE-KMS、SSE-Cで暗号化されたオブジェクトは対象外。
  • 新しい暗号化タイプとしてSSE-S3は指定できない(SSE-KMSへの変更専用)。
  • Object Lockのcompliance modeが付いているオブジェクトには使えない。governance modeなら一旦ロックを外せば可能。
  • KMSキーはフルARN指定が必須。エイリアスやキーIDだけでは受け付けない。
  • デフォルトではバケット所有アカウントが持つKMSキーのみ対象。Organizations配下の他アカウントのキーを使いたい場合はAWSサポートへの申請が必要。

必要な権限

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:UpdateObjectEncryption",
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:ReEncrypt*"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket/*",
"arn:aws:kms:ap-northeast-1:111122223333:key/yyyyyyyy"
]
}]
}

大量オブジェクトを一括で処理する場合

単発の update-object-encryption を1オブジェクトずつ叩くのは現実的じゃないので、大量にあるなら S3 Batch Operations 経由で UpdateObjectEncryption operationを実行する。S3 Inventoryのメタデータ(プレフィックス、storage class、作成日、暗号化タイプ、KMSキーARN、Bucket Key有無)を条件にオブジェクトリストを生成できるので、「特定の古いKMSキーで暗号化されてるオブジェクトだけ」みたいな絞り込みもできる。

まとめると

  • 2026年2月以前の環境や、SDK/CLIのバージョンが古くてupdate-object-encryptionが使えない場合は、aws s3 cpの再コピー方式一択。
  • 今から新規で組むならUpdateObjectEncryptionの方が速い・安い・メタデータも壊れない。既存のキーローテーション運用スクリプトがcpベースなら、移行を検討する価値はある。
  • どちらの方式でも、対象オブジェクトが多い場合はS3 Batch Operationsに寄せた方が進捗管理や完了レポートの面で楽。