7. Cloud Resume Challenge: Creating SNS Topic and Subscription

7. Cloud Resume Challenge: Creating SNS Topic and Subscription

In this module, you will create a Simple Notification Service (SNS) Topic and an SNS email subscription for your site contact form. This will enable visitors to send emails to you via your website.


Terraform SNS Topic Reference

Terraform SNS Subscription Reference


Create a new branch in GitHub

  • Login to GitHub

  • Select the Issues tab > Select New Issue

  • Add the a title, e.g. Create SNS Topic and Subscription

  • Select Submit new issue

  • On the right pane, under Development, Select Create a branch

  • Leave the defaults > Select Create branch

  • Open your IDE Terminal.

  • Input the following:

git fetch origin
git checkout YOUR_BRANCH_NAME

Modifying sns files

In this section, you will be modifying the main, variables and outputs Terraform files located in ./infra/modules/aws/sns/.

main.tf

  • To create an SNS Topic, modify your ./infra/modules/aws/sns/main.tf

    • Input the following:

        resource "aws_sns_topic" "topic" {
          name = var.name
          display_name = var.display_name
        }
      

      The display_name variable will display how the FROM email address will be shown.

  • To create the SNS Subscription, input the following:

      resource "aws_sns_topic_subscription" "subscription" {
        topic_arn = aws_sns_topic.topic.arn
        protocol  = var.protocol
        endpoint  = var.endpoint
      }
    

    The SNS subscription will determine how the SNS Topic will be utilized. In this case, it will be used as an EMAIL protocol. The endpoint will be your email address.

  • Save the file

variables.tf

  • Input the following to define the input variables:

      # SNS Topic
      variable "name" {
        description = "(Optional) The name of the topic. Topic names must be made up of only uppercase and lowercase ASCII letters, numbers, underscores, and hyphens, and must be between 1 and 256 characters long. For a FIFO (first-in-first-out) topic, the name must end with the .fifo suffix. If omitted, Terraform will assign a random, unique name. Conflicts with name_prefix"
        type = string
      }
    
      variable "display_name" {
        description = "(Optional) The display name for the topic"
        type = string
      }
    
      # SNS Subscription
      variable "protocol" {
        description = "(Required) Protocol to use. Valid values are: sqs, sms, lambda, firehose, and application. Protocols email, email-json, http and https are also valid but partially supported."
        type = string
      }
    
      variable "endpoint" {
        description = "(Required) Endpoint to send data to. The contents vary with the protocol."
        type = string
      }
    

  • Save the file

outputs.tf

  • Input the following to define your return variables:

      # SNS Topic
      output "topic_id" {
        description = "The ARN of the SNS topic"
        value = aws_sns_topic.topic.id
      }
    
      output "topic_arn" {
        description = "The ARN of the SNS topic, as a more obvious property (clone of id)"
        value = aws_sns_topic.topic.arn
      }
    
      output "tags_all" {
        description = "A map of tags assigned to the resource, including those inherited from the provider default_tags configuration block."
        value = aws_sns_topic.topic.tags_all
      }
    
      output "beginning_archive_time" {
        description = "The oldest timestamp at which a FIFO topic subscriber can start a replay."
        value = aws_sns_topic.topic.beginning_archive_time
      }
    
      # SNS subscription
      output "sub_arn" {
        description = "ARN of the subscription."
        value = aws_sns_topic_subscription.subscription.arn
      }
    
      output "confirmation_was_authenticated" {
        description = "Whether the subscription confirmation request was authenticated."
        value = aws_sns_topic_subscription.subscription.confirmation_was_authenticated
      }
    
      output "sub_id" {
        description = "ARN of the subscription."
        value = aws_sns_topic_subscription.subscription.id
      }
    

    These are optional as there are no required outputs for my_portfolio or the ./infra/main.tf

  • Save the file


Modifying my_portfolio files

In this section, you will modify the terraform files within ./infra/modules/my_portfolio.

main.tf

  • Input the following to define the SNS module block:

      module "sns" {
        source = "../aws/sns"
    
        name         = var.topic_name
        display_name = var.topic_display_name
        protocol     = var.topic_protocol
        endpoint     = var.topic_endpoint
      }
    

  • Save the file

variables.tf

  • Input the following to define the input variables for the SNS module block:

      variable "topic_name" {
        description = "Name for SNS Topic"
        type = string
      }
    
      variable "topic_display_name" {
        description = "Display name for SNS topic. How the email will show FROM"
        type = string
      }
    
      variable "topic_protocol" {
        description = "Protocol used for SNS topic"
        type = string
        default = "email"
      }
    
      variable "topic_endpoint" {
        description = "Endpoint for SNS Topic"
        type = string
      }
    

    In this module, the topic_protocol is given a default variable of "email".

  • Save the file

outputs.tf

  • Input the following to define your return variables for this module:

      # SNS Topic
      output "topic_id" {
        description = "The ARN of the SNS topic"
        value = module.sns.topic_id
      }
    
      output "topic_arn" {
        description = "The ARN of the SNS topic, as a more obvious property (clone of id)"
        value = module.sns.topic_arn
      }
    
      output "topic_tags_all" {
        description = "A map of tags assigned to the resource, including those inherited from the provider default_tags configuration block."
        value = module.sns.tags_all
      }
    
      output "beginning_archive_time" {
        description = "The oldest timestamp at which a FIFO topic subscriber can start a replay."
        value = module.sns.beginning_archive_time
      }
    
      # SNS subscription
      output "sub_arn" {
        description = "ARN of the subscription."
        value = module.sns.sub_arn
      }
    
      output "confirmation_was_authenticated" {
        description = "Whether the subscription confirmation request was authenticated."
        value = module.sns.confirmation_was_authenticated
      }
    
      output "sub_id" {
        description = "ARN of the subscription."
        value = module.sns.sub_id
      }
    

    These outputs are optional.

  • Save the file


Modifying ./infra/main.tf

main.tf

  • Modify your ./infra/main.tf

    • Input the following:

          # SNS
          topic_name = "Email_from_my_website"
          topic_display_name = "Contact Me!"
          topic_endpoint = "YOUR_EMAIL_ADDRESS"
      

variables.tf and outputs.tf

  • Since the file_path has been hard coded, you do not have to modify your variables.tf

  • Optionally, you can include the outputs.tf. Based off the example above:

# SNS Topic
output "topic_id" {
  description = "The ARN of the SNS topic"
  value = module.my_static_website.topic_id
}

output "topic_arn" {
  description = "The ARN of the SNS topic, as a more obvious property (clone of id)"
  value = module.my_static_website.topic_arn
}

output "topic_tags_all" {
  description = "A map of tags assigned to the resource, including those inherited from the provider default_tags configuration block."
  value = module.my_static_website.topic_tags_all
}

output "beginning_archive_time" {
  description = "The oldest timestamp at which a FIFO topic subscriber can start a replay."
  value = module.my_static_website.beginning_archive_time
}

# SNS subscription
output "sub_arn" {
  description = "ARN of the subscription."
  value = module.my_static_website.sub_arn
}

output "confirmation_was_authenticated" {
  description = "Whether the subscription confirmation request was authenticated."
  value = module.my_static_website.confirmation_was_authenticated
}

output "sub_id" {
  description = "ARN of the subscription."
  value = module.my_static_website.sub_id
}

This will output those values to the Terraform Cloud outputs.


Pushing to GitHub

  • Ensure your files are saved.

  • In your IDE Terminal, type the following:

git add .

Add all files that were changed.

git commit -m "Created SNS topic and subscription for email notifications"

Commit the changes with a comment.

git push

Push to GitHub.


Create Pull Request

  • Login to GitHub.

  • You should see the push on your repository.

  • Select Compare and pull request.

  • Validate the changes that were made to be pushed to main

  • Select Create pull request.

Your Terraform Plan should run before you can merge to main.

If you are using the same site files from the original template, the plan to add 2 should match.

  • Select Merge pull request > Confirm merge.

  • Delete branch.

  • In your IDE Terminal, type the following:

git checkout main
git pull

Validation:

  • Check your email and confirm the subscription

  • AWS Management Console:

  • In the Search bar, search for "sns" > Select Topics

  • You should see your new SNS Topic listed

  • Select Subscriptions:

    • You should see your email address confirmed if you selected the Confirm subscription from the email that you received.


You have completed this module and created your SNS topic and subscription. In the next module, you will upload the Lambda functions from the lambda folder and test each to interact with your DynamoDB table and SNS Topic.