diff --git a/infrastructure/README.md b/infrastructure/README.md index a9d013459..8a6bd4866 100644 --- a/infrastructure/README.md +++ b/infrastructure/README.md @@ -51,7 +51,7 @@ | [create-token-lambda](#module_create-token-lambda) | ./modules/lambda | n/a | | [create_doc_alarm](#module_create_doc_alarm) | ./modules/lambda_alarms | n/a | | [create_doc_alarm_topic](#module_create_doc_alarm_topic) | ./modules/sns | n/a | -| [create_document_reference_gateway](#module_create_document_reference_gateway) | ./modules/gateway | n/a | +| [document_reference_gateway](#module_document_reference_gateway) | ./modules/gateway | n/a | | [create_token-alarm](#module_create_token-alarm) | ./modules/lambda_alarms | n/a | | [create_token-alarm_topic](#module_create_token-alarm_topic) | ./modules/sns | n/a | | [data-collection-alarm](#module_data-collection-alarm) | ./modules/lambda_alarms | n/a | diff --git a/infrastructure/api.tf b/infrastructure/api.tf index eea30e339..1f0ad0888 100644 --- a/infrastructure/api.tf +++ b/infrastructure/api.tf @@ -49,13 +49,13 @@ resource "aws_api_gateway_deployment" "ndr_api_deploy" { module.back-channel-logout-gateway, module.back_channel_logout_lambda, module.create-doc-ref-lambda, - module.create_document_reference_gateway, module.create-token-gateway, module.create-token-lambda, module.delete-doc-ref-gateway, module.delete-doc-ref-lambda, module.document-manifest-job-gateway, module.document-manifest-job-lambda, + module.document_reference_gateway, module.feature-flags-gateway, module.feature-flags-lambda, module.fhir_document_reference_gateway, @@ -72,6 +72,7 @@ resource "aws_api_gateway_deployment" "ndr_api_deploy" { module.search-patient-details-lambda, module.send-feedback-gateway, module.send-feedback-lambda, + module.update_doc_ref_lambda, module.update-upload-state-gateway, module.update-upload-state-lambda, module.document-status-check-gateway, diff --git a/infrastructure/dynamo_db.tf b/infrastructure/dynamo_db.tf index c1e1e1e92..c4dfddcde 100644 --- a/infrastructure/dynamo_db.tf +++ b/infrastructure/dynamo_db.tf @@ -89,6 +89,10 @@ module "lloyd_george_reference_dynamodb_table" { { name = "CurrentGpOds" type = "S" + }, + { + name = "S3FileKey" + type = "S" } ] @@ -107,6 +111,11 @@ module "lloyd_george_reference_dynamodb_table" { name = "OdsCodeIndex" hash_key = "CurrentGpOds" projection_type = "ALL" + }, + { + name = "S3FileKeyIndex" + hash_key = "S3FileKey" + projection_type = "ALL" } ] diff --git a/infrastructure/gateway-document-reference.tf b/infrastructure/gateway-document-reference.tf index b41e869de..ea9189af4 100644 --- a/infrastructure/gateway-document-reference.tf +++ b/infrastructure/gateway-document-reference.tf @@ -10,3 +10,30 @@ module "fhir_document_reference_gateway" { require_credentials = true } +module "document_reference_gateway" { + source = "./modules/gateway" + api_gateway_id = aws_api_gateway_rest_api.ndr_doc_store_api.id + parent_id = aws_api_gateway_rest_api.ndr_doc_store_api.root_resource_id + http_methods = ["POST"] + authorization = "CUSTOM" + gateway_path = "DocumentReference" + authorizer_id = aws_api_gateway_authorizer.repo_authoriser.id + require_credentials = true + origin = contains(["prod"], terraform.workspace) ? "'https://${var.domain}'" : "'https://${terraform.workspace}.${var.domain}'" +} + +module "document_reference_id_gateway" { + source = "./modules/gateway" + api_gateway_id = aws_api_gateway_rest_api.ndr_doc_store_api.id + parent_id = module.document_reference_gateway.gateway_resource_id + http_methods = ["PUT"] + authorization = "CUSTOM" + gateway_path = "{id}" + authorizer_id = aws_api_gateway_authorizer.repo_authoriser.id + require_credentials = true + origin = contains(["prod"], terraform.workspace) ? "'https://${var.domain}'" : "'https://${terraform.workspace}.${var.domain}'" + + request_parameters = { + "method.request.path.id" = true + } +} diff --git a/infrastructure/iam.tf b/infrastructure/iam.tf index 91f6f3399..4b936ddb3 100644 --- a/infrastructure/iam.tf +++ b/infrastructure/iam.tf @@ -243,3 +243,26 @@ resource "aws_api_gateway_account" "logging" { count = local.is_sandbox ? 0 : 1 cloudwatch_role_arn = aws_iam_role.api_gateway_cloudwatch[0].arn } + +data "aws_iam_policy_document" "assume_role_policy_for_update_lambda" { + statement { + actions = ["sts:AssumeRole"] + + principals { + type = "AWS" + identifiers = compact([ + module.update_doc_ref_lambda.lambda_execution_role_arn + ]) + } + } +} + +resource "aws_iam_role" "update_put_presign_url_role" { + name = "${terraform.workspace}_update_put_presign_url_role" + assume_role_policy = data.aws_iam_policy_document.assume_role_policy_for_update_lambda.json +} + +resource "aws_iam_role_policy_attachment" "update_put_presign_url" { + role = aws_iam_role.update_put_presign_url_role.name + policy_arn = aws_iam_policy.s3_document_data_policy_put_only.arn +} diff --git a/infrastructure/lambda-authoriser.tf b/infrastructure/lambda-authoriser.tf index f4296d949..48c97563b 100644 --- a/infrastructure/lambda-authoriser.tf +++ b/infrastructure/lambda-authoriser.tf @@ -46,7 +46,7 @@ module "authoriser-alarm" { module "authoriser-alarm-topic" { source = "./modules/sns" sns_encryption_key_id = module.sns_encryption_key.id - topic_name = "create_doc-alarms-topic" + topic_name = "authoriser-alarms-topic" topic_protocol = "lambda" topic_endpoint = module.authoriser-lambda.lambda_arn delivery_policy = jsonencode({ diff --git a/infrastructure/lambda-create-doc-ref.tf b/infrastructure/lambda-create-doc-ref.tf index 9764b0eb6..5c7e30ab4 100644 --- a/infrastructure/lambda-create-doc-ref.tf +++ b/infrastructure/lambda-create-doc-ref.tf @@ -1,15 +1,3 @@ -module "create_document_reference_gateway" { - source = "./modules/gateway" - api_gateway_id = aws_api_gateway_rest_api.ndr_doc_store_api.id - parent_id = aws_api_gateway_rest_api.ndr_doc_store_api.root_resource_id - http_methods = ["POST"] - authorization = "CUSTOM" - gateway_path = "CreateDocumentReference" - authorizer_id = aws_api_gateway_authorizer.repo_authoriser.id - require_credentials = true - origin = contains(["prod"], terraform.workspace) ? "'https://${var.domain}'" : "'https://${terraform.workspace}.${var.domain}'" -} - module "create_doc_alarm" { source = "./modules/lambda_alarms" lambda_function_name = module.create-doc-ref-lambda.function_name @@ -73,7 +61,7 @@ module "create-doc-ref-lambda" { ] kms_deletion_window = var.kms_deletion_window rest_api_id = aws_api_gateway_rest_api.ndr_doc_store_api.id - resource_id = module.create_document_reference_gateway.gateway_resource_id + resource_id = module.document_reference_gateway.gateway_resource_id http_methods = ["POST"] memory_size = 512 @@ -92,7 +80,7 @@ module "create-doc-ref-lambda" { PRESIGNED_ASSUME_ROLE = aws_iam_role.create_post_presign_url_role.arn } depends_on = [ - module.create_document_reference_gateway, + module.document_reference_gateway, aws_api_gateway_rest_api.ndr_doc_store_api, module.document_reference_dynamodb_table, module.lloyd_george_reference_dynamodb_table, diff --git a/infrastructure/lambda-update-doc-ref.tf b/infrastructure/lambda-update-doc-ref.tf new file mode 100644 index 000000000..974353dd3 --- /dev/null +++ b/infrastructure/lambda-update-doc-ref.tf @@ -0,0 +1,87 @@ +module "update_doc_ref_alarm" { + source = "./modules/lambda_alarms" + lambda_function_name = module.update_doc_ref_lambda.function_name + lambda_timeout = module.update_doc_ref_lambda.timeout + lambda_name = "update_document_reference_handler" + namespace = "AWS/Lambda" + alarm_actions = [module.update_doc_ref_alarm_topic.arn] + ok_actions = [module.update_doc_ref_alarm_topic.arn] + depends_on = [module.update_doc_ref_lambda, module.update_doc_ref_alarm_topic] +} + + +module "update_doc_ref_alarm_topic" { + source = "./modules/sns" + sns_encryption_key_id = module.sns_encryption_key.id + topic_name = "update_doc-alarms-topic" + topic_protocol = "lambda" + topic_endpoint = module.update_doc_ref_lambda.lambda_arn + depends_on = [module.sns_encryption_key] + delivery_policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + "Effect" : "Allow", + "Principal" : { + "Service" : "cloudwatch.amazonaws.com" + }, + "Action" : [ + "SNS:Publish", + ], + "Condition" : { + "ArnLike" : { + "aws:SourceArn" : "arn:aws:cloudwatch:eu-west-2:${data.aws_caller_identity.current.account_id}:alarm:*" + } + } + "Resource" : "*" + } + ] + }) +} + +module "update_doc_ref_lambda" { + source = "./modules/lambda" + name = "UpdateDocRefLambda" + handler = "handlers.update_document_reference_handler.lambda_handler" + iam_role_policy_documents = [ + module.ndr-bulk-staging-store.s3_write_policy_document, + module.ndr-lloyd-george-store.s3_write_policy_document, + module.ndr-lloyd-george-store.s3_read_policy_document, + module.ndr-document-store.s3_read_policy_document, + module.ndr-document-store.s3_write_policy_document, + module.lloyd_george_reference_dynamodb_table.dynamodb_write_policy_document, + module.lloyd_george_reference_dynamodb_table.dynamodb_read_policy_document, + aws_iam_policy.ssm_access_policy.policy, + module.ndr-app-config.app_config_policy, + ] + kms_deletion_window = var.kms_deletion_window + rest_api_id = aws_api_gateway_rest_api.ndr_doc_store_api.id + resource_id = module.document_reference_id_gateway.gateway_resource_id + http_methods = ["PUT"] + memory_size = 512 + + api_execution_arn = aws_api_gateway_rest_api.ndr_doc_store_api.execution_arn + lambda_environment_variables = { + STAGING_STORE_BUCKET_NAME = module.ndr-bulk-staging-store.bucket_id + APPCONFIG_APPLICATION = module.ndr-app-config.app_config_application_id + APPCONFIG_ENVIRONMENT = module.ndr-app-config.app_config_environment_id + APPCONFIG_CONFIGURATION = module.ndr-app-config.app_config_configuration_profile_id + DOCUMENT_STORE_BUCKET_NAME = module.ndr-document-store.bucket_id + DOCUMENT_STORE_DYNAMODB_NAME = module.document_reference_dynamodb_table.table_name + LLOYD_GEORGE_DYNAMODB_NAME = module.lloyd_george_reference_dynamodb_table.table_name + STITCH_METADATA_DYNAMODB_NAME = module.stitch_metadata_reference_dynamodb_table.table_name + PDS_FHIR_IS_STUBBED = local.is_sandbox, + WORKSPACE = terraform.workspace + PRESIGNED_ASSUME_ROLE = aws_iam_role.update_put_presign_url_role.arn + } + depends_on = [ + module.document_reference_gateway, + aws_api_gateway_rest_api.ndr_doc_store_api, + module.document_reference_dynamodb_table, + module.lloyd_george_reference_dynamodb_table, + module.ndr-bulk-staging-store, + module.ndr-document-store, + module.ndr-app-config, + module.stitch_metadata_reference_dynamodb_table + ] +} diff --git a/infrastructure/modules/app_config/configurations/dev.json b/infrastructure/modules/app_config/configurations/dev.json index 69ed92b64..6e83b3d1d 100644 --- a/infrastructure/modules/app_config/configurations/dev.json +++ b/infrastructure/modules/app_config/configurations/dev.json @@ -14,6 +14,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "name": "lloydGeorgeValidationStrictModeEnabled" + }, + "uploadDocumentIteration2Enabled": { + "name": "uploadDocumentIteration2Enabled" + }, + "uploadDocumentIteration3Enabled": { + "name": "uploadDocumentIteration3Enabled" } }, "values": { @@ -31,6 +37,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "enabled": "true" + }, + "uploadDocumentIteration2Enabled": { + "enabled": "true" + }, + "uploadDocumentIteration3Enabled": { + "enabled": "true" } }, "version": "1" diff --git a/infrastructure/modules/app_config/configurations/pre-prod.json b/infrastructure/modules/app_config/configurations/pre-prod.json index 601740b58..db6fe63c3 100644 --- a/infrastructure/modules/app_config/configurations/pre-prod.json +++ b/infrastructure/modules/app_config/configurations/pre-prod.json @@ -14,6 +14,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "name": "lloydGeorgeValidationStrictModeEnabled" + }, + "uploadDocumentIteration2Enabled": { + "name": "uploadDocumentIteration2Enabled" + }, + "uploadDocumentIteration3Enabled": { + "name": "uploadDocumentIteration3Enabled" } }, "values": { @@ -31,6 +37,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "enabled": "true" + }, + "uploadDocumentIteration2Enabled": { + "enabled": "false" + }, + "uploadDocumentIteration3Enabled": { + "enabled": "false" } }, "version": "1" diff --git a/infrastructure/modules/app_config/configurations/prod.json b/infrastructure/modules/app_config/configurations/prod.json index 601740b58..db6fe63c3 100644 --- a/infrastructure/modules/app_config/configurations/prod.json +++ b/infrastructure/modules/app_config/configurations/prod.json @@ -14,6 +14,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "name": "lloydGeorgeValidationStrictModeEnabled" + }, + "uploadDocumentIteration2Enabled": { + "name": "uploadDocumentIteration2Enabled" + }, + "uploadDocumentIteration3Enabled": { + "name": "uploadDocumentIteration3Enabled" } }, "values": { @@ -31,6 +37,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "enabled": "true" + }, + "uploadDocumentIteration2Enabled": { + "enabled": "false" + }, + "uploadDocumentIteration3Enabled": { + "enabled": "false" } }, "version": "1" diff --git a/infrastructure/modules/app_config/configurations/sandbox.json b/infrastructure/modules/app_config/configurations/sandbox.json index 69ed92b64..6e83b3d1d 100644 --- a/infrastructure/modules/app_config/configurations/sandbox.json +++ b/infrastructure/modules/app_config/configurations/sandbox.json @@ -14,6 +14,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "name": "lloydGeorgeValidationStrictModeEnabled" + }, + "uploadDocumentIteration2Enabled": { + "name": "uploadDocumentIteration2Enabled" + }, + "uploadDocumentIteration3Enabled": { + "name": "uploadDocumentIteration3Enabled" } }, "values": { @@ -31,6 +37,12 @@ }, "lloydGeorgeValidationStrictModeEnabled": { "enabled": "true" + }, + "uploadDocumentIteration2Enabled": { + "enabled": "true" + }, + "uploadDocumentIteration3Enabled": { + "enabled": "true" } }, "version": "1" diff --git a/infrastructure/modules/gateway/main.tf b/infrastructure/modules/gateway/main.tf index c43737594..43865f11a 100644 --- a/infrastructure/modules/gateway/main.tf +++ b/infrastructure/modules/gateway/main.tf @@ -13,13 +13,14 @@ resource "aws_api_gateway_method" "preflight_method" { } resource "aws_api_gateway_method" "proxy_method" { - for_each = toset(var.http_methods) - rest_api_id = var.api_gateway_id - resource_id = aws_api_gateway_resource.gateway_resource.id - http_method = each.key - authorization = var.authorization - authorizer_id = var.authorizer_id - api_key_required = var.api_key_required + for_each = toset(var.http_methods) + rest_api_id = var.api_gateway_id + resource_id = aws_api_gateway_resource.gateway_resource.id + http_method = each.key + authorization = var.authorization + authorizer_id = var.authorizer_id + api_key_required = var.api_key_required + request_parameters = var.request_parameters } resource "aws_api_gateway_method_response" "preflight_method_response" { diff --git a/infrastructure/modules/gateway/variable.tf b/infrastructure/modules/gateway/variable.tf index 7ffb50f0e..05f6a6590 100644 --- a/infrastructure/modules/gateway/variable.tf +++ b/infrastructure/modules/gateway/variable.tf @@ -45,3 +45,9 @@ variable "api_key_required" { type = bool default = false } + +variable "request_parameters" { + description = "Request parameters for the API Gateway method." + type = map(string) + default = {} +} \ No newline at end of file diff --git a/infrastructure/moved-resources.tf b/infrastructure/moved-resources.tf index 06e9f4e17..8b3b6181b 100644 --- a/infrastructure/moved-resources.tf +++ b/infrastructure/moved-resources.tf @@ -1,8 +1,3 @@ -moved { - from = module.document_reference_gateway - to = module.create_document_reference_gateway -} - #PRME-125 moved { from = module.upload_confirm_result_gateway @@ -82,3 +77,9 @@ moved { from = module.get-doc-fhir-lambda[0].aws_lambda_permission.lambda_permission[0] to = module.get-doc-fhir-lambda.aws_lambda_permission.lambda_permission[0] } + +#PRMP-166 +moved { + from = module.create_document_reference_gateway + to = module.document_reference_gateway +} \ No newline at end of file