Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SNS topic subscription to AmazonIpSpaceChanged using terraform

I am trying to subscribe to the Aws AmazonIpSpaceChanged SNS topic using terraform. However, I keep getting the below error

SNS Topic subscription to AWS

resource "aws_sns_topic_subscription" "aws_ip_change_sns_subscription" {
  topic_arn = "arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged"
  protocol  = "lambda"
  endpoint  = "${aws_lambda_function.test_sg_lambda_function.arn}"
}

Error:

* module.test-lambda.aws_sns_topic_subscription.aws_ip_change_sns_subscription: 1 error(s) occurred:

* aws_sns_topic_subscription.aws_ip_change_sns_subscription: Error creating SNS topic: InvalidParameter: Invalid parameter: TopicArn
        status code: 400, request id: 3daa2940-8d4b-5fd8-86e7-7b074a16ada9

I tried the same using aws cli and it failed the first time when I didn't include the option --region us-east-1. But once it is included, it was able to subscribe just fine.

Any ideas?

like image 771
Bond Avatar asked Sep 29 '17 04:09

Bond


People also ask

How can I add multiple email ID in SNS topic?

To subscribe multiple endpoints, you have to invoke the object multiple times. By using the Lambda function as a custom resource, you can subscribe multiple endpoints through an input parameter. You can use this Lambda function as a custom resource in any AWS CloudFormation template.

What is SNS topic and subscription?

Amazon Simple Notification Service (Amazon SNS) is a managed service that provides message delivery from publishers to subscribers (also known as producers and consumers). Publishers communicate asynchronously with subscribers by sending messages to a topic, which is a logical access point and communication channel.

Which of the following can subscribe as an endpoint to Amazon SNS topic?

You specify the endpoint using its URL. To subscribe to a topic, you can use the Amazon SNS console, the sns-subscribe command, or the Subscribe API action.


2 Answers

I know it's an old question, but there are no accepted answers - maybe this will help someone if you agree with it and mark it as accepted?

The SNS topic arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged is only available in the region us-east-1, so you need to use a provider within Terraform that is configured for that region.

You also need to give permissions to the SNS topic to invoke the Lambda function (not sure if you'd just left this off the question).

This also works if your lambda function is defined in a different region.

provider "aws" {
  region = "{your target region}"
}

provider "aws" {
  alias  = "us_east_1"
  region = "us-east-1"
}

resource "aws_lambda_function" "my_function" {

  # This uses your default target region

  :
  :
}

resource "aws_lambda_permission" "lambda_permission" {

  # This uses your default target region

  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.my_function.function_name
  principal     = "sns.amazonaws.com"
  source_arn    = "arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged"
}

resource "aws_sns_topic_subscription" "aws_ip_change_sns_subscription" {

  # This needs to use the same region as the SNS topic
  provider = aws.us_east_1

  topic_arn = "arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged"
  protocol  = "lambda"
  endpoint  = aws_lambda_function.my_function.arn
}

like image 139
Dave Rix Avatar answered Oct 28 '22 12:10

Dave Rix


Your topic_arn is hardcoded to region us-east-1:

arn:aws:sns:us-east-1:806199016981:AmazonIpSpaceChanged

So when you have AWS_DEFAULT_REGION or similar configuration and point to another region, your code will fail.

That's the reason if you nominate the region, the code runs fine.

To avoid hardcodes, such as region, account id, you can do this:

data "aws_caller_identity" "current" {}

variable "region" {
  type = "string"
  default = "us-east-1"
}

resource "aws_sns_topic_subscription" "aws_ip_change_sns_subscription" {
  topic_arn = "arn:aws:sns:${var.region}:${data.aws_caller_identity.current.account_id}:AmazonIpSpaceChanged"
  protocol  = "lambda"
  endpoint  = "${aws_lambda_function.test_sg_lambda_function.arn}"
}

With that, you should be fine and more flexible to run it in other region and other aws account as well.

like image 1
BMW Avatar answered Oct 28 '22 14:10

BMW