Skip to content

Commit 9dfafca

Browse files
committed
feature/PI-872-enable_immutable_backups_on_prod Add infra back in for dev and create 2 backup vaults for both prod and dev
1 parent 4204d34 commit 9dfafca

File tree

11 files changed

+244
-23
lines changed

11 files changed

+244
-23
lines changed

.github/workflows/_deploy.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ jobs:
6262
save-to-cache: "true"
6363
restore-from-cache: "false"
6464
cache-suffix: ${{ env.CACHE_NAME }}
65-
- if: ${{ env.SCOPE != 'per_workspace' && inputs.account == 'prod'}}
65+
- if: ${{ env.SCOPE != 'per_workspace' && (inputs.account == 'prod' || inputs.account == 'dev') }}
6666
uses: ./.github/actions/make/
6767
with:
6868
command: build
6969
save-to-cache: "true"
7070
restore-from-cache: "false"
7171
cache-suffix: ${{ env.CACHE_NAME }}
72-
- if: ${{ env.SCOPE != 'per_workspace' && inputs.account != 'prod'}}
72+
- if: ${{ env.SCOPE != 'per_workspace' && (inputs.account != 'prod' && inputs.account != 'dev' )}}
7373
uses: ./.github/actions/make/
7474
with:
7575
command: poetry--update
Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
data "aws_secretsmanager_secret" "source_account_id" {
2-
name = "backups-source-account-id"
1+
data "aws_secretsmanager_secret" "source_account_id_prod" {
2+
name = "backups-source-account-id-prod"
33
}
44

5-
data "aws_secretsmanager_secret_version" "source_account_id" {
6-
secret_id = data.aws_secretsmanager_secret.source_account_id.id
5+
data "aws_secretsmanager_secret_version" "source_account_id_prod" {
6+
secret_id = data.aws_secretsmanager_secret.source_account_id_prod.id
7+
}
8+
9+
data "aws_secretsmanager_secret" "source_account_id_dev" {
10+
name = "backups-source-account-id-prod"
11+
}
12+
13+
data "aws_secretsmanager_secret_version" "source_account_id_dev" {
14+
secret_id = data.aws_secretsmanager_secret.source_account_id_dev.id
715
}
816

917

@@ -15,12 +23,33 @@ resource "aws_kms_key" "destination_backup_key" {
1523
enable_key_rotation = true
1624
}
1725

18-
module "destination" {
26+
module "destination_prod" {
1927
source = "../modules/aws-backup-destination"
2028

2129
source_account_name = "prod" # please note that the assigned value would be the prefix in aws_backup_vault.vault.name - change to dev/prod
2230
account_id = var.assume_account
23-
source_account_id = data.aws_secretsmanager_secret_version.source_account_id.secret_string
31+
source_account_id = data.aws_secretsmanager_secret_version.source_account_id_prod.secret_string
32+
kms_key = aws_kms_key.destination_backup_key.arn
33+
enable_vault_protection = false
34+
}
35+
36+
###
37+
# Destination vault ARN output
38+
###
39+
40+
output "destination_vault_arn_prod" {
41+
# The ARN of the backup vault in the destination account is needed by
42+
# the source account to copy backups into it.
43+
value = module.destination_prod.vault_arn
44+
}
45+
46+
47+
module "destination_dev" {
48+
source = "../modules/aws-backup-destination"
49+
50+
source_account_name = "dev" # please note that the assigned value would be the prefix in aws_backup_vault.vault.name - change to dev/prod
51+
account_id = var.assume_account
52+
source_account_id = data.aws_secretsmanager_secret_version.source_account_id_dev.secret_string
2453
kms_key = aws_kms_key.destination_backup_key.arn
2554
enable_vault_protection = false
2655
}
@@ -29,8 +58,8 @@ module "destination" {
2958
# Destination vault ARN output
3059
###
3160

32-
output "destination_vault_arn" {
61+
output "destination_vault_arn_dev" {
3362
# The ARN of the backup vault in the destination account is needed by
3463
# the source account to copy backups into it.
35-
value = module.destination.vault_arn
64+
value = module.destination_dev.vault_arn
3665
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
data "aws_secretsmanager_secret" "destination_vault_arn" {
2+
name = "destination_vault_arn"
3+
}
4+
5+
data "aws_secretsmanager_secret_version" "destination_vault_arn" {
6+
secret_id = data.aws_secretsmanager_secret.destination_vault_arn.id
7+
}
8+
9+
data "aws_secretsmanager_secret" "destination_account_id" {
10+
name = "destination_account_id"
11+
}
12+
13+
data "aws_secretsmanager_secret_version" "destination_account_id" {
14+
secret_id = data.aws_secretsmanager_secret.destination_account_id.id
15+
}
16+
17+
# First, we create an S3 bucket for compliance reports. You may already have a module for creating
18+
# S3 buckets with more refined access rules, which you may prefer to use.
19+
20+
resource "aws_s3_bucket" "backup_reports" {
21+
bucket_prefix = "${local.project}-backup-reports"
22+
}
23+
24+
# Now we have to configure access to the report bucket.
25+
26+
resource "aws_s3_bucket_ownership_controls" "backup_reports" {
27+
bucket = aws_s3_bucket.backup_reports.id
28+
rule {
29+
object_ownership = "BucketOwnerPreferred"
30+
}
31+
}
32+
33+
resource "aws_s3_bucket_acl" "backup_reports" {
34+
depends_on = [aws_s3_bucket_ownership_controls.backup_reports]
35+
36+
bucket = aws_s3_bucket.backup_reports.id
37+
acl = "private"
38+
}
39+
40+
resource "aws_s3_bucket_policy" "backup_reports_policy" {
41+
bucket = aws_s3_bucket.backup_reports.id
42+
policy = jsonencode({
43+
Version = "2012-10-17",
44+
Statement = [
45+
{
46+
Effect = "Allow",
47+
Principal = {
48+
AWS = "arn:aws:iam::${var.assume_account}:role/aws-service-role/reports.backup.amazonaws.com/AWSServiceRoleForBackupReports"
49+
},
50+
Action = "s3:PutObject",
51+
Resource = "${aws_s3_bucket.backup_reports.arn}/*",
52+
Condition = {
53+
StringEquals = {
54+
"s3:x-amz-acl" = "bucket-owner-full-control"
55+
}
56+
}
57+
}
58+
]
59+
})
60+
}
61+
62+
# We need a key for the SNS topic that will be used for notifications from AWS Backup. This key
63+
# will be used to encrypt the messages sent to the topic before they are sent to the subscribers,
64+
# but isn't needed by the recipients of the messages.
65+
66+
67+
# Now we can define the key itself
68+
resource "aws_kms_key" "backup_notifications" {
69+
description = "KMS key for AWS Backup notifications"
70+
deletion_window_in_days = 7
71+
enable_key_rotation = true
72+
policy = jsonencode({
73+
Version = "2012-10-17"
74+
Statement = [
75+
{
76+
Effect = "Allow"
77+
Sid = "Enable IAM User Permissions"
78+
Principal = {
79+
AWS = "arn:aws:iam::${var.assume_account}:root"
80+
}
81+
Action = "kms:*"
82+
Resource = "*"
83+
},
84+
{
85+
Effect = "Allow"
86+
Principal = {
87+
Service = "sns.amazonaws.com"
88+
}
89+
Action = ["kms:GenerateDataKey*", "kms:Decrypt"]
90+
Resource = "*"
91+
},
92+
{
93+
Effect = "Allow"
94+
Principal = {
95+
Service = "backup.amazonaws.com"
96+
}
97+
Action = ["kms:GenerateDataKey*", "kms:Decrypt"]
98+
Resource = "*"
99+
},
100+
]
101+
})
102+
}
103+
104+
resource "aws_kms_alias" "backup_notifications" {
105+
name = "alias/key-for-backup-notify"
106+
target_key_id = aws_kms_key.backup_notifications.key_id
107+
}
108+
109+
# Now we can deploy the source and destination modules, referencing the resources we've created above.
110+
111+
module "source" {
112+
source = "../modules/aws-backup-source"
113+
114+
backup_copy_vault_account_id = data.aws_secretsmanager_secret_version.destination_account_id.secret_string
115+
backup_copy_vault_arn = data.aws_secretsmanager_secret_version.destination_vault_arn.secret_string
116+
environment_name = var.environment
117+
bootstrap_kms_key_arn = aws_kms_key.backup_notifications.arn
118+
project_name = local.project
119+
reports_bucket = aws_s3_bucket.backup_reports.bucket
120+
terraform_role_arn = "arn:aws:iam::${var.assume_account}:role/${var.assume_role}"
121+
python_version = var.python_version
122+
notify_lambda_arn = module.notify.arn
123+
124+
backup_plan_config_dynamodb = {
125+
"compliance_resource_types" : [
126+
"DynamoDB"
127+
],
128+
"rules" : [
129+
{
130+
"copy_action" : {
131+
"delete_after" : 31
132+
},
133+
"lifecycle" : {
134+
"delete_after" : 4
135+
},
136+
"name" : "daily_kept_for_2_days",
137+
"schedule" : "cron(0 20 * * ? *)"
138+
}
139+
],
140+
"enable" : true,
141+
"selection_tag" : "NHSE-Enable-Backup"
142+
}
143+
}
144+
145+
146+
module "notify" {
147+
source = "../modules/notify/"
148+
149+
assume_account = var.assume_account
150+
project_name = local.project
151+
python_version = var.python_version
152+
environment = var.environment
153+
event_layer_arn = element([for instance in module.layers : instance if instance.name == "event"], 0).layer_arn
154+
third_party_layer_arn = element([for instance in module.third_party_layers : instance if instance.name == "third_party_core"], 0).layer_arn
155+
}

infrastructure/terraform/per_account/dev/main.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,21 @@ resource "aws_s3_bucket_logging" "truststore_to_access_logs" {
9595
resource "aws_route53_zone" "dev-ns" {
9696
name = "api.cpm.dev.national.nhs.uk"
9797
}
98+
99+
module "layers" {
100+
for_each = toset(var.layers)
101+
source = "../../modules/api_worker/api_layer"
102+
name = each.key
103+
python_version = var.python_version
104+
layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}"
105+
source_path = "${path.module}/../../../../src/layers/${each.key}/dist/${each.key}.zip"
106+
}
107+
108+
module "third_party_layers" {
109+
for_each = toset(var.third_party_layers)
110+
source = "../../modules/api_worker/api_layer"
111+
name = each.key
112+
python_version = var.python_version
113+
layer_name = "${local.project}--${replace(terraform.workspace, "_", "-")}--${replace(each.key, "_", "-")}"
114+
source_path = "${path.module}/../../../../src/layers/third_party/dist/${each.key}.zip"
115+
}

infrastructure/terraform/per_account/dev/parameters/main.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,22 @@ resource "aws_secretsmanager_secret" "ldap-changelog-password" {
5555
name = "${terraform.workspace}-ldap-changelog-password"
5656
}
5757

58+
resource "aws_secretsmanager_secret" "notify_slack_webhook_url" {
59+
name = "${terraform.workspace}--etl-notify-slack-webhook-url"
60+
}
61+
5862
resource "aws_secretsmanager_secret" "apigee-app-client-info" {
5963
name = "${terraform.workspace}--apigee-app-client-info"
6064
}
6165

6266
resource "aws_secretsmanager_secret" "external-id" {
6367
name = "${terraform.workspace}-external-id"
6468
}
69+
70+
resource "aws_secretsmanager_secret" "destination_vault_arn" {
71+
name = "destination_vault_arn"
72+
}
73+
74+
resource "aws_secretsmanager_secret" "destination_account_id" {
75+
name = "destination_account_id"
76+
}

infrastructure/terraform/per_account/dev/parameters/vars.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,11 @@ variable "workspace_type" {
2929
type = string
3030
default = "PERSISTENT"
3131
}
32+
33+
variable "layers" {
34+
type = list(string)
35+
}
36+
37+
variable "third_party_layers" {
38+
type = list(string)
39+
}

infrastructure/terraform/per_account/dev/vars.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,15 @@ variable "budget_limit" {
2828
default = "1050"
2929
type = string
3030
}
31+
32+
variable "python_version" {
33+
default = "python3.12"
34+
}
35+
36+
variable "layers" {
37+
type = list(string)
38+
}
39+
40+
variable "third_party_layers" {
41+
type = list(string)
42+
}

infrastructure/terraform/per_account/prod/aws-backups.tf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# BACKUPS_LOGIC
21
data "aws_secretsmanager_secret" "destination_vault_arn" {
32
name = "destination_vault_arn"
43
}

infrastructure/terraform/per_account/prod/parameters/main.tf

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ resource "aws_secretsmanager_secret" "apigee-app-key" {
3939
name = "${terraform.workspace}-apigee-app-key"
4040
}
4141

42-
resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" {
43-
name = "${terraform.workspace}--etl-notify-slack-webhook-url"
44-
}
45-
4642
resource "aws_secretsmanager_secret" "sds-hscn-endpoint" {
4743
name = "${terraform.workspace}-sds-hscn-endpoint"
4844
}

infrastructure/terraform/per_account/qa/parameters/main.tf

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ resource "aws_secretsmanager_secret" "apigee-app-key" {
3939
name = "${terraform.workspace}-apigee-app-key"
4040
}
4141

42-
resource "aws_secretsmanager_secret" "etl_notify_slack_webhook_url" {
43-
name = "${terraform.workspace}--etl-notify-slack-webhook-url"
44-
}
45-
4642
resource "aws_secretsmanager_secret" "sds-hscn-endpoint" {
4743
name = "${terraform.workspace}-sds-hscn-endpoint"
4844
}

0 commit comments

Comments
 (0)