クロスアカウントで色々いじっていて、IAMの権限管理についてのパターンがなんとなくわかってきたのでメモします。
クロスアカウントでの権限管理は色々なパターンがあるようですが、今回扱うのは「AアカウントのリソースポリシーでBアカウントのrootを許可→Bアカウントの中でポリシーアタッチ」のパターンです。
具体的に見ていきましょう。まずはよくあるS3のパターンです。
別アカウントのS3バケットにLambdaからアクセスする
ここではアカウントID:111111111111
のアカウント1
からアカウントID:0000000000000000
のアカウント0
のS3バケットにアクセスしたいとします。

アカウント0のコンソールで、S3のバケットポリシーを以下のように設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Example permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::1111111111111:root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::BUCKET_NAME/*"
}
]
}
ここではアカウント1のrootユーザーに対してS3バケットへのアクセスを許可しています。
次に、許可をもらったアカウント1のコンソールで以下のポリシーを作成し、S3バケットにアクセスするLambdaにアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::BUCKET_NAME/*",
"Effect": "Allow"
}
]
}
これで、ポリシーをアタッチされたLambdaはアカウント0のS3バケットに対してアクセスすることができるようになります。
まずはアカウントのrootユーザーに権限を与える → 権限を得たroot(admin)ユーザーがリソースに対して権限を与えるという流れでわかりやすいと思います。
もちろん、最初にバケットポリシーで許可したActionしかできないようになっているので、例えば今回の場合s3:GetObject以外の操作権限はLambda にもrootユーザーにも与えられていません。
LambdaからObjectを新たにPUTしたりするためには、再びアカウント0の管理者にバケットポリシーからs3:PutObjectを許可してもらう必要があります。
別アカウントのLambdaにLambdaからアクセスする
先ほどと同様にアカウント1のLambdaからアカウント0のLambdaにアクセスしたいとします。

Lambdaの場合はリソースポリシーというものがあるので、ここで、アカウント1のrootユーザーに権限を与えます。
参考: AWS Lambda でリソースベースのポリシーを使用する (Lambda 関数ポリシー) - AWS Lambda
この操作は現在AWS CLIやAPIでしか行えないようです。
aws lambda add-permission \
--function-name FUNC_NAME \
--statement-id Example permissions \
--action lambda:InvokeFunction \
--principal 111111111111 \
--output json
上記のコマンドを実行すると以下のjsonが返ってきます。
{
"Statement": "{\"Action\":[\"lambda:InvokeFunction\"],
\"Resource\":\"arn:aws:lambda:YOUR_REGION:000000000000:function:FUNC_NAME\",
\"Effect\":\"Allow\",
\"Principal\":{\"AWS\":\"111111111111\"},
\"Sid\":\"Example permissions\"}"
}
CLIなので、見ためは違いますが、やっていることとしては先ほどのバケットポリシーと対して変わりません。アカウント1のrootユーザーに対してアカウント0のLambdaへのlambda:InvokeFunction
の権限を与えています。
次に、アカウント1のコンソールから、Lambda(アクセスする方)の実行ロールにアカウント0のLambdaへアクセスする権限を与えるポリシーをアタッチします。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:YOUR_REGION:000000000000:function:FUNC_NAME",
"Effect": "Allow"
}
]
}
これで、アカウント1のLambdaからアカウント0のLambdaにアクセスすることができるようになります。
おまけ: kmsのキーポリシーをIAMポリシーで管理する
実はクロスアカウントの権限管理以外にも、似たような権限の与え方をするパターンがあります。
それが、KMSのキーポリシーです。
AWSでは若干複雑なことに、KMSで作ったCMKに対する権限をKMSのキーポリシーで管理するということになっています。
ただ、特にLambdaに関しては実行ロールに付与されているIAMポリシーでLambdaの権限を管理できた方がわかりやすいため、IAMポリシーで管理できた方が便利だと思います。
そういった場合に、キーポリシーをIAMポリシーで管理できるようにするキーポリシーの書き方が以下です。
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111111111111:root"},
"Action": "kms:*",
"Resource": "*"
}
これで、IAMポリシーでKMSのCMKの権限を管理できるようになります。
Lambdaの実行ロールには以下の権限を付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"kms:*"
],
"Resource": "arn:aws:kms:YOUR_REGION:111111111111:key/xxxxxxxxxx",
"Effect": "Allow"
}
]
}