<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rafael Ribeiro</title>
    <description>The latest articles on DEV Community by Rafael Ribeiro (@rribeiro1).</description>
    <link>https://dev.to/rribeiro1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F123053%2F0ff88403-9705-429e-81fd-1ed78189dba3.jpg</url>
      <title>DEV Community: Rafael Ribeiro</title>
      <link>https://dev.to/rribeiro1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rribeiro1"/>
    <language>en</language>
    <item>
      <title>Budget alarms for AWS accounts and services using Terraform</title>
      <dc:creator>Rafael Ribeiro</dc:creator>
      <pubDate>Fri, 31 Jul 2020 19:59:42 +0000</pubDate>
      <link>https://dev.to/rribeiro1/budgets-alarms-for-aws-accounts-and-services-using-terraform-4lmf</link>
      <guid>https://dev.to/rribeiro1/budgets-alarms-for-aws-accounts-and-services-using-terraform-4lmf</guid>
      <description>&lt;p&gt;Who never had a surprise when checking the billing panel from Amazon, google, or another cloud provider? It happened with me, a couple of times actually, and I am sure it happens with you as well as in your organization 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Common problems and motivations 💸
&lt;/h2&gt;

&lt;p&gt;It’s not rare that we sometimes think service would cost X and it ends up costing 2X in the final of the month, sometimes we also create resources manually for experimentations and forget to clean them up, on the other hand, it is not healthy to access the budgets panel every day to check whether the costs are okay or not, so the best way to avoid surprises at the end of the month would be automating this process and creating some sort of alarms when something is wrong.&lt;/p&gt;

&lt;p&gt;Is this post we are going to create a process to keep track of our budgets in AWS by defining a threshold in the account level as well as by services. When the threshold is reached we are going to receive an alert via email (Slack users can use the &lt;a href="https://slack.com/apps/A0F81496D-email"&gt;Email Slack App&lt;/a&gt; so that they can receive the email in a specific channel).&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;This guide assumes some basic familiarity with the usual Terraform workflow (init, plan, and apply). It also assumes that you have your terraform and AWS provider properly configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Scenario
&lt;/h2&gt;

&lt;p&gt;Using AWS Billings it is possible to keep track of costs using a lot of approaches, for instance, resource tags where we can filter costs by a specific business or teams, resource names using amazon services names, etc. It is also possible to set alarms for forecast values or current values.&lt;/p&gt;

&lt;p&gt;Let's say that we have a &lt;code&gt;development account&lt;/code&gt; in AWS and we usually use two services: &lt;code&gt;EC2&lt;/code&gt; and &lt;code&gt;S3&lt;/code&gt; which costs $ 15/month.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2:&lt;/strong&gt; $ 10,00 &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3:&lt;/strong&gt; $ 5,00&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also want to reserve $ 5,00 in the account for eventual costs, in the end, what we need to achieve is:&lt;/p&gt;

&lt;p&gt;Receive an alert when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forecast amount for the &lt;code&gt;Development account&lt;/code&gt; is &lt;code&gt;greater than 20,00&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Forecast amount for &lt;code&gt;EC2&lt;/code&gt; is &lt;code&gt;greater than 10,00&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Forecast amount for &lt;code&gt;S3&lt;/code&gt; is &lt;code&gt;greater than 5,00&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After implementing the module in terraform, we are going to use it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"billing_alarm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"./../../modules/budgets"&lt;/span&gt;

  &lt;span class="nx"&gt;account_name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Development"&lt;/span&gt;
  &lt;span class="nx"&gt;account_budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"20.0"&lt;/span&gt;

  &lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;EC2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;S3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"5.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Before Starting
&lt;/h2&gt;

&lt;p&gt;If you in a hurry, you can find this module ready to use &lt;a href="https://registry.terraform.io/modules/rribeiro1/budget-alarms/aws/0.0.2"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform Module Structure
&lt;/h2&gt;

&lt;p&gt;Let’s get started by creating a terraform module so that we can reuse in cases where we have more than one account, our folder's structure will be something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── accounts
│   └── development
│       ├── budgets.tf
│       └── provider.tf &lt;span class="c"&gt;# not configured in this post    &lt;/span&gt;
│       
└── modules
    └── budgets
        ├── main.tf
        ├── services.tf
        └── variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Input Variables
&lt;/h4&gt;

&lt;p&gt;First, create the directory &lt;code&gt;modules/budgets&lt;/code&gt; and the file &lt;code&gt;variables.tf&lt;/code&gt;, it will have input variables for our module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Account name:&lt;/strong&gt; Name of the AWS account to be tracked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Account budget limit:&lt;/strong&gt; Threshold cost for the account level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Services:&lt;/strong&gt; List of AWS services to be tracked, we need to inform the name and values for each service.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/budgets/variables.tf&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"account_name"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"account_budget_limit"&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"services"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"List of AWS services to be monitored in terms of costs"&lt;/span&gt;

  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Services Helper
&lt;/h4&gt;

&lt;p&gt;The name of the service should match the name AWS expects otherwise the filter will not work properly, thus, we can create a support map to define some common services (if the service you want is not listed here you can add it later), in the same folder create a new a file called &lt;code&gt;services.tf&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/budgets/services.tf&lt;/span&gt;

&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;aws_services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Athena&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Athena"&lt;/span&gt;
    &lt;span class="nx"&gt;EC2&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Elastic Compute Cloud - Compute"&lt;/span&gt;
    &lt;span class="nx"&gt;ECR&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon EC2 Container Registry (ECR)"&lt;/span&gt;
    &lt;span class="nx"&gt;ECS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon EC2 Container Service"&lt;/span&gt;
    &lt;span class="nx"&gt;Kubernetes&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Elastic Container Service for Kubernetes"&lt;/span&gt;
    &lt;span class="nx"&gt;EBS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Elastic Block Store"&lt;/span&gt;
    &lt;span class="nx"&gt;CloudFront&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon CloudFront"&lt;/span&gt;
    &lt;span class="nx"&gt;CloudTrail&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS CloudTrail"&lt;/span&gt;
    &lt;span class="nx"&gt;CloudWatch&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AmazonCloudWatch"&lt;/span&gt;
    &lt;span class="nx"&gt;Cognito&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Cognito"&lt;/span&gt;
    &lt;span class="nx"&gt;Config&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Config"&lt;/span&gt;
    &lt;span class="nx"&gt;DynamoDB&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon DynamoDB"&lt;/span&gt;
    &lt;span class="nx"&gt;DMS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Database Migration Service"&lt;/span&gt;
    &lt;span class="nx"&gt;ElastiCache&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon ElastiCache"&lt;/span&gt;
    &lt;span class="nx"&gt;Elasticsearch&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Elasticsearch Service"&lt;/span&gt;
    &lt;span class="nx"&gt;ELB&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Elastic Load Balancing"&lt;/span&gt;
    &lt;span class="nx"&gt;Gateway&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon API Gateway"&lt;/span&gt;
    &lt;span class="nx"&gt;Glue&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Glue"&lt;/span&gt;
    &lt;span class="nx"&gt;Kafka&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Managed Streaming for Apache Kafka"&lt;/span&gt;
    &lt;span class="nx"&gt;KMS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Key Management Service"&lt;/span&gt;
    &lt;span class="nx"&gt;Kinesis&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Kinesis"&lt;/span&gt;
    &lt;span class="nx"&gt;Lambda&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Lambda"&lt;/span&gt;
    &lt;span class="nx"&gt;Lex&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Lex"&lt;/span&gt;
    &lt;span class="nx"&gt;Matillion&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Matillion ETL for Amazon Redshift"&lt;/span&gt;
    &lt;span class="nx"&gt;Pinpoint&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Pinpoint"&lt;/span&gt;
    &lt;span class="nx"&gt;Polly&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Polly"&lt;/span&gt;
    &lt;span class="nx"&gt;Rekognition&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Rekognition"&lt;/span&gt;
    &lt;span class="nx"&gt;RDS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Relational Database Service"&lt;/span&gt;
    &lt;span class="nx"&gt;Redshift&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Redshift"&lt;/span&gt;
    &lt;span class="nx"&gt;S3&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Simple Storage Service"&lt;/span&gt;
    &lt;span class="nx"&gt;SFTP&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Transfer for SFTP"&lt;/span&gt;
    &lt;span class="nx"&gt;Route53&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Route 53"&lt;/span&gt;
    &lt;span class="nx"&gt;SageMaker&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon SageMaker"&lt;/span&gt;
    &lt;span class="nx"&gt;SecretsManager&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS Secrets Manager"&lt;/span&gt;
    &lt;span class="nx"&gt;SES&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Simple Email Service"&lt;/span&gt;
    &lt;span class="nx"&gt;SNS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Simple Notification Service"&lt;/span&gt;
    &lt;span class="nx"&gt;SQS&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Simple Queue Service"&lt;/span&gt;
    &lt;span class="nx"&gt;Tax&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Tax"&lt;/span&gt;
    &lt;span class="nx"&gt;VPC&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Amazon Virtual Private Cloud"&lt;/span&gt;
    &lt;span class="nx"&gt;WAF&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS WAF"&lt;/span&gt;
    &lt;span class="nx"&gt;XRay&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS X-Ray"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can implement the budgets module, let's start by creating an SNS topic so that when an alarm is triggered, it will send a message in this topic and everyone subscribed in this topic will receive the message, in our case, it will be an email, we will get into that later.&lt;/p&gt;

&lt;h4&gt;
  
  
  Budget Module
&lt;/h4&gt;

&lt;p&gt;Here we are creating a new topic and defining a policy that allows AWS budgets to Publish Message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/budgets/main.tf&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_sns_topic"&lt;/span&gt; &lt;span class="s2"&gt;"account_billing_alarm_topic"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"account-billing-alarm-topic"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_sns_topic_policy"&lt;/span&gt; &lt;span class="s2"&gt;"account_billing_alarm_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;arn&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_billing_alarm_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sns_topic_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"sns_topic_policy"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sid&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWSBudgetsSNSPublishingPermissions"&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;

    &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"SNS:Receive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"SNS:Publish"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nx"&gt;principals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Service"&lt;/span&gt;
      &lt;span class="nx"&gt;identifiers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"budgets.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_billing_alarm_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have a topic, we can create a budget resource for the account level and subscribe to the topic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/budgets/main.tf&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_budgets_budget"&lt;/span&gt; &lt;span class="s2"&gt;"budget_account"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Account Monthly Budget"&lt;/span&gt;
  &lt;span class="nx"&gt;budget_type&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"COST"&lt;/span&gt;
  &lt;span class="nx"&gt;limit_amount&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_budget_limit&lt;/span&gt;
  &lt;span class="nx"&gt;limit_unit&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"USD"&lt;/span&gt;
  &lt;span class="nx"&gt;time_unit&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MONTHLY"&lt;/span&gt;
  &lt;span class="nx"&gt;time_period_start&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2020-01-01_00:00"&lt;/span&gt;

  &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;comparison_operator&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GREATER_THAN"&lt;/span&gt;
    &lt;span class="nx"&gt;threshold&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="nx"&gt;threshold_type&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PERCENTAGE"&lt;/span&gt;
    &lt;span class="nx"&gt;notification_type&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"FORECASTED"&lt;/span&gt;
    &lt;span class="nx"&gt;subscriber_sns_topic_arns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_billing_alarm_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_billing_alarm_topic&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last resource will be the budgets for services, it will receive a list of services and create a budget for each one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# modules/budgets/main.tf&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_budgets_budget"&lt;/span&gt; &lt;span class="s2"&gt;"budget_resources"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;

  &lt;span class="nx"&gt;name&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_name&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; Monthly Budget"&lt;/span&gt;
  &lt;span class="nx"&gt;budget_type&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"COST"&lt;/span&gt;
  &lt;span class="nx"&gt;limit_amount&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;budget_limit&lt;/span&gt;
  &lt;span class="nx"&gt;limit_unit&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"USD"&lt;/span&gt;
  &lt;span class="nx"&gt;time_unit&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MONTHLY"&lt;/span&gt;
  &lt;span class="nx"&gt;time_period_start&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2020-01-01_00:00"&lt;/span&gt;

  &lt;span class="nx"&gt;cost_filters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_services&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;comparison_operator&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GREATER_THAN"&lt;/span&gt;
    &lt;span class="nx"&gt;threshold&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="nx"&gt;threshold_type&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PERCENTAGE"&lt;/span&gt;
    &lt;span class="nx"&gt;notification_type&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"FORECASTED"&lt;/span&gt;
    &lt;span class="nx"&gt;subscriber_sns_topic_arns&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_billing_alarm_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;aws_sns_topic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account_billing_alarm_topic&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The module is complete, now we can easily reuse in our amazon accounts, to do so, create a &lt;code&gt;budgets.tf&lt;/code&gt; in the account folder and import the module, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# accounts/development/budgets.tf&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"billing_alarm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"../../modules/budgets"&lt;/span&gt;

  &lt;span class="nx"&gt;account_name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Development"&lt;/span&gt;
  &lt;span class="nx"&gt;account_budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"20.0"&lt;/span&gt;

  &lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;EC2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"10.0"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;S3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;budget_limit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"5.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To deploy this infrastructure, go to the development folder and type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;terraform init
&lt;span class="nv"&gt;$ &lt;/span&gt;terraform plan

&lt;span class="c"&gt;# After check the plan command we can apply &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After applying you should have the budgets as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IhGvzB-c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://rafaelribeiro.io/assets/public/budgets.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IhGvzB-c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://rafaelribeiro.io/assets/public/budgets.png" alt="budgets.png" width="880" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the SNS topic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MvGzy0dc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://rafaelribeiro.io/assets/public/sns-topic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MvGzy0dc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://rafaelribeiro.io/assets/public/sns-topic.png" alt="sns-topic.png" width="880" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step is to subscribe to this topic via Email app in Slack or any email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slack or Email Integration
&lt;/h2&gt;

&lt;p&gt;If you have a slack paid plan, you can use the &lt;a href="https://slack.com/apps/A0F81496D-email"&gt;Email Slack App&lt;/a&gt; integration, it provides a custom email to be used in the slack channel, thus, every email that is sent to this account will appear in the channel.&lt;/p&gt;

&lt;p&gt;I don't have a pro slack plan, so for simplicity, I will use my email for it, however, the process would be the same using the email integration app. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This part of the process is not supported by Terraform, so we are going to do it manually. &lt;/p&gt;

&lt;h3&gt;
  
  
  Subscribing the email to the topic
&lt;/h3&gt;

&lt;p&gt;Go to SNS panel in AWS and select &lt;code&gt;Subscriptions&lt;/code&gt; and create a new subscription by choosing the topic that was created in the previous step and in Protocol chose &lt;strong&gt;email&lt;/strong&gt;, after creating the subscription you should receive an email from AWS SNS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1EAofh7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://rafaelribeiro.io/assets/public/subscription.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1EAofh7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://rafaelribeiro.io/assets/public/subscription.png" alt="subscription.png" width="880" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From now on, every time you hit a threshold you will receive an email notification like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS Budget Notification May 04, 2020
AWS Account XXXXXXXXX

Dear AWS Customer,

You requested that we alert you when the FORECASTED Cost associated with your Development EC2 Monthly Budget is greater than $10.00 for the current month. 

The FORECASTED Cost associated with this budget is $15.00. 

You can find additional details below and by accessing the AWS Budgets dashboard.

Budget Name: Development EC2 Monthly Budget
Budget Type: Cost
Budgeted Amount: $10.00
Alert Type: FORECASTED
Alert Threshold: &amp;gt; $10.00
FORECASTED Amount: $15.00 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This implementation uses the version 0.12 of Terraform, you can find the same implementation using the version 0.11 &lt;a href="https://gist.github.com/rribeiro1/9062cec2e0f89564314ecca771ae1111"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>budgets</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
