LoginSignup
7
8

More than 5 years have passed since last update.

CloudFormationでIAMポリシーを作ってUserに付与するときの注意点

Posted at

TL;DR

  • IAMユーザにインラインポリシーを当てるときに最大文字制限に引っかかってハマった話です。
  • https://aws.amazon.com/jp/iam/faqs/

    ユーザーポリシーサイズは最大 2,048 文字です。
    ロールポリシーサイズは最大 10,240 文字です。
    グループポリシーサイズは最大 5,120 文字です。

  • マネジメントコンソールからポリシーを書いた場合はエラー内容が出てすぐに分かるのですが、CloudFormationでスタックをアップデートした場合にCREATE(UPDATE) IN PROGRESSのまま止まってしまいエラー内容も出ずハマりました

  • グループポリシーにインラインポリシーを当て、ユーザをそのグループに入れればとりあえず回避できます。

何が起こったのか

Lambdaを中心にserverlessの構成を構築しているのですがLambdaに色々と権限を持たせたためにポリシーが長くなっています。(多分2,500文字程度)
具体的には、

  • CloudWatchLogsへログを書き込む権限
  • DynamoDBを操作する権限 ‐ DynamoDB Triggerを操作する権限
  • Cognitoの認証情報を操作する権限
  • VPC内に入れるためにENIを操作する権限
  • S3にアクセスするための権限
  • SNS(プッシュ通知)を管理するための権限
  • SQSを管理するための権限

といった権限をつらつらとポリシーに書いてCloudFormationでアップデートしました。ここまでは特に問題はなかったのです。

構成例(A)

テーブル

リソース ポリシー
IamRoleLambda IamPolicyLambda

CloudFormation

LambdaにRoleを渡すためのCloudFormationです。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Sample",
  "Resources": {
    "IamRoleLambda": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/"
      }
    },
    "IamPolicyLambda": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "${stage}-${project}-lambda",
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:${region}:*:*"
            },
            {
              "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:DeleteItem",
                "dynamodb:Scan",
                "dynamodb:Query"
              ],
              "Effect": "Allow",
              "Resource": "arn:aws:dynamodb:${region}:${account}:table/${project}-*-${stage}"
            }
          ]
        },
        "Roles": [
          {
            "Ref": "IamRoleLambda"
          }
        ]
      }
    }
  }
}

問題発生

Lambdaに渡すのはIAMロールなので、ローカルで動作確認をしようと思った時に困ってしまいます。そこで、同じポリシーを持ったIAMユーザを準備しCloudFormationでアップデートした時に問題が発生しました!
いつまで待ってもアップデートが終わらないのです…。

スクリーンショット 2016-06-10 1.56.32.png

※17:22:42に始まったAWS::IAM::Policyのアップデートが一向に終わらないので、17:28:50にキャンセルを掛けました

構成例(B)

テーブル

リソース ポリシー
IamUserLambdaTest IamPolicyLambda ←これでエラー発生
IamRoleLambda IamPolicyLambda

CloudFormation

このときのCloudFormationです。IamUserLambdaTest周りが増えています。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Sample",
  "Resources": {
    "IamUserLambdaTest": {
      "Type": "AWS::IAM::User",
    },
    "IamRoleLambda": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/"
      }
    },
    "IamPolicyLambda": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "${stage}-${project}-lambda",
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:${region}:*:*"
            },
            {
              "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:DeleteItem",
                "dynamodb:Scan",
                "dynamodb:Query"
              ],
              "Effect": "Allow",
              "Resource": "arn:aws:dynamodb:${region}:${account}:table/${project}-*-${stage}"
            }
          ]
        },
        "Roles": [
          {
            "Ref": "IamRoleLambda"
          }
        ],
        "Users": [
          {
            "Ref": "IamUserLambdaTest"
          }
        ]
      }
    }
  }
}

何が起こっていたのか

ここで全く分からずハマっていたのですが、マネジメントコンソールでIAMユーザに対して同様のポリシーを与えてみたところ、原因が発覚しました…。

スクリーンショット 2016-06-10 2.02.45.png

なんか制限が掛かっている模様ですね…。
ということで、ドキュメントを確認します。(最初から見ておきましょう)

https://aws.amazon.com/jp/iam/faqs/
ユーザーポリシーサイズは最大 2,048 文字です。
ロールポリシーサイズは最大 10,240 文字です。
グループポリシーサイズは最大 5,120 文字です。

ガーン…そういうことですか!
今回書いていたポリシーが恐らく2,500文字程度と思われるので、IAMユーザに対しては文字数オーバーだったのですね…。

CloudFormationでもエラーが発生しているはずなのに、エラーで終了しないのは何故なんでしょうね。

解決策

ドキュメントに依るとグループポリシーは5,120文字まで行けるということなので、そちらを使って対処しましょう。
すなわち、Lambdaに渡すロールと同様のポリシーをグループに与えて、ユーザはそのグループに属するという構成になります。

構成例(C)

テーブル

リソース ポリシー
IamGroupLambdaTest IamPolicyLambda ←グループにポリシーを当てる
IamUserLambdaTest IamGroupLambdaTest ←ユーザにはグループを当てる
IamRoleLambda IamPolicyLambda

CloudFormation

このときのCloudFormationです。グループが増えて、ユーザがそのグループに属する形となっております。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Sample",
  "Resources": {
    "IamGroupLambdaTest": {
      "Type": "AWS::IAM::Group"
    },
    "IamUserLambdaTest": {
      "Type": "AWS::IAM::User",
      "Properties": {
        "Groups": [
          {
            "Ref": "IamGroupLambdaTest"
          }
        ]
      }
    },
    "IamRoleLambda": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "lambda.amazonaws.com"
                ]
              },
              "Action": [
                "sts:AssumeRole"
              ]
            }
          ]
        },
        "Path": "/"
      }
    },
    "IamPolicyLambda": {
      "Type": "AWS::IAM::Policy",
      "Properties": {
        "PolicyName": "${stage}-${project}-lambda",
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:${region}:*:*"
            },
            {
              "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:BatchGetItem",
                "dynamodb:BatchWriteItem",
                "dynamodb:DeleteItem",
                "dynamodb:Scan",
                "dynamodb:Query"
              ],
              "Effect": "Allow",
              "Resource": "arn:aws:dynamodb:${region}:${account}:table/${project}-*-${stage}"
            }
          ]
        },
        "Roles": [
          {
            "Ref": "IamRoleLambda"
          }
        ],
        "Groups": [
          {
            "Ref": "IamGroupLambdaTest"
          }
        ]
      }
    }
  }
}

結果

この変更により、無事CloudFormationでスタックをアップデートすることが出来ました!

スクリーンショット 2016-06-10 2.13.30.png

参考になれば幸いです。

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8