1
votes

Creating Lambda functions using serverless and I am trying to create a SNS topic with Email protocol. I want to then pass that arn as an ENV variable to a lambda function. I cannot find any documentation other than appending a topic to function in the creation process. Any help/examples is appreciated (I am working in python).

To elaborate, the below would create a function with an sns topic attached.:

functions:
  dispatcher:
    handler: dispatcher.dispatch
    events:
      - sns: dispatch

Looking to do "something" like (this does not work... just an example):

events:
  sns:
    topicName: thing
    subscription: 
      - endPoint: "[email protected]"
      - protocol: "email"

functions:
  dispatcher:
    handler: dispatcher.dispatch
    environment:
      SNS_TOPIC: {Ref: ThingSnsTopic}

Ideally the sns part would be created outside of the functions, and the I could reference the sns arn and use it as a env var

2

2 Answers

0
votes

When using Serverless, you can use environment variables in your .yml file like this:

myProperty: ${env:MY_ENV_VAR}

If you want to bind it to SNS, your .yml file should look something like:

service: my-service


provider:
  name: aws
  runtime: python3.6


functions:
  hello:
    handler: handler.hello

   events:
     - sns: ${env:MY_ENV_VAR}

Now, if you mean you'd like to accesss an Environment Variable from within your Lambda function, it will depend on what language you are coding on, but since you're using Python, it'd be something like:

import os

print("environment variable: " + os.environ['MY_ENV_VAR'])

EDIT: After the OP's comment, I think I fully understand the problem:

ARNs are predictable values. They're pretty much a concatenation of your region/user-id/topic-name, like this:

arn:aws:sns:us-east-1:00000000:aaa

If you provide an environment variable to your Serverless.yml, such as:

provider:
 name: aws
 stage: ${opt:stage, 'dev'}
 environment:
  MY_SECRET: ${env:MY_ENV_VAR}

You could then programmatically create a Subscription to that topic based on the predictable subscription's ARN + the environment variable you defined.

Another option would be to define the Outputs section on your .yml file and use the CloudFormation Event to trigger a Lambda which will programatically create a subscription based on the outputted ARN

0
votes

I create SNS topic and subscription in the resource section and then add a policy in the lambda role which can be assigned to lambda function, for example

Resources:  
  # SNS Topic Resources for email notification
  uploadProgressNotificationTopic:
    Type: AWS::SNS::Topic
    Properties:
      DisplayName: "The notification topic for upload progress"
      TopicName: ${self:custom.uploadProgressNotificationTopicName}

  # SNS email subscription for upload completion
  emailToSNSUploadProgressNotificationTopicSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      Endpoint: "$subscription_email_here"
      Protocol: "email"
      TopicArn: ${self:custom.uploadProgressNotificationTopicArn}

and then your lambda roles resource look like below (personally I separate the SNS and lambda roles resources into different yaml)

  Resources: 
    # Upload lambda roles
      UploadLambdaRole:
        Type: AWS::IAM::Role
        Properties:
          RoleName: ${self:custom.uploadLambdaRoleName}
          AssumeRolePolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Principal:
                  Service: lambda.amazonaws.com
                Action:
                  - sts:AssumeRole
          Policies:
            - PolicyName: AccessUploadProgressNotificationSNSTopic
                PolicyDocument:
                  Statement:
                    - Effect: Allow
                      Action:
                        - "sns:*"
                      Resource: "${self:custom.uploadProgressNotificationTopicArn}"

and lastly you can use this lambda role in your lambda function like below

upload:
  handler: src/handler/upload-handler
  role: UploadLambdaRole
  ...

So what this functionality does is your lambda can fire an message to your SNS topic and SNS will forward the message to your email.