From b3a937a810d554a9942b2dcadd2de4958b454437 Mon Sep 17 00:00:00 2001 From: Akol125 Date: Tue, 26 Aug 2025 13:42:42 +0100 Subject: [PATCH 01/12] VED-500: Role, permissions and trustpolicies to push events to csoc's event bus --- terraform/csoc_cloudwatch.tf | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 terraform/csoc_cloudwatch.tf diff --git a/terraform/csoc_cloudwatch.tf b/terraform/csoc_cloudwatch.tf new file mode 100644 index 000000000..9ad921e87 --- /dev/null +++ b/terraform/csoc_cloudwatch.tf @@ -0,0 +1,98 @@ +resource "aws_iam_role" "eventbridge_forwarder_role" { + name = "${local.short_prefix}-eventbridge-forwarder-role" + assume_role_policy = jsonencode({ + Version : "2012-10-17", + Statement = [{ + Sid = "TrustEventBridgeService", + Effect = "Allow", + Principal = { Service = "events.amazonaws.com" }, + Action = "sts:AssumeRole", + Condition = { + StringEquals = { + "aws:SourceAccount" = var.immunisation_account_id + } + } + }] + }) +} + +resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { + name = "${local.short_prefix}-eventbridge-forwarder-policy" + role = aws_iam_role.eventbridge_forwarder_role.id + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [{ + Sid = "ActionsForResource", + Effect = "Allow", + Action = ["events:PutEvents"], + Resource = [ + "arn:aws:events:eu-west-2:693466633220:event-bus/shield-eventbus" + ] + }] + }) +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +resource "aws_iam_role" "dynamo_s3_access_role" { + name = "${local.short_prefix}-dynamo-s3-access-role" + assume_role_policy = jsonencode({ + Version : "2012-10-17", + Statement : [ + { + Effect : "Allow", + Principal : { + AWS : "arn:aws:iam::${var.dspp_core_account_id}:root" + }, + Action : "sts:AssumeRole" + } + ] + }) +} + +resource "aws_iam_role_policy" "dynamo_s3_access_policy" { + name = "${local.short_prefix}-dynamo_s3_access-policy" + role = aws_iam_role.dynamo_s3_access_role.id + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "dynamodb:BatchGetItem", + "dynamodb:GetItem", + "dynamodb:Query" + ], + Resource = [ + aws_dynamodb_table.delta-dynamodb-table.arn, + "${aws_dynamodb_table.delta-dynamodb-table.arn}/index/*" + ] + } + ] + }) +} From ac609496af6ebf3c925d0badb0a41557a488dafd Mon Sep 17 00:00:00 2001 From: Akol125 Date: Tue, 26 Aug 2025 14:24:11 +0100 Subject: [PATCH 02/12] VED-500: remove unused permissions --- terraform/csoc_cloudwatch.tf | 66 +----------------------------------- 1 file changed, 1 insertion(+), 65 deletions(-) diff --git a/terraform/csoc_cloudwatch.tf b/terraform/csoc_cloudwatch.tf index 9ad921e87..e183624c1 100644 --- a/terraform/csoc_cloudwatch.tf +++ b/terraform/csoc_cloudwatch.tf @@ -31,68 +31,4 @@ resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { ] }] }) -} - - - - - - - - - - - - - - - - - - - - - - - - - - - -resource "aws_iam_role" "dynamo_s3_access_role" { - name = "${local.short_prefix}-dynamo-s3-access-role" - assume_role_policy = jsonencode({ - Version : "2012-10-17", - Statement : [ - { - Effect : "Allow", - Principal : { - AWS : "arn:aws:iam::${var.dspp_core_account_id}:root" - }, - Action : "sts:AssumeRole" - } - ] - }) -} - -resource "aws_iam_role_policy" "dynamo_s3_access_policy" { - name = "${local.short_prefix}-dynamo_s3_access-policy" - role = aws_iam_role.dynamo_s3_access_role.id - policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Action = [ - "dynamodb:BatchGetItem", - "dynamodb:GetItem", - "dynamodb:Query" - ], - Resource = [ - aws_dynamodb_table.delta-dynamodb-table.arn, - "${aws_dynamodb_table.delta-dynamodb-table.arn}/index/*" - ] - } - ] - }) -} +} \ No newline at end of file From f434f162d0441b9d55cecac2091dafc444bd7ea3 Mon Sep 17 00:00:00 2001 From: Akol125 Date: Fri, 3 Oct 2025 03:09:37 +0100 Subject: [PATCH 03/12] VED-500: creating shield advance and protecting edge-facing resources with it --- infra/shield_protection.tf | 37 +++++++++++++++++++ infra/shield_subscription.tf | 7 ++++ ...oc_cloudwatch.tf => csoc_role_creation.tf} | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 infra/shield_protection.tf create mode 100644 infra/shield_subscription.tf rename terraform/{csoc_cloudwatch.tf => csoc_role_creation.tf} (91%) diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf new file mode 100644 index 000000000..a5c84ab5c --- /dev/null +++ b/infra/shield_protection.tf @@ -0,0 +1,37 @@ + +# AWS Dynamic Lookups +data "aws_availability_zones" "available" {} +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} + + + + +# Protect the NAT Gateway Elastic IP +resource "aws_shield_protection" "nat_eip" { + name = "example" + resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.example.id}" + + tags = { + Environment = "Dev" + } +} + +resource "aws_cloudwatch_metric_alarm" "nat_eip_ddos" { + alarm_name = "infra_shield_ddos_natgw" + alarm_description = "Alarm when Shield detects DDoS on NAT Gateway EIP" + + namespace = "AWS/DDoSProtection" + metric_name = "DDoSDetected" + statistic = "Maximum" + period = 60 + evaluation_periods = 20 + datapoints_to_alarm = 1 + threshold = 0 + comparison_operator = "GreaterThanThreshold" + treat_missing_data = "notBreaching" + + dimensions = { + ResourceArn = "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.nat.id}" + } +} diff --git a/infra/shield_subscription.tf b/infra/shield_subscription.tf new file mode 100644 index 000000000..9c6c3e197 --- /dev/null +++ b/infra/shield_subscription.tf @@ -0,0 +1,7 @@ +// One-time Shield Advanced subscription for the account. +// This resource is account-level. + +resource "aws_shield_subscription" "shield_subscription" { + auto_renew = "ENABLED" + +} diff --git a/terraform/csoc_cloudwatch.tf b/terraform/csoc_role_creation.tf similarity index 91% rename from terraform/csoc_cloudwatch.tf rename to terraform/csoc_role_creation.tf index e183624c1..67c4e44a3 100644 --- a/terraform/csoc_cloudwatch.tf +++ b/terraform/csoc_role_creation.tf @@ -27,7 +27,7 @@ resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { Effect = "Allow", Action = ["events:PutEvents"], Resource = [ - "arn:aws:events:eu-west-2:693466633220:event-bus/shield-eventbus" + "arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus" ] }] }) From e2ecb46333cd6f02845f5de7bac1c28003db30ff Mon Sep 17 00:00:00 2001 From: Akol125 Date: Fri, 3 Oct 2025 11:08:21 +0100 Subject: [PATCH 04/12] create protection for shield resources --- infra/shield_protection.tf | 63 +++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index a5c84ab5c..1bfac288e 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -13,7 +13,7 @@ resource "aws_shield_protection" "nat_eip" { resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.example.id}" tags = { - Environment = "Dev" + Environment = "imms-${var.environment}-fhir-api-nat-shield" } } @@ -35,3 +35,64 @@ resource "aws_cloudwatch_metric_alarm" "nat_eip_ddos" { ResourceArn = "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.nat.id}" } } + +# Protect the Route53 Parent and child hosted zone (must be created in us-east-1) + + + +# Protect the parent hosted zone +resource "aws_shield_protection" "parent_dns" { + provider = aws.use1 + name = "shield_ddos_parent_zone" + resource_arn = aws_route53_zone.parent_hosted_zone.arn + + tags = { + Environment = var.environment + Owner = "infra" + } +} + +resource "aws_cloudwatch_metric_alarm" "parent_dns_ddos" { + provider = aws.use1 + alarm_name = "shield_ddos_parent_zone" + alarm_description = "Alarm when Shield detects DDoS on parent hosted zone" + + namespace = "AWS/DDoSProtection" + metric_name = "DDoSDetected" + statistic = "Maximum" + period = 60 + evaluation_periods = 20 + datapoints_to_alarm = 1 + threshold = 0 + comparison_operator = "GreaterThanThreshold" + treat_missing_data = "notBreaching" + + dimensions = { + ResourceArn = aws_route53_zone.parent_hosted_zone.arn + } +} + + +resource "aws_shield_protection" "child_dns" { + provider = aws.use1 + name = "route53_shield_ddos_childzone" + resource_arn = aws_route53_zone.child_hosted_zone.arn +} + +resource "aws_cloudwatch_metric_alarm" "child_dns_ddos" { + provider = aws.use1 + alarm_name = "route53_shield_ddos_childzone" + namespace = "AWS/DDoSProtection" + metric_name = "DDoSDetected" + statistic = "Maximum" + period = 60 + evaluation_periods = 20 + datapoints_to_alarm = 1 + threshold = 0 + comparison_operator = "GreaterThanThreshold" + treat_missing_data = "notBreaching" + + dimensions = { + ResourceArn = aws_route53_zone.child_hosted_zone.arn + } +} From 12368f77fe198709022c488700ca9f5176dac34a Mon Sep 17 00:00:00 2001 From: Akol125 Date: Fri, 3 Oct 2025 12:21:18 +0100 Subject: [PATCH 05/12] add variables and csoc account id per environment --- infra/csoc_role_creation.tf | 34 ++++++++ infra/environments/dev/variables.tfvars | 1 + infra/environments/preprod/variables.tfvars | 1 + infra/environments/prod/variables.tfvars | 1 + infra/shield_protection.tf | 89 +++++++++++---------- infra/variables.tf | 6 ++ 6 files changed, 89 insertions(+), 43 deletions(-) create mode 100644 infra/csoc_role_creation.tf diff --git a/infra/csoc_role_creation.tf b/infra/csoc_role_creation.tf new file mode 100644 index 000000000..67c4e44a3 --- /dev/null +++ b/infra/csoc_role_creation.tf @@ -0,0 +1,34 @@ +resource "aws_iam_role" "eventbridge_forwarder_role" { + name = "${local.short_prefix}-eventbridge-forwarder-role" + assume_role_policy = jsonencode({ + Version : "2012-10-17", + Statement = [{ + Sid = "TrustEventBridgeService", + Effect = "Allow", + Principal = { Service = "events.amazonaws.com" }, + Action = "sts:AssumeRole", + Condition = { + StringEquals = { + "aws:SourceAccount" = var.immunisation_account_id + } + } + }] + }) +} + +resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { + name = "${local.short_prefix}-eventbridge-forwarder-policy" + role = aws_iam_role.eventbridge_forwarder_role.id + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [{ + Sid = "ActionsForResource", + Effect = "Allow", + Action = ["events:PutEvents"], + Resource = [ + "arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus" + ] + }] + }) +} \ No newline at end of file diff --git a/infra/environments/dev/variables.tfvars b/infra/environments/dev/variables.tfvars index a6fd60afd..9bff9955d 100644 --- a/infra/environments/dev/variables.tfvars +++ b/infra/environments/dev/variables.tfvars @@ -1,6 +1,7 @@ imms_account_id = "345594581768" dspp_account_id = "603871901111" mns_account_id = "631615744739" +csoc_account_id = "693466633220" admin_role = "root" # We shouldn't be using the root account. There should be an Admin role dev_ops_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_DEV-IMMS-Devops_745af4f208886ecc" dspp_admin_role = "root" diff --git a/infra/environments/preprod/variables.tfvars b/infra/environments/preprod/variables.tfvars index 06df49545..0f8031e58 100644 --- a/infra/environments/preprod/variables.tfvars +++ b/infra/environments/preprod/variables.tfvars @@ -1,6 +1,7 @@ imms_account_id = "084828561157" dspp_account_id = "603871901111" mns_account_id = "631615744739" +csoc_account_id = "693466633220" # admin_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PREPROD-IMMS-Admin_acce656dcacf6f4c" admin_role = "root" dev_ops_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PREPROD-IMMS-Devops_1d28e4f37b940bcd" diff --git a/infra/environments/prod/variables.tfvars b/infra/environments/prod/variables.tfvars index c4999291e..d5a7a4903 100644 --- a/infra/environments/prod/variables.tfvars +++ b/infra/environments/prod/variables.tfvars @@ -1,6 +1,7 @@ imms_account_id = "664418956997" dspp_account_id = "232116723729" mns_account_id = "758334270304" +csoc_account_id = "693466633220" # admin_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PROD-IMMS-Admin_edd6691e4b74064e" admin_role = "root" dev_ops_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PROD-IMMS-Devops_8f32c62195d56b76" diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index 1bfac288e..fc300ec95 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -4,58 +4,63 @@ data "aws_availability_zones" "available" {} data "aws_region" "current" {} data "aws_caller_identity" "current" {} +provider "aws" { + alias = "use1" + region = "us-east-1" +} - - -# Protect the NAT Gateway Elastic IP +# Create all resources to Protect resource "aws_shield_protection" "nat_eip" { - name = "example" + name = "shield_nat_eip" resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.example.id}" tags = { - Environment = "imms-${var.environment}-fhir-api-nat-shield" + Environment = "imms-${var.environment}-fhir-api-eip-shield" } } -resource "aws_cloudwatch_metric_alarm" "nat_eip_ddos" { - alarm_name = "infra_shield_ddos_natgw" - alarm_description = "Alarm when Shield detects DDoS on NAT Gateway EIP" - - namespace = "AWS/DDoSProtection" - metric_name = "DDoSDetected" - statistic = "Maximum" - period = 60 - evaluation_periods = 20 - datapoints_to_alarm = 1 - threshold = 0 - comparison_operator = "GreaterThanThreshold" - treat_missing_data = "notBreaching" +resource "aws_shield_protection" "parent_dns" { + provider = aws.use1 + name = "shield_ddos_parent_zone" + resource_arn = aws_route53_zone.parent_hosted_zone.arn - dimensions = { - ResourceArn = "arn:aws:ec2:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.nat.id}" + tags = { + Environment = "imms-${var.environment}-fhir-api-parent-dns-shield" } } -# Protect the Route53 Parent and child hosted zone (must be created in us-east-1) +resource "aws_shield_protection" "child_dns" { + provider = aws.use1 + name = "route53_shield_ddos_childzone" + resource_arn = aws_route53_zone.child_hosted_zone.arn + + tags = { + Environment = "imms-${var.environment}-fhir-api-child-dns-shield" + } +} -# Protect the parent hosted zone -resource "aws_shield_protection" "parent_dns" { - provider = aws.use1 - name = "shield_ddos_parent_zone" - resource_arn = aws_route53_zone.parent_hosted_zone.arn +locals { + regional_shield_arn = { + nat_gateway_eip = aws_shield_protection.nat_eip.resource_arn + } +} - tags = { - Environment = var.environment - Owner = "infra" +locals { + global_shield_arn = { + route53_parent_zone = aws_shield_protection.parent_dns.resource_arn + route53_child_zone = aws_shield_protection.child_dns.resource_arn } } -resource "aws_cloudwatch_metric_alarm" "parent_dns_ddos" { - provider = aws.use1 - alarm_name = "shield_ddos_parent_zone" - alarm_description = "Alarm when Shield detects DDoS on parent hosted zone" + +# Create Metric Alarms for each of those resources +resource "aws_cloudwatch_metric_alarm" "ddos_protection_regional" { + for_each = local.regional_shield_arn + + alarm_name = "shield_ddos_${each.key}" + alarm_description = "Alarm when Shield detects DDoS on ${each.key}" namespace = "AWS/DDoSProtection" metric_name = "DDoSDetected" @@ -68,20 +73,18 @@ resource "aws_cloudwatch_metric_alarm" "parent_dns_ddos" { treat_missing_data = "notBreaching" dimensions = { - ResourceArn = aws_route53_zone.parent_hosted_zone.arn + ResourceArn = each.value } } +# Create Metric Alarms for Global Resources in us-east-1 Region +resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" { + for_each = locals.global_shield_arn -resource "aws_shield_protection" "child_dns" { - provider = aws.use1 - name = "route53_shield_ddos_childzone" - resource_arn = aws_route53_zone.child_hosted_zone.arn -} - -resource "aws_cloudwatch_metric_alarm" "child_dns_ddos" { provider = aws.use1 - alarm_name = "route53_shield_ddos_childzone" + alarm_name = "shield_ddos_${each.key}" + alarm_description = "Alarm when Shield detects DDoS on ${each.key}" + namespace = "AWS/DDoSProtection" metric_name = "DDoSDetected" statistic = "Maximum" @@ -93,6 +96,6 @@ resource "aws_cloudwatch_metric_alarm" "child_dns_ddos" { treat_missing_data = "notBreaching" dimensions = { - ResourceArn = aws_route53_zone.child_hosted_zone.arn + ResourceArn = each.value } } diff --git a/infra/variables.tf b/infra/variables.tf index 717f38b22..6d46a5b01 100644 --- a/infra/variables.tf +++ b/infra/variables.tf @@ -10,6 +10,12 @@ variable "dspp_account_id" { description = "DSPP Core AWS account ID" type = string } +variable "csoc_account_id" { + description = "CSOC Core AWS account ID" + type = string + +} + variable "auto_ops_role" { default = "role/auto-ops" type = string From 736fd64555927b7dc37d2fb6b2383109b5f726d0 Mon Sep 17 00:00:00 2001 From: Akol125 Date: Fri, 3 Oct 2025 12:35:54 +0100 Subject: [PATCH 06/12] create event bus forwarding rule --- infra/shield_protection.tf | 49 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index fc300ec95..519d31433 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -99,3 +99,52 @@ resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" { ResourceArn = each.value } } + + +# Event Bus Rule for eu-west-2 Region + +resource "aws_cloudwatch_event_rule" "shield_ddos_rule_regional" { + name = "imms_${var.environment}_shield_ddos_rule_${data.aws_region.current.name}" + description = "Forward Shield DDoS CloudWatch alarms to CSOC event bus" + + event_pattern = jsonencode({ + "source" = ["aws.cloudwatch"], + "detail-type" = ["CloudWatch Alarm State Change"], + "resources" = [ + for alarm in aws_cloudwatch_metric_alarm.ddos_protection_regional : alarm.arn + ] + }) +} + + + +resource "aws_cloudwatch_event_target" "shield_ddos_target_regional" { + rule = aws_cloudwatch_event_rule.shield_ddos_rule_regional.name + target_id = "csoc-eventbus" + arn = "arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus" + role_arn = aws_iam_role.shield_ddos_forwarder.arn +} + +# Event Bus Rule for us-east-1 Region + +resource "aws_cloudwatch_event_rule" "shield_ddos_rule_global" { + provider = aws.use1 + name = "imms_${var.environment}_shield_ddos_rule_us-east-1" + description = "Forward Shield DDoS CloudWatch alarms (global) to CSOC event bus" + + event_pattern = jsonencode({ + "source" = ["aws.cloudwatch"], + "detail-type" = ["CloudWatch Alarm State Change"], + "resources" = [ + for alarm in aws_cloudwatch_metric_alarm.ddos_protection_global : alarm.arn + ] + }) +} + +resource "aws_cloudwatch_event_target" "shield_ddos_target_global" { + provider = aws.use1 + rule = aws_cloudwatch_event_rule.shield_ddos_rule_global.name + target_id = "csoc-eventbus" + arn = "arn:aws:events:us-east-1:${var.csoc_account_id}:event-bus/shield-eventbus" + role_arn = aws_iam_role.shield_ddos_forwarder.arn +} \ No newline at end of file From c0228c3c4bdfb72ab5d77864ee09399fa566a471 Mon Sep 17 00:00:00 2001 From: Akol125 Date: Mon, 6 Oct 2025 09:46:41 +0100 Subject: [PATCH 07/12] remove and refactor some terraform changes --- infra/shield_protection.tf | 2 +- terraform/csoc_role_creation.tf | 34 --------------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 terraform/csoc_role_creation.tf diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index 519d31433..ca54bdd5d 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -12,7 +12,7 @@ provider "aws" { # Create all resources to Protect resource "aws_shield_protection" "nat_eip" { name = "shield_nat_eip" - resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.example.id}" + resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.nat.id}" tags = { Environment = "imms-${var.environment}-fhir-api-eip-shield" diff --git a/terraform/csoc_role_creation.tf b/terraform/csoc_role_creation.tf deleted file mode 100644 index 67c4e44a3..000000000 --- a/terraform/csoc_role_creation.tf +++ /dev/null @@ -1,34 +0,0 @@ -resource "aws_iam_role" "eventbridge_forwarder_role" { - name = "${local.short_prefix}-eventbridge-forwarder-role" - assume_role_policy = jsonencode({ - Version : "2012-10-17", - Statement = [{ - Sid = "TrustEventBridgeService", - Effect = "Allow", - Principal = { Service = "events.amazonaws.com" }, - Action = "sts:AssumeRole", - Condition = { - StringEquals = { - "aws:SourceAccount" = var.immunisation_account_id - } - } - }] - }) -} - -resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { - name = "${local.short_prefix}-eventbridge-forwarder-policy" - role = aws_iam_role.eventbridge_forwarder_role.id - - policy = jsonencode({ - Version = "2012-10-17", - Statement = [{ - Sid = "ActionsForResource", - Effect = "Allow", - Action = ["events:PutEvents"], - Resource = [ - "arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus" - ] - }] - }) -} \ No newline at end of file From 5efb634ca22f92d281f7943357fecc613efb1e24 Mon Sep 17 00:00:00 2001 From: Akol125 Date: Mon, 6 Oct 2025 11:57:54 +0100 Subject: [PATCH 08/12] refactor infra changes --- ...reation.tf => csoc_eventforwarder_role.tf} | 8 ++++---- infra/shield_protection.tf | 19 ++++--------------- 2 files changed, 8 insertions(+), 19 deletions(-) rename infra/{csoc_role_creation.tf => csoc_eventforwarder_role.tf} (81%) diff --git a/infra/csoc_role_creation.tf b/infra/csoc_eventforwarder_role.tf similarity index 81% rename from infra/csoc_role_creation.tf rename to infra/csoc_eventforwarder_role.tf index 67c4e44a3..b1252e98f 100644 --- a/infra/csoc_role_creation.tf +++ b/infra/csoc_eventforwarder_role.tf @@ -1,5 +1,5 @@ resource "aws_iam_role" "eventbridge_forwarder_role" { - name = "${local.short_prefix}-eventbridge-forwarder-role" + name = "imms-${var.environment}-eventbridge-forwarder-role" assume_role_policy = jsonencode({ Version : "2012-10-17", Statement = [{ @@ -9,7 +9,7 @@ resource "aws_iam_role" "eventbridge_forwarder_role" { Action = "sts:AssumeRole", Condition = { StringEquals = { - "aws:SourceAccount" = var.immunisation_account_id + "aws:SourceAccount" = var.imms_account_id } } }] @@ -17,7 +17,7 @@ resource "aws_iam_role" "eventbridge_forwarder_role" { } resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { - name = "${local.short_prefix}-eventbridge-forwarder-policy" + name = "imms-${var.environment}-eventbridge-forwarder-policy" role = aws_iam_role.eventbridge_forwarder_role.id policy = jsonencode({ @@ -31,4 +31,4 @@ resource "aws_iam_role_policy" "eventbridge_forwarder_policy" { ] }] }) -} \ No newline at end of file +} diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index ca54bdd5d..458451c6b 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -11,32 +11,24 @@ provider "aws" { # Create all resources to Protect resource "aws_shield_protection" "nat_eip" { - name = "shield_nat_eip" + name = "imms-${var.environment}-fhir-api-eip-shield" resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.nat.id}" - - tags = { - Environment = "imms-${var.environment}-fhir-api-eip-shield" - } } resource "aws_shield_protection" "parent_dns" { provider = aws.use1 - name = "shield_ddos_parent_zone" + name = "imms-${var.environment}-fhir-api-parent-dns-shield" resource_arn = aws_route53_zone.parent_hosted_zone.arn tags = { - Environment = "imms-${var.environment}-fhir-api-parent-dns-shield" + Environment = } } resource "aws_shield_protection" "child_dns" { provider = aws.use1 - name = "route53_shield_ddos_childzone" + name = "imms-${var.environment}-fhir-api-parent-dns-shield" resource_arn = aws_route53_zone.child_hosted_zone.arn - - tags = { - Environment = "imms-${var.environment}-fhir-api-child-dns-shield" - } } @@ -45,9 +37,6 @@ locals { regional_shield_arn = { nat_gateway_eip = aws_shield_protection.nat_eip.resource_arn } -} - -locals { global_shield_arn = { route53_parent_zone = aws_shield_protection.parent_dns.resource_arn route53_child_zone = aws_shield_protection.child_dns.resource_arn From 1c2a37f44b94a2bddec8b8285ed212a3a0d1ba2d Mon Sep 17 00:00:00 2001 From: Akol125 Date: Tue, 7 Oct 2025 09:27:59 +0100 Subject: [PATCH 09/12] add provide to main.tf --- infra/main.tf | 11 +++++++++++ infra/shield_protection.tf | 5 ----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/infra/main.tf b/infra/main.tf index 0ae01c4b0..2b28ba4ae 100644 --- a/infra/main.tf +++ b/infra/main.tf @@ -21,3 +21,14 @@ provider "aws" { } } } + +provider "aws" { + alias = "use1" + region = "us-east-1" + default_tags { + tags = { + Project = "immunisation-fhir-api" + Environment = var.environment + } + } +} \ No newline at end of file diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index 458451c6b..f1a7a0904 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -4,11 +4,6 @@ data "aws_availability_zones" "available" {} data "aws_region" "current" {} data "aws_caller_identity" "current" {} -provider "aws" { - alias = "use1" - region = "us-east-1" -} - # Create all resources to Protect resource "aws_shield_protection" "nat_eip" { name = "imms-${var.environment}-fhir-api-eip-shield" From 1381908ee76874b851508f0cc6448b1e6201d0e6 Mon Sep 17 00:00:00 2001 From: Daniel Yip Date: Tue, 7 Oct 2025 14:37:17 +0100 Subject: [PATCH 10/12] Minor fixes - tested plan works --- infra/shield_protection.tf | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index f1a7a0904..fe37adc73 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -14,10 +14,6 @@ resource "aws_shield_protection" "parent_dns" { provider = aws.use1 name = "imms-${var.environment}-fhir-api-parent-dns-shield" resource_arn = aws_route53_zone.parent_hosted_zone.arn - - tags = { - Environment = - } } resource "aws_shield_protection" "child_dns" { @@ -63,7 +59,7 @@ resource "aws_cloudwatch_metric_alarm" "ddos_protection_regional" { # Create Metric Alarms for Global Resources in us-east-1 Region resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" { - for_each = locals.global_shield_arn + for_each = local.global_shield_arn provider = aws.use1 alarm_name = "shield_ddos_${each.key}" @@ -106,7 +102,7 @@ resource "aws_cloudwatch_event_target" "shield_ddos_target_regional" { rule = aws_cloudwatch_event_rule.shield_ddos_rule_regional.name target_id = "csoc-eventbus" arn = "arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus" - role_arn = aws_iam_role.shield_ddos_forwarder.arn + role_arn = aws_iam_role.eventbridge_forwarder_role.arn } # Event Bus Rule for us-east-1 Region @@ -130,5 +126,5 @@ resource "aws_cloudwatch_event_target" "shield_ddos_target_global" { rule = aws_cloudwatch_event_rule.shield_ddos_rule_global.name target_id = "csoc-eventbus" arn = "arn:aws:events:us-east-1:${var.csoc_account_id}:event-bus/shield-eventbus" - role_arn = aws_iam_role.shield_ddos_forwarder.arn -} \ No newline at end of file + role_arn = aws_iam_role.eventbridge_forwarder_role.arn +} From c7a9905a0bf909b1de86c6e30e195a6d53868841 Mon Sep 17 00:00:00 2001 From: Daniel Yip Date: Tue, 7 Oct 2025 15:10:08 +0100 Subject: [PATCH 11/12] Remove deprecated reference --- infra/shield_protection.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index fe37adc73..0ad5522ac 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -84,7 +84,7 @@ resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" { # Event Bus Rule for eu-west-2 Region resource "aws_cloudwatch_event_rule" "shield_ddos_rule_regional" { - name = "imms_${var.environment}_shield_ddos_rule_${data.aws_region.current.name}" + name = "imms_${var.environment}_shield_ddos_rule_${data.aws_region.current.region}" description = "Forward Shield DDoS CloudWatch alarms to CSOC event bus" event_pattern = jsonencode({ From 2f813cc3b665dfec9408277df4c7afb0e4ac745d Mon Sep 17 00:00:00 2001 From: Akol125 Date: Wed, 8 Oct 2025 03:22:59 +0100 Subject: [PATCH 12/12] rename metric alarm per env --- infra/shield_protection.tf | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/infra/shield_protection.tf b/infra/shield_protection.tf index f1a7a0904..967f94ae7 100644 --- a/infra/shield_protection.tf +++ b/infra/shield_protection.tf @@ -14,10 +14,6 @@ resource "aws_shield_protection" "parent_dns" { provider = aws.use1 name = "imms-${var.environment}-fhir-api-parent-dns-shield" resource_arn = aws_route53_zone.parent_hosted_zone.arn - - tags = { - Environment = - } } resource "aws_shield_protection" "child_dns" { @@ -43,7 +39,7 @@ locals { resource "aws_cloudwatch_metric_alarm" "ddos_protection_regional" { for_each = local.regional_shield_arn - alarm_name = "shield_ddos_${each.key}" + alarm_name = "imms-${var.environment}-shield_ddos_${each.key}" alarm_description = "Alarm when Shield detects DDoS on ${each.key}" namespace = "AWS/DDoSProtection" @@ -63,10 +59,10 @@ resource "aws_cloudwatch_metric_alarm" "ddos_protection_regional" { # Create Metric Alarms for Global Resources in us-east-1 Region resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" { - for_each = locals.global_shield_arn + for_each = local.global_shield_arn provider = aws.use1 - alarm_name = "shield_ddos_${each.key}" + alarm_name = "imms-${var.environment}-shield_ddos_${each.key}" alarm_description = "Alarm when Shield detects DDoS on ${each.key}" namespace = "AWS/DDoSProtection" @@ -88,7 +84,7 @@ resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" { # Event Bus Rule for eu-west-2 Region resource "aws_cloudwatch_event_rule" "shield_ddos_rule_regional" { - name = "imms_${var.environment}_shield_ddos_rule_${data.aws_region.current.name}" + name = "imms-${var.environment}-shield_ddos_rule_${data.aws_region.current.region}" description = "Forward Shield DDoS CloudWatch alarms to CSOC event bus" event_pattern = jsonencode({ @@ -113,7 +109,7 @@ resource "aws_cloudwatch_event_target" "shield_ddos_target_regional" { resource "aws_cloudwatch_event_rule" "shield_ddos_rule_global" { provider = aws.use1 - name = "imms_${var.environment}_shield_ddos_rule_us-east-1" + name = "imms-${var.environment}-shield_ddos_rule-us-east-1" description = "Forward Shield DDoS CloudWatch alarms (global) to CSOC event bus" event_pattern = jsonencode({