- 公開日
- 最終更新日
【SAM】IAM ロールを AWS SAM Policy Templates に移行してみた
この記事を共有する
目次
はじめに
突然ですが、AWS Serverless Application Model(以下、SAM)を使いこなせているでしょうか。
私は AWS CloudFormation(以下、CloudFormation)が少し短く書けるくらいの認識で、これまで使っていました。
特に AWS Identity and Access Management(以下、IAM)ロールはずっと AWS::IAM::Role で書いていたのですが、SAM にはもっと短く書ける仕組みがあると最近になって知りました。
せっかくなので、SAM 独自の機能を意識して使ってみることにしました。
いきなり結論
結論:手持ちの SAM プロジェクトを移行してみたところ、テンプレート全体で約 25 パーセントのコード削減になりました。
IAM ロールの記述部分に限れば、約 7 割が消えています。
Lambda 用の IAM ロールをすべて削除し、各関数の Policies プロパティへ移行した結果です。
定型文を書く量が減るので、関数を増やすときの手間もその分軽くなります。
ただし、短くなったことと引き換えに気をつける点もありました。
そちらは記事の後半で説明します。
Policy Templates で何が短くなるのか
移行前は、関数ごとに AWS::IAM::Role を自分で定義していました。
ExampleFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Policies:
- PolicyName: DynamoDBAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:Query
- dynamodb:PutItem
- dynamodb:GetItem
Resource: !GetAtt ExampleTable.Arn
これが移行後は 2 行になります。
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref ExampleTable
AssumeRolePolicyDocument と ManagedPolicyArns の記述が丸ごと不要になる点が大きいです。
SAM が Lambda 用の信頼関係と基本実行ロールを自動で付けてくれるため、毎回書く必要がありません。
関数が 10 個あれば、この定型文を 10 回書いていたことになります。
今回使ったテンプレートは以下の 6 種類です。
- AWSSecretsManagerGetSecretValuePolicy
- SSMParameterReadPolicy
- DynamoDBCrudPolicy
- DynamoDBReadPolicy
- StepFunctionsExecutionPolicy
- LambdaInvokePolicy
いずれもリソース名やパラメータ名を引数として渡す形式で、対象リソースは絞り込まれます。
権限の対象は絞られますが、アクションの種類は絞れません。ここが後半の話につながります。
用意されているテンプレートの一覧は公式ドキュメントにまとまっています。
AWS SAM ポリシーテンプレート - AWS Serverless Application Model
移行できなかった 2 つのパターン
すべてを Policy Templates に置き換えられたわけではありません。
移行できなかったものは、きれいに 2 つに分類できました。
パターン 1:対応するテンプレートが存在しない
Amazon Bedrock(以下、Bedrock)の呼び出し権限がこれに当たりました。
bedrock:InvokeModel に相当する Policy Template が用意されていないため、インラインの Statement で書いています。
同じ理由で iam:PassRole も自分で書く必要がありました。
さらに Bedrock の場合、クロスリージョン推論プロファイル経由でモデルを呼び出すには、リソースを 2 つ指定する必要があります。
- Effect: Allow
Action:
- bedrock:InvokeModel
Resource:
- !Sub 'arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:inference-profile/${BedrockModelId}'
- 'arn:aws:bedrock:*::foundation-model/anthropic.claude-sonnet-4-5-20250929-v1:0'
推論プロファイルの ARN と、その裏側で実際に呼ばれる基盤モデルの ARN の両方が要ります。
片方だけでは権限エラーになります。
仮にテンプレートが用意されたとしても、この 2 つを同時に扱う形は表現しにくいと思います。
新しめのサービスを使っている場合、テンプレートが追いついていないことは前提にしておいた方がよいです。
パターン 2:そもそも Policies プロパティが使えない
Policies プロパティは AWS::Serverless::Function などの SAM 独自リソースにしか存在しません。
SAM独自リソース以外で利用する IAM ロール については、引き続き AWS::IAM::Role で書き続けることになります。
今回も、AI エージェント基盤のサービスプリンシパルが引き受けるロールは移行対象外として残しました。
つまり Policy Templates は「Lambda 関数と Step Functions ステートマシンの実行ロールを短く書く仕組み」であって、テンプレート内の IAM 定義がすべて消えるわけではありません。
移行してから気づいたデメリット
短くなった代わりに、権限が広くなりました。
移行前、集計処理を行う関数に付けていた Amazon DynamoDB(以下、DynamoDB)の権限は 3 つだけでした。
- dynamodb:Query
- dynamodb:PutItem
- dynamodb:GetItem
- dynamodb:DeleteItem
読み取りと書き込み・削除はするものの、テーブル全件をスキャンする処理もないので dynamodb:Scan は含めていませんでした。
これを DynamoDBCrudPolicy に置き換えました。
このテンプレートが実際に付与するアクションは以下の 10 個です。
dynamodb:GetItem
dynamodb:DeleteItem
dynamodb:PutItem
dynamodb:Scan
dynamodb:Query
dynamodb:UpdateItem
dynamodb:BatchWriteItem
dynamodb:BatchGetItem
dynamodb:DescribeTable
dynamodb:ConditionCheckItem
4 個で足りていた関数に 10 個が付きました。
使う予定のない UpdateItem や BatchWriteItem まで含まれています。
「DynamoDBCrudPolicy 用のひとまとまり」として定義されているので、その一部だけを選ぶ手段はありません。
読み取り専用でよければ DynamoDBReadPolicy という選択肢がありますが、粒度はそこまでです。
同じことは他のテンプレートでも起きます。
SSMParameterReadPolicy も、指定したパラメータの読み取りに加えて ssm:DescribeParameters を全リソース対象で付与します。
テンプレートの定義は SAM のリポジトリで公開されています。
名前から想像せず、実際に何を許可するのかを事前に確認してください。
まとめ
今回は既存の IAM ロール定義を SAM Policy Templates に移行しました。
テンプレートは短くなりましたが、引き換えに IAM 権限は広くなりました。
一方で、最初から使っていれば定型文を何度も書く手間はなかったはずです。
新規なら最初から使い、権限を絞りたい関数だけあとで置き換えるという順番が現実的だと思います。
同じように SAM で権限設計を悩んでいる方の参考になれば幸いです。
この記事は私が書きました
野間 太一
記事一覧猫とCloudFormationが好きです。