Skip to content

Resource: awsSnsTopicSubscription

Provides a resource for subscribing to SNS topics. Requires that an SNS topic exist for the subscription to attach to. This resource allows you to automatically place messages sent to SNS topics in SQS queues, send them as HTTP(S) POST requests to a given endpoint, send SMS messages, or notify devices / applications. The most likely use case for Terraform users will probably be SQS queues.

\~> NOTE: If the SNS topic and SQS queue are in different AWS regions, the awsSnsTopicSubscription must use an AWS provider that is in the same region as the SNS topic. If the awsSnsTopicSubscription uses a provider with a different region than the SNS topic, Terraform will fail to create the subscription.

\~> NOTE: Setup of cross-account subscriptions from SNS topics to SQS queues requires Terraform to have access to BOTH accounts.

\~> NOTE: If an SNS topic and SQS queue are in different AWS accounts but the same region, the awsSnsTopicSubscription must use the AWS provider for the account with the SQS queue. If awsSnsTopicSubscription uses a Provider with a different account than the SQS queue, Terraform creates the subscription but does not keep state and tries to re-create the subscription at every apply.

\~> NOTE: If an SNS topic and SQS queue are in different AWS accounts and different AWS regions, the subscription needs to be initiated from the account with the SQS queue but in the region of the SNS topic.

\~> NOTE: You cannot unsubscribe to a subscription that is pending confirmation. If you use email, emailJson, or http/https (without auto-confirmation enabled), until the subscription is confirmed (e.g., outside of Terraform), AWS does not allow Terraform to delete / unsubscribe the subscription. If you destroy an unconfirmed subscription, Terraform will remove the subscription from its state but the subscription will still exist in AWS. However, if you delete an SNS topic, SNS deletes all the subscriptions associated with the topic. Also, you can import a subscription after confirmation and then have the capability to delete it.

Example Usage

You can directly supply a topic and ARN by hand in the topicArn property along with the queue ARN:

/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
new aws.snsTopicSubscription.SnsTopicSubscription(
  this,
  "user_updates_sqs_target",
  {
    endpoint: "arn:aws:sqs:us-west-2:432981146916:terraform-queue-too",
    protocol: "sqs",
    topicArn: "arn:aws:sns:us-west-2:432981146916:user-updates-topic",
  }
);

Alternatively you can use the ARN properties of a managed SNS topic and SQS queue:

/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
const awsSnsTopicUserUpdates = new aws.snsTopic.SnsTopic(this, "user_updates", {
  name: "user-updates-topic",
});
const awsSqsQueueUserUpdatesQueue = new aws.sqsQueue.SqsQueue(
  this,
  "user_updates_queue",
  {
    name: "user-updates-queue",
  }
);
new aws.snsTopicSubscription.SnsTopicSubscription(
  this,
  "user_updates_sqs_target",
  {
    endpoint: awsSqsQueueUserUpdatesQueue.arn,
    protocol: "sqs",
    topicArn: awsSnsTopicUserUpdates.arn,
  }
);

You can subscribe SNS topics to SQS queues in different Amazon accounts and regions:

import * as cdktf from "cdktf";
/*Provider bindings are generated by running cdktf get.
See https://cdk.tf/provider-generation for more details.*/
import * as aws from "./.gen/providers/aws";
/*Terraform Variables are not always the best fit for getting inputs in the context of Terraform CDK.
You can read more about this at https://cdk.tf/variables*/
const sns = new cdktf.TerraformVariable(this, "sns", {
  default: [
    {
      "account-id": "111111111111",
      display_name: "example",
      name: "example-sns-topic",
      region: "us-west-1",
      "role-name": "service/service-hashicorp-terraform",
    },
  ],
});
const sqs = new cdktf.TerraformVariable(this, "sqs", {
  default: [
    {
      "account-id": "222222222222",
      name: "example-sqs-queue",
      region: "us-east-1",
      "role-name": "service/service-hashicorp-terraform",
    },
  ],
});
const dataAwsIamPolicyDocumentSnsTopicPolicy =
  new aws.dataAwsIamPolicyDocument.DataAwsIamPolicyDocument(
    this,
    "sns-topic-policy",
    {
      policyId: "__default_policy_ID",
      statement: [
        {
          actions: [
            "SNS:Subscribe",
            "SNS:SetTopicAttributes",
            "SNS:RemovePermission",
            "SNS:Publish",
            "SNS:ListSubscriptionsByTopic",
            "SNS:GetTopicAttributes",
            "SNS:DeleteTopic",
            "SNS:AddPermission",
          ],
          condition: [
            {
              test: "StringEquals",
              values: [`\${${sns.value}["account-id"]}`],
              variable: "AWS:SourceOwner",
            },
          ],
          effect: "Allow",
          principals: [
            {
              identifiers: ["*"],
              type: "AWS",
            },
          ],
          resources: [
            `arn:aws:sns:\${${sns.value}["region"]}:\${${sns.value}["account-id"]}:\${${sns.value}["name"]}`,
          ],
          sid: "__default_statement_ID",
        },
        {
          actions: ["SNS:Subscribe", "SNS:Receive"],
          condition: [
            {
              test: "StringLike",
              values: [
                `arn:aws:sqs:\${${sqs.value}["region"]}:\${${sqs.value}["account-id"]}:\${${sqs.value}["name"]}`,
              ],
              variable: "SNS:Endpoint",
            },
          ],
          effect: "Allow",
          principals: [
            {
              identifiers: ["*"],
              type: "AWS",
            },
          ],
          resources: [
            `arn:aws:sns:\${${sns.value}["region"]}:\${${sns.value}["account-id"]}:\${${sns.value}["name"]}`,
          ],
          sid: "__console_sub_0",
        },
      ],
    }
  );
const dataAwsIamPolicyDocumentSqsQueuePolicy =
  new aws.dataAwsIamPolicyDocument.DataAwsIamPolicyDocument(
    this,
    "sqs-queue-policy",
    {
      policyId: `arn:aws:sqs:\${${sqs.value}["region"]}:\${${sqs.value}["account-id"]}:\${${sqs.value}["name"]}/SQSDefaultPolicy`,
      statement: [
        {
          actions: ["SQS:SendMessage"],
          condition: [
            {
              test: "ArnEquals",
              values: [
                `arn:aws:sns:\${${sns.value}["region"]}:\${${sns.value}["account-id"]}:\${${sns.value}["name"]}`,
              ],
              variable: "aws:SourceArn",
            },
          ],
          effect: "Allow",
          principals: [
            {
              identifiers: ["*"],
              type: "AWS",
            },
          ],
          resources: [
            `arn:aws:sqs:\${${sqs.value}["region"]}:\${${sqs.value}["account-id"]}:\${${sqs.value}["name"]}`,
          ],
          sid: "example-sns-topic",
        },
      ],
    }
  );
new aws.provider.AwsProvider(this, "aws", {
  alias: "sns",
  assumeRole: [
    {
      roleArn: `arn:aws:iam::\${${sns.value}["account-id"]}:role/\${${sns.value}["role-name"]}`,
      sessionName: `sns-\${${sns.value}["region"]}`,
    },
  ],
  region: `\${${sns.value}["region"]}`,
});
new aws.provider.AwsProvider(this, "aws_5", {
  alias: "sqs",
  assumeRole: [
    {
      roleArn: `arn:aws:iam::\${${sqs.value}["account-id"]}:role/\${${sqs.value}["role-name"]}`,
      sessionName: `sqs-\${${sqs.value}["region"]}`,
    },
  ],
  region: `\${${sqs.value}["region"]}`,
});
new aws.provider.AwsProvider(this, "aws_6", {
  alias: "sns2sqs",
  assumeRole: [
    {
      roleArn: `arn:aws:iam::\${${sqs.value}["account-id"]}:role/\${${sqs.value}["role-name"]}`,
      sessionName: `sns2sqs-\${${sns.value}["region"]}`,
    },
  ],
  region: `\${${sns.value}["region"]}`,
});
const awsSnsTopicSnsTopic = new aws.snsTopic.SnsTopic(this, "sns-topic", {
  displayName: `\${${sns.value}["display_name"]}`,
  name: `\${${sns.value}["name"]}`,
  policy: dataAwsIamPolicyDocumentSnsTopicPolicy.json,
  provider: "aws.sns",
});
const awsSqsQueueSqsQueue = new aws.sqsQueue.SqsQueue(this, "sqs-queue", {
  name: `\${${sqs.value}["name"]}`,
  policy: dataAwsIamPolicyDocumentSqsQueuePolicy.json,
  provider: "aws.sqs",
});
const awsSnsTopicSubscriptionSnsTopic =
  new aws.snsTopicSubscription.SnsTopicSubscription(this, "sns-topic_9", {
    endpoint: awsSqsQueueSqsQueue.arn,
    protocol: "sqs",
    provider: "aws.sns2sqs",
    topicArn: awsSnsTopicSnsTopic.arn,
  });
/*This allows the Terraform resource name to match the original name. You can remove the call if you don't need them to match.*/
awsSnsTopicSubscriptionSnsTopic.overrideLogicalId("sns-topic");

Argument Reference

The following arguments are required:

  • endpoint - (Required) Endpoint to send data to. The contents vary with the protocol. See details below.
  • protocol - (Required) Protocol to use. Valid values are: sqs, sms, lambda, firehose, and application. Protocols email, emailJson, http and https are also valid but partially supported. See details below.
  • subscriptionRoleArn - (Required if protocol is firehose) ARN of the IAM role to publish to Kinesis Data Firehose delivery stream. Refer to SNS docs.
  • topicArn - (Required) ARN of the SNS topic to subscribe to.

The following arguments are optional:

  • confirmationTimeoutInMinutes - (Optional) Integer indicating number of minutes to wait in retrying mode for fetching subscription arn before marking it as failure. Only applicable for http and https protocols. Default is 1.
  • deliveryPolicy - (Optional) JSON String with the delivery policy (retries, backoff, etc.) that will be used in the subscription - this only applies to HTTP/S subscriptions. Refer to the SNS docs for more details.
  • endpointAutoConfirms - (Optional) Whether the endpoint is capable of auto confirming subscription (e.g., PagerDuty). Default is false.
  • filterPolicy - (Optional) JSON String with the filter policy that will be used in the subscription to filter messages seen by the target resource. Refer to the SNS docs for more details.
  • filterPolicyScope - (Optional) Whether the filterPolicy applies to messageAttributes (default) or messageBody.
  • rawMessageDelivery - (Optional) Whether to enable raw message delivery (the original message is directly passed, not wrapped in JSON with the original message in the message property). Default is false.
  • redrivePolicy - (Optional) JSON String with the redrive policy that will be used in the subscription. Refer to the SNS docs for more details.

Protocol support

Supported values for protocol include:

  • application - Delivers JSON-encoded messages. endpoint is the endpoint ARN of a mobile app and device.
  • firehose - Delivers JSON-encoded messages. endpoint is the ARN of an Amazon Kinesis Data Firehose delivery stream (e.g., arn:aws:firehose:usEast1:123456789012:deliverystream/ticketUploadStream).
  • lambda - Delivers JSON-encoded messages. endpoint is the ARN of an AWS Lambda function.
  • sms - Delivers text messages via SMS. endpoint is the phone number of an SMS-enabled device.
  • sqs - Delivers JSON-encoded messages. endpoint is the ARN of an Amazon SQS queue (e.g., arn:aws:sqs:usWest2:123456789012:terraformQueueToo).

Partially supported values for protocol include:

\~> NOTE: If an awsSnsTopicSubscription uses a partially-supported protocol and the subscription is not confirmed, either through automatic confirmation or means outside of Terraform (e.g., clicking on a "Confirm Subscription" link in an email), Terraform cannot delete / unsubscribe the subscription. Attempting to destroy an unconfirmed subscription will remove the awsSnsTopicSubscription from Terraform's state but will not remove the subscription from AWS. The pendingConfirmation attribute provides confirmation status.

  • email - Delivers messages via SMTP. endpoint is an email address.
  • emailJson - Delivers JSON-encoded messages via SMTP. endpoint is an email address.
  • http -- Delivers JSON-encoded messages via HTTP POST. endpoint is a URL beginning with http://.
  • https -- Delivers JSON-encoded messages via HTTPS POST. endpoint is a URL beginning with https://.

Attributes Reference

In addition to all arguments above, the following attributes are exported:

  • arn - ARN of the subscription.
  • confirmationWasAuthenticated - Whether the subscription confirmation request was authenticated.
  • id - ARN of the subscription.
  • ownerId - AWS account ID of the subscription's owner.
  • pendingConfirmation - Whether the subscription has not been confirmed.

Import

SNS Topic Subscriptions can be imported using the subscriptionArn, e.g.,

$ terraform import aws_sns_topic_subscription.user_updates_sqs_target arn:aws:sns:us-west-2:0123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f