# build local data structure data "aws_caller_identity" "this" {} locals { backup-config = { "Aurora" : { enabled = var.service-opt-in.Aurora.enabled arn-prefix = "arn:aws:rds:*:*:cluster:*" } "DynamoDB" : { enabled = var.service-opt-in.DynamoDB.enabled arn-prefix = "arn:aws:dynamodb:*:*:table/*" } "EBS" : { enabled = var.service-opt-in.EBS.enabled arn-prefix = "arn:aws:ec2:*:*:volume/*" } "EC2" : { enabled = var.service-opt-in.EC2.enabled arn-prefix = "arn:aws:ec2:*:*:instance/*" } "EFS" : { enabled = var.service-opt-in.EFS.enabled arn-prefix = "arn:aws:elasticfilesystem:*:*:file-system/*" } "FSx" : { enabled = var.service-opt-in.FSx.enabled arn-prefix = "arn:*:fsx:*" } "Redshift" : { enabled = var.service-opt-in.Redshift.enabled arn-prefix = "arn:aws:redshift:*:*:cluster:*" } "RDS" : { enabled = var.service-opt-in.RDS.enabled arn-prefix = "arn:aws:rds:*:*:db:*" } # this version can't handle space # "Storage Gateway" : { # enabled = var.opt-in-storagegateway # arn-prefix = "arn:aws:storagegateway:*:*:gateway/*" # } "VirtualMachine" : { enabled = var.service-opt-in.VirtualMachine.enabled arn-prefix = "arn:aws:backup-gateway:*:*:vm/*" } "S3" : { enabled = var.service-opt-in.S3.enabled arn-prefix = "arn:aws:s3:::*" } "EKS" : { enabled = var.service-opt-in.EKS.enabled arn-prefix = "arn:aws:eks:*:*:cluster/*" } "CloudFormation" : { enabled = var.service-opt-in.CloudFormation.enabled } "Neptune" : { enabled = var.service-opt-in.Neptune.enabled } "Redshift Serverless" : { enabled = var.service-opt-in["Redshift Serverless"].enabled } "SAP HANA on Amazon EC2" : { enabled = var.service-opt-in["SAP HANA on Amazon EC2"].enabled } "Storage Gateway" : { enabled = var.service-opt-in["Storage Gateway"].enabled } } } resource "aws_backup_region_settings" "ab-settings" { resource_type_opt_in_preference = { for k, v in local.backup-config : k => v.enabled } } resource "aws_backup_vault" "ab-vault" { for_each = toset([ for k, v in local.backup-config : k if v.enabled ]) name = "BackupVault-${each.value}" kms_key_arn = var.backup_kms_key } resource "aws_backup_vault_policy" "ab-vault-policy" { for_each = aws_backup_vault.ab-vault backup_vault_name = each.value.name policy = jsonencode( { "Version" : "2012-10-17", "Id" : "default", "Statement" : [ { "Sid" : "default", "Effect" : "Allow", "Principal" : { "AWS" : data.aws_caller_identity.this.account_id }, "Action" : [ "backup:DescribeBackupVault", "backup:DeleteBackupVault", "backup:PutBackupVaultAccessPolicy", "backup:DeleteBackupVaultAccessPolicy", "backup:GetBackupVaultAccessPolicy", "backup:StartBackupJob", "backup:GetBackupVaultNotifications", "backup:PutBackupVaultNotifications" ], "Resource" : each.value.arn } ] }) } resource "aws_backup_plan" "ab-plan" { for_each = aws_backup_vault.ab-vault name = "BackupPlan-${replace(each.value.name, "BackupVault-", "")}" # daily backup rule { rule_name = "Daily" target_vault_name = each.value.name schedule = var.daily-backup-cron start_window = 60 completion_window = 240 lifecycle { delete_after = var.daily-backup-retention } recovery_point_tags = { "CreatedBy" : "AWSBackup" "AWSBackupPlan" : "BackupPlan-${replace(each.value.name, "BackupVault-", "")}-Daily" } } # monthly backup (when overlap with daily, only monthly backup will be created. # see https://docs.aws.amazon.com/aws-backup/latest/devguide/creating-a-backup-plan.html) dynamic "rule" { for_each = var.enable-monthly-backup ? [1] : [] content { rule_name = "Monthly" target_vault_name = each.value.name schedule = var.monthly-backup-cron start_window = 60 completion_window = 240 lifecycle { delete_after = var.monthly-backup-retention cold_storage_after = var.daily-backup-retention # move to cold storage after daily retention, supported on a few services only } recovery_point_tags = { "CreatedBy" : "AWSBackup" "AWSBackupPlan" : "BackupPlan-${replace(each.value.name, "BackupVault-", "")}-Monthly" } } } # advanced_backup_setting { # backup_options = { # WindowsVSS = "enabled" # } # resource_type = "EC2" # } } # resource "aws_iam_role" "ab-iam-role" { name = "AwsBackupRole" assume_role_policy = jsonencode( { "Version" : "2012-10-17", "Statement" : [ { "Action" : ["sts:AssumeRole"], "Effect" : "allow", "Principal" : { "Service" : ["backup.amazonaws.com"] } } ] }) } resource "aws_iam_role_policy_attachment" "ab-iam-role-policy" { for_each = toset([ "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup", "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores", "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Backup", "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Restore" ]) policy_arn = each.value role = aws_iam_role.ab-iam-role.name } resource "aws_backup_selection" "ab-selection-by-service-type" { for_each = aws_backup_plan.ab-plan iam_role_arn = aws_iam_role.ab-iam-role.arn name = "SelectionByServiceType" plan_id = each.value.id resources = [lookup(local.backup-config, replace(each.value.name, "BackupPlan-", "")).arn-prefix] }