【AWS中級へのステップ】 SSE-KMS で暗号化された S3 へのクロスアカウントアクセス 2 選
はじめに
猫とアポロチョコとSystems Managerが好きな m.hayakawa です。
本記事は、AWS サービスの基本設計には慣れてきたものの、「この構成で問題ないのか」「より良い設計方法はないのか」といった実務的な課題に直面している方向けの内容となります。
AWS 初学者が中級者へとステップアップするために押さえておきたい実践的な知識や TIPS のひとつを紹介し、初学者の方が知識をより深めるため、またベテランの方が知識を再確認するための一助となることを目指しています。
以前、「ACL 無効化時代の S3 へのクロスアカウントアクセス 2 選」という記事を書きました。
前回は暗号化を考慮しないシンプルなケースを扱いましたが、実際の運用では S3 バケットが SSE-KMS で暗号化されていることが多いです。SSE-KMS が絡むと、S3 のアクセス制御に加えて KMS キーポリシーの設定が必要になります。
本記事では、SSE-KMS(カスタマーマネージドキー)で暗号化された S3 バケットへのクロスアカウントアクセスについて、前回記事と同じ 2 パターンの方法で必要なポリシー設定を解説します。
前知識: SSE-KMS 暗号化とクロスアカウントアクセスの関係
S3 サーバーサイド暗号化の選択肢
S3 のサーバーサイド暗号化は、実用上以下の 3 パターンが検討対象となります。
| 暗号化方式 | キー管理 | クロスアカウント共有 |
|---|---|---|
| SSE-S3 | AWS が完全管理 | 可能(透過的) |
SSE-KMS(AWS マネージドキー aws/s3) |
AWS が管理(キーポリシー変更不可) | 不可 |
| SSE-KMS(カスタマーマネージドキー) | ユーザーが管理(キーポリシー編集可) | 可能 |
SSE-KMS(AWS マネージドキー)で暗号化されたオブジェクトは、キーポリシーを変更できないため、クロスアカウントで共有できません。クロスアカウントアクセスが必要で、かつ暗号化に対して監査証跡やアクセス制御などの要件がある場合は、SSE-KMS(カスタマーマネージドキー)を使用します。
なお、AWS マネージドキーは 2021 年以降、新しい AWS サービスでは作成されなくなったレガシーキータイプです。S3 の新しいバケットタイプ(Directory Buckets、Table Buckets)でもサポートされていません。新規設計においては、SSE-S3 または SSE-KMS(カスタマーマネージドキー)のいずれかを選択することが一般的です。
KMS キー指定時はフル ARN を使用する
KMS キーを指定する際にエイリアス(例: alias/my-key)を使用すると、リクエスターのアカウント内でエイリアスが解決されます。その結果、バケット所有者ではなくリクエスターに属するキーで暗号化される可能性があります。クロスアカウントでは、フル ARN(arn:aws:kms:ap-northeast-1:123456789012:key/xxxx-xxxx-xxxx)の使用が推奨されます。
S3 操作に必要な KMS アクション
SSE-KMS で暗号化されたオブジェクトに対して S3 操作を行う場合、以下の KMS アクションが必要です。
| S3 操作 | 必要な KMS アクション |
|---|---|
| オブジェクトのアップロード (PutObject) | kms:GenerateDataKey |
| オブジェクトのダウンロード (GetObject) | kms:Decrypt |
| マルチパートアップロード | kms:GenerateDataKey, kms:Decrypt |
同一アカウントとクロスアカウントの評価論理の違い
前回記事でも触れましたが、S3 のアクセス可否は、バケットポリシーと IAM ポリシーの評価論理によって決まります。同一アカウントとクロスアカウントで論理が異なります。
同一アカウントでのアクセスの場合、バケットポリシーと IAM ポリシーのいずれかで許可されていればアクセスできます(明示的な拒否がある場合を除く)。
| バケットポリシー | IAMポリシー | 結果 |
|---|---|---|
| 指定なし | 指定なし | 失敗 |
| 許可 | 指定なし | 成功 |
| 指定なし | 許可 | 成功 |
| 許可 | 許可 | 成功 |
| 明示的な拒否 | 許可 | 失敗 |
| 許可 | 明示的な拒否 | 失敗 |
| 明示的な拒否 | 明示的な拒否 | 失敗 |
クロスアカウントアクセスの場合は、バケットポリシーと IAM ポリシーの両方で許可されている必要があります。
| バケットポリシー | IAMポリシー | 結果 |
|---|---|---|
| 指定なし | 指定なし | 失敗 |
| 許可 | 指定なし | 失敗 |
| 指定なし | 許可 | 失敗 |
| 許可 | 許可 | 成功 |
| 明示的な拒否 | 許可 | 失敗 |
| 許可 | 明示的な拒否 | 失敗 |
| 明示的な拒否 | 明示的な拒否 | 失敗 |
ここまでの S3 側の評価論理は、暗号化方式に依存しません。SSE-S3(Amazon S3 マネージドキー)で暗号化されたバケットの場合も、同じ評価論理でアクセス可否が決まります。SSE-S3 はキーの指定やキーポリシーが不要で、S3 へのアクセス権限があれば透過的に復号されるためです。
SSE-KMS が絡む場合は、上記の S3 側の評価に加えて、KMS キーへのアクセス制御も考慮する必要があります。ここで、KMS キーポリシーと IAM ポリシーの関係を再度整理してみましょう。
KMS キーへのアクセスを IAM ポリシーで制御するには、前提としてキーポリシー側で「このアカウントの IAM ポリシーを有効にする」設定が必要です。この設定がないと、IAM ポリシーでいくら許可してもキーは使えません。
この「IAM ポリシーの使用をアカウントに許可する」役割を担うのが、デフォルトのキーポリシーに含まれる次のステートメントです。
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AccountId>:root"
},
"Action": "kms:*",
"Resource": "*"
}
Principal はアカウントの root(arn:aws:iam::<AccountId>:root)を指しています。これは root ユーザー個人に権限を与えるものではなく、そのアカウントの IAM ポリシーによってキーへのアクセスを制御することを許可するものです。
なお、キーポリシーが root へのアクセスを許可していても、それだけでは個々のプリンシパルにキーの使用権限が付与されるわけではありません。実際にキーを使用するには、アクセス元の IAM ポリシーでキーへのアクセス許可(kms:Decrypt など)を付与する必要があります。
以上が KMS キーへのアクセス制御の基本です。この前提を踏まえ、具体的にどのポリシーをどう設定するかは、次章以降のパターン1・パターン2 で解説します。
前提
登場するリソースは下記とします。
- アクセス元のアカウント A:
111111111111 - アクセス先のアカウント B:
222222222222 - アカウント B(アクセス先)の S3 バケット S(SSE-KMS で暗号化、カスタマーマネージドキー使用)
- アカウント B(アクセス先)の KMS キー:
arn:aws:kms:ap-northeast-1:222222222222:key/key-id-xxxx - アカウント A(アクセス元)の IAM ユーザー X
- アカウント B(アクセス先)の IAM ロール Z
パターン1. S3 が存在するアカウントの IAM ロールにスイッチする
具体的な方法
アクセス元の IAM ユーザー X から、アクセス先の IAM ロール Z にスイッチロールをし、IAM ロール Z の認証情報を用いてアクセスすることで、最終的にクロスアカウントでのアクセスを実現します。

各リソースは下記のように設定します。
アクセス元 IAM ユーザー X のアクセス許可ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/RoleZ"
}
]
}
アクセス先 IAM ロール Z の信頼ポリシー(アクセス許可ポリシーではありません。)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/UserX"
},
"Action": "sts:AssumeRole"
}
]
}
アクセス先 IAM ロール Z のアクセス許可ポリシー
スイッチロール後は同一アカウント内のアクセスとなるため、IAM ポリシーで S3 アクションと KMS アクションの両方を許可します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Access",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket-s",
"arn:aws:s3:::bucket-s/*"
]
},
{
"Sid": "AllowKMSAccess",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:ap-northeast-1:222222222222:key/key-id-xxxx"
}
]
}
なお、この場合、アカウント B(アクセス先)の S3 バケット S とアカウント B(アクセス先)の IAM ロール Z は同一アカウントに存在するという扱いになるため、S3 バケット S のバケットポリシーと、IAM ロール Z の許可ポリシーの内、どちらかが許可されていればアクセス可能になります。つまり、バケットポリシーの変更は不要です。
同様に、KMS キーポリシーについても、デフォルトのキーポリシーで以下のステートメントが含まれていれば、IAM ポリシーへの委任が有効となり、KMS キーポリシーの追加変更は不要です。
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::222222222222:root"
},
"Action": "kms:*",
"Resource": "*"
}
利点
この方法の利点としては、クロスアカウントアクセスをはく奪したい場合、または、特定の期間のみアクセスさせたいなどの用途が、比較的に容易にできる点です。さらに SSE-KMS が絡む場合でも、KMS キーポリシーやバケットポリシーの変更が不要であるため、管理対象が少なく済みます。
クロスアカウントアクセスをはく奪したい場合
IAM ロールの信頼関係を編集するのみで済みます。実際には記述を削除すればOKですが、あえて明示的に拒否する場合は下記のように記述します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/UserX"
},
"Action": "sts:AssumeRole"
}
]
}
KMS キーポリシーやバケットポリシーの変更は一切不要です。信頼ポリシーの 1 箇所のみで制御が完結します。
特定の期間のみアクセスさせたい
IAM ロールの信頼関係で、Condition 要素を使用して特定の期間のみスイッチロールを許可しています。この期間外ではスイッチロールが拒否されます。
例:2026年1月1日0時(UTC)から2026年2月1日0時(UTC)のみ許可する場合
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/UserX"
},
"Action": "sts:AssumeRole",
"Condition": {
"DateGreaterThan": {
"aws:CurrentTime": "2026-01-01T00:00:00Z"
},
"DateLessThan": {
"aws:CurrentTime": "2026-02-01T00:00:00Z"
}
}
}
]
}
上記のように、アクセス先 IAM ロール Z の設定のみを変えればいいため、作業量が少なく、また、何か問題が発生した場合のロールバックも容易となります。
パターン2. バケットポリシー+KMS キーポリシーで他アカウントからのアクセスを許可する
具体的な方法
アクセス先アカウント B の S3 バケットポリシーおよび KMS キーポリシーを編集して、アクセス元の IAM ユーザー X からのアクセスを明示的に許可するという方法です。(加えて、アクセス元の IAM ユーザー X 自身も S3 バケットおよび KMS キーへのアクセスを許可する必要があります)

各リソースは下記のように設定します。
アクセス先 S3 バケット S のバケットポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/UserX"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::bucket-s/*"
},
{
"Sid": "AllowCrossAccountListBucket",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/UserX"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::bucket-s"
}
]
}
アクセス先 KMS キーのキーポリシー
KMS キーポリシーに、アクセス元アカウントの IAM ユーザー X を許可するステートメントを追加します。
{
"Sid": "AllowCrossAccountKMSAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:user/UserX"
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "*"
}
KMS キーポリシーの Resource は "*" と記述します。これはキーポリシーが特定のキーに紐づいているため、"*" はそのキー自身を指します。
アクセス元 IAM ユーザー X のアクセス許可ポリシー
アクセス元の IAM ユーザー X にも S3 バケットおよび KMS キーへのアクセスを許可する IAM ポリシーを付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowS3Access",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket-s",
"arn:aws:s3:::bucket-s/*"
]
},
{
"Sid": "AllowKMSAccess",
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:ap-northeast-1:222222222222:key/key-id-xxxx"
}
]
}
この方法はスイッチロールをしないので、一見楽なように見えますが、下記の点に注意する必要があります。
- アクセス先のアカウント B の S3 バケットに対して、バケットポリシーの編集が必要
- アクセス先のアカウント B の KMS キーに対して、キーポリシーの編集が必要
- アクセス元のアカウント A の IAM ユーザーに対して、S3 バケットおよび KMS キーへのアクセス許可が必要
上記が何を意味するかというと、クロスアカウントでのアクセスを中止させたいときにも同様の操作が必要ということです。
例えば、S3 バケットが 10 個あり、それぞれ異なるカスタマーマネージドキーで暗号化されていたらどうでしょうか。対象の S3 バケット 10 個分のバケットポリシーに加えて、10 個分の KMS キーポリシーについて、クロスアカウントでのアクセスができないように編集しなおす必要があります。
アクセスのはく奪自体は、キーポリシーから該当のステートメントを削除すれば実現できます。ただし、キーポリシーの編集には注意が必要です。キーポリシーは、他アカウントへの許可ステートメントだけでなく、Enable IAM User Permissions ステートメントも含んでいます。編集を誤ってこのステートメントまで削除してしまうと、そのキーの管理ができなくなる恐れがあります。編集対象のキーポリシーが増えるほど、こうした操作ミスのリスクも高まります。
作業の抜け漏れが発生する可能性や、権限付与やはく奪を簡便にするといった要件から、通常の場合は「パターン1. S3が存在するアカウントのIAMロールにスイッチする」が推奨されます。
パターン2 が考えられるケース
パターン2 が採用されるケースとしては、少ないですが下記が考えられます。
- アカウント A(アクセス元)の IAM ユーザー X にスイッチロールを可能とする権限を付けたくない。
- アカウント B(アクセス先)の IAM ロール Z に外部アカウントからスイッチさせたくない。
- アクセス対象のバケットと KMS キーが少数に限定されており、管理負荷が許容範囲内である。
2 つのパターンで必要な設定の比較
ここまで解説した内容を、KMS キーへのアクセス制御の観点で整理します。パターン1 はスイッチロール後にアクセス先アカウント内でのアクセスとなるため「同一アカウント」、パターン2 は「クロスアカウント」に相当します。
前知識で述べたとおり、アクセス元の IAM ポリシーでキーへのアクセス許可が必要な点は両パターンで共通です。違いは KMS キーポリシー側にあります。
| パターン | KMS キーポリシー | アクセス元 IAM ポリシー |
|---|---|---|
| パターン1(スイッチロール後 = 同一アカウント) | 「IAM ポリシーの使用をアカウントに許可する」設定のみでよい(アクセス元プリンシパルの個別指定は不要) | キーへのアクセス許可が必要 |
| パターン2(クロスアカウント) | アクセス元のプリンシパルを明示的に許可する必要がある | キーへのアクセス許可が必要 |
パターン1 では、スイッチロール後はアクセス先アカウント内のアクセスとなるため、デフォルトのキーポリシー(Enable IAM User Permissions による IAM ポリシーの使用許可)のままで、IAM ロール Z の IAM ポリシー側でキーへのアクセスを制御できます。一方、パターン2 では、アクセス先のキーポリシーにアクセス元プリンシパルを明示的に許可するステートメントを追加する必要があります。これが、パターン2 でアクセス先のキーポリシー編集が必須となる理由です。
まとめ
SSE-KMS(カスタマーマネージドキー)で暗号化された S3 バケットへのクロスアカウントアクセスについて、2 パターンを紹介しました。
SSE-KMS が絡む場合、パターン2 ではバケットポリシーに加えて KMS キーポリシーの管理も必要になるため、前回記事(暗号化なし)と比較して管理対象が増加します。一方、パターン1 ではスイッチロール後は同一アカウント内のアクセスとなるため、KMS キーポリシーやバケットポリシーの追加変更が不要であり、管理がシンプルに保てます。
それぞれの特徴を捉えて、要件に沿った方法を選択ください。
参考資料
- IAM ポリシーの使用 - AWS KMS Developer Guide
- Using server-side encryption with AWS KMS keys (SSE-KMS) - Amazon S3 User Guide
- AWS KMS キーによるサーバー側の暗号化 (SSE-KMS) の使用 - Amazon Simple Storage Service
- AWS KMS keys - AWS Key Management Service
- 他のアカウントのユーザーに KMS キーの使用を許可する - AWS Key Management Service
- Amazon S3 バケット向けのサーバー側のデフォルトの暗号化動作の設定 - Amazon Simple Storage Service
- カスタマーマネージドキーで暗号化されたS3オブジェクトにクロスアカウントアクセスする方法
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AI をフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。※2026 年 1 月 アノテーション㈱から社名変更しました







