diff --git a/.github/dependabot.yml b/.github/dependabot.yml index be2227661..1c221ea35 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -71,7 +71,6 @@ updates: directories: - "/grafana/non-prod/terraform" - "/infra" - - "/mesh-infra" - "/terraform" - "/terraform_aws_backup/**" schedule: diff --git a/README.md b/README.md index bea0cd7d0..8dbd303d5 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ See https://nhsd-confluence.digital.nhs.uk/display/APM/Glossary. | `terraform_old` | Old tf code used to create INT to mimic prod. | | `terraform_sandbox` | Sandbox environment for testing infrastructure changes. | | `terraform_aws_backup` | Streamlined backup processing with AWS. | -| `mesh-infra` | Infrastructure setup for Imms batch MESH integration. | | `proxies` | Apigee API proxy definitions. | --- diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl index 594e72b5a..48f160900 100644 --- a/infra/.terraform.lock.hcl +++ b/infra/.terraform.lock.hcl @@ -1,26 +1,86 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. +provider "registry.terraform.io/hashicorp/archive" { + version = "2.7.1" + constraints = ">= 2.0.0" + hashes = [ + "h1:A7EnRBVm4h9ryO9LwxYnKr4fy7ExPMwD5a1DsY7m1Y0=", + "zh:19881bb356a4a656a865f48aee70c0b8a03c35951b7799b6113883f67f196e8e", + "zh:2fcfbf6318dd514863268b09bbe19bfc958339c636bcbcc3664b45f2b8bf5cc6", + "zh:3323ab9a504ce0a115c28e64d0739369fe85151291a2ce480d51ccbb0c381ac5", + "zh:362674746fb3da3ab9bd4e70c75a3cdd9801a6cf258991102e2c46669cf68e19", + "zh:7140a46d748fdd12212161445c46bbbf30a3f4586c6ac97dd497f0c2565fe949", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:875e6ce78b10f73b1efc849bfcc7af3a28c83a52f878f503bb22776f71d79521", + "zh:b872c6ed24e38428d817ebfb214da69ea7eefc2c38e5a774db2ccd58e54d3a22", + "zh:cd6a44f731c1633ae5d37662af86e7b01ae4c96eb8b04144255824c3f350392d", + "zh:e0600f5e8da12710b0c52d6df0ba147a5486427c1a2cc78f31eea37a47ee1b07", + "zh:f21b2e2563bbb1e44e73557bcd6cdbc1ceb369d471049c40eb56cb84b6317a60", + "zh:f752829eba1cc04a479cf7ae7271526b402e206d5bcf1fcce9f535de5ff9e4e6", + ] +} + provider "registry.terraform.io/hashicorp/aws" { - version = "6.2.0" - constraints = "~> 6.0" + version = "6.3.0" + constraints = ">= 5.0.0, >= 6.0.0, ~> 6.0" hashes = [ - "h1:+Qr9xg0yGTwNyrZtYQaBAnyf6BI2+/4JoTWF/kVLa5o=", - "h1:ziUjk3KGwBa7bAwZaPuQklfcQ3Qlx2d0rlYFvdZn4g8=", - "zh:224b20371f7c7ce14d69a84e16ae94baa0a06c132474d4bc4d192d86936bc750", - "zh:2c079ad275c32b9abae7616d07c24901340207a85995ce0025ac38af16b317b7", - "zh:2d139c99d6e8e48cc5439c2945eee583bb3a2d7faf484639cdfd4590ebc294f2", - "zh:2f2dc72de43d845e5df5a1adeadd4a48f3cacfe413b89b95f50294a386a90124", - "zh:304d4e706ac34aba080a81867209c65cdd28f8e596c02b3565f6530ab697cf94", - "zh:40e69328ae11fe1711b34226d45aa4c685f73e8f958c76c49f4f6a6627a1a54f", - "zh:5c5c9faab6fe242b77f0d0ab6664313dd89409371123e2ec376c72e8f2cd97b3", - "zh:7824709f0226afec5e3ad41392233b4bd7d925bae0d35f4a2ac854b3516e955c", + "h1:p8RNhYsu0ewxz13m4nNmc/gXB9tfn9b3d2KKdj91T5g=", + "zh:0502dc1889cca94c89bfc00b214970bffa2d81a2cdb55e05ab6192484ddb1532", + "zh:0a009c6f643410dc29fe2c07aee57e726ac86335fad84788fc7412abbd3a55be", + "zh:0ddd577e5f23dc0be23b87d62dff1f5694b88b1fbc01bdd3046b4b51cc18a00c", + "zh:1b2754cb01fa2c1a6a59c4195212f6bd4b3d1602e3f4ffb94ab609e01f2ea11a", + "zh:2bc0edb35a1411670d74e827db58ef32a07e11757fdaa17934dce5451511e55a", + "zh:703415b5c58d9232bdb686816e90525dfe96b0a374062bd8e27bec553cac5538", + "zh:8c4f1f41722aacb4b128dfb269f5b3f0aa1239a5742f22abb012f87095b2244c", + "zh:9815c0cc480acfef7c9b6b31505070bb0247a0982d98b4b6e51b1923b3a65f7e", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:ab5417435121e8f9a6f539a6972f20c060ebc78624c1ce7c190671f163c423e4", - "zh:d6939385de4931f9fe07c87b744468fbfa96bd4b47861020d68e7ba1efb4185f", - "zh:e51434d1ba106c55d04fdc223aaf403b897ff96cba9bfce4c51854c805c36ed8", - "zh:e6d1012bafe338759ac42a59f566f8c4ad64a67faa3152c7fb758704d890cd75", - "zh:ee24b989ee3b6be79a7f24e97c144535bf7053471ae65343220db3ae78c7632a", - "zh:f61ec9482b9887c4901946407992874531b0c2eadab0c743fdfca4e6cd6dd889", + "zh:b3563ce1e4c40fa139c045a1db06c3308fcf8aa9722c0a586a18bfbcedc111b5", + "zh:bbcf01aa5188416cb0f31425c2dfc3a4df41248d4dce9ebab709d416177a3011", + "zh:bc49559699e6a03ff57675172fc367db9993df74a502e0c6f273127af82990a9", + "zh:c89bbeee5db6bbe80ce152481b85a4d44b733d7c1e1a37924f36c9cde0b7ce2d", + "zh:d26793472e127a98dfa5d32a71adc4c960b573afc427604c9815bae9cda31a72", + "zh:eb8db004ccbf52b3ed8b15189c59560c233abd2c2f5ac5ee68768841c3c8e206", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.4" + constraints = ">= 2.0.0, >= 3.0.0" + hashes = [ + "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", + "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a", + "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991", + "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f", + "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e", + "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615", + "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442", + "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5", + "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f", + "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f", + ] +} + +provider "registry.terraform.io/kreuzwerker/docker" { + version = "3.6.2" + constraints = ">= 3.5.0" + hashes = [ + "h1:/Oe7tViXf/xyQ4Pg8cDifMlD3RthOYkslwQiRgx7BTE=", + "zh:22b51a8fb63481d290bdad9a221bc8c9e45d66d1a0cd45beed3f3627bf1debd8", + "zh:2b902eb80a1ae033af1135cc165d192668820a7f8ea15beb5472f811c18bea1f", + "zh:57815dcea28aedb86ed33924cd186aaee8bd31670bd78437a2a2daf2b00ce2ae", + "zh:583af9c6fe7e3bfc04f50aec046a9b4f98b7eddd6d1e143454e5d06a66afcf87", + "zh:80f8cba54f639a53c4d7714edb7246064b7f4f48ba93a70f18c914d656d799db", + "zh:894709f0c393c4ee91fdb849128e7f0bce688f293cd1643a6d4e39c842367278", + "zh:a91b41dbcb203d6dae2bb72b98c4c21c41255026b35df01895882784c4650071", + "zh:aec40a8157aae093412a1fb9a71ab2bea370db152e285c2d81e37ed378444b9c", + "zh:b87d7def2485dde6e57723c1265158f371440a8a84954c9fdb0580cf89de66bf", + "zh:b9dc243200ad9cd00250cb8c793ecea4ee3c57a121faf8efdb289f30008b5778", + "zh:dcb103831db6d3ef95468685cd104be3928793996542a1f675dc34a2ce67951d", + "zh:e59b4a0f2b5881016896d4417b1ab2fb87f34450663efeb01f3bcf7c3606fbbb", + "zh:fbd068c01114f0712578cf02f363b5521338ab1befedddf7090da532298b43d0", ] } diff --git a/infra/environments/int/variables.tfvars b/infra/environments/int/variables.tfvars index cb4f23f7d..2a42580cb 100644 --- a/infra/environments/int/variables.tfvars +++ b/infra/environments/int/variables.tfvars @@ -7,3 +7,5 @@ dspp_admin_role = "root" environment = "int" parent_route53_zone_name = "int.vds.platform.nhs.uk" child_route53_zone_name = "imms.int.vds.platform.nhs.uk" +mesh_mailbox_id = "X26OT303" +mesh_dlq_mailbox_id = "X26OT304" diff --git a/infra/environments/non-prod/variables.tfvars b/infra/environments/non-prod/variables.tfvars index 1d07aca45..c7e4b4ca6 100644 --- a/infra/environments/non-prod/variables.tfvars +++ b/infra/environments/non-prod/variables.tfvars @@ -7,3 +7,8 @@ dspp_admin_role = "root" environment = "dev" parent_route53_zone_name = "dev.vds.platform.nhs.uk" child_route53_zone_name = "imms.dev.vds.platform.nhs.uk" +# TODO - null these out once we're using the int account +# mesh_mailbox_id = null +# mesh_dlq_mailbox_id = null +mesh_mailbox_id = "X26OT303" +mesh_dlq_mailbox_id = "X26OT304" diff --git a/infra/environments/prod/variables.tfvars b/infra/environments/prod/variables.tfvars index 587f69084..00218c21a 100644 --- a/infra/environments/prod/variables.tfvars +++ b/infra/environments/prod/variables.tfvars @@ -7,3 +7,5 @@ dspp_admin_role = "root" environment = "prod" parent_route53_zone_name = "prod.vds.platform.nhs.uk" child_route53_zone_name = "imms.prod.vds.platform.nhs.uk" +mesh_mailbox_id = "X26HC138" +mesh_dlq_mailbox_id = null diff --git a/infra/mesh.tf b/infra/mesh.tf new file mode 100644 index 000000000..e7ad8b6c1 --- /dev/null +++ b/infra/mesh.tf @@ -0,0 +1,15 @@ +# MESH Client Module - conditionally created based on environment configuration +module "mesh" { + count = var.mesh_mailbox_id != null ? 1 : 0 + source = "git::https://github.com/nhsdigital/terraform-aws-mesh-client.git//module?ref=v2.1.5" + + name_prefix = "imms-${var.environment}" + account_id = var.imms_account_id + mesh_env = var.environment == "prod"? "production" : "integration" + subnet_ids = toset([]) + mailbox_ids = [var.mesh_mailbox_id] + + compress_threshold = 1 * 1024 * 1024 + get_message_max_concurrency = 10 + handshake_schedule = "rate(24 hours)" +} diff --git a/infra/variables.tf b/infra/variables.tf index 34a1fcff3..38a49423b 100644 --- a/infra/variables.tf +++ b/infra/variables.tf @@ -16,3 +16,9 @@ variable "build_agent_account_id" { variable "environment" { default = "non-prod" } +variable "mesh_mailbox_id" { + default = null +} +variable "mesh_dlq_mailbox_id" { + default = null +} diff --git a/mesh-infra/main.tf b/mesh-infra/main.tf deleted file mode 100644 index 7002a0297..000000000 --- a/mesh-infra/main.tf +++ /dev/null @@ -1,41 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 6" - } - } - backend "s3" { - region = "eu-west-2" - key = "state" - } - required_version = ">= 1.5.0" -} - - - -data "aws_vpc" "default" { - default = true -} -data "aws_subnets" "default" { - filter { - name = "vpc-id" - values = [data.aws_vpc.default.id] - } -} - -module "mesh" { - source = "git::https://github.com/nhsdigital/terraform-aws-mesh-client.git//module?ref=v2.1.5" - - name_prefix = "local-immunisation" - mesh_env = "integration" - subnet_ids = data.aws_subnets.default.ids - - mailbox_ids = ["X26OT303"] - verify_ssl = "true" - get_message_max_concurrency = 10 - compress_threshold = 1 * 1024 * 1024 - handshake_schedule = "rate(24 hours)" - - account_id = 345594581768 -} \ No newline at end of file diff --git a/terraform/mesh_processor.tf b/terraform/mesh_processor.tf index ff43bd7de..700e9759a 100644 --- a/terraform/mesh_processor.tf +++ b/terraform/mesh_processor.tf @@ -1,12 +1,28 @@ # Define the directory containing the Docker image and calculate its SHA-256 hash for triggering redeployments locals { + create_mesh_processor = local.environment == "int" || local.environment == "prod" mesh_processor_lambda_dir = abspath("${path.root}/../mesh_processor") mesh_processor_lambda_files = fileset(local.mesh_processor_lambda_dir, "**") mesh_processor_lambda_dir_sha = sha1(join("", [for f in local.mesh_processor_lambda_files : filesha1("${local.mesh_processor_lambda_dir}/${f}")])) + # This should match the prefix used in the infra Terraform + mesh_module_prefix = "imms-${local.config_env}" } +data "aws_s3_bucket" "mesh" { + count = local.create_mesh_processor ? 1 : 0 + + bucket = "${local.mesh_module_prefix}-mesh" +} + +data "aws_kms_key" "mesh" { + count = local.create_mesh_processor ? 1 : 0 + + key_id = "alias/${local.mesh_module_prefix}-mesh" +} resource "aws_ecr_repository" "mesh_file_converter_lambda_repository" { + count = local.create_mesh_processor ? 1 : 0 + image_scanning_configuration { scan_on_push = true } @@ -16,11 +32,13 @@ resource "aws_ecr_repository" "mesh_file_converter_lambda_repository" { # Module for building and pushing Docker image to ECR module "mesh_processor_docker_image" { + count = local.create_mesh_processor ? 1 : 0 + source = "terraform-aws-modules/lambda/aws//modules/docker-build" version = "8.0.1" create_ecr_repo = false - ecr_repo = aws_ecr_repository.mesh_file_converter_lambda_repository.name + ecr_repo = aws_ecr_repository.mesh_file_converter_lambda_repository[0].name ecr_repo_lifecycle_policy = jsonencode({ "rules" : [ { @@ -48,7 +66,9 @@ module "mesh_processor_docker_image" { # Define the lambdaECRImageRetreival policy resource "aws_ecr_repository_policy" "mesh_processor_lambda_ECRImageRetreival_policy" { - repository = aws_ecr_repository.mesh_file_converter_lambda_repository.name + count = local.create_mesh_processor ? 1 : 0 + + repository = aws_ecr_repository.mesh_file_converter_lambda_repository[0].name policy = jsonencode({ Version = "2012-10-17" @@ -78,6 +98,8 @@ resource "aws_ecr_repository_policy" "mesh_processor_lambda_ECRImageRetreival_po # IAM Role for Lambda resource "aws_iam_role" "mesh_processor_lambda_exec_role" { + count = local.create_mesh_processor ? 1 : 0 + name = "${local.short_prefix}-mesh_processor-lambda-exec-role" assume_role_policy = jsonencode({ Version = "2012-10-17", @@ -94,6 +116,8 @@ resource "aws_iam_role" "mesh_processor_lambda_exec_role" { # Policy for Lambda execution role resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" { + count = local.create_mesh_processor ? 1 : 0 + name = "${local.short_prefix}-mesh_processor-lambda-exec-policy" policy = jsonencode({ Version = "2012-10-17", @@ -130,9 +154,8 @@ resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" { "s3:DeleteObject" ] Resource = [ - "arn:aws:s3:::local-immunisation-mesh", - "arn:aws:s3:::local-immunisation-mesh/*", - "arn:aws:s3:::local-immunisation-mesh-s3logs/*" + data.aws_s3_bucket.mesh[0].arn, + "${data.aws_s3_bucket.mesh[0].arn}/*" ] } ] @@ -140,6 +163,8 @@ resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" { } resource "aws_iam_policy" "mesh_processor_lambda_kms_access_policy" { + count = local.create_mesh_processor ? 1 : 0 + name = "${local.short_prefix}-mesh_processor-lambda-kms-policy" description = "Allow Lambda to decrypt environment variables" @@ -154,8 +179,7 @@ resource "aws_iam_policy" "mesh_processor_lambda_kms_access_policy" { "kms:GenerateDataKey*" ] Resource = [ - data.aws_kms_key.mesh_s3_encryption_key.arn - # "arn:aws:kms:eu-west-2:345594581768:key/9b756762-bc6f-42fb-ba56-2c0c00c15289" + data.aws_kms_key.mesh[0].arn ] } ] @@ -164,59 +188,64 @@ resource "aws_iam_policy" "mesh_processor_lambda_kms_access_policy" { # Attach the execution policy to the Lambda role resource "aws_iam_role_policy_attachment" "mesh_processor_lambda_exec_policy_attachment" { - role = aws_iam_role.mesh_processor_lambda_exec_role.name - policy_arn = aws_iam_policy.mesh_processor_lambda_exec_policy.arn + count = local.create_mesh_processor ? 1 : 0 + + role = aws_iam_role.mesh_processor_lambda_exec_role[0].name + policy_arn = aws_iam_policy.mesh_processor_lambda_exec_policy[0].arn } # Attach the kms policy to the Lambda role resource "aws_iam_role_policy_attachment" "mesh_processor_lambda_kms_policy_attachment" { - role = aws_iam_role.mesh_processor_lambda_exec_role.name - policy_arn = aws_iam_policy.mesh_processor_lambda_kms_access_policy.arn + count = local.create_mesh_processor ? 1 : 0 + + role = aws_iam_role.mesh_processor_lambda_exec_role[0].name + policy_arn = aws_iam_policy.mesh_processor_lambda_kms_access_policy[0].arn } # Lambda Function with Security Group and VPC. resource "aws_lambda_function" "mesh_file_converter_lambda" { + count = local.create_mesh_processor ? 1 : 0 + function_name = "${local.short_prefix}-mesh_processor_lambda" - role = aws_iam_role.mesh_processor_lambda_exec_role.arn + role = aws_iam_role.mesh_processor_lambda_exec_role[0].arn package_type = "Image" - image_uri = module.mesh_processor_docker_image.image_uri + image_uri = module.mesh_processor_docker_image[0].image_uri architectures = ["x86_64"] timeout = 360 environment { variables = { - Destination_BUCKET_NAME = aws_s3_bucket.batch_data_source_bucket.bucket - MESH_FILE_PROC_LAMBDA_NAME = "imms-${local.env}-meshfileproc_lambda" + Destination_BUCKET_NAME = aws_s3_bucket.batch_data_source_bucket.bucket } } - } # Permission for S3 to invoke Lambda function resource "aws_lambda_permission" "mesh_s3_invoke_permission" { + count = local.create_mesh_processor ? 1 : 0 + statement_id = "AllowExecutionFromS3" action = "lambda:InvokeFunction" - function_name = aws_lambda_function.mesh_file_converter_lambda.function_name + function_name = aws_lambda_function.mesh_file_converter_lambda[0].function_name principal = "s3.amazonaws.com" source_arn = "arn:aws:s3:::local-immunisation-mesh" } -# TODO - This is scoped to the bucket, so is overwritten by each deployment -# That might be intentional in prod, to switch between blue and green, but surely isn't in non-prod -# S3 Bucket notification to trigger Lambda function resource "aws_s3_bucket_notification" "mesh_datasources_lambda_notification" { - # TODO - what is this bucket and why isn't it managed by Terraform? - bucket = "local-immunisation-mesh" + count = local.create_mesh_processor ? 1 : 0 + + bucket = data.aws_s3_bucket.mesh[0].bucket lambda_function { - lambda_function_arn = aws_lambda_function.mesh_file_converter_lambda.arn + lambda_function_arn = aws_lambda_function.mesh_file_converter_lambda[0].arn events = ["s3:ObjectCreated:*"] - #filter_prefix ="" } } resource "aws_cloudwatch_log_group" "mesh_file_converter_log_group" { + count = local.create_mesh_processor ? 1 : 0 + name = "/aws/lambda/${local.short_prefix}-mesh_processor_lambda" retention_in_days = 30 } diff --git a/terraform/variables.tf b/terraform/variables.tf index 629fb1d02..b3b707740 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -20,7 +20,8 @@ locals { prefix = "${var.project_name}-${var.service}-${local.env}" short_prefix = "${var.project_short_name}-${local.env}" batch_prefix = "immunisation-batch-${local.env}" - config_env = local.environment == "prod" ? "prod" : "dev" + # TODO - add int when we switch to the new account + config_env = local.environment == "prod" ? "prod" : "dev" root_domain = "${local.config_env}.vds.platform.nhs.uk" project_domain_name = data.aws_route53_zone.project_zone.name @@ -93,7 +94,3 @@ data "aws_kms_key" "existing_lambda_encryption_key" { data "aws_kms_key" "existing_kinesis_encryption_key" { key_id = "alias/imms-batch-kinesis-stream-encryption" } - -data "aws_kms_key" "mesh_s3_encryption_key" { - key_id = "alias/local-immunisation-mesh" -}