AWS SAMでLambda関数を作成する際のポリシーの書き方について
AWS SAMでLambda関数を作成する際のポリシーの書き方について
こんにちは。データ事業本部のキタガワです。
今回はAWS SAM(以下SAM)を使用してLambda関数を作成する際に、Lambda関数にアタッチするポリシー(より正確にはLambdaが実行時に使用するIAMロールにアタッチされるポリシー)の設定方法をいろいろ調べたのでまとめます。
SAMについて
SAMはAWS Serverless Application Modelのことで、要するにサーバレスなアプリケーションを手軽に構築できるフレームワークのことです。
詳細については公式リンクを参照してください。
記事で書くこと
SAMはCloudFormationライクなテンプレートファイルを記述することでリソースをプロビジョニングすることができます。
この記事ではそんなSAMのテンプレートファイルの中でも特にLambda関数のポリシーの定義方法について記述します。
記事で書かないこと
SAM自体の使い方についてはこの記事では扱いません。
SAMの使い方について学びたい方は公式のチュートリアルを参考に、実際に手を動かすのが一番だと思います。
SAMにおけるLambdaのポリシーの記述方法
SAMの中でも特に中心的な役割を果たすであろうLambdaが、AWSのどのようなリソースにアクセスでき、何を行えるかを定義するのが Policies
のプロパティです。
Policies
は次の3通りで書くことができます。
- SAMのポリシーテンプレートを使用する
- AWS管理ポリシーまたはカスタマー管理ポリシーを使用する
- YAMLのMap型の形式でインラインポリシーを定義する
これから一つひとつ見ていきます。
SAMのポリシーテンプレートを使用する
SAMでは公式がポリシーのテンプレートを豊富に用意してくれています。
単純なタスクであればこのポリシーを使うだけで難しいことは考えなくても実装できるようにしてくれています。
現時点で多数のポリシーテンプレートが用意されており、この中から必要なポリシーを追加するとLambda関数の実行ロールにアタッチされるようになっています。
ポリシーはこちらから詳細を確認できます。
テンプレートファイルでは次のように記述します。
MyFunction:
Type: AWS::Serverless::Function
Properties:
Policies:
- PolicyTemplateName1: # Policy template with placeholder value
Key1: Value1
- PolicyTemplateName2: {} # Policy template with no placeholder value
よって、例えばAthenaにクエリを投げてその結果を取得するようなLambda関数を実装する場合、テンプレートファイルは
MyFunction:
Type: AWS::Serverless::Function
Properties:
Policies:
- AthenaQueryPolicy:
WorkGroupName: your_work_group
のようになります。
AWS管理ポリシーまたはカスタマー管理ポリシーを使用する
これはIAMのコンソール画面から直接確認できるポリシーをそのまま使用することができます。
AWS管理ポリシーの場合はポリシー名またはARN、カスタマー管理ポリシーの場合はARNで指定するようになっています。
AWS管理ポリシーを使用する場合はAWSのGitHubページに一覧が記載されていますので、この中から必要なものを選んでください。
テンプレートファイルでは次のように記述します。
MyFunction:
Type: AWS::Serverless::Function
Properties:
Policies:
- AmazonRedshiftReadOnlyAccess # ARNで書く場合は arn:aws:iam::aws:policy/AmazonRedshiftReadOnlyAccess
YAMLのMap型の形式でインラインポリシーを定義する
上記の2つで述べてきたような、あらかじめ用意されたポリシーを使用するのではなく、インラインポリシーをテンプレートファイルの中で定義して設定することも可能です。
AWSの最小権限の原則に従うように設定をしたかったり、ポリシーテンプレートでは必要な権限が揃わなかったりする場合に使用でき、柔軟性を持った権限の付与ができます。
例えばLambda関数が特定のS3バケットへのPutObjectとGetObjectのみを必要とする場合、次のように記述します。
MyFunction:
Type: AWS::Serverless::Function
Properties:
Policies:
- Version: "2012-10-17"
Statement:
- Sid: S3Access
Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
Resource: "arn:aws:s3:::bucket_for_sam/*"
こちらはCloudFormationでインラインポリシーを定義する時の書き方とおおよそ同じだと思います。
CloudFormationでは PolicyDocument
セクションの中に書く内容をSAMでは Policies
の中に書くイメージです。
ポリシーの設定を組み合わせる
もちろんここまでで述べたポリシーの設定方法を組み合わせて使用することもできます。
例えば
- Lambda関数からAthenaにクエリを投げ、その結果をインメモリに読み込み、Pandasで処理したのちデータフレームをS3に出力したい
- ただしLambda関数には特定のS3バケットへのPutObjectのみ許可したい
のような要件があるとして、SAMのポリシーテンプレートの中の S3WritePolicy
では権限範囲が大きいのでインラインポリシーとして設定したいとします。
この要件は、テンプレートファイルで次のように2つの書き方を組み合わせることで実現できます。
MyFunction:
Type: AWS::Serverless::Function
Properties:
Policies:
- Version: "2012-10-17"
Statement:
- Sid: S3Access
Effect: Allow
Action:
- s3:PutObject
Resource: "arn:aws:s3:::bucket_for_sam/*"
- AthenaQueryPolicy:
WorkGroupName: your_work_group
実際に上記の内容でデプロイをしてみるとLambda実行ロールのデフォルトのポリシーに加え、追加で2つ付与されていることがコンソール画面からも確認できます。
またそれぞれ中を覗いてみると上記のテンプレートファイルに基づいた内容になっていることも確認できます。
まとめ
SAMはサーバレスアーキテクチャを実装するにはうってつけのフレームワークですが、実際にテンプレートファイルを書くときはその記述方法に迷うこともよくあると思います。
特にCloudFormationにあまり慣れていない状態だと、どのようにLambdaにポリシーを付与していくのか分からず、せっかくのSAMの利点であるシンプルかつスピーディーな開発体験が損なわれてしまいます。
この記事がポリシーの書き方に悩んでいる方の一助になれば幸いです。