マルチアカウントの AWS 環境で Amazon S3 でファイル連携する場面を考えます。アカウント間の共通リソースをまとめる VPC を持つアカウント(便宜上「アカウント A」とします)に S3 のバケットを集約して作成し、アプリケーション VPC を持つ別のアカウント(「アカウント B」とします)からこの S3 バケットにアクセスさせたいと思います。
ここで、アカウント A の S3 バケットは機微な情報を含んでいるとし、バケット内のオブジェクトの暗号化は SSE-S3 でなく、暗号鍵のアクセス許可などを管理者が詳細にコントロールできるよう、SSE-KMS でカスタマーマネージドキーを使うこととします。
SSE-KMS のカスタマーマネージドキーで暗号化されたバケットへ、別のアカウントからアクセスさせるためには、次の設定が必要です。
- AWS Key Management Service (KMS) で S3 バケットの暗号化に設定したカスタマーマネージドキーのキーポリシーに別アカウントからのアクセス許可を追加
- S3 バケットのバケットポリシーに別アカウントの IAM ロールからのアクセス許可(クロスアカウントアクセス)を追加
それでは早速検証してみます。
S3 バケットの暗号化の設定(アカウント A)
KMS でカスタマーマネージドキーを作成
アカウント A の KMS のマネージメントコンソールから「カスタマー管理型のキー」→「キーの作成」に進みます。パラメーターは基本的にデフォルトのままとします。
キーの管理アクセス許可は適切なものを設定してください、キーの使用法アクセス許可とキーポリシーは、一旦ここでは何も設定せずにキーを作成します。
作成したキーの ARN は後の設定で使うので控えておきます。
SSE-KMS(カスタマーマネージドキー)での暗号化がデフォルトの S3 バケットを作成
アカウント A にて S3 バケット(バケット名は「test01-dev-bucket-crossaccounttest」とします)を作成する際に、「デフォルトの暗号化」で先ほど KMS で作成したキーを指定します。
これにより、オブジェクトを S3 バケットをアップロードする際に特に指定しなくても、設定されたキーでオブジェクトが自動的に暗号化されます。
別アカウントでの S3 バケット及び KMS キーへのアクセス許可の設定(アカウント B)
IAM ポリシーと IAM ロールの作成
アカウント A の S3 バケットと KMS キーにアクセスできるよう、アカウント B に以下の IAM ポリシーを作成します。
アカウント B 側で、アカウント A の S3 バケットと KMS キーの ARN が必要となりますので、何らかの方法で伝達しましょう。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessToSpecificBucket",
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::test01-dev-bucket-crossaccounttest",
"arn:aws:s3:::test01-dev-bucket-crossaccounttest/*"
]
},
{
"Sid": "AllowUseOfKeyInAccount012345678901",
"Effect": "Allow",
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "arn:aws:kms:ap-northeast-1:(アカウント A の ID):key/(KMS キーの ID)"
}
]
}
作成した IAM ポリシーをアタッチした IAM ロールを作成します。
別アカウントの EC2 に作成した IAM ロールをアタッチする
作成した IAM ロールをアカウント B の EC2 インスタンスにアタッチし、EC2 インスタンスからアカウント A の S3 バケットへアクセスできるようにします。
S3 バケットに別アカウントからのアクセス許可を設定(アカウント A)
S3 バケットポリシーの設定
アカウント A の S3 バケットにアカウント B の IAM ロールからのアクセスを許可するため、以下のバケットポリシーを設定します。
先ほどアカウント B で作成した IAM ロールの ARN が必要となります。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Allow-access-to-specific-IAM-role",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::(アカウント B の ID):role/test02-dev-role-crossaccounttest-ap"
},
"Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::test01-dev-bucket-crossaccounttest",
"arn:aws:s3:::test01-dev-bucket-crossaccounttest/*"
]
}
]
}
これだけではアカウント B からはまだこのバケットにアクセスできないため、このバケットを暗号化している KMS キーに対するアクセス許可の設定が必要です。
KMS キーポリシーの設定
アカウント A の S3 バケットの暗号化に設定している KMS キーのキーポリシーに、以下のとおりアカウント B の IAM ロールからのアクセス許可を設定します。
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-3",
"Statement": [
{
# root ユーザーや管理者ロールなどへの設定は省略
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::(アカウント B の ID):role/test02-dev-role-crossaccounttest-ap"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
}
]
}
これでアカウント B の EC2 インスタンスから、アカウント A の S3 バケットへクロスアカウントアクセスができるはずです。
なお、EC2 インスタンスがプライベートサブネットにありインターネットアクセスができない閉域環境の場合、S3 にアクセスするためにはゲートウェイ型 VPC エンドポイントが必要になります。
別アカウントから S3 バケットへのクロスアカウントアクセスを確認する
テスト用にアカウント A で適当なファイル(gov-cloud-metalcity.jpeg)を S3 バケットへアップロードしておきます。ファイルは設定どおり暗号化されるはずです。
それでは EC2 インスタンスのコンソールからこのファイルへアクセスしてみます。
KMS キーで暗号化されたオブジェクトにもちゃんと別アカウントからアクセスができました。
STS の Assume Role で別アカウントから S3 バケットへアクセスさせる
クロスアカウントの設定は以上のとおりですが、STS でアカウント A の IAM ロールをアカウント B から Assume Role させてアカウント A の S3 バケットへアクセスさせる方法もあります。
アカウント A に S3 バケットと KMS キーへアクセスできる IAM ロールを作成
アカウント A の方に、クロスアカウントアクセスの手順でアカウント B に作成したものと同様の、S3 バケットと KMS キーへのアクセス許可を設定した IAM ポリシーを作成し、IAM ロールにアタッチします。
アカウント B にアカウント A の信頼ポリシーが設定された IAM ロールへ Assume Role 可能な IAM ロールを作成
アカウント B に以下のような、アカウント A の IAM ロールへの Assume Role を許可する IAM ポリシーを作成し、これをアタッチした IAM ロールを作成します。
アカウント A の IAM ロールの ARN が必要です。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::(アカウント A の ID):role/test01-dev-role-assumeroletest"
]
}
]
}
IAM ロールが作成できたら、EC2 インスタンスにアタッチします。
なお、EC2 インスタンスが閉域環境にある場合は、STS へのインターフェース型 VPC エンドポイントが必要になります。
アカウント A の IAM ロールにアカウント B の IAM ロールへの信頼ポリシーを追加
IAM ロールにはアカウント B から Assume Role できるように以下のような信頼ポリシーを設定します。
アカウント B の IAM ロールの ARN が必要です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::(アカウント B の ID):role/test02-dev-role-assumeroletest"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
アカウント B からアカウント A の IAM ロールに Assume Role して S3 バケットへアクセスを確認
それではアカウント B の EC2 インスタンスからアカウント A の IAM ロールに Assume Role して一時的なクレデンシャルを手に入れたら、これを環境変数に設定してアカウント A の S3 バケットにアクセスしてみます。
Assume Role の方法でも別アカウントから KMS キーで暗号化された S3 バケットのオブジェクトにアクセスできました。
まとめ
KMS キーで暗号化した S3 バケットに別のアカウントからアクセスさせるには、アカウント間で以下の情報をやりとりする必要があります。
クロスアカウントアクセスの場合
- S3 バケット名と KMS キーの ARN をアクセスさせたい別アカウントへ伝える。
- 別アカウントで S3 バケットと KMS キーにアクセスを許可する IAM ロールを作成し、IAM ロールの ARN を S3 のある元アカウントへ伝える。
- 元アカウントの S3 バケットのバケットポリシーと KMS キーのキーポリシーに、別アカウントの IAM ロールの ARN を許可するポリシーを追加する。
Assume Role の場合
- S3 のある元アカウントで S3 バケットと KMS キーにアクセスを許可する IAM ロールを作成し、IAM ロールの ARN を別アカウントへ伝える。
- 別アカウントで元アカウントの IAM ロールへ Assume Role を許可する IAM ロールを作成し、IAM ロールの ARN を元アカウントへ伝える。
- 元アカウントの IAM ロールに別アカウントの IAM ロールの ARN を許可する信頼ポリシーを追加する。
SSE-KMS で暗号化する設定をしている S3 バケットの場合は、バケットポリシーだけじゃなく KMS のキーポリシーも設定が必要なことに注意しましょう。















