Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ updates:
directories:
- "/grafana/non-prod/terraform"
- "/infra"
- "/mesh-infra"
- "/terraform"
- "/terraform_aws_backup/**"
schedule:
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
---

Expand Down
2 changes: 2 additions & 0 deletions infra/environments/int/variables.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -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"
2 changes: 2 additions & 0 deletions infra/environments/non-prod/variables.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ 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"
mesh_mailbox_id = null
mesh_dlq_mailbox_id = null
2 changes: 2 additions & 0 deletions infra/environments/prod/variables.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 20 additions & 0 deletions infra/mesh.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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

# TODO single or many mailbox ids
mailbox_ids = [var.mesh_mailbox_id]
dlq_mailbox_id = var.mesh_dlq_mailbox_id
verify_ssl = "true"
get_message_max_concurrency = 10
compress_threshold = 1 * 1024 * 1024
handshake_schedule = "rate(24 hours)"

account_id = local.immunisation_account_id
# TODO these bucket names need attention - enviroment specific names to avoid conflicts
mesh_bucket_name = "imms-${var.environment}-mesh-data-sources"
mesh_logs_bucket_name = "imms-${var.environment}-mesh-s3logs"
}
81 changes: 50 additions & 31 deletions terraform/mesh_processor.tf → infra/mesh_processor.tf
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
# Only create MESH processor resources if MESH is configured for this environment
locals {
create_mesh_processor = var.mesh_mailbox_id != null
}

# Define the directory containing the Docker image and calculate its SHA-256 hash for triggering redeployments
locals {
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}")]))
mesh_s3_bucket_name = local.create_mesh_processor ? module.mesh[0].mesh_bucket_name : null
mesh_s3_logs_bucket_name = local.create_mesh_processor ? module.mesh[0].mesh_logs_bucket_name : null
mesh_processor_name = "imms-${var.environment}-mesh-processor"
mesh_processor_lambda_name = "${local.mesh_processor_name}-lambda"
}


resource "aws_ecr_repository" "mesh_file_converter_lambda_repository" {
count = local.create_mesh_processor ? 1 : 0

image_scanning_configuration {
scan_on_push = true
}
name = "${local.short_prefix}-mesh_processor-repo"
force_delete = local.is_temp
name = "${local.mesh_processor_name}-repo"
force_delete = false
}

# 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" : [
{
Expand Down Expand Up @@ -48,7 +59,8 @@ 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"
Expand All @@ -68,7 +80,7 @@ resource "aws_ecr_repository_policy" "mesh_processor_lambda_ECRImageRetreival_po
],
"Condition" : {
"StringLike" : {
"aws:sourceArn" : "arn:aws:lambda:eu-west-2:${local.immunisation_account_id}:function:${local.short_prefix}-mesh_processor_lambda"
"aws:sourceArn" : "arn:aws:lambda:eu-west-2:${var.imms_account_id}:function:${local.mesh_processor_lambda_name}"
}
}
}
Expand All @@ -78,7 +90,8 @@ resource "aws_ecr_repository_policy" "mesh_processor_lambda_ECRImageRetreival_po

# IAM Role for Lambda
resource "aws_iam_role" "mesh_processor_lambda_exec_role" {
name = "${local.short_prefix}-mesh_processor-lambda-exec-role"
count = local.create_mesh_processor ? 1 : 0
name = "${local.mesh_processor_lambda_name}-exec-role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Expand All @@ -94,7 +107,8 @@ resource "aws_iam_role" "mesh_processor_lambda_exec_role" {

# Policy for Lambda execution role
resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" {
name = "${local.short_prefix}-mesh_processor-lambda-exec-policy"
count = local.create_mesh_processor ? 1 : 0
name = "${local.mesh_processor_lambda_name}-exec-policy"
policy = jsonencode({
Version = "2012-10-17",
Statement = [
Expand All @@ -105,7 +119,7 @@ resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" {
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Resource = "arn:aws:logs:${var.aws_region}:${local.immunisation_account_id}:log-group:/aws/lambda/${local.short_prefix}-mesh_processor_lambda:*"
Resource = "arn:aws:logs:${var.aws_region}:${var.imms_account_id}:log-group:/aws/lambda/${local.mesh_processor_lambda_name}:*"
},
{
Effect = "Allow"
Expand All @@ -130,6 +144,9 @@ resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" {
"s3:DeleteObject"
]
Resource = [
"arn:aws:s3:::${local.mesh_s3_bucket_name}",
"arn:aws:s3:::${local.mesh_s3_bucket_name}/*",
"arn:aws:s3:::${local.mesh_s3_logs_bucket_name}/*",
"arn:aws:s3:::local-immunisation-mesh",
"arn:aws:s3:::local-immunisation-mesh/*",
"arn:aws:s3:::local-immunisation-mesh-s3logs/*"
Expand All @@ -140,7 +157,8 @@ resource "aws_iam_policy" "mesh_processor_lambda_exec_policy" {
}

resource "aws_iam_policy" "mesh_processor_lambda_kms_access_policy" {
name = "${local.short_prefix}-mesh_processor-lambda-kms-policy"
count = local.create_mesh_processor ? 1 : 0
name = "${aws_lambda_function.mesh_file_converter_lambda[0].function_name}-kms-policy"
description = "Allow Lambda to decrypt environment variables"

policy = jsonencode({
Expand All @@ -155,7 +173,6 @@ resource "aws_iam_policy" "mesh_processor_lambda_kms_access_policy" {
]
Resource = [
data.aws_kms_key.mesh_s3_encryption_key.arn
# "arn:aws:kms:eu-west-2:345594581768:key/9b756762-bc6f-42fb-ba56-2c0c00c15289"
]
}
]
Expand All @@ -164,59 +181,61 @@ 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" {
function_name = "${local.short_prefix}-mesh_processor_lambda"
role = aws_iam_role.mesh_processor_lambda_exec_role.arn
count = local.create_mesh_processor ? 1 : 0
function_name = "${local.mesh_processor_name}_lambda"
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"
MESH_FILE_PROC_LAMBDA_NAME = "${local.mesh_processor_lambda_name}"
}
}

}

# 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"
source_arn = "arn:aws:s3:::${local.mesh_s3_bucket_name}"
}

# 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 = local.mesh_s3_bucket_name

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 =""
}

depends_on = [aws_lambda_permission.mesh_s3_invoke_permission]
}

resource "aws_cloudwatch_log_group" "mesh_file_converter_log_group" {
name = "/aws/lambda/${local.short_prefix}-mesh_processor_lambda"
count = local.create_mesh_processor ? 1 : 0
name = "/aws/lambda/${aws_lambda_function.mesh_file_converter_lambda[0].function_name}"
retention_in_days = 30
}
}
6 changes: 6 additions & 0 deletions infra/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
41 changes: 0 additions & 41 deletions mesh-infra/main.tf

This file was deleted.

3 changes: 2 additions & 1 deletion terraform/configs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ locals {
is_temp = length(regexall("[a-z]{2,4}-?[0-9]+", local.env)) > 0
dspp_core_account_id = local.environment == "prod" ? 232116723729 : 603871901111
immunisation_account_id = local.environment == "prod" ? 664418956997 : 345594581768
}

}
20 changes: 20 additions & 0 deletions terraform/mesh.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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

# TODO single or many mailbox ids
mailbox_ids = [local.mesh_mailbox_id]
dlq_mailbox_id = local.mesh_dlq_mailbox_id
verify_ssl = "true"
get_message_max_concurrency = 10
compress_threshold = 1 * 1024 * 1024
handshake_schedule = "rate(24 hours)"

account_id = local.immunisation_account_id
# TODO these bucket names need attention - enviroment specific names to avoid conflicts
mesh_bucket_name = "local-immunisation-mesh"
mesh_logs_bucket_name = "local-immunisation-mesh-s3logs"
}
1 change: 1 addition & 0 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,4 @@ data "aws_kms_key" "existing_kinesis_encryption_key" {
data "aws_kms_key" "mesh_s3_encryption_key" {
key_id = "alias/local-immunisation-mesh"
}

Loading