.rute1/

キャリア/心理学/読書/Pythonなどなど

AWS クロスアカウント権限管理 「リソースポリシーからrootに許可するパターン」編

クロスアカウントで色々いじっていて、IAMの権限管理についてのパターンがなんとなくわかってきたのでメモします。

クロスアカウントでの権限管理は色々なパターンがあるようですが、今回扱うのは「AアカウントのリソースポリシーでBアカウントのrootを許可→Bアカウントの中でポリシーアタッチ」のパターンです。

具体的に見ていきましょう。まずはよくあるS3のパターンです。

別アカウントのS3バケットにLambdaからアクセスする

ここではアカウントID:111111111111アカウント1からアカウントID:0000000000000000アカウント0のS3バケットにアクセスしたいとします。 f:id:rutei:20190105180724p:plain
アカウント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にアクセスしたいとします。
f:id:rutei:20190105181018p:plain
Lambdaの場合はリソースポリシーというものがあるので、ここで、アカウント1のrootユーザーに権限を与えます。
参考: AWS Lambda でリソースベースのポリシーを使用する (Lambda 関数ポリシー) - AWS Lambda この操作は現在AWS CLIAPIでしか行えないようです。

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"
        }
    ]
}