Skip to content
Merged
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
6 changes: 3 additions & 3 deletions .github/workflows/_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
47 changes: 38 additions & 9 deletions infrastructure/terraform/per_account/backups/aws-backups.tf
Original file line number Diff line number Diff line change
@@ -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
}


Expand All @@ -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
}
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

Expand Down
1 change: 0 additions & 1 deletion infrastructure/terraform/per_account/dev/aws-backups.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# BACKUPS_LOGIC
data "aws_secretsmanager_secret" "destination_vault_arn" {
name = "destination_vault_arn"
}
Expand Down
2 changes: 0 additions & 2 deletions infrastructure/terraform/per_account/dev/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down
6 changes: 2 additions & 4 deletions infrastructure/terraform/per_account/dev/parameters/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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"
}
2 changes: 0 additions & 2 deletions infrastructure/terraform/per_account/dev/parameters/vars.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
3 changes: 0 additions & 3 deletions infrastructure/terraform/per_account/dev/vars.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
4 changes: 0 additions & 4 deletions infrastructure/terraform/per_account/int/parameters/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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" {
Expand Down
155 changes: 155 additions & 0 deletions infrastructure/terraform/per_account/prod/aws-backups.tf
Original file line number Diff line number Diff line change
@@ -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
}
Loading
Loading