[アップデート] AWS SAM Connector で複数の送信先をまとめて定義出来るようになりました

2023.03.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

いわさです。

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 自体は登場したばかりですが、結構細かいアップデートが多いですね。
混乱しそうですが、色々な記述方法があるという点も覚えておきましょう。