Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion modules/aws-backup-source/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ No modules.
| [aws_backup_selection.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_selection) | resource |
| [aws_backup_selection.dynamodb](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_selection) | resource |
| [aws_backup_vault.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault) | resource |
| [aws_backup_logically_air_gapped_vault.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_logically_air_gapped_vault) | resource |
| [aws_backup_vault_notifications.backup_notification](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_notifications) | resource |
| [aws_backup_vault_notifications.backup_notification_lag](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_notifications) | resource |
| [aws_backup_vault_policy.vault_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/backup_vault_policy) | resource |
| [aws_iam_role.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.backup](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
Expand Down Expand Up @@ -95,6 +97,13 @@ No modules.

## Outputs

No outputs.
| Name | Description |
|---------------------------------| -------------------------|
| backup_role_arn | ARN of the of the backup role |
| backup_vault_arn | ARN of the of the Backup Vault |
| backup_vault_name | Name of the of the Backup Vault |
| logically_air_gapped_vault_arn | ARN of the of the Logically Air-gapped Vault |
| logically_air_gapped_vault_name | Name of the of the Logically Air-gapped Vault |
<!-- END_TF_DOCS -->

<!-- markdownlint-enable MD037 -->
4 changes: 2 additions & 2 deletions modules/aws-backup-source/backup_framework.tf
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ resource "aws_backup_framework" "main" {

input_parameter {
name = "requiredRetentionDays"
value = "35"
value = var.vault_lock_min_retention_days
}
}

Expand All @@ -87,7 +87,7 @@ resource "aws_backup_framework" "main" {

input_parameter {
name = "requiredRetentionDays"
value = "35"
value = var.vault_lock_min_retention_days
}

input_parameter {
Expand Down
13 changes: 13 additions & 0 deletions modules/aws-backup-source/backup_notification.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,16 @@ resource "aws_backup_vault_notifications" "backup_notification" {
"COPY_JOB_FAILED"
]
}

resource "aws_backup_vault_notifications" "backup_notification_lag" {
count = var.enable_logically_air_gapped_vault && var.notifications_target_email_address != "" ? 1 : 0
backup_vault_name = aws_backup_logically_air_gapped_vault.main[0].name
sns_topic_arn = aws_sns_topic.backup[0].arn
backup_vault_events = [
"BACKUP_JOB_COMPLETED",
"RESTORE_JOB_COMPLETED",
"S3_BACKUP_OBJECT_FAILED",
"S3_RESTORE_OBJECT_FAILED",
"COPY_JOB_FAILED"
]
}
45 changes: 25 additions & 20 deletions modules/aws-backup-source/backup_plan.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ resource "aws_backup_plan" "default" {
recovery_point_tags = {
backup_rule_name = rule.value.name
}
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
schedule = rule.value.schedule
completion_window = rule.value.completion_window
enable_continuous_backup = rule.value.enable_continuous_backup != null ? rule.value.enable_continuous_backup : null
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
target_logically_air_gapped_backup_vault_arn = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].arn : null
schedule = rule.value.schedule
completion_window = rule.value.completion_window
enable_continuous_backup = rule.value.enable_continuous_backup != null ? rule.value.enable_continuous_backup : null
lifecycle {
delete_after = rule.value.lifecycle.delete_after != null ? rule.value.lifecycle.delete_after : null
cold_storage_after = rule.value.lifecycle.cold_storage_after != null ? rule.value.lifecycle.cold_storage_after : null
Expand Down Expand Up @@ -40,10 +41,11 @@ resource "aws_backup_plan" "dynamodb" {
recovery_point_tags = {
backup_rule_name = rule.value.name
}
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
schedule = rule.value.schedule
completion_window = rule.value.completion_window
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
target_logically_air_gapped_backup_vault_arn = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].arn : null
schedule = rule.value.schedule
completion_window = rule.value.completion_window
lifecycle {
delete_after = rule.value.lifecycle.delete_after != null ? rule.value.lifecycle.delete_after : null
cold_storage_after = rule.value.lifecycle.cold_storage_after != null ? rule.value.lifecycle.cold_storage_after : null
Expand Down Expand Up @@ -71,9 +73,10 @@ resource "aws_backup_plan" "ebsvol" {
recovery_point_tags = {
backup_rule_name = rule.value.name
}
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
schedule = rule.value.schedule
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
target_logically_air_gapped_backup_vault_arn = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].arn : null
schedule = rule.value.schedule
lifecycle {
delete_after = rule.value.lifecycle.delete_after != null ? rule.value.lifecycle.delete_after : null
cold_storage_after = rule.value.lifecycle.cold_storage_after != null ? rule.value.lifecycle.cold_storage_after : null
Expand Down Expand Up @@ -102,9 +105,10 @@ resource "aws_backup_plan" "aurora" {
recovery_point_tags = {
backup_rule_name = rule.value.name
}
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
schedule = rule.value.schedule
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
target_logically_air_gapped_backup_vault_arn = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].arn : null
schedule = rule.value.schedule
lifecycle {
delete_after = rule.value.lifecycle.delete_after != null ? rule.value.lifecycle.delete_after : null
cold_storage_after = rule.value.lifecycle.cold_storage_after != null ? rule.value.lifecycle.cold_storage_after : null
Expand Down Expand Up @@ -133,11 +137,12 @@ resource "aws_backup_plan" "parameter_store" {
recovery_point_tags = {
backup_rule_name = rule.value.name
}
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
schedule = rule.value.schedule
completion_window = rule.value.completion_window
enable_continuous_backup = rule.value.enable_continuous_backup != null ? rule.value.enable_continuous_backup : null
rule_name = rule.value.name
target_vault_name = aws_backup_vault.main.name
target_logically_air_gapped_backup_vault_arn = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].arn : null
schedule = rule.value.schedule
completion_window = rule.value.completion_window
enable_continuous_backup = rule.value.enable_continuous_backup != null ? rule.value.enable_continuous_backup : null
lifecycle {
delete_after = rule.value.lifecycle.delete_after
cold_storage_after = rule.value.lifecycle.cold_storage_after
Expand Down
8 changes: 4 additions & 4 deletions modules/aws-backup-source/backup_restore_testing.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ resource "awscc_backup_restore_testing_plan" "backup_restore_testing_plan" {
start_window_hours = var.restore_testing_plan_start_window
recovery_point_selection = {
algorithm = var.restore_testing_plan_algorithm
include_vaults = [aws_backup_vault.main.arn]
include_vaults = concat([aws_backup_vault.main.arn], (var.enable_logically_air_gapped_vault ? [aws_backup_logically_air_gapped_vault.main[0].arn] : []))
recovery_point_types = var.restore_testing_plan_recovery_point_types
selection_window_days = var.restore_testing_plan_selection_window_days
}
Expand All @@ -20,7 +20,7 @@ resource "awscc_backup_restore_testing_selection" "backup_restore_testing_select
protected_resource_conditions = {
string_equals = [{
key = "aws:ResourceTag/${var.backup_plan_config_dynamodb.selection_tag}"
value = "True"
value = (var.backup_plan_config_dynamodb.selection_tag_value == null) ? "True" : var.backup_plan_config_dynamodb.selection_tag_value
}]
}
}
Expand All @@ -36,7 +36,7 @@ resource "awscc_backup_restore_testing_selection" "backup_restore_testing_select
protected_resource_conditions = {
string_equals = [{
key = "aws:ResourceTag/${var.backup_plan_config_ebsvol.selection_tag}"
value = "True"
value = (var.backup_plan_config_ebsvol.selection_tag_value == null) ? "True" : var.backup_plan_config_ebsvol.selection_tag_value
}]
}
}
Expand All @@ -51,7 +51,7 @@ resource "awscc_backup_restore_testing_selection" "backup_restore_testing_select
protected_resource_conditions = {
string_equals = [{
key = "aws:ResourceTag/${var.backup_plan_config_aurora.selection_tag}"
value = "True"
value = (var.backup_plan_config_aurora.selection_tag_value == null) ? "True" : var.backup_plan_config_aurora.selection_tag_value
}]
}
restore_metadata_overrides = local.aurora_overrides
Expand Down
7 changes: 7 additions & 0 deletions modules/aws-backup-source/backup_vault.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ resource "aws_backup_vault" "main" {
name = "${local.resource_name_prefix}-vault"
kms_key_arn = aws_kms_key.aws_backup_key.arn
}

resource "aws_backup_logically_air_gapped_vault" "main" {
count = var.enable_logically_air_gapped_vault ? 1 : 0
name = "${local.resource_name_prefix}-vault-lag"
min_retention_days = var.vault_lock_min_retention_days
max_retention_days = var.vault_lock_max_retention_days
}
33 changes: 18 additions & 15 deletions modules/aws-backup-source/kms.tf
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,24 @@ data "aws_iam_policy_document" "backup_key_policy" {
actions = ["kms:*"]
resources = ["*"]
}
statement {
sid = "Allow attachment of persistent resources"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${var.backup_copy_vault_account_id}:root"]
dynamic "statement" {
for_each = var.backup_copy_vault_arn != "" && var.backup_copy_vault_account_id != "" ? [1] : []
content {
sid = "Allow attachment of persistent resources"
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${var.backup_copy_vault_account_id}:root"]
}
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:CreateGrant",
"kms:ListGrants",
"kms:DescribeKey"
]
resources = ["*"]
}
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:CreateGrant",
"kms:ListGrants",
"kms:DescribeKey"
]
resources = ["*"]
}
}
14 changes: 12 additions & 2 deletions modules/aws-backup-source/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,20 @@ output "backup_role_arn" {

output "backup_vault_arn" {
value = aws_backup_vault.main.arn
description = "ARN of the of the vault"
description = "ARN of the of the Backup Vault"
}

output "backup_vault_name" {
value = aws_backup_vault.main.name
description = "Name of the of the vault"
description = "Name of the of the Backup Vault"
}

output "logically_air_gapped_vault_arn" {
value = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].arn : null
description = "ARN of the of the Logically Air-gapped Vault"
}

output "logically_air_gapped_vault_name" {
value = var.enable_logically_air_gapped_vault ? aws_backup_logically_air_gapped_vault.main[0].name : null
description = "Name of the of the Logically Air-gapped Vault"
}
29 changes: 29 additions & 0 deletions modules/aws-backup-source/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -520,3 +520,32 @@ variable "lambda_restore_to_s3_max_wait_minutes" {
type = number
default = 5
}

variable "enable_logically_air_gapped_vault" {
description = "Enable backing up to Logically Air-gapped Vault for supported resources"
type = bool
default = false
}

variable "vault_lock_min_retention_days" {
description = "The minimum retention period that the Backup Vault retains its recovery points"
type = number
default = 35

validation {
condition = var.vault_lock_min_retention_days >= 7
error_message = "The minimum retention in days must be at least 7"
}
}

variable "vault_lock_max_retention_days" {
description = "The maximum retention period that the Backup Vault retains its recovery points"
type = number
default = 365
}

variable "logically_air_gapped_vault_approval_team_arn" {
description = "The ARN of the Multi-party approval Team to be assigned to the logically air-gapped vault"
type = string
default = null
}