[アップデート] AWS SAM Connector がリソース属性として定義出来るようになり、読みやすくなりました

2023.02.10

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

いわさです。

AWS SAM ではリソースの実行ポリシーなどの記述を簡略化出来る SAM Connector という機能があり、以前紹介させて頂きました。

本日こちらに関連した次のアップデートがあり、SAM Connector を定義する際に新しい方法が使えるようになっています。

別の SAM リソースではなく、ソースリソースの属性としてインラインで定義出来るように

例えば Lambda から SNS トピックへメッセージを送信する場合だと、Lambda へ SNS への送信許可ポリシーを与えてやる必要があります。
以前までは SAM Connector を使って以下のように定義することが出来ました。ハイライト部分です。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ---
Resources:
  HogeFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.9
      Handler: index.lambda_handler     
      InlineCode: !Sub |
        import boto3
        client = boto3.client('sns')
        def lambda_handler(event, context):
            
            params = {
            'TopicArn': '${HogeTopic}',
            'Message': 'hoge message from lambda'
            }
            client.publish(**params)

      MemorySize: 128
      Timeout: 100
      Architectures:
        - x86_64
      Policies:
        - AWSLambdaBasicExecutionRole 

  HogeTopic:
    Type: AWS::SNS::Topic

  HogeConnector:
    Type: AWS::Serverless::Connector
    Properties:
      Source:
        Id: HogeFunction
      Destination:
        Id: HogeTopic
      Permissions:
        - Write

これでカスタムマネージドポリシーが作成されて Lambda の実行ロールにアタッチされます。
この時点で抽象化されているので個人的には最高なのですが、言われてみれば確かに Lambda 関数とちょっと離れて定義してあるので、コードを読む際などにはひとつコンテキストが増えるような印象があります。

今回のアップデートによって次のように、ソースリソースの Connectors プロパティ内に定義することが出来るようになりました。
コネクター内の記述方法は以前と同じですが、Source プロパティは対象リソースになるので記述が不要になっています。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ---
Resources:
  HogeFunction:
    Type: AWS::Serverless::Function
    Connectors:
      HogeConnector:
        Properties:
          Destination:
            Id: HogeTopic
          Permissions:
            - Write
    Properties:
      Runtime: python3.9
      Handler: index.lambda_handler     
      InlineCode: !Sub |
        import boto3
        client = boto3.client('sns')
        def lambda_handler(event, context):
            
            params = {
            'TopicArn': '${HogeTopic}',
            'Message': 'hoge message from lambda'
            }
            client.publish(**params)
      MemorySize: 128
      Timeout: 100
      Architectures:
        - x86_64
      Policies:
        - AWSLambdaBasicExecutionRole 

  HogeTopic:
    Type: AWS::SNS::Topic

IAM ロールやセキュリティグループなどで、個別のルールやポリシーをインラインで定義するべきか否かみたいなところはあると思いますが、SAM の場合は AWS リソースに対する抽象化度合いが良い感じなのが良い点のひとつだと思っています。
例えば詳細な設定の API Gateway とかを CloudFormation で定義すると様々なリソースを組み合わせる必要があって少し苦労しますが SAM だと楽に定義出来る上に後からコードを読んでもスタック全体の構造が直感的に理解しやすいです。

ちなみに作成されるリソースとしては以前と変わらず、カスタムマネージドポリシーが Lambda 実行ロールにアタッチされています。

今回リソース内に定義出来るので関係するリソースが増えても、例えば次のようにトピックが増えたとしても Connectors 内にまとまるので、コード見るだけでポリシーとして網羅されてるのかもすぐわかるようになりましたね。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ---
Resources:
  HogeFunction:
    Type: AWS::Serverless::Function
    Connectors:
      HogeConnector:
        Properties:
          Destination:
            Id: HogeTopic
          Permissions:
            - Write
      FugaConnector:
        Properties:
          Destination:
            Id: FugaTopic
          Permissions:
            - Write
    Properties:
      Runtime: python3.9
      Handler: index.lambda_handler     
      InlineCode: !Sub |
        import boto3
        client = boto3.client('sns')
        def lambda_handler(event, context):
            
            params = {
            'TopicArn': '${HogeTopic}',
            'Message': 'hoge message from lambda'
            }
            client.publish(**params)
      MemorySize: 128
      Timeout: 100
      Architectures:
        - x86_64
      Policies:
        - AWSLambdaBasicExecutionRole 

  HogeTopic:
    Type: AWS::SNS::Topic

  FugaTopic:
    Type: AWS::SNS::Topic

ソース側での定義が必要

以前まではどちらかというと 2 つのリソースの間に存在するコンポーネントの位置づけという印象だったのですが、今回の機能は送信元リソース側での定義となります。

次のように送信先リソースで、以前のように Source プロパティのみを定義して試してみました。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ---
Resources:
  HogeFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.9
      Handler: index.lambda_handler     
      InlineCode: !Sub |
        import boto3
        client = boto3.client('sns')
        def lambda_handler(event, context):
            
            params = {
            'TopicArn': '${HogeTopic}',
            'Message': 'hoge message from lambda'
            }
            client.publish(**params)
      MemorySize: 128
      Timeout: 100
      Architectures:
        - x86_64
      Policies:
        - AWSLambdaBasicExecutionRole 

  HogeTopic:
    Type: AWS::SNS::Topic
    Connectors:
      HogeConnector:
        Type: AWS::Serverless::Connector
        Properties:
          Source:
            Id: HogeFunction
          Permissions:
            - Write

しかし、次のように Destination が必須というエラーが発生します。
今回の機能を使う場合は送信元リソースへの定義が必要です。

早速英語版ドキュメントも更新されていましたので、利用にあたって以下も確認頂くと良いと思います。

さいごに

本日は AWS SAM Connector がリソース属性として定義出来るようになったので使ってみました。

地味ですが使い勝手が良くなりそうで、私は嬉しいですね。
利用はオプションで、従来のようにコネクターリソースを分けたりあるいはポリシーで直接記述する使い方も引き続き出来るので、気の向いた時にでも使ってみてください。