diff --git a/infrastructure/terraform/per_account/dev/main.tf b/infrastructure/terraform/per_account/dev/main.tf index 2fb525520..10751de6d 100644 --- a/infrastructure/terraform/per_account/dev/main.tf +++ b/infrastructure/terraform/per_account/dev/main.tf @@ -101,3 +101,16 @@ module "vpc" { resource "aws_route53_zone" "dev-ns" { name = "api.cpm.dev.national.nhs.uk" } + +module "billing-alert" { + source = "../modules/billing-alert" + prefix = "${local.project}--${terraform.workspace}" + metric_name = "EstimatedCharges" + metric_statistic = "Maximum" + metric_number_of_evaluation_periods = 1 + threshold_dollars = 20 + recipients = [] # get from secrets + tags = { + Name = "${local.project}--${replace(terraform.workspace, "_", "-")}" + } +} diff --git a/infrastructure/terraform/per_account/modules/billing-alert/main.tf b/infrastructure/terraform/per_account/modules/billing-alert/main.tf new file mode 100644 index 000000000..8f7d17aaf --- /dev/null +++ b/infrastructure/terraform/per_account/modules/billing-alert/main.tf @@ -0,0 +1,33 @@ +resource "aws_cloudwatch_metric_alarm" "account_billing_alarm" { + alarm_name = "${var.prefix}--billing-alarm--${var.threshold_dollars}--${var.metric_name}" + alarm_description = "Billing Alarm of ${var.threshold_dollars} USD (${var.metric_name})" + namespace = "AWS/Billing" + tags = var.tags + + # If statistic(metric) >= threshold in dollars then trigger topic + metric_name = var.metric_name + comparison_operator = "GreaterThanOrEqualToThreshold" + threshold = var.threshold_dollars + alarm_actions = [aws_sns_topic.sns_alert_topic.arn] + + # Evaluate a new statistic(metric) every 6 hours + period = 6 * 60 * 60 # seconds + + # Calculate statistic(metric) over the specified number evaluation periods + statistic = var.metric_statistic + evaluation_periods = var.metric_number_of_evaluation_periods + datapoints_to_alarm = 1 +} + + +resource "aws_sns_topic" "sns_alert_topic" { + name = "${var.prefix}--billing-alarm-${var.threshold_dollars}--${var.metric_name}" + tags = var.tags +} + +resource "aws_sns_topic_subscription" "email_target" { + count = length(var.recipients) + topic_arn = aws_sns_topic.sns_alert_topic.arn + protocol = "email" + endpoint = var.recipients[count.index] +} diff --git a/infrastructure/terraform/per_account/modules/billing-alert/vars.tf b/infrastructure/terraform/per_account/modules/billing-alert/vars.tf new file mode 100644 index 000000000..c3fa341fa --- /dev/null +++ b/infrastructure/terraform/per_account/modules/billing-alert/vars.tf @@ -0,0 +1,26 @@ +variable "prefix" { + type = string +} + +variable "threshold_dollars" { + type = number +} +variable "recipients" { + type = list(string) +} + +variable "metric_name" { + type = string +} + +variable "metric_number_of_evaluation_periods" { + type = number +} + +variable "metric_statistic" { + type = string +} + +variable "tags" { + +} diff --git a/pyproject.toml b/pyproject.toml index 1aebb32da..30bacaf82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,7 @@ urllib3 = "<3" orjson = "^3.9.15" attrs = "^24.2.0" locust = "^2.29.1" +gevent = "<24.10.2" [tool.poetry.group.dev.dependencies] pre-commit = "^4.0.0" diff --git a/scripts/infrastructure/policies/deployment2-policy.json b/scripts/infrastructure/policies/deployment2-policy.json index 643b904d1..e62025976 100644 --- a/scripts/infrastructure/policies/deployment2-policy.json +++ b/scripts/infrastructure/policies/deployment2-policy.json @@ -256,7 +256,11 @@ "acm:ListCertificates", "resource-groups:ListGroups", "lambda:ListEventSourceMappings", - "iam:ListRoles" + "iam:ListRoles", + "sns:CreateTopic", + "sns:TagResource", + "sns:SetTopicAttributes", + "sns:GetTopicAttributes" ], "Resource": ["*"] }