Skip to content

Commit fb50f98

Browse files
authored
VED-500: Shield Advanced Alerts for CSOC (#769)
1 parent 0b5b454 commit fb50f98

File tree

8 files changed

+191
-0
lines changed

8 files changed

+191
-0
lines changed

infra/csoc_eventforwarder_role.tf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
resource "aws_iam_role" "eventbridge_forwarder_role" {
2+
name = "imms-${var.environment}-eventbridge-forwarder-role"
3+
assume_role_policy = jsonencode({
4+
Version : "2012-10-17",
5+
Statement = [{
6+
Sid = "TrustEventBridgeService",
7+
Effect = "Allow",
8+
Principal = { Service = "events.amazonaws.com" },
9+
Action = "sts:AssumeRole",
10+
Condition = {
11+
StringEquals = {
12+
"aws:SourceAccount" = var.imms_account_id
13+
}
14+
}
15+
}]
16+
})
17+
}
18+
19+
resource "aws_iam_role_policy" "eventbridge_forwarder_policy" {
20+
name = "imms-${var.environment}-eventbridge-forwarder-policy"
21+
role = aws_iam_role.eventbridge_forwarder_role.id
22+
23+
policy = jsonencode({
24+
Version = "2012-10-17",
25+
Statement = [{
26+
Sid = "ActionsForResource",
27+
Effect = "Allow",
28+
Action = ["events:PutEvents"],
29+
Resource = [
30+
"arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus"
31+
]
32+
}]
33+
})
34+
}

infra/environments/dev/variables.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
imms_account_id = "345594581768"
22
dspp_account_id = "603871901111"
33
mns_account_id = "631615744739"
4+
csoc_account_id = "693466633220"
45
admin_role = "root" # We shouldn't be using the root account. There should be an Admin role
56
dev_ops_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_DEV-IMMS-Devops_745af4f208886ecc"
67
dspp_admin_role = "root"

infra/environments/preprod/variables.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
imms_account_id = "084828561157"
22
dspp_account_id = "603871901111"
33
mns_account_id = "631615744739"
4+
csoc_account_id = "693466633220"
45
# admin_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PREPROD-IMMS-Admin_acce656dcacf6f4c"
56
admin_role = "root"
67
dev_ops_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PREPROD-IMMS-Devops_1d28e4f37b940bcd"

infra/environments/prod/variables.tfvars

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
imms_account_id = "664418956997"
22
dspp_account_id = "232116723729"
33
mns_account_id = "758334270304"
4+
csoc_account_id = "693466633220"
45
# admin_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PROD-IMMS-Admin_edd6691e4b74064e"
56
admin_role = "root"
67
dev_ops_role = "role/aws-reserved/sso.amazonaws.com/eu-west-2/AWSReservedSSO_PROD-IMMS-Devops_8f32c62195d56b76"

infra/main.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,14 @@ provider "aws" {
2121
}
2222
}
2323
}
24+
25+
provider "aws" {
26+
alias = "use1"
27+
region = "us-east-1"
28+
default_tags {
29+
tags = {
30+
Project = "immunisation-fhir-api"
31+
Environment = var.environment
32+
}
33+
}
34+
}

infra/shield_protection.tf

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
2+
# AWS Dynamic Lookups
3+
data "aws_availability_zones" "available" {}
4+
data "aws_region" "current" {}
5+
data "aws_caller_identity" "current" {}
6+
7+
# Create all resources to Protect
8+
resource "aws_shield_protection" "nat_eip" {
9+
name = "imms-${var.environment}-fhir-api-eip-shield"
10+
resource_arn = "arn:aws:ec2:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:eip-allocation/${aws_eip.nat.id}"
11+
}
12+
13+
resource "aws_shield_protection" "parent_dns" {
14+
provider = aws.use1
15+
name = "imms-${var.environment}-fhir-api-parent-dns-shield"
16+
resource_arn = aws_route53_zone.parent_hosted_zone.arn
17+
}
18+
19+
resource "aws_shield_protection" "child_dns" {
20+
provider = aws.use1
21+
name = "imms-${var.environment}-fhir-api-parent-dns-shield"
22+
resource_arn = aws_route53_zone.child_hosted_zone.arn
23+
}
24+
25+
26+
27+
locals {
28+
regional_shield_arn = {
29+
nat_gateway_eip = aws_shield_protection.nat_eip.resource_arn
30+
}
31+
global_shield_arn = {
32+
route53_parent_zone = aws_shield_protection.parent_dns.resource_arn
33+
route53_child_zone = aws_shield_protection.child_dns.resource_arn
34+
}
35+
}
36+
37+
38+
# Create Metric Alarms for each of those resources
39+
resource "aws_cloudwatch_metric_alarm" "ddos_protection_regional" {
40+
for_each = local.regional_shield_arn
41+
42+
alarm_name = "imms-${var.environment}-shield_ddos_${each.key}"
43+
alarm_description = "Alarm when Shield detects DDoS on ${each.key}"
44+
45+
namespace = "AWS/DDoSProtection"
46+
metric_name = "DDoSDetected"
47+
statistic = "Maximum"
48+
period = 60
49+
evaluation_periods = 20
50+
datapoints_to_alarm = 1
51+
threshold = 0
52+
comparison_operator = "GreaterThanThreshold"
53+
treat_missing_data = "notBreaching"
54+
55+
dimensions = {
56+
ResourceArn = each.value
57+
}
58+
}
59+
60+
# Create Metric Alarms for Global Resources in us-east-1 Region
61+
resource "aws_cloudwatch_metric_alarm" "ddos_protection_global" {
62+
for_each = local.global_shield_arn
63+
64+
provider = aws.use1
65+
alarm_name = "imms-${var.environment}-shield_ddos_${each.key}"
66+
alarm_description = "Alarm when Shield detects DDoS on ${each.key}"
67+
68+
namespace = "AWS/DDoSProtection"
69+
metric_name = "DDoSDetected"
70+
statistic = "Maximum"
71+
period = 60
72+
evaluation_periods = 20
73+
datapoints_to_alarm = 1
74+
threshold = 0
75+
comparison_operator = "GreaterThanThreshold"
76+
treat_missing_data = "notBreaching"
77+
78+
dimensions = {
79+
ResourceArn = each.value
80+
}
81+
}
82+
83+
84+
# Event Bus Rule for eu-west-2 Region
85+
86+
resource "aws_cloudwatch_event_rule" "shield_ddos_rule_regional" {
87+
name = "imms-${var.environment}-shield_ddos_rule_${data.aws_region.current.region}"
88+
description = "Forward Shield DDoS CloudWatch alarms to CSOC event bus"
89+
90+
event_pattern = jsonencode({
91+
"source" = ["aws.cloudwatch"],
92+
"detail-type" = ["CloudWatch Alarm State Change"],
93+
"resources" = [
94+
for alarm in aws_cloudwatch_metric_alarm.ddos_protection_regional : alarm.arn
95+
]
96+
})
97+
}
98+
99+
100+
101+
resource "aws_cloudwatch_event_target" "shield_ddos_target_regional" {
102+
rule = aws_cloudwatch_event_rule.shield_ddos_rule_regional.name
103+
target_id = "csoc-eventbus"
104+
arn = "arn:aws:events:eu-west-2:${var.csoc_account_id}:event-bus/shield-eventbus"
105+
role_arn = aws_iam_role.eventbridge_forwarder_role.arn
106+
}
107+
108+
# Event Bus Rule for us-east-1 Region
109+
110+
resource "aws_cloudwatch_event_rule" "shield_ddos_rule_global" {
111+
provider = aws.use1
112+
name = "imms-${var.environment}-shield_ddos_rule-us-east-1"
113+
description = "Forward Shield DDoS CloudWatch alarms (global) to CSOC event bus"
114+
115+
event_pattern = jsonencode({
116+
"source" = ["aws.cloudwatch"],
117+
"detail-type" = ["CloudWatch Alarm State Change"],
118+
"resources" = [
119+
for alarm in aws_cloudwatch_metric_alarm.ddos_protection_global : alarm.arn
120+
]
121+
})
122+
}
123+
124+
resource "aws_cloudwatch_event_target" "shield_ddos_target_global" {
125+
provider = aws.use1
126+
rule = aws_cloudwatch_event_rule.shield_ddos_rule_global.name
127+
target_id = "csoc-eventbus"
128+
arn = "arn:aws:events:us-east-1:${var.csoc_account_id}:event-bus/shield-eventbus"
129+
role_arn = aws_iam_role.eventbridge_forwarder_role.arn
130+
}

infra/shield_subscription.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// One-time Shield Advanced subscription for the account.
2+
// This resource is account-level.
3+
4+
resource "aws_shield_subscription" "shield_subscription" {
5+
auto_renew = "ENABLED"
6+
7+
}

infra/variables.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ variable "dspp_account_id" {
1010
description = "DSPP Core AWS account ID"
1111
type = string
1212
}
13+
variable "csoc_account_id" {
14+
description = "CSOC Core AWS account ID"
15+
type = string
16+
17+
}
18+
1319
variable "auto_ops_role" {
1420
default = "role/auto-ops"
1521
type = string

0 commit comments

Comments
 (0)