diff --git a/infrastructure/terraform/components/acct/README.md b/infrastructure/terraform/components/acct/README.md index bcbd3c620..b37c3af0d 100644 --- a/infrastructure/terraform/components/acct/README.md +++ b/infrastructure/terraform/components/acct/README.md @@ -25,13 +25,16 @@ | [region](#input\_region) | The AWS Region | `string` | n/a | yes | | [root\_domain\_name](#input\_root\_domain\_name) | The service's root DNS root nameespace, like nonprod.nhsnotify.national.nhs.uk | `string` | `"nonprod.nhsnotify.national.nhs.uk"` | no | | [support\_sandbox\_environments](#input\_support\_sandbox\_environments) | Does this account support dev sandbox environments? | `bool` | `false` | no | +| [vpc\_cidr](#input\_vpc\_cidr) | n/a | `string` | `"10.0.0.0/16"` | no | +| [vpc\_subnet\_cidr\_bits](#input\_vpc\_subnet\_cidr\_bits) | Number of additional bits to use for subnetting the VPC CIDR block. The bits are evently distributed |
object({
public = number
private = number
}) | {
"private": 3,
"public": 12
} | no |
## Modules
| Name | Source | Version |
|------|--------|---------|
| [kms\_sandbox](#module\_kms\_sandbox) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/kms | v1.0.8 |
-| [s3bucket\_access\_logs](#module\_s3bucket\_access\_logs) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket | v1.0.8 |
+| [s3bucket\_access\_logs](#module\_s3bucket\_access\_logs) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket | v1.0.9 |
| [s3bucket\_backup\_reports](#module\_s3bucket\_backup\_reports) | git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket | v1.0.8 |
+| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | 5.19.0 |
## Outputs
| Name | Description |
@@ -39,6 +42,8 @@
| [dns\_zone](#output\_dns\_zone) | n/a |
| [github\_pat\_ssm\_param\_name](#output\_github\_pat\_ssm\_param\_name) | n/a |
| [s3\_buckets](#output\_s3\_buckets) | n/a |
+| [vpc\_nat\_ips](#output\_vpc\_nat\_ips) | n/a |
+| [vpc\_public\_subnets](#output\_vpc\_public\_subnets) | n/a |
diff --git a/infrastructure/terraform/components/acct/cloudwatch_event_rule_aws_backup_errors.tf b/infrastructure/terraform/components/acct/cloudwatch_event_rule_aws_backup_errors.tf
index f114ddd7f..7c56a72ee 100644
--- a/infrastructure/terraform/components/acct/cloudwatch_event_rule_aws_backup_errors.tf
+++ b/infrastructure/terraform/components/acct/cloudwatch_event_rule_aws_backup_errors.tf
@@ -1,9 +1,9 @@
resource "aws_cloudwatch_event_rule" "aws_backup_errors" {
- name = "${local.csi}-aws-backup-errors"
+ name = "${local.csi}-aws-backup-errors"
description = "Forwards AWS Backup state changes to Custom Event Bus in Observability Account"
event_pattern = jsonencode({
- source = ["aws.backup"],
+ source = ["aws.backup"],
"detail-type" = ["Backup Job State Change", "Restore Job State Change", "Copy Job State Change"],
detail = {
state = ["FAILED", "ABORTED"]
diff --git a/infrastructure/terraform/components/acct/data_availability_zones_available.tf b/infrastructure/terraform/components/acct/data_availability_zones_available.tf
new file mode 100644
index 000000000..87d8f4820
--- /dev/null
+++ b/infrastructure/terraform/components/acct/data_availability_zones_available.tf
@@ -0,0 +1,3 @@
+data "aws_availability_zones" "available" {
+ state = "available"
+}
diff --git a/infrastructure/terraform/components/acct/iam_policy_github_deploy_overload.tf b/infrastructure/terraform/components/acct/iam_policy_github_deploy_overload.tf
index b7e6fa6ce..188508134 100644
--- a/infrastructure/terraform/components/acct/iam_policy_github_deploy_overload.tf
+++ b/infrastructure/terraform/components/acct/iam_policy_github_deploy_overload.tf
@@ -30,4 +30,25 @@ data "aws_iam_policy_document" "github_deploy" {
]
resources = ["*"]
}
+
+ statement {
+ effect = "Allow"
+
+ actions = [
+ "ec2:AllocateAddress",
+ "ec2:Associate*",
+ "ec2:AttachInternetGateway",
+ "ec2:AuthorizeSecurityGroup*",
+ "ec2:Create*",
+ "ec2:Delete*",
+ "ec2:Describe*",
+ "ec2:DetachInternetGateway",
+ "ec2:Disassociate*",
+ "ec2:ModifySubnet*",
+ "ec2:ModifyVpc*",
+ "ec2:ReleaseAddress",
+ "ec2:Replace*",
+ ]
+ resources = ["*"]
+ }
}
diff --git a/infrastructure/terraform/components/acct/locals.tf b/infrastructure/terraform/components/acct/locals.tf
index fe71c80aa..2e61aa42c 100644
--- a/infrastructure/terraform/components/acct/locals.tf
+++ b/infrastructure/terraform/components/acct/locals.tf
@@ -1,3 +1,17 @@
locals {
- event_bus_arn = "arn:aws:events:eu-west-2:${var.observability_account_id}:event-bus/nhs-notify-main-acct-alerts-bus"
+ event_bus_arn = "arn:aws:events:eu-west-2:${var.observability_account_id}:event-bus/nhs-notify-main-acct-alerts-bus"
+
+ # VPC Subnet Maths (Equally devise a number of subnets across the availble AZs from a provided supernet)
+ required_bits_public = ceil(log(length(data.aws_availability_zones.available.names), 2))
+ required_bits_private = ceil(log(length(data.aws_availability_zones.available.names), 2))
+
+ public_subnet_cidrs = [
+ for az_index, az in data.aws_availability_zones.available.names :
+ cidrsubnet(var.vpc_cidr, max(var.vpc_subnet_cidr_bits.public, local.required_bits_public), az_index)
+ ]
+
+ private_subnet_cidrs = [
+ for az_index, az in data.aws_availability_zones.available.names :
+ cidrsubnet(var.vpc_cidr, max(var.vpc_subnet_cidr_bits.private, local.required_bits_private), az_index + length(data.aws_availability_zones.available.names))
+ ]
}
diff --git a/infrastructure/terraform/components/acct/module_s3bucket_access_logs.tf b/infrastructure/terraform/components/acct/module_s3bucket_access_logs.tf
index 1c20fda94..89c69babf 100644
--- a/infrastructure/terraform/components/acct/module_s3bucket_access_logs.tf
+++ b/infrastructure/terraform/components/acct/module_s3bucket_access_logs.tf
@@ -1,5 +1,5 @@
module "s3bucket_access_logs" {
- source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket?ref=v1.0.8"
+ source = "git::https://github.com/NHSDigital/nhs-notify-shared-modules.git//infrastructure/modules/s3bucket?ref=v1.0.9"
name = "access-logs"
@@ -96,7 +96,7 @@ data "aws_iam_policy_document" "s3bucket_access_logs" {
]
principals {
- type = "AWS"
+ type = "AWS"
identifiers = [
"arn:aws:iam::${var.aws_account_id}:root"
]
@@ -116,7 +116,7 @@ data "aws_iam_policy_document" "s3bucket_access_logs" {
]
principals {
- type = "AWS"
+ type = "AWS"
identifiers = [
"arn:aws:iam::${var.aws_account_id}:root"
]
diff --git a/infrastructure/terraform/components/acct/module_vpc.tf b/infrastructure/terraform/components/acct/module_vpc.tf
new file mode 100644
index 000000000..81f50d809
--- /dev/null
+++ b/infrastructure/terraform/components/acct/module_vpc.tf
@@ -0,0 +1,27 @@
+module "vpc" {
+ source = "terraform-aws-modules/vpc/aws"
+ version = "5.19.0"
+
+ name = local.csi
+ cidr = var.vpc_cidr
+
+ azs = data.aws_availability_zones.available.names
+ public_subnets = local.public_subnet_cidrs
+ private_subnets = local.private_subnet_cidrs
+
+ enable_nat_gateway = true
+ single_nat_gateway = true
+
+ create_database_subnet_group = false
+ create_elasticache_subnet_group = false
+ create_redshift_subnet_group = false
+
+ manage_default_vpc = false
+ manage_default_network_acl = false
+ manage_default_route_table = false
+ manage_default_security_group = false
+
+ private_subnet_tags = {
+ Subnet = "Private"
+ }
+}
diff --git a/infrastructure/terraform/components/acct/outputs.tf b/infrastructure/terraform/components/acct/outputs.tf
index df42f2275..ecbbcade5 100644
--- a/infrastructure/terraform/components/acct/outputs.tf
+++ b/infrastructure/terraform/components/acct/outputs.tf
@@ -19,3 +19,14 @@ output "s3_buckets" {
}
}
}
+
+output "vpc_public_subnets" {
+ value = {
+ public = module.vpc.public_subnets
+ private = module.vpc.private_subnets
+ }
+}
+
+output "vpc_nat_ips" {
+ value = module.vpc.nat_public_ips
+}
diff --git a/infrastructure/terraform/components/acct/variables.tf b/infrastructure/terraform/components/acct/variables.tf
index 578904082..2ec7cf09b 100644
--- a/infrastructure/terraform/components/acct/variables.tf
+++ b/infrastructure/terraform/components/acct/variables.tf
@@ -87,3 +87,20 @@ variable "support_sandbox_environments" {
description = "Does this account support dev sandbox environments?"
default = false
}
+
+variable "vpc_cidr" {
+ type = string
+ default = "10.0.0.0/16"
+}
+
+variable "vpc_subnet_cidr_bits" {
+ type = object({
+ public = number
+ private = number
+ })
+ description = "Number of additional bits to use for subnetting the VPC CIDR block. The bits are evently distributed "
+ default = {
+ public = 12 # Smaller subnets for public resources. 12 creates /28 subnets over 3x Az
+ private = 3 # Larger subnets for private resources, 3 creates /19 subnets over 3x Az
+ }
+}