You can use a Lambda function in one AWS account to subscribe to an Amazon SNS topic in a separate AWS account. In this tutorial, you use the AWS Command Line Interface to perform AWS Lambda operations such as creating a Lambda function, creating an Amazon SNS topic and granting permissions to allow these two resources to access each other.
This tutorial assumes that you have some knowledge of basic Lambda operations and the Lambda console. If you haven't already, follow the instructions in Create a Lambda function with the console to create your first Lambda function.
To complete the following steps, you need a command line terminal or shell to run commands. Commands and the expected output are listed in separate blocks:
aws --version
You should see the following output:
aws-cli/2.0.57 Python/3.7.4 Darwin/19.6.0 exe/x86_64
For long commands, an escape character (\
) is used to split a command over multiple lines.
On Linux and macOS, use your preferred shell and package manager. On Windows 10, you can install the Windows Subsystem for Linux to get a Windows-integrated version of Ubuntu and Bash.
In the tutorial, you use two accounts. The AWS CLI commands illustrate this by using two named profiles, each configured for use with a different account. If you use profiles with different names, or the default profile and one named profile, modify the commands as needed.
In Account A, create the source Amazon SNS topic.
aws sns create-topic --name sns-topic-for-lambda --profile accountA
After creating the topic, record its Amazon Resource Name (ARN). You need it later when you add permissions to the Lambda function to subscribe to the topic.
In Account B, create the execution role that gives your function permission to access AWS resources.
To create an execution role
-
Open the roles page in the IAM console.
-
Choose Create role.
-
Create a role with the following properties.
- Trusted entity – AWS Lambda.
- Permissions – AWSLambdaBasicExecutionRole.
- Role name – lambda-sns-role.
The AWSLambdaBasicExecutionRole policy has the permissions that the function needs to write logs to CloudWatch Logs.
In Account B, create the function that processes events from Amazon SNS. The following example code receives an Amazon SNS event input and processes the messages that it contains. For illustration, the code writes some of the incoming event data to CloudWatch Logs.
Note
For sample code in other languages, see Sample function code.
Example index.js
console.log('Loading function');
exports.handler = function(event, context, callback) {
// console.log('Received event:', JSON.stringify(event, null, 4));
var message = event.Records[0].Sns.Message;
console.log('Message received from SNS:', message);
callback(null, "Success");
};
To create the function
-
Copy the sample code into a file named
index.js
. -
Create a deployment package.
zip function.zip index.js
-
Create a Lambda function with the
create-function
command.aws lambda create-function --function-name Function-With-SNS \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs12.x \ --role arn:aws:iam::<AccountB_ID>:role/service-role/lambda-sns-execution-role \ --timeout 60 --profile accountB
After creating the function, record its function ARN. You need it later when you add permissions to allow Amazon SNS to invoke your function.
In Account A, grant permission to Account B to subscribe to the topic:
aws sns add-permission --label lambda-access --aws-account-id <AccountB_ID> \
--topic-arn arn:aws:sns:us-east-2:<AccountA_ID>:sns-topic-for-lambda \
--action-name Subscribe ListSubscriptionsByTopic --profile accountA
In Account B, add the Lambda permission to allow invocation from Amazon SNS.
aws lambda add-permission --function-name Function-With-SNS \
--source-arn arn:aws:sns:us-east-2:<AccountA_ID>:sns-topic-for-lambda \
--statement-id function-with-sns --action "lambda:InvokeFunction" \
--principal sns.amazonaws.com --profile accountB
You should see the following output:
{
"Statement": "{\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":
\"arn:aws:sns:us-east-2:<AccountA_ID>:sns-topic-for-lambda\"}},
\"Action\":[\"lambda:InvokeFunction\"],
\"Resource\":\"arn:aws:lambda:us-east-2:<AccountB_ID>:function:Function-With-SNS\",
\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"sns.amazonaws.com\"},
\"Sid\":\"function-with-sns1\"}"
}
Do not use the --source-account
parameter to add a source account to the Lambda policy when adding the policy. Source account is not supported for Amazon SNS event sources and will result in access being denied.
Note
If the account with the SNS topic is hosted in an opt-in region, you need to specify the region in the principal. For an example, see Invoking Lambda functions using Amazon SNS notifications in the Amazon Simple Notification Service Developer Guide.
In Account B, subscribe the Lambda function to the topic. When a message is sent to the sns-topic-for-lambda
topic in Account A, Amazon SNS invokes the Function-With-SNS
function in Account B.
aws sns subscribe --protocol lambda \
--topic-arn arn:aws:sns:us-east-2:<AccountA_ID>:sns-topic-for-lambda \
--notification-endpoint arn:aws:lambda:us-east-2:<AccountB_ID>:function:Function-With-SNS \
--profile accountB
You should see the following output:
{
"SubscriptionArn": "arn:aws:sns:us-east-2:<AccountA_ID>:sns-topic-for-lambda:5d906xxxx-7c8x-45dx-a9dx-0484e31c98xx"
}
The output contains the ARN of the topic subscription.
In Account A, test the subscription. Type Hello World
into a text file and save it as message.txt
. Then run the following command:
aws sns publish --message file://message.txt --subject Test \
--topic-arn arn:aws:sns:us-east-2:<AccountA_ID>:sns-topic-for-lambda \
--profile accountA
This will return a message id with a unique identifier, indicating the message has been accepted by the Amazon SNS service. Amazon SNS will then attempt to deliver it to the topic's subscribers. Alternatively, you could supply a JSON string directly to the message
parameter, but using a text file allows for line breaks in the message.
To learn more about Amazon SNS, see What is Amazon Simple Notification Service.
You can now delete the resources that you created for this tutorial, unless you want to retain them. By deleting AWS resources that you're no longer using, you prevent unnecessary charges to your AWS account.
In Account A, clean up your Amazon SNS topic.
To delete the Amazon SNS topic
-
Open the Topics page of the Amazon SNS console.
-
Select the topic you created.
-
Choose Delete.
-
Enter delete me in the text box.
-
Choose Delete.
In Account B, clean up your execution role, Lambda function, and Amazon SNS subscription.
To delete the execution role
-
Open the Roles page of the IAM console.
-
Select the execution role that you created.
-
Choose Delete role.
-
Choose Yes, delete.
To delete the Lambda function
-
Open the Functions page of the Lambda console.
-
Select the function that you created.
-
Choose Actions, then choose Delete.
-
Choose Delete.
To delete the Amazon SNS subscription
-
Open the Subscriptions page of the Amazon SNS console.
-
Select the subscription you created.
-
Choose Delete, Delete.