AWS Lambda 関数に適切に AWS IAM のポリシーを設定しよう!

2023-09-01
How to be a Developer

Author : 野邊 哲男

builders.flash 読者の皆さん!こんにちは!

AWS のシニアテクニカルトレーナー 野邊(のべ)です。

今回は AWS Lambda 関数に設定するポリシーについて初学者の方向けに解説していきます!

なお、AWS Lambda の初学者の方は、この記事をご覧になる前に builders.flash の 「AWS Lambda 関数の実行の仕組みを知ろう!」 の記事を読んで頂くことをお薦めします!

また、今回の記事のタイトルの中で「AWS Lambda 関数」という言葉を使ってますが、記事の本文では用語として次のように使っていきますので、あらかじめ確認しておいて下さい!

  • AWS Lambda
    • サーバーを意識せずにコードを実行できる AWS のサーバーレスコンピューティングサービス
  • Lambda 関数
    • AWS Lambda によって管理、実行されるアプリケーションのコードとその設定

ちなみに今回の記事に掲載しているスライドは、あくまで筆者のテクニカルトレーナーとしてのネタ帳の一部であり、AWS の有償トレーニングのテキストからの抜粋ではないことを念のためお伝えしておきます!

この連載記事のその他の記事はこちら

選択
  • 選択
  • AWS Lambda 関数の実行の仕組みを知ろう !
  • AWS Lambda 関数に適切に AWS IAM のポリシーを設定しよう!
  • AWS Lambda 関数をモニタリングしてみよう!

Lambda 関数へ設定するポリシーを意識しよう!

もう何年も前の話ですが、私が初めて AWS Lambda を触り始めた時は、とにかく色んなコードを書いて、動かしてみよう!とだけ意識していました。ただ取り組み始めてすぐに、その意識だけでは Lambda 関数を思い通りに動かすことができない、と気づきました。それは、AWS Identity and Access Management (IAM) のポリシーに対する意識が足りなかったからです。そう、Lambda 関数のコードを正しく書けたとしても、その Lambda 関数に対して IAM のポリシーを正しく設定しないと意図したとおりに動作しません。

では、どのように IAM のポリシーを Lambda 関数に対して設定すればいいでしょうか?
意識すべき主要な点は 3 つです。

  1. Lambda 関数から他の AWS のサービスにアクセスする場合のポリシー
  2. Lambda 関数を呼び出す場合のポリシー
  3. イベントソースとポリシーの関係

この 3 点についてみていきましょう!


1. Lambda 関数から他の AWS のサービスにアクセスする場合のポリシー

例として、source_lambda という Lambda 関数から、lambda-bucket という Amazon Simple Storage Service (Amazon S3) バケットにオブジェクト(つまりデータ)を格納したい場合を考えてみましょう。次の図をご覧ください。

この図のように、source_lambda には lambda-bucket にオブジェクトを格納するためには、PutObject という操作を行うコードを AWS Software Development Kit (AWS SDK)を使用して記述します。
ただ、そのコードを正しく記述するだけでなく、ポリシーの設定も必要になります。この例でいうと、source_lambda に対して、lambda-bucket に対する PutObject の操作を許可する という IAM のポリシーを source_lambda に対して設定する必要があります。
下記は、そのポリシーの例です。(このポリシーの例は、AWS アカウント ID の値や Lambda 関数のリージョンなどは使用する環境により変更が必要です。)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ExampleSourceFunctionArn",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::lambda-bucket/*",
            "Condition": {
                "ArnEquals": {
                    "lambda:SourceFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:source_lambda"
                }
            }
        }
    ]
}

このポリシーは、確かに source_lambda にとって必要な 操作は許可しています。ただ、実運用においては、どんな Lambda 関数でも基本的に必ず設定しておくことが推奨されるポリシーが存在します。それは、AWSLambdaBasicExecutionRole というポリシーです。このポリシーは AWS マネージドポリシー、つまり AWS によって事前に用意されているポリシーで、Lambda 関数が Amazon CloudWatch にログを送信するために必要な許可を付与するものです。実運用では、Lambda 関数の動作状況を確認するためにログの取得は重要ですので、この AWSLambdaBasicExecutionRole ポリシーも併せて使用するか、もしくはそれと同じ内容を含むポリシーを用意することをお薦めします。

ポリシーは、Lambda 関数がどのようなサービスに対して、どのような操作を行うのかという要件に応じて作成します。ポリシーの作成においては、不必要に強大な権限を許可しないようにしましょう。これは、 IAM のベストプラクティスの一つである「最小特権アクセス許可を適用する」でも提唱されていますね。

では、そのポリシーをどうやって source_lambda に設定すればいいでしょうか?
それは、 IAM のロールを使用します。次の図をご覧ください。

この図のように、Lambda 関数に対して設定する IAM ロールのことを 実行ロール といいます。この実行ロールには、Lambda 関数がそのロールを引き受けることを許可するための信頼ポリシーを設定します。下記は、信頼ポリシーの例です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

実行ロールを Lambda 関数に設定すると、Lambda 関数が呼び出された時は自動的に AWS Security Token Service (AWS STS) というサービスへ AssumeRole という操作が行われ、一時的な認証情報が Lambda 関数へ渡されます。つまり、認証情報を取得するコードを記述する必要はありません。
なお、 IAM のロールについては、builders.flash の「テクニカルトレーナーと学ぶ AWS IAM ロール」の記事に詳細な解説がありますのでそちらもご参照ください!

また、もし AWS マネジメントコンソールを用いて Lambda 関数を作成する場合は、AWSLambdaBasicExecutionRole ポリシーが設定された実行ロールを自動的に作成することもできます。ただ、マネジメントコンソールで自動的に作成される実行ロールには必ずしも その Lambda 関数にとって十分なポリシーが設定されているとは限りません。そのため、基本的には Lambda 関数の設計段階で必要なポリシーと実行ロールも併せて設計しておき、Lambda 関数の作成前に適用する実行ロールを作成しておくことをお薦めします。


2. Lambda 関数を呼び出す場合のポリシー

次に Lambda 関数を呼び出す場合のポリシーについてみていきましょう。例として、Amazon S3 の my-bucket というバケットにオブジェクトが格納されたイベントに応じて非同期的に my-function という Lambda 関数を呼び出す場合を考えてみましょう。次の図をご覧ください。この場合、Lambda 関数 my-function は呼び出される側です。よって、Amazon S3 から Lambda 関数を呼び出す許可が必要です。では、このポリシーはどのように設定すればいいでしょうか?

この場合、Lambda 関数にリソースベースのポリシーを設定して Amazon S3 のイベントにより Lambda 関数を呼び出されることを許可します。

下記は、リソースベースのポリシーの例です。(AWS アカウント ID の値や Lambda 関数のリージョンなどは使用する環境により変更が必要です。)

{
    "Version": "2012-10-17",
    "Id": "default",
    "Statement": [
        {
            "Sid": "lambda-allow-s3-my-function",
            "Effect": "Allow",
            "Principal": {
              "Service": "s3.amazonaws.com"
            },
            "Action": "lambda:InvokeFunction",
            "Resource":  "arn:aws:lambda:us-east-2:123456789012:function:my-function",
            "Condition": {
              "StringEquals": {
                "AWS:SourceAccount": "123456789012"
              },
              "ArnLike": {
                "AWS:SourceArn": "arn:aws:s3:::my-bucket"
              }
            }
        }
     ]
}

ただ、AWS マネジメントコンソール を使用して、 Amazon S3 バケットを Lambda 関数のイベントソースに設定した場合は、Lambda 関数のリソースベースのポリシーは自動的に設定されます。そのため、もしかするとその存在を意識していない人もいるかもしれませんが、AWS のサービスであったとしても、無条件で Lambda 関数を呼び出せるわけでなく、ポリシーによって許可される必要があることを意識しておきましょう。
今回は、Amazon S3 のイベントで Lambda 関数を呼び出す例で説明しましたが、これは Amazon Simple Notification Service (Amazon SNS) のトピックのサブスクリプションとして Lambda 関数を設定した場合や、Amazon Event Bridge のイベントバスのルールにおいて、ターゲットに Lambda 関数を設定した場合でも同じです。

また、Amazon API Gateway で API が Call されたときに同期的に Lambda 関数を呼び出す場合でも、Lambda 関数側のリソースベースのポリシーで、その呼び出しを許可できます。AWS マネジメントコンソールで API と Lambda 関数の統合設定を行うと、このリソースベースのポリシーを自動的に設定できます。ただ、Amazon API Gateway の場合は、API 側に AWS IAM のロールを設定できるので、もしリソースベースのポリシーを設定してない場合でも、そのロールのポリシーで許可していれば Lambda 関数を呼出せます。Amazon API Gateway の API に限らず、 IAM のポリシーを付与できるリソースであれば、そのポリシーで呼び出しを許可することができます。

このように、Lambda 関数を呼び出す場合は、Lambda 関数側のリソースベースのポリシー、もしくは呼び出し側に設定するポリシーで呼出しを許可するということを理解しておきましょう。ただ、複数のポリシーが存在し、許可と拒否がバッティングした場合には拒否が優先となります。よって、例えばリソースベースのポリシーで呼び出しが許可されていたとても、実行ロールのポリシーで明示的に呼び出しが拒否されていると、ポリシーの評価としては拒否となり、呼び出しできないことは留意しておきましょう。


3. イベントソースとポリシーの関係

では次に、Lambda 関数のイベントソースとして、Amazon Simple Queue Service (Amazon SQS) のキューや DynamoDB Streams のストリーム、また Amazon Kinesis Data Streams のストリームを設定する場合を考えてみましょう。次の図をご覧ください。この場合は、どこに、どんなポリシーを設定すればいいでしょうか?

ここで重要なのが、「何がどこにアクセスしているか」 という意識です。Lambda 関数のイベントソースとして Amazon SQS のキューや DynamoDB Streams のストリーム、また Amazon Kinesis Data Streams のストリームを設定できますが、これらのイベントソースには、AWS Lambda からポーリングを行ってメッセージのデータを取得します。よって、AWS Lambda に対して Amazon SQS のキューや DynamoDB Streams へのアクセスを許可する必要があります。そのため、Lambda 関数の実行ロールでそれを許可するポリシーを設定します。これは、AWS Lambda デベロッパーガイドの「他のサービスで AWS Lambda を使用する」ー「サービスの一覧と詳細情報へのリンク」セクションの表で「呼び出し方法」の列に「Lambda ポーリング」と記載されているリソースも同様です。

また、これらのユースケースに適用できる 下記の管理ポリシーも用意されています。

管理ポリシー名 説明
AWSLambdaSQSQueueExecutionRole Amazon SQS のキューからメッセージを読み取る許可とAmazon CloudWatch Logs に書き込むための許可
AWSLambdaDynamoDBExecutionRole DynamoDB Streams からメッセージを読み取る許可とAmazon CloudWatch Logs に書き込むための許可
AWSLambdaKinesisExecutionRole Amazon Kinesis Data Streams のストリームからメッセージを読み取る許可とAmazon CloudWatch Logs に書き込むための許可

なお、少し細かい話ですが、Amazon SQS のキューにはリソースベースのポリシーを設定できます。よって Lambda 関数の実行ロールにキューに対するアクセスを許可するポリシーがなくても、キュー側のリソースベースのポリシーで許可されていればアクセス可能です。
ただ、Lambda 関数には Amazon CloudWatch Logs へログを送信する許可も実行ロールのポリシーで付与するケースがほとんどなので、併せて対象のキューへのアクセスも許可しておくと、その Lambda 関数に対するポリシーを一元的に管理できるメリットはありますね。


まとめ

今回は AWS Lambda の初学者の方向けに AWS Lambda 関数への IAM ポリシーの設定をテーマに、以下のトピックについて説明しました。

  1. Lambda 関数から他の AWS のサービスにアクセスする場合のポリシー
  2. Lambda 関数を呼び出す場合のポリシー
  3. イベントソースとポリシーの関係

Lambda 関数のコードを正しく書くことはもちろん重要ですが、 IAM のポリシーを正しく設定することの意識も忘れないようにしましょう!

今回の記事と、「AWS Lambda 関数の実行の仕組みを知ろう!」 の記事の両方を読むことで、AWS Lambda の基本として知っておきたいトピックを学習して頂けると思います。
みなさんがこれらの記事で、 AWS Lambda などのサーバーレスのサービスについて、より理解と関心を深めていただけると嬉しいです!
もっと、AWS のサーバーレスについて学びたい!という方向けの学習パスとして、「 サーバーレスの始め⽅ 」という資料もありますので、ぜひご参照ください!

この連載記事のその他の記事はこちら

選択
  • 選択
  • AWS Lambda 関数の実行の仕組みを知ろう !
  • AWS Lambda 関数に適切に AWS IAM のポリシーを設定しよう!
  • AWS Lambda 関数をモニタリングしてみよう!

builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます


筆者プロフィール

野邊 哲男
アマゾン ウェブ サービス ジャパン合同会社
AWS トレーニングサービス本部 シニアテクニカルトレーナー

自分が体験した「成功」と「失敗」、そこから「学んだこと」を皆さんにお伝えするべく、日々 AWS のトレーニングの登壇をしています。
最近は「仮面サーバーレス」として サーバーレスのトレーニングデジタルトレーニング の情報を皆様にお届けしています。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する