diff --git a/.github/workflows/_deploy.yml b/.github/workflows/_deploy.yml index d3b913541..579513d97 100644 --- a/.github/workflows/_deploy.yml +++ b/.github/workflows/_deploy.yml @@ -47,7 +47,7 @@ jobs: branch_name=${branch_name#*refs/tags/} echo "branch_name=${branch_name}" >> $GITHUB_OUTPUT - # BACKUPS_LOGIC (Source account needs layers building) + # Source account for immutable backups needs layers building build: runs-on: [self-hosted, ci] needs: get-branch-from-workflow-file @@ -62,14 +62,14 @@ jobs: save-to-cache: "true" restore-from-cache: "false" cache-suffix: ${{ env.CACHE_NAME }} - - if: ${{ env.SCOPE != 'per_workspace' && inputs.account == 'dev'}} + - if: ${{ env.SCOPE != 'per_workspace' && (inputs.account == 'prod' || inputs.account == 'dev') }} uses: ./.github/actions/make/ with: command: build save-to-cache: "true" restore-from-cache: "false" cache-suffix: ${{ env.CACHE_NAME }} - - if: ${{ env.SCOPE != 'per_workspace' && inputs.account != 'dev'}} + - if: ${{ env.SCOPE != 'per_workspace' && (inputs.account != 'prod' && inputs.account != 'dev' )}} uses: ./.github/actions/make/ with: command: poetry--update diff --git a/infrastructure/terraform/per_account/backups/aws-backups.tf b/infrastructure/terraform/per_account/backups/aws-backups.tf index c61586b1a..efd8ccc21 100644 --- a/infrastructure/terraform/per_account/backups/aws-backups.tf +++ b/infrastructure/terraform/per_account/backups/aws-backups.tf @@ -1,9 +1,17 @@ -data "aws_secretsmanager_secret" "source_account_id" { - name = "backups-source-account-id" +data "aws_secretsmanager_secret" "source_account_id_prod" { + name = "backups-source-account-id-prod" } -data "aws_secretsmanager_secret_version" "source_account_id" { - secret_id = data.aws_secretsmanager_secret.source_account_id.id +data "aws_secretsmanager_secret_version" "source_account_id_prod" { + secret_id = data.aws_secretsmanager_secret.source_account_id_prod.id +} + +data "aws_secretsmanager_secret" "source_account_id_dev" { + name = "backups-source-account-id-dev" +} + +data "aws_secretsmanager_secret_version" "source_account_id_dev" { + secret_id = data.aws_secretsmanager_secret.source_account_id_dev.id } @@ -15,12 +23,33 @@ resource "aws_kms_key" "destination_backup_key" { enable_key_rotation = true } -module "destination" { +module "destination_prod" { + source = "../modules/aws-backup-destination" + + source_account_name = "prod" # please note that the assigned value would be the prefix in aws_backup_vault.vault.name - change to dev/prod + account_id = var.assume_account + source_account_id = data.aws_secretsmanager_secret_version.source_account_id_prod.secret_string + kms_key = aws_kms_key.destination_backup_key.arn + enable_vault_protection = false +} + +### +# Destination vault ARN output +### + +output "destination_vault_arn_prod" { + # The ARN of the backup vault in the destination account is needed by + # the source account to copy backups into it. + value = module.destination_prod.vault_arn +} + + +module "destination_dev" { source = "../modules/aws-backup-destination" - source_account_name = "dev" # please note that the assigned value would be the prefix in aws_backup_vault.vault.name - change to dev/prod BACKUPS_LOGIC + source_account_name = "dev" # please note that the assigned value would be the prefix in aws_backup_vault.vault.name - change to dev/prod account_id = var.assume_account - source_account_id = data.aws_secretsmanager_secret_version.source_account_id.secret_string + source_account_id = data.aws_secretsmanager_secret_version.source_account_id_dev.secret_string kms_key = aws_kms_key.destination_backup_key.arn enable_vault_protection = false } @@ -29,8 +58,8 @@ module "destination" { # Destination vault ARN output ### -output "destination_vault_arn" { +output "destination_vault_arn_dev" { # The ARN of the backup vault in the destination account is needed by # the source account to copy backups into it. - value = module.destination.vault_arn + value = module.destination_dev.vault_arn } diff --git a/infrastructure/terraform/per_account/backups/parameters/main.tf b/infrastructure/terraform/per_account/backups/parameters/main.tf index 476be9dae..70b88646d 100644 --- a/infrastructure/terraform/per_account/backups/parameters/main.tf +++ b/infrastructure/terraform/per_account/backups/parameters/main.tf @@ -28,8 +28,13 @@ JSON } -resource "aws_secretsmanager_secret" "source-account-id-for-backup" { - name = "${terraform.workspace}-source-account-id" +resource "aws_secretsmanager_secret" "source-account-id-for-backup-prod" { + name = "${terraform.workspace}-source-account-id-prod" + description = "ID of the account we want to backup" +} + +resource "aws_secretsmanager_secret" "source-account-id-for-backup-dev" { + name = "${terraform.workspace}-source-account-id-dev" description = "ID of the account we want to backup" } diff --git a/infrastructure/terraform/per_account/dev/aws-backups.tf b/infrastructure/terraform/per_account/dev/aws-backups.tf index fa82a4270..5cacf0901 100644 --- a/infrastructure/terraform/per_account/dev/aws-backups.tf +++ b/infrastructure/terraform/per_account/dev/aws-backups.tf @@ -1,4 +1,3 @@ -# BACKUPS_LOGIC data "aws_secretsmanager_secret" "destination_vault_arn" { name = "destination_vault_arn" } diff --git a/infrastructure/terraform/per_account/dev/main.tf b/infrastructure/terraform/per_account/dev/main.tf index d61098164..1c11dd945 100644 --- a/infrastructure/terraform/per_account/dev/main.tf +++ b/infrastructure/terraform/per_account/dev/main.tf @@ -96,7 +96,6 @@ resource "aws_route53_zone" "dev-ns" { name = "api.cpm.dev.national.nhs.uk" } -# BACKUPS_LOGIC module "layers" { for_each = toset(var.layers) source = "../../modules/api_worker/api_layer" @@ -106,7 +105,6 @@ module "layers" { source_path = "${path.module}/../../../../src/layers/${each.key}/dist/${each.key}.zip" } -# BACKUPS_LOGIC module "third_party_layers" { for_each = toset(var.third_party_layers) source = "../../modules/api_worker/api_layer" diff --git a/infrastructure/terraform/per_account/dev/parameters/main.tf b/infrastructure/terraform/per_account/dev/parameters/main.tf index 04553c6ed..447d28616 100644 --- a/infrastructure/terraform/per_account/dev/parameters/main.tf +++ b/infrastructure/terraform/per_account/dev/parameters/main.tf @@ -55,8 +55,8 @@ resource "aws_secretsmanager_secret" "ldap-changelog-password" { name = "${terraform.workspace}-ldap-changelog-password" } -resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" { - name = "${terraform.workspace}--etl-notify-slack-webhook-url" +resource "aws_secretsmanager_secret" "notify_slack_webhook_url" { + name = "${terraform.workspace}-notify-slack-webhook-url" } resource "aws_secretsmanager_secret" "apigee-app-client-info" { @@ -67,12 +67,10 @@ resource "aws_secretsmanager_secret" "external-id" { name = "${terraform.workspace}-external-id" } -# BACKUPS_LOGIC resource "aws_secretsmanager_secret" "destination_vault_arn" { name = "destination_vault_arn" } -# BACKUPS_LOGIC resource "aws_secretsmanager_secret" "destination_account_id" { name = "destination_account_id" } diff --git a/infrastructure/terraform/per_account/dev/parameters/vars.tf b/infrastructure/terraform/per_account/dev/parameters/vars.tf index 8750b8aa2..8a6a64855 100644 --- a/infrastructure/terraform/per_account/dev/parameters/vars.tf +++ b/infrastructure/terraform/per_account/dev/parameters/vars.tf @@ -30,12 +30,10 @@ variable "workspace_type" { default = "PERSISTENT" } -# BACKUPS_LOGIC variable "layers" { type = list(string) } -# BACKUPS_LOGIC variable "third_party_layers" { type = list(string) } diff --git a/infrastructure/terraform/per_account/dev/vars.tf b/infrastructure/terraform/per_account/dev/vars.tf index b4e4bc352..ec37790ec 100644 --- a/infrastructure/terraform/per_account/dev/vars.tf +++ b/infrastructure/terraform/per_account/dev/vars.tf @@ -29,17 +29,14 @@ variable "budget_limit" { type = string } -# BACKUPS_LOGIC variable "python_version" { default = "python3.12" } -# BACKUPS_LOGIC variable "layers" { type = list(string) } -# BACKUPS_LOGIC variable "third_party_layers" { type = list(string) } diff --git a/infrastructure/terraform/per_account/int/parameters/main.tf b/infrastructure/terraform/per_account/int/parameters/main.tf index 4784a7f25..b29608361 100644 --- a/infrastructure/terraform/per_account/int/parameters/main.tf +++ b/infrastructure/terraform/per_account/int/parameters/main.tf @@ -39,10 +39,6 @@ resource "aws_secretsmanager_secret" "apigee-app-key" { name = "${terraform.workspace}-apigee-app-key" } -resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" { - name = "${terraform.workspace}--etl-notify-slack-webhook-url" -} - resource "aws_secretsmanager_secret" "sds-hscn-endpoint" { name = "${terraform.workspace}-sds-hscn-endpoint" } diff --git a/infrastructure/terraform/per_account/modules/notify/main.tf b/infrastructure/terraform/per_account/modules/notify/main.tf index d89d6b458..f8d428db7 100644 --- a/infrastructure/terraform/per_account/modules/notify/main.tf +++ b/infrastructure/terraform/per_account/modules/notify/main.tf @@ -1,5 +1,5 @@ data "aws_secretsmanager_secret" "slack_webhook_url" { - name = "${var.environment}--etl-notify-slack-webhook-url" + name = "${var.environment}-notify-slack-webhook-url" } data "aws_secretsmanager_secret_version" "slack_webhook_url" { diff --git a/infrastructure/terraform/per_account/prod/aws-backups.tf b/infrastructure/terraform/per_account/prod/aws-backups.tf new file mode 100644 index 000000000..5cacf0901 --- /dev/null +++ b/infrastructure/terraform/per_account/prod/aws-backups.tf @@ -0,0 +1,155 @@ +data "aws_secretsmanager_secret" "destination_vault_arn" { + name = "destination_vault_arn" +} + +data "aws_secretsmanager_secret_version" "destination_vault_arn" { + secret_id = data.aws_secretsmanager_secret.destination_vault_arn.id +} + +data "aws_secretsmanager_secret" "destination_account_id" { + name = "destination_account_id" +} + +data "aws_secretsmanager_secret_version" "destination_account_id" { + secret_id = data.aws_secretsmanager_secret.destination_account_id.id +} + +# First, we create an S3 bucket for compliance reports. You may already have a module for creating +# S3 buckets with more refined access rules, which you may prefer to use. + +resource "aws_s3_bucket" "backup_reports" { + bucket_prefix = "${local.project}-backup-reports" +} + +# Now we have to configure access to the report bucket. + +resource "aws_s3_bucket_ownership_controls" "backup_reports" { + bucket = aws_s3_bucket.backup_reports.id + rule { + object_ownership = "BucketOwnerPreferred" + } +} + +resource "aws_s3_bucket_acl" "backup_reports" { + depends_on = [aws_s3_bucket_ownership_controls.backup_reports] + + bucket = aws_s3_bucket.backup_reports.id + acl = "private" +} + +resource "aws_s3_bucket_policy" "backup_reports_policy" { + bucket = aws_s3_bucket.backup_reports.id + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Principal = { + AWS = "arn:aws:iam::${var.assume_account}:role/aws-service-role/reports.backup.amazonaws.com/AWSServiceRoleForBackupReports" + }, + Action = "s3:PutObject", + Resource = "${aws_s3_bucket.backup_reports.arn}/*", + Condition = { + StringEquals = { + "s3:x-amz-acl" = "bucket-owner-full-control" + } + } + } + ] + }) +} + +# We need a key for the SNS topic that will be used for notifications from AWS Backup. This key +# will be used to encrypt the messages sent to the topic before they are sent to the subscribers, +# but isn't needed by the recipients of the messages. + + +# Now we can define the key itself +resource "aws_kms_key" "backup_notifications" { + description = "KMS key for AWS Backup notifications" + deletion_window_in_days = 7 + enable_key_rotation = true + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Sid = "Enable IAM User Permissions" + Principal = { + AWS = "arn:aws:iam::${var.assume_account}:root" + } + Action = "kms:*" + Resource = "*" + }, + { + Effect = "Allow" + Principal = { + Service = "sns.amazonaws.com" + } + Action = ["kms:GenerateDataKey*", "kms:Decrypt"] + Resource = "*" + }, + { + Effect = "Allow" + Principal = { + Service = "backup.amazonaws.com" + } + Action = ["kms:GenerateDataKey*", "kms:Decrypt"] + Resource = "*" + }, + ] + }) +} + +resource "aws_kms_alias" "backup_notifications" { + name = "alias/key-for-backup-notify" + target_key_id = aws_kms_key.backup_notifications.key_id +} + +# Now we can deploy the source and destination modules, referencing the resources we've created above. + +module "source" { + source = "../modules/aws-backup-source" + + backup_copy_vault_account_id = data.aws_secretsmanager_secret_version.destination_account_id.secret_string + backup_copy_vault_arn = data.aws_secretsmanager_secret_version.destination_vault_arn.secret_string + environment_name = var.environment + bootstrap_kms_key_arn = aws_kms_key.backup_notifications.arn + project_name = local.project + reports_bucket = aws_s3_bucket.backup_reports.bucket + terraform_role_arn = "arn:aws:iam::${var.assume_account}:role/${var.assume_role}" + python_version = var.python_version + notify_lambda_arn = module.notify.arn + + backup_plan_config_dynamodb = { + "compliance_resource_types" : [ + "DynamoDB" + ], + "rules" : [ + { + "copy_action" : { + "delete_after" : 31 + }, + "lifecycle" : { + "delete_after" : 4 + }, + "name" : "daily_kept_for_2_days", + "schedule" : "cron(0 20 * * ? *)" + } + ], + "enable" : true, + "selection_tag" : "NHSE-Enable-Backup" + } +} + + +module "notify" { + source = "../modules/notify/" + + assume_account = var.assume_account + project_name = local.project + python_version = var.python_version + environment = var.environment + event_layer_arn = element([for instance in module.layers : instance if instance.name == "event"], 0).layer_arn + third_party_layer_arn = element([for instance in module.third_party_layers : instance if instance.name == "third_party_core"], 0).layer_arn +} diff --git a/infrastructure/terraform/per_account/prod/main.tf b/infrastructure/terraform/per_account/prod/main.tf index ea9d23fcd..9b3101eb7 100644 --- a/infrastructure/terraform/per_account/prod/main.tf +++ b/infrastructure/terraform/per_account/prod/main.tf @@ -96,69 +96,20 @@ resource "aws_route53_zone" "prod-ns" { name = "api.cpm.national.nhs.uk" } -module "snapshot_bucket" { - source = "terraform-aws-modules/s3-bucket/aws" - version = "3.15.2" - bucket = "${local.project}--${replace(terraform.workspace, "_", "-")}--snapshot" - versioning = { - enabled = true - } - tags = { - Name = "${local.project}--${replace(terraform.workspace, "_", "-")}--snapshot" - } +module "layers" { + for_each = toset(var.layers) + source = "../../modules/api_worker/api_layer" + name = each.key + python_version = var.python_version + layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}" + source_path = "${path.module}/../../../../src/layers/${each.key}/dist/${each.key}.zip" } -resource "aws_s3_bucket_policy" "snapshot_bucket_policy" { - bucket = module.snapshot_bucket.s3_bucket_id - policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Sid = "AWSAccessLogDeliveryWrite", - Effect = "Allow", - Principal = { - Service = "logging.s3.amazonaws.com" - }, - Action = "s3:PutObject", - Resource = "${module.snapshot_bucket.s3_bucket_arn}/*" - }, - { - Sid = "AWSAccessLogDeliveryAclCheck", - Effect = "Allow", - Principal = { - Service = "logging.s3.amazonaws.com" - }, - Action = "s3:GetBucketAcl", - Resource = "${module.snapshot_bucket.s3_bucket_arn}" - }, - { - Sid = "denyInsecureTransport", - Effect = "Deny", - Principal = "*", - Action = "s3:*", - Resource = [ - "${module.snapshot_bucket.s3_bucket_arn}", - "${module.snapshot_bucket.s3_bucket_arn}/*" - ], - Condition = { - Bool = { - "aws:SecureTransport" = "false" - } - } - }, - { - Sid = "AllowDynamoDBExport", - Effect = "Allow", - Principal = { - Service = "dynamodb.amazonaws.com" - }, - Action = [ - "s3:PutObject", - "s3:AbortMultipartUpload", - "s3:ListMultipartUploadParts" - ], - Resource = "${module.snapshot_bucket.s3_bucket_arn}/*" - } - ] - }) +module "third_party_layers" { + for_each = toset(var.third_party_layers) + source = "../../modules/api_worker/api_layer" + name = each.key + python_version = var.python_version + layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}" + source_path = "${path.module}/../../../../src/layers/third_party/dist/${each.key}.zip" } diff --git a/infrastructure/terraform/per_account/prod/parameters/main.tf b/infrastructure/terraform/per_account/prod/parameters/main.tf index 4784a7f25..70f0d6e68 100644 --- a/infrastructure/terraform/per_account/prod/parameters/main.tf +++ b/infrastructure/terraform/per_account/prod/parameters/main.tf @@ -39,10 +39,6 @@ resource "aws_secretsmanager_secret" "apigee-app-key" { name = "${terraform.workspace}-apigee-app-key" } -resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" { - name = "${terraform.workspace}--etl-notify-slack-webhook-url" -} - resource "aws_secretsmanager_secret" "sds-hscn-endpoint" { name = "${terraform.workspace}-sds-hscn-endpoint" } @@ -59,6 +55,18 @@ resource "aws_secretsmanager_secret" "ldap-changelog-password" { name = "${terraform.workspace}-ldap-changelog-password" } +resource "aws_secretsmanager_secret" "notify_slack_webhook_url" { + name = "${terraform.workspace}-notify-slack-webhook-url" +} + resource "aws_secretsmanager_secret" "external-id" { name = "${terraform.workspace}-external-id" } + +resource "aws_secretsmanager_secret" "destination_vault_arn" { + name = "destination_vault_arn" +} + +resource "aws_secretsmanager_secret" "destination_account_id" { + name = "destination_account_id" +} diff --git a/infrastructure/terraform/per_account/prod/parameters/vars.tf b/infrastructure/terraform/per_account/prod/parameters/vars.tf index 8d34250b8..8a6a64855 100644 --- a/infrastructure/terraform/per_account/prod/parameters/vars.tf +++ b/infrastructure/terraform/per_account/prod/parameters/vars.tf @@ -29,3 +29,11 @@ variable "workspace_type" { type = string default = "PERSISTENT" } + +variable "layers" { + type = list(string) +} + +variable "third_party_layers" { + type = list(string) +} diff --git a/infrastructure/terraform/per_account/prod/vars.tf b/infrastructure/terraform/per_account/prod/vars.tf index 3c3029cd3..04668c99e 100644 --- a/infrastructure/terraform/per_account/prod/vars.tf +++ b/infrastructure/terraform/per_account/prod/vars.tf @@ -28,3 +28,15 @@ variable "budget_limit" { default = "1300" type = string } + +variable "python_version" { + default = "python3.12" +} + +variable "layers" { + type = list(string) +} + +variable "third_party_layers" { + type = list(string) +} diff --git a/infrastructure/terraform/per_account/qa/parameters/main.tf b/infrastructure/terraform/per_account/qa/parameters/main.tf index 4784a7f25..b29608361 100644 --- a/infrastructure/terraform/per_account/qa/parameters/main.tf +++ b/infrastructure/terraform/per_account/qa/parameters/main.tf @@ -39,10 +39,6 @@ resource "aws_secretsmanager_secret" "apigee-app-key" { name = "${terraform.workspace}-apigee-app-key" } -resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" { - name = "${terraform.workspace}--etl-notify-slack-webhook-url" -} - resource "aws_secretsmanager_secret" "sds-hscn-endpoint" { name = "${terraform.workspace}-sds-hscn-endpoint" } diff --git a/infrastructure/terraform/per_account/ref/parameters/main.tf b/infrastructure/terraform/per_account/ref/parameters/main.tf index 2ddca03b6..78e3eac6c 100644 --- a/infrastructure/terraform/per_account/ref/parameters/main.tf +++ b/infrastructure/terraform/per_account/ref/parameters/main.tf @@ -39,10 +39,6 @@ resource "aws_secretsmanager_secret" "apigee-app-key" { name = "${terraform.workspace}-apigee-app-key" } -resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" { - name = "${terraform.workspace}--etl-notify-slack-webhook-url" -} - resource "aws_secretsmanager_secret" "sds-hscn-endpoint" { name = "${terraform.workspace}-sds-hscn-endpoint" } diff --git a/infrastructure/terraform/per_workspace/modules/api_storage/dynamodb.tf b/infrastructure/terraform/per_workspace/modules/api_storage/dynamodb.tf index c2900c0ea..1db0f912b 100644 --- a/infrastructure/terraform/per_workspace/modules/api_storage/dynamodb.tf +++ b/infrastructure/terraform/per_workspace/modules/api_storage/dynamodb.tf @@ -19,7 +19,7 @@ module "dynamodb_table" { { Name = var.name }, - var.environment == "dev" ? { + var.environment == "prod" ? { "NHSE-Enable-Backup" = "True" } : {} ) diff --git a/scripts/infrastructure/policies/deployment2-policy.json b/scripts/infrastructure/policies/deployment2-policy.json index 51f30f802..053db4c79 100644 --- a/scripts/infrastructure/policies/deployment2-policy.json +++ b/scripts/infrastructure/policies/deployment2-policy.json @@ -159,7 +159,7 @@ "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-apigee-credentials-*", "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-apigee-cpm-apikey-*", "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-apigee-app-key-*", - "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-etl-notify-slack-webhook-url-*" + "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-notify-slack-webhook-url-*" ] }, { diff --git a/scripts/infrastructure/policies/development2-policy.json b/scripts/infrastructure/policies/development2-policy.json index 51f30f802..053db4c79 100644 --- a/scripts/infrastructure/policies/development2-policy.json +++ b/scripts/infrastructure/policies/development2-policy.json @@ -159,7 +159,7 @@ "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-apigee-credentials-*", "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-apigee-cpm-apikey-*", "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-apigee-app-key-*", - "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-etl-notify-slack-webhook-url-*" + "arn:aws:secretsmanager:*:${ACCOUNT_ID}:secret:*-notify-slack-webhook-url-*" ] }, { diff --git a/scripts/infrastructure/terraform/terraform-commands.sh b/scripts/infrastructure/terraform/terraform-commands.sh index 7bc5d5d92..0991d1159 100644 --- a/scripts/infrastructure/terraform/terraform-commands.sh +++ b/scripts/infrastructure/terraform/terraform-commands.sh @@ -125,7 +125,7 @@ function _terraform_plan() { -var "layers=${layers}" \ -var "third_party_layers=${third_party_layers}" || return 1 else - if [[ "${account}" = "dev" ]]; then # BACKUPS_LOGIC + if [[ "${account}" = "prod" || "${account}" = "dev" ]]; then # Immutable backups requires layers, but is only enabled in prod terraform plan $args \ -out="$plan_file" \ -var-file="$var_file" \