/** * # aws-backup * * Module to configure AWSBackup service opt in and manage backup settings for typical workloads */ 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:*" } "Storage Gateway" : { enabled = var.service-opt-in["Storage Gateway"].enabled 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 arn-prefix = "arn:aws:cloudformation:*:*:stack/*/*" } "Neptune" : { enabled = var.service-opt-in["Neptune"].enabled arn-prefix = "arn:aws:neptune-db:*:*:cluster:*" } "Redshift Serverless" : { enabled = var.service-opt-in["Redshift Serverless"].enabled arn-prefix = "arn:aws:redshift-serverless:*:*:workgroup/*" } "SAP HANA on Amazon EC2" : { enabled = var.service-opt-in["SAP HANA on Amazon EC2"].enabled arn-prefix = "arn:aws:sap:*:*:application/*/*" } } } 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-${trimspace(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" } } } dynamic "advanced_backup_setting" { for_each = var.enable-vss ? [1] : [] content { 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] }