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 + } +}