いわさです。
AWS SAM では、昨年 10 月に SAM Connector が登場してポリシー周りをより抽象化した定義が出来るようになりました。
また、先月には SAM Connector の新しい定義方法が出来るようにもなりました。
そんな SAM Connector ですが、少し前にまた新しいことが出来るようになりました。
かなり細かいアップデートではありますが、複数送信先をまとめて定義出来るようになりました。
これまでは、ひとつの Lambda から複数の送信先リソースが存在する場合だとリソースごとに Connector プロパティを指定する必要がありました。
今回のアップデートで複数の送信先をまとめて記述出来るようになったので、大規模なサーバーレス構成の場合にかなりすっきりした記述になりそうです。
実際に使ってみたので紹介します。
アップデート前
SAM Connector なし
SAM Connector のおさらいを先に軽くしておきましょう。
ここでは簡略的に、次のように Lambda 関数から SQS へメッセージ送信するようなサーバーレスアプリケーションを作成してみます。
Function.cs
using Amazon.Lambda.Core;
using Amazon.SQS;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace hoge0306sam
{
public class Function
{
public async Task<string> FunctionHandler(string input, ILambdaContext context)
{
try
{
var sqsClient = new AmazonSQSClient();
var sqsSendResult1 = await sqsClient.SendMessageAsync(Environment.GetEnvironmentVariable("HOGE_QUEUE1"), "hoge");
System.Console.WriteLine($"SqsSendResult: {sqsSendResult1.HttpStatusCode}");
var sqsSendResult2 = await sqsClient.SendMessageAsync(Environment.GetEnvironmentVariable("HOGE_QUEUE2"), "fuga");
System.Console.WriteLine($"SqsSendResult: {sqsSendResult2.HttpStatusCode}");
}
catch (System.Exception ex)
{
System.Console.WriteLine($"SQS Error: {ex.ToString()}");
}
return "hoge";
}
}
}
ここでテンプレートを次のように定義しました。
template.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: >-
hoge0306sam
Transform:
- AWS::Serverless-2016-10-31
Resources:
helloFromLambdaFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./src/hoge0306sam/
Handler: hoge0306sam::hoge0306sam.Function::FunctionHandler
Runtime: dotnet6
Architectures:
- x86_64
MemorySize: 256
Timeout: 100
Description: A Lambda function that returns a static string.
Policies:
- AWSLambdaBasicExecutionRole
Environment:
Variables:
HOGE_QUEUE1 : !Ref sqsQueue1
HOGE_QUEUE2 : !Ref sqsQueue2
sqsQueue1:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub "${AWS::StackName}-queue1"
sqsQueue2:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub "${AWS::StackName}-queue2"
この場合、Lambda と SQS のリソースは作成されるのですが、Lambda 実行ロールに SQS へのアクセス許可が付与されていないので、権限不足で実行時にエラーとなります。
SAM Connector を使わない場合だと、Lambda だと Policies 属性を使ったり、個別に IAM ポリシーを定義する必要があります。
SAM Connector あり
これが、SAM Connector を使うことで次のように IAM ポリシーの記述方法などに依存せずに、SAM 上で抽象化した形で特定リソースから特定リソースへのアクセス許可を行うことが出来るようになりました。
template.yaml
:
Resources:
helloFromLambdaFunction:
Type: AWS::Serverless::Function
Connectors:
sqsQueue1:
Properties:
Destination:
Id: sqsQueue1
Permissions:
- Write
sqsQueue2:
Properties:
Destination:
Id: sqsQueue2
Permissions:
- Write
Properties:
CodeUri: ./src/hoge0306sam/
Handler: hoge0306sam::hoge0306sam.Function::FunctionHandler
Runtime: dotnet6
Architectures:
- x86_64
MemorySize: 256
Timeout: 100
Description: A Lambda function that returns a static string.
Policies:
- AWSLambdaBasicExecutionRole
Environment:
Variables:
HOGE_QUEUE1 : !Ref sqsQueue1
HOGE_QUEUE2 : !Ref sqsQueue2
:
ただし、この場合でも今回のように複数の送信先が存在する場合は Connectors 属性にそのリソース数だけブロックを増やす必要がありました。
アップデート後
今回のアップデートでは次のように Desctination 内にリストでの記述が出来るようになりました。
template.yaml
:
Resources:
helloFromLambdaFunction:
Type: AWS::Serverless::Function
Connectors:
sqsQueues:
Properties:
Destination:
- Id: sqsQueue1
- Id: sqsQueue2
Permissions:
- Write
Properties:
CodeUri: ./src/hoge0306sam/
Handler: hoge0306sam::hoge0306sam.Function::FunctionHandler
Runtime: dotnet6
Architectures:
- x86_64
MemorySize: 256
Timeout: 100
Description: A Lambda function that returns a static string.
Policies:
- AWSLambdaBasicExecutionRole
Environment:
Variables:
HOGE_QUEUE1 : !Ref sqsQueue1
HOGE_QUEUE2 : !Ref sqsQueue2
:
かなりシンプルに定義出来るようになりましたね。
しかも従来の記述方法は引き続き利用出来るので、今回のアップデートによって既存のテンプレートを修正する必要はありません。
なお、今回は送信先がどちらも SQS ですが、SQS と Dynamo と S3 のように異なるリソースを組み合わせることも出来ます。
論理 ID が今までと違う
今回の記述方法でデプロイすると、IAM マネージドポリシーの論理 ID が従来に加えてDestinationXXX
というサフィックスが付与されるようになっています。
:
Waiting for changeset to be created..
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add helloFromLambdaFunctionsqsQueuesPolicyDestination0 AWS::IAM::ManagedPolicy N/A
+ Add helloFromLambdaFunctionsqsQueuesPolicyDestination1 AWS::IAM::ManagedPolicy N/A
- Delete helloFromLambdaFunctionsqsQueue1Policy AWS::IAM::ManagedPolicy N/A
- Delete helloFromLambdaFunctionsqsQueue2Policy AWS::IAM::ManagedPolicy N/A
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:123456789012:changeSet/samcli-deploy1678095491/acabb243-6bd5-488f-ae10-415aa84d4e10
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]:
そのため、先程のスタックを更新しようとすると新規作成されます。
SAM を使う上であまりこのあたりは気にしないと思いますが。私はスタック更新の際に「あれ?」と思ったので、こういった細かい違いがある点は知っておくと良いと思います。
さいごに
本日は AWS SAM Connector で複数の送信先をまとめて定義出来るようになったので使い方などを確認しました。
SAM Connector 自体は登場したばかりですが、結構細かいアップデートが多いですね。
混乱しそうですが、色々な記述方法があるという点も覚えておきましょう。