Configuring A Tag-based AWS Backup Using AWS CloudFormation Template

Backups are an essential part of every implementation as they provide us with the required copies that can be used to restore in case of any incidents. Backups must be done automatically, consistently, and reliably for them to be effective. AWS Backup is one such service in the Amazon Cloud which tries to tackle the problem of having backups that meet this criterion. In this blog post, we are going to describe the steps and processes that can be used to automate backups using a tag-based assignment so that it can be extended to a large number of resources automatically. We will be using AWS CloudFormation and AWS Backup services for achieving this objective.
 
AWS Backup offers a cost-effective, fully-managed, policy-based service that enables us to centralize and automate data protection at scale. Amongst its various other features is "Tag-based backup policies". AWS Backup allows us to apply backup plans to AWS resources by using AWS tags. This particular feature integrates with AWS Tags and enables us to quickly apply a backup plan to a group of AWS resources. This is particularly useful for cases where we have more than one instance of a resource (like EC2s, RDSs, etc.) and we want them to be backed up in a consistent and compliant manner. AWS recommends using Tag-based backup policies when we are trying to protect more than 100 resources in a single plan. But there is no restriction to use this for a lower volume as well and I recommend using this approach wherever possible. 
 
AWS CloudFormation (CF) provides us with the capability to provision and manage AWS resources using templates in a repeatable and consistent fashion. A CF template basically describes all the resources and their dependencies so that they can be launched and configured together as a stack. 
  
There are some other terms also associated and used as part of AWS Backups for which I am giving a brief overview below. Details for each of them can be looked upon in the AWS documentation available.
  • Backup Vault - storage container for backups
  • Backup Plan - scheduler for backups. This basically defines when the backups should be done and with what frequency. A backup plan will be attached to the backup vault
  • Recovery Point - snapshot/backup of resource that can be restored with AWS Backups
  • Resource Assignment/Backup Selection - defines the target resources to backup. It gets attached to the backup vault 
With all the items now defined, let's just look at the CloudFormation template that we are going to use. In the below template, we are creating a new AWS backup configuration and applying it to all AWS resources that will have a tag "backup-plan" with the value set as "BackupPlan-01-31days-daily".
  1. Parameters:    
  2.   UpdateParameter:    
  3.     Description: (optional) This parameter is a fake param please use/change it just if you want to force the update to the new SC version    
  4.     Type: String    
  5.     Default: ""    
  6.     
  7.   BackupPlanName:     
  8.     Description: Enter the name of the backup plan (Required)    
  9.     Type: String    
  10.     Default: "test-01"    
  11.       
  12.   CronExpression:    
  13.     Description: Enter the cron expression for your backup plan (Required)    
  14.     Type: String    
  15.     Default: "cron(0 0 ? * * *)"    
  16.       
  17.   Retention:    
  18.     Description: This value will identify how many days your backup will be expired after (Required)    
  19.     Type: String    
  20.     Default: 31    
  21. Metadata:    
  22.   AWS::CloudFormation::Interface:    
  23.     ParameterGroups:    
  24.       -    
  25.         Label:    
  26.             default: BackupPlan Configurations (Mandatory)    
  27.         Parameters:    
  28.           - BackupPlanName    
  29.       -      
  30.         Label:    
  31.           default: Bckup Rule configuration    
  32.         Parameters:    
  33.           - CronExpression    
  34.           - Retention    
  35. Resources:    
  36.   BackupRole:    
  37.     Type: 'AWS::IAM::Role'    
  38.     Properties:    
  39.       RoleName: SampleBackupRole    
  40.       AssumeRolePolicyDocument:    
  41.         Version: 2012-10-17    
  42.         Statement:    
  43.           - Effect: Allow    
  44.             Principal:    
  45.               Service:    
  46.                 - backup.amazonaws.com    
  47.             Action:    
  48.               - 'sts:AssumeRole'    
  49.       ManagedPolicyArns:    
  50.         - >-    
  51.           arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup    
  52.             
  53.   BackupVault:    
  54.     Type: "AWS::Backup::BackupVault"    
  55.     Properties:    
  56.       BackupVaultName: !Sub ${BackupPlanName}-BackupVaultName    
  57.       AccessPolicy:     
  58.         Version: '2012-10-17'    
  59.         Statement:    
  60.         -    
  61.             Sid: 'Vault-Access-Policy'    
  62.             Effect: Deny    
  63.             Principal: "*"    
  64.             Action: "backup:DeleteRecoveryPoint"    
  65.             Resource:    
  66.               - "*"    
  67.   BackupPlan:    
  68.     Type: "AWS::Backup::BackupPlan"    
  69.     Properties:    
  70.       BackupPlan:    
  71.         BackupPlanName: !Ref BackupPlanName    
  72.         BackupPlanRule:    
  73.           -    
  74.             RuleName: !Sub ${BackupPlanName}-BackupRuleName    
  75.             TargetBackupVault: !Ref BackupVault    
  76.             ScheduleExpression: !Ref CronExpression    
  77.             Lifecycle:    
  78.               DeleteAfterDays: !Ref Retention    
  79.     DependsOn: BackupVault    
  80.             
  81.   TagBasedBackupSelection:    
  82.     Type: "AWS::Backup::BackupSelection"    
  83.     Properties:    
  84.       BackupSelection:    
  85.         SelectionName: "TagBasedBackupSelection-01"    
  86.         IamRoleArn:  !GetAtt BackupRole.Arn     
  87.         ListOfTags:    
  88.          -    
  89.            ConditionType: "STRINGEQUALS"    
  90.            ConditionKey: "backup-plan"     
  91.            ConditionValue: !Sub ${BackupPlanName}-${Retention}days-daily    
  92.       BackupPlanId: !Ref BackupPlan    
  93.     DependsOn: BackupPlan    
  • The CloudFormation template begins by firstly creating the BackupRole. In this section of the template, we are creating our role and using the default service role (AWSBackupServiceRolePolicyForBackup). If you have any existing roles that can be used, then please update this section.
Note
When creating a tag-based backup plan, if you choose a role other than the Default role, make sure that it has the necessary permissions to back up all tagged resources. AWS Backup tries to process all resources with the selected tags. If it encounters a resource that it doesn't have permission to access, the backup plan fails.
  • Next section, we are creating a BackupVault to store our backups. In addition to creation, we are also placing a deny policy for deleting recovery points. The policy configuration is optional and will depend on your specific requirements.
  • Once BackupVault is created, the next step is to create the backup plan. This will define the frequency of backup using CRON expressions and the target location for backups by specifying BackupVault that we created in step#2. The CRON expression used in our example configures a daily backup to be executed at midnight UTC. We are also configuring the life cycle (retention period) and setting it to 31 days.
  • In the next section, we are doing the configuration setting for "TagBasedBackupSelection". In this section, we have to specify the AWS Tags key-value pair for which this backup plan is going to apply. In our case, we are setting it to be applied to all resources having a "backup-plan" tag and value "BackupPlan-01-31days-daily".
We have not specified any parameters for this template. For purposes of reuse, I recommend using parameters and then modifying this template accordingly to use the parameters instead of the currently specified hard-coded value. You can find an example of the parameterized template here
 
The CloudFormation template is now ready for execution. Go to your AWS account and execute it using the CloudFromation Create Stack option.
 
If you visualize in designer, this should look something like this,
 
Configuring A Tag-based AWS Backup Using AWS CloudFormation Template
 
On execution, you should get the following information logged in your stack. 
 
Configuring A Tag-based AWS Backup Using AWS CloudFormation Template 
 
That's it. Now that the template has completed execution, you should see all the resources being created and configured based on the values that we have provided. The backup plan created will have the backup rule and tag-based selection condition applied as shown in the snapshot below,
 
Configuring A Tag-based AWS Backup Using AWS CloudFormation Template 
 
With these settings in place, any resource with the specified tag value will get the backup configuration created. This reduces a lot of administrative effort and ensures consistency. We will need to also define a standard format for the tag names to be used in the condition specified. I would recommend having resource type as one of the conditions in a standard format so that it is easier to identify the backup plans and tags. You should be able to easily add more backup and selection plans based on your specific use cases and requirements now with this reusable CloudFormation template.
 
Happy Clouding!