Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke Lambda using SNS from Outside Account

I've been following the following blog post from Amazon (Scenario 3: Triggering a Lambda function from an Amazon S3 bucket notification in another account) about authorizing Lambda functions for various uses. I would like to setup a Lambda function to accept SNS messages from external accounts (external to the acct with the lambda function).

https://aws.amazon.com/blogs/compute/easy-authorization-of-aws-lambda-functions/

I was expecting to add the permission to invoke the function remotely as follows:

$ aws lambda add-permission \
     --function-name MyFunction \
     --region us-west-2 \
     --statement-id Id-123 \
     --action "lambda:InvokeFunction" \
     --principal sns.amazonaws.com \
     --source-arn arn:aws:sns:::<topic name> \
     --source-account <account number> \
     --profile adminuser

I then attempted to go to my SNS topic and set Lambda as the endpoint, and type in the remote ARN for the lambda function in the first account. This doesn't work so well, as the endpoint expects an arn for a function in the account...

Plan B: Try creating the subscription via the CLI to circumvent the limitation in the console...

 aws sns --profile adminuser \
     --region us-west-2 subscribe 
     --topic-arn arn:aws:sns:us-west-2:<account #>:<topic name> 
     --protocol lambda 
     --notification-endpoint arn:aws:lambda:us-west-2:<account id>:function:<lambda function name>

Response:
A client error (AuthorizationError) occurred when calling the Subscribe operation: The account <account id> is not the owner of the lambda function arn:aws:lambda:us-west-2:<account id>:function:<function name>

Has anyone been able to invoke a Lambda Function from a "remote" SNS in another account? I'm a little stumped as to where I may have gone wrong... Based on the note in the blog post, I fully expected a remote SNS to work:
Note: Amazon SNS (Simple Notification Service) events sent to Lambda works the same way, with “sns.amazonaws.com” replacing “s3.amazonaws.com” as the principal.

like image 449
CloudTreading Avatar asked Jan 12 '16 16:01

CloudTreading


3 Answers

You can if the provider account authorizes the consumer account that owns the lambda to subscribe to the SNS topic. This is can be done in the "Edit topic policy" under the topics page.

Here's a summary of the steps to allow a lambda to listen to an SNS topic from an external account:

  1. Consumer account creates lambda,
  2. Consumer account adds event source to lambda in AWS console by specifying the provider's SNS topic ARN (don't worry about error messages here),
  3. Provider account adds SNS subscription permissions to a consumer IAM account created in the third-party's AWS account (done via "edit topic policy" mentioned above),
  4. Consumer uses the IAM account from step 2 to add subscription to provider account using AWS CLI.

Example command that worked for me previously for step 4:

aws sns subscribe --topic-arn <provider_sns_arn> --protocol lambda --notification-endpoint <consumer_lambda_arn> --profile consumer-IAM-account
like image 179
Daniel Avatar answered Oct 09 '22 08:10

Daniel


Was having the similar requirement today. In summary there are 3 steps. Let's assume 111111111 is the producer account which has the SNS topic and 2222222222 is the consumer which has the lambda, and

  1. Allowing the Lambda function to subscribe to the topic

    aws sns --profile SNS_Owner_Profile add-permission \  
          --topic-arn "arn:aws:sns:us-east-1:111111111:your-sns-top" \  
          --label "AllowCrossAccountSns" \  
          --aws-account-id "2222222222" \  
          --action-name "Receive" "Subscribe"  
    
  2. allow the topic to invoke the Lambda function,

    aws lambda --profile Lambda_Owner_Profile add-permission \                                                                                                                     
          --function-name "your-lambda-function" \  
          --statement-id "allowCrossAccountSNS" \  
          --principal "sns.amazonaws.com" \  
          --action "lambda:InvokeFunction" \  
          --source-arn "arn:aws:sns:us-east-1:111111111:your-sns-top"  
    
  3. subscribe the lambda function to the topic.

    aws sns --profile Lambda_Owner_Profile subscribe \                                                                                                                          
          --topic-arn "arn:aws:sns:us-east-1:111111111:your-sns-top" \  
          --protocol "lambda" \  
          --notification-endpoint "arn:aws:lambda:us-east-1:2222222222:function:your-lambda-function" 
    
like image 35
LeOn - Han Li Avatar answered Oct 09 '22 07:10

LeOn - Han Li


In AWS Lambda Developer Guide there is a tutorial where AWS CLI commands are used to set up an invocation of a Lambda function from SNS that belongs to another account.

The procedure is quite similar as the procedure in the accepted answer. The subscription doesn't have to be confirmed. It was ready for testing right after aws sns subscribe command.

like image 35
Pasi H Avatar answered Oct 09 '22 07:10

Pasi H