Apply tags to resources for automating backups

Automate backups for your AWS resources by applying tags to resources at scale

Your company's cloud environment is valuable: data, applications, logs, and the infrastructure behind them are all valuable. Ransomware attacks or accidental deletion can cost companies millions of dollars directly, while damaging brand reputations and customer relationships.

In this tutorial, we'll walk through how to set up backups for your existing AWS infrastructure at scale using Resourcely. We will automatically apply tags to relevant resources, and then use that to set up an aws_backup_vault.

Define the assets you want recurring backups on

Critical infrastructure is likely some of the following:

  • EC2 instances

  • EBS volumes

  • RDS instances

  • Aurora Clusters

  • DynamoDB tables

  • EFS file systems

For each of these resources, we'll add a backup tag that we can use with aws_backup_vault:

  tags = {
    backup = "true"
  }

Make sure you have aws_backup_vault configured

Setting up an aws_backup_vault like below, with a tag-based selection that looks for our backup tag, will allow us to automatically backup all of our relevant resources.

resource "aws_backup_vault" "main" {
  name = "primary-backup-vault"
}

resource "aws_backup_plan" "example" {
  name = "my-backup-plan"

  rule {
    rule_name         = "daily-backup"
    target_vault_name = aws_backup_vault.main.name
    schedule          = "cron(0 5 * * ? *)" # Daily at 5 AM UTC
    lifecycle {
      
    }
  }
}

resource "aws_backup_selection" "example" {
  name         = "tag-based-selection"
  plan_id      = aws_backup_plan.example.id
  resources    = []
   {
    type  = "STRINGEQUALS"
    key   = "backup"
    value = "true"
  }
}

Constructing relevant policy

Now, we'll move into Resourcely. If you haven't already, follow the Remediate policy violations in existing infrastructure quickstart to set up the Campaigns agent for scanning your existing infrastructure..

Writing a Guardrail

Resourcely Guardrails feature a flexible policy language. We can write a single policy that will allow us to find relevant resources without a backup tag and apply it.

// Guardrail for applying a backup tag to relevant resources

GUARDRAIL "Require backup tags on relevant AWS resources" 
  WHEN aws_db_instance OR aws_ebs_volume OR aws_rds_cluster OR aws_rds_cluster_instance OR aws_dynamodb_table OR aws_efs_file_system
    REQUIRE tags.backup = "true"

This policy will flag any resources that don't have the appropriate tag when we include it in a Campaign. You can choose this Guardrail from our pre-built policies in Resourcely, just search for "Require backup tags".

You can also write it yourself in the Foundry.

Implement backup tags: Running a Campaign

Campaigns lets companies orchestrate remediation across their existing resources. Here is the existing Terraform code that we have in our playground repo (feel free to use it for yourself for testing purposes).

main.tf
// 3 RDS resources: one with an incorrect tag, and two missing tags

resource "aws_db_instance" "example-rds_TJXZTFi3qSy724Fv" {
  identifier                   = "example-rds"
  engine                       = "postgres"
  engine_version               = "17.2"
  instance_class               = "db.t3.micro"
  allocated_storage            = 20
  max_allocated_storage        = 100
  db_name                      = "app_database"
  username                     = "db_user"
  password                     = "password"
  backup_retention_period      = 7
  storage_encrypted            = false
  multi_az                     = true
  deletion_protection          = true
  performance_insights_enabled = true
  skip_final_snapshot          = true
  tags = {
    backup = "false"
  }
}

resource "aws_db_instance" "key-application-dev" {
  identifier                   = "key-application-dev"
  engine                       = "postgres"
  engine_version               = "17.2"
  instance_class               = "db.t3.micro"
  allocated_storage            = 20
  max_allocated_storage        = 100
  db_name                      = "app_database"
  username                     = "db_user"
  password                     = "password"
  backup_retention_period      = 7
  storage_encrypted            = false
  multi_az                     = true
  deletion_protection          = true
  performance_insights_enabled = true
  skip_final_snapshot          = true
}

resource "aws_db_instance" "key-application-prod" {
  identifier                   = "key-application-prod"
  engine                       = "postgres"
  engine_version               = "17.2"
  instance_class               = "db.t3.micro"
  allocated_storage            = 20
  max_allocated_storage        = 100
  db_name                      = "app_database"
  username                     = "db_user"
  password                     = "password"
  backup_retention_period      = 7
  storage_encrypted            = false
  multi_az                     = true
  deletion_protection          = true
  performance_insights_enabled = true
  skip_final_snapshot          = true
}

Create Campaign

First, we'll create a Campaign. We'll choose relevant repositories and the policies that we want to scan for. I selected the Guardrail that we created above.

Creating a Campaign to apply tags
Campaign Summary
The specific resource addresses with violations

Remediate code

Now that we know there are 3 resources missing the correct backup tag, let's remediate them! Navigating to the remediation screen shows us our violations against our Terraform code:

Remediation IDE with inline violations

Let's look at each of our scenarios. The first is the example-rds instance, with an incorrect tag

example-rds
resource "aws_db_instance" "example-rds_TJXZTFi3qSy724Fv" {
  identifier                   = "example-rds"
  engine                       = "postgres"
  engine_version               = "17.2"
  instance_class               = "db.t3.micro"
  allocated_storage            = 20
  max_allocated_storage        = 100
  db_name                      = "app_database"
  username                     = "db_user"
  password                     = "password"
  backup_retention_period      = 7
  storage_encrypted            = false
  multi_az                     = true
  deletion_protection          = true
  performance_insights_enabled = true
  skip_final_snapshot          = true
  tags = {
    backup = "false"
  }
}

Given this resource has a tag keypair that matches our Guardrail, that specific parameter is highlighted when we click on our violation:

Inline violation
Hovering gives us a suggested fix

Changing the value to "true" gives us feedback that our change was accepted (with the green check).

Let's now consider our violation against key-application-prod. This resource is missing any tag parameters, so we highlight the overall resource. In this case, I must add a tag parameter.

We'll be releasing human-in-the-loop remediation support in the future: where the tag parameter will be automatically generated for a user to review.

Our violation highlights the overall resource when a parameter is missing

When I add the tag parameter, Resourcely gives me feedback with a green check - to let me know that I've added the correct Terraform.

Added a backup parameter

Managing exceptions

Let's consider our final violation. In this case, the RDS database is for development only. If your organization doesn't want to spend money backing up development databases, we may not want to add the tag. How can we satisfy the Guardrail without adding the tag?

The answer: exceptions. As a user I can request an exception by clicking on the Guardrail and "Manage Exception".

Requesting an exception

Submit PR

We have green checks for our violations!

We have now satisfied our backup tag Guardrail. The next step is to submit these changes through our existing CI. This way we:

  • Preserve our existing approval workflows

  • Avoid Terraform drift as compared to automated remediation

By clicking Evaluate Changes --> Finalize, I can submit a change request through my version control tool of choice.

Submitting a PR

Here is the PR I made in GitHub via Resourcely remediation, that will add relevant backup tags.

Files changed view

The exception request for our dev database is included in the conversation, and a reviewer is automatically tagged to review the changes.

Exception request within PR

Summary

We've demonstrated two key use cases in one: adding backups to existing resources that are missing them at scale, and adding or changing tags to existing resources - again at scale.

Resourcely Campaigns are a flexible framework for changing Terraform configuration of existing resources. While a single person could manage the example we gave, it could easily scale to hundreds of different developers. Many Resourcely customers have security teams creating and managing Campaigns, while individual developers use the Remediation functionality for the resources they are responsible for.

Fixing misconfigurations can help you stay compliant, mitigate risk & liability, and reduce breaches or incidents. Get started yourself at https://portal.resourcely.io today!

Last updated