Invoking Lambda from SNS

Invoking Lambda from SNS

Invoking Lambda from SNS

The following pages address social networking.

https://awstut.com/en/2022/07/30/introduction-to-sns-with-cfn-email-en

In the above page, we specified an email address as the subscriber.

This time, we will check how to specify a Lambda function as a subscriber.

Environment

Diagram of invoking Lambda from SNS

The configuration is generally the same as in the page introduced at the beginning of this article.

Lambda function 2 sends a message to the SNS topic.
In other words, this function acts as a publisher.
The function gets the UNIX time from the current date/time and sends it as a message.

Specify Lambda function 1 as a subscriber to the SNS topic.
This function determines whether the UNIX time passed as a message is even or odd.

CloudFormation template files

The above configuration is built using CloudFormation.
The CloudFormation templates are located at the following URL

https://github.com/awstut-an-r/awstut-fa/blob/main/100/fa-100.yaml

Explanation of key points of the template files

(Reference) Publish to SNS with Lambda function

Resources:
  Function2:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Environment:
        Variables:
          REGION: !Ref AWS::Region
          TOPIC: !Ref TopicArn
      Code:
        ZipFile: |
          import boto3
          import datetime
          import os
          import time

          topic = os.environ['TOPIC']
          region = os.environ['REGION']

          client = boto3.client('sns', region_name=region)

          def lambda_handler(event, context):
            now = datetime.datetime.now()
            now_str = now.strftime('%Y-%m-%d %H:%M:%S.%f')
            unix_time = str(time.mktime(now.timetuple()))
            print(now_str, unix_time)

            response = client.publish(
              TopicArn=topic,
              Subject=now_str,
              Message=unix_time
              )
            print(response)
      FunctionName: !Sub "${Prefix}-function-02"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole2.Arn

  FunctionRole2:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: SNSPublishPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - sns:Publish
                Resource:
                  - !Ref TopicArn
Code language: YAML (yaml)

Publish messages from Lambda functions to SNS.
For details, please refer to the page mentioned at the beginning of this article.

For more information on how to create a Lambda function in CloudFormation, please refer to the following page.

https://awstut.com/en/2022/02/02/3-parterns-to-create-lambda-with-cloudformation-s3-inline-container

This time, we will describe the code to be invoked inline.

Specify Lambda function in SNS subscriber

Resources:
  Topic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: !Ref FunctionArn1
          Protocol: lambda
      TopicName: !Ref Prefix
Code language: YAML (yaml)

Set the subscriber with the Subscription property.
In this case, the SNS message will be received by a Lambda function, so specify the ARN of the function in the Endpoint property and “lambda” in the Protocol property.

When a Lambda function is specified as a subscriber, the SNS invokes the function internally.
Therefore, it is necessary to authorize the SNS to invoke the function.

Resources:
  SNSPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref Function1
      Action: lambda:InvokeFunction
      Principal: sns.amazonaws.com
      SourceArn: !Ref Topic
Code language: YAML (yaml)

I set it up with reference to the following official AWS page

https://aws.amazon.com/premiumsupport/knowledge-center/lambda-subscribe-sns-topic-same-account/?nc1=h_ls

Receive SNS messages by Lambda function

Resources:
  Function1:
    Type: AWS::Lambda::Function
    Properties:
      Architectures:
        - !Ref Architecture
      Code:
        ZipFile: |
          def lambda_handler(event, context):
            subject = event['Records'][0]['Sns']['Subject']
            message = event['Records'][0]['Sns']['Message']
            print(subject, message)

            unix_time = int(float(message))

            if (unix_time % 2) == 0:
              print('{int} is even !'.format(int=unix_time))
            else:
              print('{int} is odd !'.format(int=unix_time))
      FunctionName: !Sub "${Prefix}-function-01"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole1.Arn
Code language: YAML (yaml)

Messages sent out from SNS are stored in the event object.
This time, the received UNIX time is determined to be even/odd.

Architecting

Using CloudFormation, we will build this environment and check the actual behavior.

Create CloudFormation stacks and check resources in stacks

Create CloudFormation stacks.
For information on how to create stacks and check each stack, please refer to the following page

https://awstut.com/en/2021/12/11/cloudformations-nested-stack

After checking the resources in each stack, information on the main resources created this time is as follows

  • SNS topic: fa-100
  • Lambda function 2: fa-100-function-02
  • Lambda function 1: fa-100-function-01

Check the created resource from AWS Management Console.
Check the SNS topic.

Detail of SNS 1.
Detail of SNS 2.

You can see that the SNS topic has been successfully created.
You can also see that the Lambda function 1 is registered as a subscriber.

Check the Lambda function.

Detail of Lambda 1.
Detail of Lambda 2.

We can see that two functions have also been created successfully.
If we look at function 1, we can also see that invokes from SNS are allowed.

Checking Operation

1st time

Now that we are ready, we invoke Function 2.
From the Test tab of Function 2, click on “Test” to execute it.

Detail of Lambda 3.

You will see that the function has been successfully executed.
You can see that the UNIX time was calculated from the current date and time and that it was sent out as a SNS message.
This time the UNIX time was “1669204672”.

Next, check the log of Function 1.

Detail of Lambda 4.

There is evidence that the function was executed.
This means that the SNS message was published by the publisher function 2, which automatically invoked the subscriber function 1.

As a result of the even/odd determination of UNIX time, “1669204672 is even ! was output.

2nd time

Perform the same operation again.

The following is the execution log of both functions.

Detail of Lambda 5.
Detail of Lambda 6.

This time, a SNS message with UNIX time “1669204701” was sent out by function 2.
Function 1 is automatically executed in response to this and outputs “1669204701 is odd ! is odd !

Summary

We have confirmed how to specify a Lambda function to the SNS subscriber.