モジュール 4: 他の AWS サービスとの連携
学習モジュール
他の AWS サービスと連携する方法はいくつかあります。
アクセスしているサービスが SQL Server や Postgres などの AWS RDS データベースである場合は、データベースを自分のコンピューターまたはデータセンターでホストする場合と同じライブラリを使用します。ユーザー名とパスワードを含む接続文字列、または任意の別の形式の認証が必要です。データベースを日常的に使用するのと何も変わりません。データベースサーバーにアクセスするには、追加の権限は必要ありません。唯一の注意点は、データベースがパブリックにアクセスできない場合、Lambda を VPC に接続する必要があることです (そのプロセスには追加の権限が必要です)。
Lambda 関数が S3、DynamoDB、Kinesis などを使用している場合は、AWS SDK を使用してそれらのサービスとやり取りします。Lambda 関数が実行されているロールには、各サービスとやり取りするための適切な権限が必要です。たとえば、S3 バケットに項目を追加する場合、ロールにはそのバケットへの書き込み権限が必要です。DynamoDB テーブルから項目を取得する場合、ロールにはそのテーブルから読み取る権限が必要です。
3 番目のシナリオは、あるイベントに応答して別のサービスに Lambda 関数をトリガーさせたい場合です。たとえば、特定の S3 バケットに新しい項目が追加されたときや、Kinesis ストリームにイベントが到着したときに、Lambda 関数をトリガーしたい場合があります。そのためには、Lambda 関数が「リソースベースのポリシー」を使用する必要があります。このポリシーは、他のサービスに Lambda 関数を呼び出す権限を与えます。
所要時間
30 分
Lambda 関数から RDS データベースサーバーにアクセスする
SQL Server、Postgres、MySQL などの使い慣れたサービスを使用するメリットは、コードの観点から見ると、Lambda 関数から呼び出すときに何も変更する必要がないことです。エンティティフレームワーク/ADO/NpgSql などは、AWS がホストするデータベースでも、ローカル/ラック型データベースでも同様に機能します。同じように呼びますが、AWS SDK ライブラリは必要ありません。もちろん、関連する NuGet パッケージをプロジェクトに追加する必要があります。しかし、それ以外はすべて同じです。
Lambda 関数から AWS サービスにアクセスする
2.任意のロールにアタッチできるスタンドアロンポリシーとして。AWS では、後者は顧客管理ポリシーと呼ばれます。
ロールにはできるだけ少ない権限を与えることをお勧めします。DynamoDB テーブルからデータを読み取る次の例では、Lambda ロールに DynamoDB: GetItem と dynamodb: DescribeTable という 2 つの権限を付与する必要があります。また、それらの権限を関心のある特定のテーブルに制限します。
まず、People という名前の新しい DynamoDB テーブルを作成します。Windows コマンドプロンプトを使用している場合は、次のコマンドが PowerShell でも機能します。Linux シェルでは、文字列に対して異なるエスケープ処理が必要になります。
次のクエリを実行します。
aws dynamodb create-table --table-name People --attribute-definitions AttributeName=PersonId,AttributeType=N --key-schema AttributeName=PersonId,KeyType=HASH --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
テーブルにいくつかの項目を追加します。
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"1"},"State":{"S":"MA"}, "FirstName": {"S":"Alice"}, "LastName": {"S":"Andrews"}}'
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"2"},"State":{"S":"MA"}, "FirstName": {"S":"Ben"}, "LastName": {"S":"Bradley"}}'
aws dynamodb put-item --table-name People --item '{"PersonId":{"N":"3"},"State":{"S":"MA"}, "FirstName": {"S":"Claire"}, "LastName": {"S":"Connor"}}'
次に、以下を使用して Lambda 関数を作成します。
dotnet new lambda.EmptyFunction -n LambdaFunctionDynamoDB
cd LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB
dotnet add package AWSSDK.DynamoDBv2
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace LambdaFunctionDynamoDB ;
public class Function
{
public async Task<string> FunctionHandler(ILambdaContext lambdaContext)
{
AmazonDynamoDBConfig clientConfig = new AmazonDynamoDBConfig();
AmazonDynamoDBClient client = new AmazonDynamoDBClient(clientConfig);
DynamoDBContext dynamoDbContext = new DynamoDBContext(client);
Person person = await dynamoDbContext.LoadAsync<Person>(1);
return $"{person.FirstName} {person.LastName} lives in {person.State}";
}
}
[DynamoDBTable("People")]
public class Person
{
[DynamoDBHashKey]
public int PersonId {get; set;}
public string State {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
dotnet lambda deploy-function LambdaFunctionDynamoDB
以下を使用して Lambda 関数を AWS Lambda にデプロイします。
dotnet lambda デプロイ - Lambda 関数 DynamoDB
次に、「コードに AWS 認証情報を提供する IAM ロールを選択してください」という質問が表示され、以前に作成したロールのリストが表示される場合がありますが、リストの一番下に「*** Create new IAM Role ***」というオプションがあり、そのオプションの横にその番号を入力します。
「新しい IAM ロールの名前を入力してください:」と表示されます。「LambdaFunctionDynamoDBRoleと入力します。」
次に、「新しいロールにアタッチして権限を付与する IAM ポリシーを選択」するように求められ、ポリシーのリストが表示されます。AWSLambdaBasicExecutionRole を選択してください。私のリストの 6 番目です。(AWSLambdaDynamoDBExecutionRole というポリシーがあることは知っていますが、このモジュールの目的は、必要な権限を自分で追加する方法を示すことです)。
その後、Lambda 関数を再度呼び出します。
dotnet lambda invoke-function LambdaFunctionDynamoDB
"errorMessage": "User: arn:aws:sts::YOUR_ACCOUNT_NUMBER:assumed-role/LambdaFunctionDynamoDB Role/LambdaFunctionDynamoDB is not authorized to perform: dynamodb:DescribeTable on resource: arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People because no identity-based policy allows the dynamodb:DescribeTable action"
これは、Lambda 関数が実行されているロールに必要な dynamodb: DescribeTable 権限がないことを示しています。
これを修正するには、ロールに dynamodb: DescribeTable アクセス権限を付与するポリシーを追加する必要があります。前述のように、インラインポリシー (このロールのみ) またはスタンドアロンポリシー (すべてのロールで使用可能) を追加できます。
LambdaFunctionDynamoDB /src/LambdaFunctionDynamoDB フォルダーに DynamoDBAccessPolicy.json という名前のファイルを作成します。
DynamoDBAccessPolicy を編集しますが、リソースには自分のアカウント番号を使用してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable"
],
"Resource": "arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People"
}
]
}
aws iam put-role-policy --role-name LambdaFunctionDynamoDBRole --policy-name LambdaFunctionDynamoDBAccess --policy-document file://DynamoDBAccessPolicy.json
dotnet lambda deploy-function LambdaFunctionDynamoDB
dotnet lambda invoke-function LambdaFunctionDynamoDB
今回のメッセージは:
"errorMessage": "User: arn:aws:sts::YOUR_ACCOUNT_NUMBER:assumed-role/LambdaFunctionDynamoDB Role/LambdaFunctionDynamoDB is not authorized to perform: dynamodb:GetItem on resource: arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People because no identity-based policy allows the dynamodb:GetItem action",
DynamoDBAccessPolicy.json ファイルを次のように更新します-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DescribeTable",
"dynamodb:GetItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:YOUR_ACCOUNT_NUMBER:table/People"
}
]
}
dotnet lambda deploy-function LambdaFunctionDynamoDB
dotnet lambda invoke-function LambdaFunctionDynamoDB
Amazon Lambda Tools for .NET Core applications (5.4.2)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet
Payload:
"Alice Andrews lives in MA"
また、使用している SDK メソッドにカーソルを合わせる方法もあります。メタデータには、権限に関する有用な情報が含まれている場合があります。すべてのメソッドメタデータに権限情報が含まれるわけではありません。
これで、関数に必要な権限を確認する方法と、Lambda 関数が実行されているロールに正しいアクセス権限を付与する方法がわかりました。
他のサービスが Lambda 関数を呼び出すことを許可する
前のセクションでは、他のサービスでアクションを実行する権限を Lambda 関数に付与する方法について説明しました。このセクションでは、他のサービスに Lambda 関数を呼び出すアクセス権限を与える方法を説明します。
serverless.* テンプレートを使用している場合は、Lambda 関数を呼び出すために必要なアクセス権限をすでに API Gateway に付与しているはずです。このような機能をデプロイした場合は、[設定] タブに移動し、左側の [権限] を選択し、[リソースベースのポリシー] セクションまでスクロールします。API ゲートウェイが Lambda 関数を呼び出すことを許可するポリシーが表示されます。このポリシーは、dotnet lambda デプロイサーバーレスコマンドと、プロジェクト内の serverless.template によって追加されました。
以下の画像では、API Gateway が Lambda 関数を呼び出すことを許可する 2 つのポリシーステートメントを示しています。
S3 バケットの作成
us-east-1 にバケットを置きたい場合は、次のコマンドを使用できます-
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course
aws s3api create-bucket --bucket my-unique-bucket-name-lambda-course --create-bucket-configuration LocationConstraint=REGION
Lambda 関数を作成する
コマンドラインから以下を実行します。
dotnet new lambda.S3 -n S3EventHandler
cd S3EventHandler/src/S3EventHandler
public async Task FunctionHandler(S3Event evnt, ILambdaContext context)
{
context.Logger.LogInformation($"A S3 event has been received, it contains {evnt.Records.Count} records.");
foreach (var s3Event in evnt.Records)
{
context.Logger.LogInformation($"Action: {s3Event.EventName}, Bucket: {s3Event.S3.Bucket.Name}, Key: {s3Event.S3.Object.Key}");
if (!s3Event.EventName.Contains("Delete"))
{
try
{
var response = await this.S3Client.GetObjectMetadataAsync(s3Event.S3.Bucket.Name, s3Event.S3.Object.Key);
context.Logger.LogInformation( $"The file type is {response.Headers.ContentType}");
}
catch (Exception e)
{
context.Logger.LogError(e.Message);
context.Logger.LogError($"An exception occurred while retrieving {s3Event.S3.Bucket.Name}/{s3Event.S3.Object.Key}. Exception - ({e.Message})");
}
}
else
{
context.Logger.LogInformation($"You deleted {s3Event.S3.Bucket.Name}/{s3Event.S3.Object.Key}");
}
}
}
S3 イベントがオブジェクトの削除に対する応答である場合、関数はバケット/キー名を CloudWatch に記録します。
Lambda 関数をデプロイする
dotnet lambda deploy-function S3EventHandler
次に、「コードに AWS 認証情報を提供する IAM ロールを選択してください」という質問が表示され、以前に作成したロールのリストが表示される場合がありますが、リストの一番下に「*** Create new IAM Role ***」というオプションがあり、そのオプションの横にその番号を入力します。
「新しい IAM ロールの名前を入力してください:」と表示されます。「S3EventHandlerRole」と入力します。
次に、「新しいロールにアタッチして権限を付与する IAM ポリシーを選択」するように求められ、ポリシーのリストが表示されます。AWSLambdaBasicExecutionRole を選択してください。私のリストの 6 番目です。GetObjectMetadataAsync (..) 呼び出しを機能させるには、S3 バケットへのアクセスを許可するポリシーを追加する必要があります。
Lambda 関数にオブジェクトメタデータを取得する権限を付与する
その方法をいくつか見ていきましょう。
ポリシーは次のようになりますが、リソースにはバケット名が表示されます。末尾の /* に注意してください。これは、s3: GetObject がバケット内のすべてのオブジェクトに適用されることを意味します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::my-unique-bucket-name-lambda-course/*"
}
]
}
aws iam create-policy --policy-name S3AccessPolicyForCourseBucket --policy-document file://S3AccessPolicyForCourseBucket.json
次に、以前に作成したロールにポリシーをアタッチします。次のクエリを実行します。
aws iam attach-role-policy --role-name S3EventHandlerRole --policy-arn arn:aws:iam::694977046108:policy/S3AccessPolicyForCourseBucket
[設定] タブをクリックし、左側の [権限] をクリックして、ロールの名前をクリックします。
[ Add permissions (権限の追加)] と [ Attach policies (ポリシーを添付する)] をクリックします。
[Create Policy (ポリシーの作成)] をクリックします。
「アクション」セクションで「getobject」と入力し、リストから「GetObject」を選択します。
リソースセクションで [特定] を選択し、[Add ARN (ARN の追加)] をクリックします。
[ポリシーの作成] をクリックしたタブに戻ります。以下の手順を実行してください。
1.ポリシーのリストをリロードする
2.フィルタにS3AccessPolicyForCourseBucket を入力します
3.ポリシーの横にあるボックスにチェックを入れてください
4.[Attach policies (ポリシーを添付する)] をクリックします。
この時点で、S3 バケット、Lambda 関数、S3 バケットからオブジェクトメタデータを取得するために必要な権限が揃っています。
次は S3 バケットを Lambda 関数に接続して、作成イベントと削除イベントによって Lambda 関数がトリガーされるようにします。
S3 バケットから Lambda 関数をトリガーする
S3 https://s3.console.aws.amazon.com/s3/buckets のバケットのリストを開きます。
作成したものをクリックします。
「イベント通知」セクションまでスクロールします。
「イベント通知を作成」をクリックします。
イベント通知の名前を入力します。
左側の最初の 2 つのチェックボックス ([すべてのオブジェクト作成イベント] と [すべてのオブジェクト削除イベント]) を選択します。
一番下の「目的地」セクションまでスクロールします。
送信先として Lambda 関数を選択します。
ドロップダウンリストに、以前に作成した Lambda 関数の名前を入力します。
[変更を保存] をクリックします。
AWS コンソールで、前に作成した Lambda 関数に移動します。
S3 が Lambda 関数のトリガーとしてリストされるようになったことに注意してください。
[設定] タブをクリックし、左側の [権限] をクリックします。
S3 が Lambda 関数を呼び出すことを許可するポリシーステートメントが表示されます。
テストしてみる
代わりに、Lambda 関数が CloudWatch にログを記録するので、そこで関数が機能していることを確認する必要があります。
コンピュータ上にテキストファイルを作成して S3 にアップロードします。
コマンドラインから、以下を実行します。
aws s3api put-object --bucket my-unique-bucket-name-lambda-course --key Hello.txt --body Hello.txt --content-type "text/plain"
aws s3api delete-object --bucket my-unique-bucket-name-lambda-course --key Hello.txt
次に、AWS コンソールの Lambda 関数に移動し、ログを確認します。
[監視] タブをクリックし、[CloudWatch でログを表示] をクリックします。
手順は 3 つとも同様です。AWS 拡張機能を開き、CloudWatch ログをクリックして、/aws/Lambda/S3EventHandler のログストリーム/グループを探します。次に、最新のストリームを開きます。
手順は 3 つとも同様です。AWS 拡張機能を開き、CloudWatch ログをクリックして、/aws/Lambda/S3EventHandler のログストリーム/グループを探します。次に、最新のストリームを開きます。
まとめ
ここで重要なポイントは、Lambda 関数が他の AWS サービスとやり取りできるようにするには、そのサービス上で動作するためのアクセス権限を関数に与える必要があるということです。
他のサービスで関数を呼び出したい場合は、リソースベースのポリシーを使用して、それらのサービスが関数にアクセスできるようにする必要があります。
知識のチェック
1.別のサービスで Lambda 関数を呼び出したい場合、何をする必要がありますか?(1 つ選択してください)
b.呼び出し元サービスに Lambda 関数を呼び出すアクセス権限を与えるリソースベースのポリシードキュメントを作成する
c.何もありません。Lambda は他のすべての AWS サービスを信頼しています
d.Lambda 関数が 1 として実行するロールに正しいアクセス権限を追加します。
2.AWS サービスにアクセスする権限をロールに付与するには、ロールに何を追加する必要がありますか?(1 つ選択してください)
b.リソースベースのポリシー
c.必要な権限を持つポリシー
d.アクセス制御リスト文書
3.Lambda 関数が実行されるロールで使用する顧客管理ポリシーを作成するには、次の 2 つの方法がありますか?(2 つ選択してください)
a.コマンドラインを使用する:
b.関数のソースコードに含める
c.その AWS コンソール経由
d.関数を実行するときにペイロードに追加します
回答:1-b、2-c、3-ac
まとめ
ここで重要なポイントは、Lambda 関数が他の AWS サービスとやり取りできるようにするには、そのサービス上で動作するためのアクセス権限を関数に与える必要があるということです。
他のサービスで関数を呼び出したい場合は、リソースベースのポリシーを使用して、それらのサービスが関数にアクセスできるようにする必要があります。