AWS Budget notifications with AWS Chatbot, Slack and Terraform

Morné Snyman
5 min readAug 14, 2023

--

This is a step-by-step guide on configure AWS Budget notifications with Slack using AWS Chatbot and Terraform.

Prerequisites

  • AWS Account
  • Terraform bootstrapped (Created Dynamodb lock table and s3 bucket for Terraform state) in AWS Account. You can follow the Terraform state documentation here to configure the state.
  • Existing Slack workspace

Process Breakdown

AWS Budget alerts trigger notifications to an AWS SNS topic, with email addresses subscribed to the topic. The setup involves configuring the AWS Chatbot to utilize this SNS topic, enabling the transmission of AWS Budget alerts to the AWS Chatbot Slack App. Subsequently, the AWS Chatbot Slack App relays these alerts to the designated Slack channel.

This setup will send AWS Budget Alerts via email and Slack.

Step 1

Create a new Slack channel named aws-budgets in your Slack workspace.

Step 2

Configure AWS Chatbot Slack application in your Slack workspace.

Navigate to Add apps in your Slack workspace and add the AWS Chatbot app to your workspace. You might be redirected to a new page in your browser.

Step 3

Configure AWS Chatbot in the AWS Chatbot console at https://console.aws.amazon.com/chatbot/.

Click on Configure new Client

For client type, select Slack and click on Configure.

You will be redirected to a new page requesting for permission to install AWS Chatbot in your Slack workspace.

Enter a Description message and click submit.

Depending on your Slack Workspace configuration, you can either approve the request or an Administrator can.

Step 4

Create the following Terraform resources using the below structure.
You can also clone the repository below.

https://github.com/msnyman1991/terraform-aws-budgets-slack

Below are the contents of the files

  • terraform-aws-budgets-slack/budgets.tf
resource "aws_sns_topic" "aws_budget_alerts" {
name = "${var.aws_account_id}-aws-budget-alerts"
# kms_master_key_id = "alias/aws/sns"
}

resource "aws_sns_topic_policy" "default" {
arn = aws_sns_topic.aws_budget_alerts.arn
policy = data.aws_iam_policy_document.sns_topic_policy.json
}

resource "aws_sns_topic_subscription" "aws_budget_alerts_target" {
topic_arn = aws_sns_topic.aws_budget_alerts.arn
protocol = "email"
endpoint = var.email_address
}

resource "aws_budgets_budget" "monthly" {
name = "budget-monthly"
budget_type = "COST"
limit_amount = var.limit_amount
limit_unit = "USD"
time_unit = "MONTHLY"

notification {
comparison_operator = "GREATER_THAN"
threshold = var.threshold
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_sns_topic_arns = [aws_sns_topic.aws_budget_alerts.arn]
}
}

resource "aws_iam_policy" "chatbot_role_policy" {
name = "chatbot-policy"
policy = data.aws_iam_policy_document.chatbot_policy.json
}

resource "aws_iam_role" "chatbot_role" {
name = "chatbot-role"
assume_role_policy = data.aws_iam_policy_document.aws_budgets_assume_role_policy.json
}

resource "aws_iam_role_policy_attachment" "chatbot_policy_attach" {
role = aws_iam_role.chatbot_role.name
policy_arn = aws_iam_policy.chatbot_role_policy.arn
}

resource "awscc_chatbot_slack_channel_configuration" "aws_budget_alerts_slack" {
configuration_name = "slack_aws_budget_alerts"
iam_role_arn = aws_iam_role.chatbot_role.arn
slack_channel_id = var.slack_channel_id
slack_workspace_id = var.slack_workspace_id
sns_topic_arns = [aws_sns_topic.aws_budget_alerts.arn]
logging_level = "ERROR"
}
  • terraform-aws-budgets-slack/data.tf
data "aws_iam_policy_document" "aws_budgets_assume_role_policy" {
statement {
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["sns.amazonaws.com", "budgets.amazonaws.com"]
}
}
}

data "aws_iam_policy_document" "chatbot_policy" {
statement {
actions = [
"sns:ListTagsForResource",
"sns:ListSubscriptionsByTopic",
"sns:GetTopicAttributes",
"sns:ListSMSSandboxPhoneNumbers",
"sns:ListTopics",
"sns:GetPlatformApplicationAttributes",
"sns:GetSubscriptionAttributes",
"sns:ListSubscriptions",
"sns:CheckIfPhoneNumberIsOptedOut",
"sns:GetDataProtectionPolicy",
"sns:ListOriginationNumbers",
"sns:ListPhoneNumbersOptedOut",
"sns:ListEndpointsByPlatformApplication",
"sns:GetEndpointAttributes",
"sns:Publish",
"sns:GetSMSSandboxAccountStatus",
"sns:Subscribe",
"sns:ConfirmSubscription",
"sns:GetSMSAttributes",
"sns:ListPlatformApplications"
]
resources = [
"*"
]
}
}

data "aws_iam_policy_document" "sns_topic_policy" {
statement {
actions = [
"sns:Publish"
]

principals {
type = "Service"
identifiers = ["budgets.amazonaws.com"]
}

resources = [
aws_sns_topic.aws_budget_alerts.arn
]

}
}
  • terraform-aws-budgets-slack/variables.tf
variable "email_address" {
type = string
}

variable "slack_channel_id" {
type = string
}

variable "slack_workspace_id" {
type = string
}

variable "aws_account_id" {
type = string
}

variable "threshold" {
type = string
}

variable "limit_amount" {
type = string
}
  • terraform-aws-budgets-slack/provider.tf
provider "awscc" {
# Configure the required arguments for the AWS Cloud Control provider
region = "eu-west-1" # Replace with your desired AWS region
# Add any other necessary configuration options
}

Update the following variable values in the variables.tf file.

  • email_address
    The email address to whome AWS Budget Alerts will be sent.
  • slack_channel_id
    The Slack channel id to where AWS Budget Alerts will be sent.
  • slack_workspace_id
    The workspace id in which the Slack channel is located in.
  • aws_account_id
    The AWS Account ID where AWS Chatbot has been configured.
  • threshold
    When the budget set reaches this percentage an alert will be sent to Slack.
  • limit_amount
    The budget amount limit.

Where to find the Slack channel id

The Slack channel id will be in the format of CAPKFDUAS17

You can find the Channel ID on the About section of a channel.

Where to find the Slack workspace id

You can find the Slack Workspace ID in the Slack web client url by navigating to your Slack workspace in your browser. It should look like below. The ID after “client/” is the Slack Workspace ID.

https://app.slack.com/client/TT896HKILP/

Step 5

Run Terraform apply.

cd terraform-aws-budgets-slack
terraform apply

This will create the AWS Budget Alert, AWS Monthly Budget, SNS Topic, Chatbot IAM Role and Policy and configure the AWS Chatbot Slack client.

If you did not follow Step 3 correctly Terraform will fail with the following error message.

Invalid
│ request provided: AWS Chatbot can't create the configuration because Slack
│ workspace <workspace_id> is not authorized with AWS account <account_id>. See
│ https://docs.aws.amazon.com/chatbot/latest/adminguide/setting-up.html#Setup

Testing the AWS Chatbot Slack notifications

Navigate to https://console.aws.amazon.com/chatbot/ and select the new Slack client created earlier.

Click on the channel under the Configured channels section.

Under Slack channel details click on Send test message

You should see the following notification appear.

You should see the following message in the aws-budgets Slack channel that was created earlier.

Notes

  • Do not enable kms encryption on the SNS topic for AWS Chatbot. This will block AWS Chatbot to send messages to the SNS topic. AWS Chatbot Automatically encrypts the messages sent to the SNS Topic.
  • There can be some issues using the awscc Terraform provider. If you did not follow Step 3 correctly it will not allow the Terraform provider to authenticate with AWS Chatbot.
  • You can leave out the Terraform steps and configure everything manually if that is your preference.

--

--

Morné Snyman

Enthusiastic DevOps Engineer with 6 years+ cloud and DevOps engineering experience in multiple industries such as insurance, retail and fintech.