#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でアップデートした時に問題が発生しました!
いつまで待ってもアップデートが終わらないのです…。
※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ユーザに対して同様のポリシーを与えてみたところ、原因が発覚しました…。
なんか制限が掛かっている模様ですね…。
ということで、ドキュメントを確認します。(最初から見ておきましょう)
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でスタックをアップデートすることが出来ました!
参考になれば幸いです。