diff --git a/.github/workflows/automated-deploy-stack.yml b/.github/workflows/automated-deploy-stack.yml index 6f34935d..761e1810 100644 --- a/.github/workflows/automated-deploy-stack.yml +++ b/.github/workflows/automated-deploy-stack.yml @@ -72,7 +72,7 @@ jobs: echo "changed=$changed" >> $GITHUB_OUTPUT deductions-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/mesh-forwarder') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: contains(needs.get-changed-files.outputs.changed, 'stacks/deductions') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') name: Deductions Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files] @@ -109,7 +109,12 @@ jobs: secrets: inherit mesh-forwarder-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/mesh-forwarder') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/mesh-forwarder') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: MESH Forwarder Infrastructure needs: [get-changed-files, deductions-ci, deductions-cross-account] uses: ./.github/workflows/deploy-stack.yml @@ -121,7 +126,12 @@ jobs: secrets: inherit pds-adaptor-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/pds-adaptor') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/pds-adaptor') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: PDS Adaptor Infrastructure needs: [get-changed-files, deductions-ci, deductions-cross-account] uses: ./.github/workflows/deploy-stack.yml @@ -133,7 +143,12 @@ jobs: secrets: inherit re-registration-service-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/re-registration-service') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/re-registration-service') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: Re-Registration Service Infrastructure needs: [get-changed-files, deductions-ci, deductions-cross-account] uses: ./.github/workflows/deploy-stack.yml @@ -145,7 +160,12 @@ jobs: secrets: inherit suspension-service-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/suspension-service') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/suspension-service') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: Suspension Service Infrastructure needs: [get-changed-files, deductions-ci, deductions-cross-account] uses: ./.github/workflows/deploy-stack.yml @@ -154,10 +174,16 @@ jobs: ecr_alias: repo/suspension-service environment: dev is_deployment: ${{ github.ref == 'refs/heads/main' }} + is_end_of_transfer: ${{ contains(needs.get-changed-files.outputs.changed, 'end-of-transfer') }} secrets: inherit nems-event-processor-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/nems-event-processor') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/nems-event-processor') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: NEMS Event Processor Infrastructure needs: [get-changed-files, deductions-ci, deductions-cross-account] uses: ./.github/workflows/deploy-stack.yml @@ -169,7 +195,12 @@ jobs: secrets: inherit ehr-repo-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-repo') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-repo') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: EHR Repo Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files, deductions-ci, deductions-cross-account] @@ -181,7 +212,10 @@ jobs: secrets: inherit ehr-repo-db-roles-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-repo') || contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-repo-db-roles') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-repo') || contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-repo-db-roles') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: EHR Repo DB Roles Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files, deductions-ci, ehr-repo-ci] @@ -193,7 +227,11 @@ jobs: secrets: inherit ehr-out-service-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-out-service') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-out-service') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: EHR Out Service Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files, deductions-ci, deductions-cross-account] @@ -205,7 +243,12 @@ jobs: secrets: inherit ehr-transfer-service-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-transfer-service') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + contains(needs.get-changed-files.outputs.changed, 'stacks/ehr-transfer-service') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') name: EHR Transfer Service Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files, deductions-ci, deductions-cross-account] @@ -217,7 +260,12 @@ jobs: secrets: inherit gp2gp-messenger-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/gp2gp-messenger') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/gp2gp-messenger') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: GP2GP Messenger Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files, deductions-ci, deductions-cross-account] @@ -229,7 +277,12 @@ jobs: secrets: inherit mhs-ci: - if: contains(needs.get-changed-files.outputs.changed, 'stacks/mhs') || contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml') + if: | + always() && + (needs.deductions-ci.result == 'success' || needs.deductions-ci.result == 'skipped') && + (needs.deductions-cross-account.result == 'success'|| needs.deductions-cross-account.result == 'skipped') && + (contains(needs.get-changed-files.outputs.changed, 'stacks/mhs') || + contains(needs.get-changed-files.outputs.changed, '.github/workflows/automated-deploy-stack.yml')) name: MHS Infrastructure CI uses: ./.github/workflows/deploy-stack.yml needs: [get-changed-files, deductions-ci, deductions-cross-account] diff --git a/.github/workflows/deploy-stack.yml b/.github/workflows/deploy-stack.yml index c61cfc46..1074ff96 100644 --- a/.github/workflows/deploy-stack.yml +++ b/.github/workflows/deploy-stack.yml @@ -42,6 +42,10 @@ on: workflow_call: inputs: + is_end_of_transfer: + default: false + type: boolean + description: "Is this the end of transfer deployment?" environment: default: dev description: "Environment to deploy to" @@ -139,6 +143,7 @@ jobs: environment: ${{ !inputs.ci_account && inputs.environment || 'ci_account' }} env: GITHUB_ENV: ${{ !inputs.ci_account && inputs.environment || 'ci_account' }} + IS_END_OF_TRANSFER: ${{ inputs.is_end_of_transfer }} runs-on: ubuntu-latest needs: [promote-images-from-source-ecr-account] if: always() && (needs.promote-images-from-source-ecr-account.result == 'skipped' || needs.promote-images-from-source-ecr-account.result == 'success') @@ -248,6 +253,9 @@ jobs: KEY="${STACK}-$ENV" fi fi + if [ '$IS_END_OF_TRANSFER' == 'true' ]; then + KEY="end-of-transfer-service-$ENV" + fi echo "Using backend key: $KEY/terraform.tfstate" terraform init -no-color \ diff --git a/stacks/deductions-dashboard/terraform/dashboard_repository.tf b/stacks/deductions-dashboard/terraform/dashboard_repository.tf index 2be8c823..6a2498e2 100644 --- a/stacks/deductions-dashboard/terraform/dashboard_repository.tf +++ b/stacks/deductions-dashboard/terraform/dashboard_repository.tf @@ -118,6 +118,14 @@ locals { { name = "${var.environment}-ehr-transfer-service-ehr-complete-observability" title = "EHR Complete Observability Queue" + }, + { + name = "${var.environment}-end-of-transfer-service-transfer-complete" + title = "Transfer Complete Queue" + }, + { + name = "${var.environment}-end-of-transfer-service-transfer-complete-observability" + title = "Transfer Complete Observability Queue" } ] @@ -131,6 +139,11 @@ locals { title = "EHR Transfer Service" } + end_of_transfer_service = { + name = "end-of-transfer-service" + title = "End of Transfer Service" + } + ehr_repo = { name = "ehr-repo" title = "EHR Repository Service" @@ -162,6 +175,7 @@ locals { repo_task_widget_components = [ local.re_registration_service, local.ehr_transfer_service, + local.end_of_transfer_service, local.ehr_repo, local.gp2gp_messenger, local.mhs_inbound, @@ -190,6 +204,7 @@ module "repo_error_count_widgets" { for_each = { re_registration_service = local.re_registration_service ehr_transfer_service = local.ehr_transfer_service + end_of_transfer_service = local.end_of_transfer_service gp2gp_messenger = local.gp2gp_messenger ehr_repo = local.ehr_repo mhs_inbound = local.mhs_inbound @@ -203,6 +218,7 @@ module "repo_health_widgets" { for_each = { re_registration_service = local.re_registration_service ehr_transfer_service = local.ehr_transfer_service + end_of_transfer_service = local.end_of_transfer_service } source = "./widgets/health_widget" component = each.value diff --git a/stacks/deductions/terraform/backups-cross-account.tf b/stacks/deductions/terraform/backups-cross-account.tf index c971d603..c9976047 100644 --- a/stacks/deductions/terraform/backups-cross-account.tf +++ b/stacks/deductions/terraform/backups-cross-account.tf @@ -60,6 +60,7 @@ resource "aws_backup_selection" "cross_account" { data.aws_s3_bucket.ehr_repo_bucket.arn, data.aws_s3_bucket.ehr_repo_access_logs.arn, data.aws_dynamodb_table.ehr_transfer_service_transfer_tracker.arn, + data.aws_dynamodb_table.end_of_transfer_service_dynamodb.arn, data.aws_dynamodb_table.re_registration_service_active_suspensions.arn, data.aws_dynamodb_table.repo_mhs_state.arn, data.aws_dynamodb_table.repo_mhs_sync_async_state.arn, diff --git a/stacks/deductions/terraform/data.tf b/stacks/deductions/terraform/data.tf index ca4f9db7..b454549a 100644 --- a/stacks/deductions/terraform/data.tf +++ b/stacks/deductions/terraform/data.tf @@ -32,6 +32,10 @@ data "aws_dynamodb_table" "ehr_transfer_service_transfer_tracker" { name = "${var.environment}-ehr-transfer-service-transfer-tracker" } +data "aws_dynamodb_table" "end_of_transfer_service_dynamodb" { + name = "${var.environment}-end-of-transfer-service-dynamodb" +} + data "aws_dynamodb_table" "re_registration_service_active_suspensions" { name = "${var.environment}-re-registration-service-active-suspensions" } diff --git a/stacks/ehr-transfer-service/terraform/iam.tf b/stacks/ehr-transfer-service/terraform/iam.tf index d77b9a54..91b84c5e 100644 --- a/stacks/ehr-transfer-service/terraform/iam.tf +++ b/stacks/ehr-transfer-service/terraform/iam.tf @@ -569,11 +569,6 @@ resource "aws_iam_role_policy_attachment" "ecs_role_s3_large_bucket_policy_attac policy_arn = aws_iam_policy.sqs_large_message_bucket_access_policy.arn } -resource "aws_sqs_queue_policy" "repo_incoming" { - queue_url = aws_sqs_queue.repo_incoming.id - policy = data.aws_iam_policy_document.repo_incoming_topic_access_to_queue.json -} - resource "aws_sqs_queue_policy" "splunk_audit_uploader_access_policy" { queue_url = aws_sqs_queue.ehr_transfer_service_audit_uploader.id policy = data.aws_iam_policy_document.splunk_uploader_sns_topic_access_to_queue.json diff --git a/stacks/ehr-transfer-service/terraform/queue.tf b/stacks/ehr-transfer-service/terraform/queue.tf index dde4a005..451620e8 100644 --- a/stacks/ehr-transfer-service/terraform/queue.tf +++ b/stacks/ehr-transfer-service/terraform/queue.tf @@ -21,20 +21,6 @@ locals { thirty_minute_retention_period = 1800 } -resource "aws_sqs_queue" "repo_incoming" { - name = local.repo_incoming_queue_name - message_retention_seconds = local.max_retention_period - kms_master_key_id = data.aws_ssm_parameter.repo_incoming_kms_key.value - receive_wait_time_seconds = 20 - visibility_timeout_seconds = 43200 - - tags = { - Name = local.repo_incoming_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - resource "aws_sqs_queue" "negative_acks" { name = local.negative_acks_queue_name message_retention_seconds = local.max_retention_period diff --git a/stacks/pds-adaptor/terraform/data.tf b/stacks/pds-adaptor/terraform/data.tf index c3f86e01..254539e8 100644 --- a/stacks/pds-adaptor/terraform/data.tf +++ b/stacks/pds-adaptor/terraform/data.tf @@ -40,6 +40,10 @@ data "aws_ssm_parameter" "suspension-service-ecs-sg-id" { name = "/repo/${var.environment}/output/suspension-service/ecs-sg-id" } +data "aws_ssm_parameter" "end-for-transfer-service-ecs-sg-id" { + name = "/repo/${var.environment}/output/end-of-transfer-service/ecs-sg-id" +} + data "aws_ssm_parameter" "re-registration-ecs-sg-id" { name = "/repo/${var.environment}/output/re-registration-service/ecs-sg-id" } \ No newline at end of file diff --git a/stacks/re-registration-service/terraform/data.tf b/stacks/re-registration-service/terraform/data.tf index 7c3ec8a7..99cae023 100644 --- a/stacks/re-registration-service/terraform/data.tf +++ b/stacks/re-registration-service/terraform/data.tf @@ -55,3 +55,7 @@ data "aws_ssm_parameter" "active_suspensions_kms_key_id" { data "aws_ssm_parameter" "suspension_active_suspensions_topic_arn" { name = "/repo/${var.environment}/output/suspension-service/active-suspensions-topic-arn" } + +data "aws_ssm_parameter" "end_of_transfer_active_suspensions_topic_arn" { + name = "/repo/${var.environment}/output/end-of-transfer-service/active-suspensions-topic-arn" +} \ No newline at end of file diff --git a/stacks/re-registration-service/terraform/iam.tf b/stacks/re-registration-service/terraform/iam.tf index 067e99a5..9379385f 100644 --- a/stacks/re-registration-service/terraform/iam.tf +++ b/stacks/re-registration-service/terraform/iam.tf @@ -271,6 +271,7 @@ data "aws_iam_policy_document" "active_suspensions_sns_topic_access_to_queue" { test = "ArnEquals" values = [ data.aws_ssm_parameter.suspension_active_suspensions_topic_arn.value, + data.aws_ssm_parameter.end_of_transfer_active_suspensions_topic_arn.value ] variable = "aws:SourceArn" } diff --git a/stacks/re-registration-service/terraform/topic-subscriptions.tf b/stacks/re-registration-service/terraform/topic-subscriptions.tf index b713186f..49b7ab4b 100644 --- a/stacks/re-registration-service/terraform/topic-subscriptions.tf +++ b/stacks/re-registration-service/terraform/topic-subscriptions.tf @@ -11,3 +11,10 @@ resource "aws_sns_topic_subscription" "suspension_active_suspensions" { topic_arn = data.aws_ssm_parameter.suspension_active_suspensions_topic_arn.value endpoint = aws_sqs_queue.active_suspensions.arn } + +resource "aws_sns_topic_subscription" "end_of_transfer_active_suspensions" { + protocol = "sqs" + raw_message_delivery = true + topic_arn = data.aws_ssm_parameter.end_of_transfer_active_suspensions_topic_arn.value + endpoint = aws_sqs_queue.active_suspensions.arn +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/cloudwatch.tf b/stacks/suspension-service/terraform/cloudwatch.tf index afcf762d..5334b0af 100644 --- a/stacks/suspension-service/terraform/cloudwatch.tf +++ b/stacks/suspension-service/terraform/cloudwatch.tf @@ -7,161 +7,4 @@ locals { sns_topic_error_logs_metric_name = "NumberOfNotificationsFailed" } -resource "aws_cloudwatch_log_group" "log_group" { - name = "/nhs/deductions/${var.environment}-${data.aws_caller_identity.current.account_id}/${var.component_name}" - tags = { - Environment = var.environment - CreatedBy = var.repo_name - } -} - -resource "aws_cloudwatch_log_metric_filter" "log_metric_filter" { - name = "${var.environment}-${var.component_name}-error-logs" - pattern = "{ $.level = \"ERROR\" }" - log_group_name = aws_cloudwatch_log_group.log_group.name - - metric_transformation { - name = local.error_logs_metric_name - namespace = local.suspension_service_metric_namespace - value = 1 - default_value = 0 - } -} - -resource "aws_cloudwatch_metric_alarm" "error_log_alarm" { - alarm_name = "${var.environment}-${var.component_name}-error-logs" - comparison_operator = "GreaterThanThreshold" - threshold = "0" - evaluation_periods = "1" - period = "60" - metric_name = local.error_logs_metric_name - namespace = local.suspension_service_metric_namespace - statistic = "Sum" - alarm_description = "This alarm monitors errors logs in ${var.component_name}" - treat_missing_data = "notBreaching" - actions_enabled = "true" - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "not_suspended_sns_topic_error_log_alarm" { - alarm_name = "${local.not_suspended_sns_topic_name}-error-logs" - comparison_operator = "GreaterThanThreshold" - threshold = "0" - evaluation_periods = "1" - period = "60" - metric_name = local.sns_topic_error_logs_metric_name - namespace = local.sns_topic_namespace - dimensions = { - TopicName = local.not_suspended_sns_topic_name - } - statistic = "Sum" - alarm_description = "This alarm monitors errors logs in ${local.not_suspended_sns_topic_name}" - treat_missing_data = "notBreaching" - actions_enabled = "true" - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "suspension_out_of_order_audit" { - alarm_name = "${var.environment}-${var.component_name}-out-of-order-audit" - comparison_operator = "GreaterThanThreshold" - threshold = "900" - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "This alarm triggers when messages on the out of order audit queue is not polled by splunk in last 15 mins" - statistic = "Maximum" - period = "900" - dimensions = { - QueueName = aws_sqs_queue.event_out_of_order_audit.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "suspension_not_suspended_audit" { - alarm_name = "${var.environment}-${var.component_name}-not-suspended-audit" - comparison_operator = "GreaterThanThreshold" - threshold = "900" - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "This alarm triggers when messages on the not suspended audit queue is not polled by splunk in last 15 mins" - statistic = "Maximum" - period = "900" - dimensions = { - QueueName = aws_sqs_queue.not_suspended_audit.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "suspension_mof_not_updated_audit" { - alarm_name = "${var.environment}-${var.component_name}-mof-not-updated-audit" - comparison_operator = "GreaterThanThreshold" - threshold = "900" - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "This alarm triggers when messages on the MOF not updated audit queue is not polled by splunk in last 15 mins" - statistic = "Maximum" - period = "900" - dimensions = { - QueueName = aws_sqs_queue.mof_not_updated_audit.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "suspension_mof_updated_audit" { - alarm_name = "${var.environment}-${var.component_name}-mof-updated-audit" - comparison_operator = "GreaterThanThreshold" - threshold = "900" - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "This alarm triggers when messages on the MOF updated audit queue is not polled by splunk in last 15 mins" - statistic = "Maximum" - period = "900" - dimensions = { - QueueName = aws_sqs_queue.mof_updated_audit.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "suspension_deceased_patient_audit" { - alarm_name = "${var.environment}-${var.component_name}-deceased-patient-audit" - comparison_operator = "GreaterThanThreshold" - threshold = "900" - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "This alarm triggers when messages on the deceased patient audit queue is not polled by splunk in last 15 mins" - statistic = "Maximum" - period = "900" - dimensions = { - QueueName = aws_sqs_queue.deceased_patient_audit.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -resource "aws_cloudwatch_metric_alarm" "suspension_invalid_suspension_dlq_audit" { - alarm_name = "${var.environment}-${var.component_name}-invalid-suspension-dlq-audit" - comparison_operator = "GreaterThanThreshold" - threshold = "900" - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "This alarm triggers when messages on the invalid suspensions dlq audit queue is not polled by splunk in last 15 mins" - statistic = "Maximum" - period = "900" - dimensions = { - QueueName = aws_sqs_queue.invalid_suspension_audit.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} diff --git a/stacks/suspension-service/terraform/configs/end-of-transfer-service/dev.tfvars b/stacks/suspension-service/terraform/configs/end-of-transfer-service/dev.tfvars new file mode 100644 index 00000000..dd131f70 --- /dev/null +++ b/stacks/suspension-service/terraform/configs/end-of-transfer-service/dev.tfvars @@ -0,0 +1,7 @@ +environment = "dev" + +synthetic_patient_prefix = "96937" +process_only_synthetic_patients = false + +ecs_desired_count = 0 +repo_process_only_safe_listed_ods_codes = true \ No newline at end of file diff --git a/stacks/suspension-service/terraform/configs/end-of-transfer-service/end-of-transfer-service.tfvars b/stacks/suspension-service/terraform/configs/end-of-transfer-service/end-of-transfer-service.tfvars new file mode 100644 index 00000000..472a04cf --- /dev/null +++ b/stacks/suspension-service/terraform/configs/end-of-transfer-service/end-of-transfer-service.tfvars @@ -0,0 +1,6 @@ +component_name = "end-of-transfer-service" +repo_name = "end-of-transfer-service" +metric_namespace = "EndOfTransferService" + +can_update_managing_organisation_to_repo = false +is_end_of_transfer_service = true diff --git a/stacks/suspension-service/terraform/configs/end-of-transfer-service/pre-prod.tfvars b/stacks/suspension-service/terraform/configs/end-of-transfer-service/pre-prod.tfvars new file mode 100644 index 00000000..086abfd2 --- /dev/null +++ b/stacks/suspension-service/terraform/configs/end-of-transfer-service/pre-prod.tfvars @@ -0,0 +1,6 @@ +environment = "pre-prod" + +synthetic_patient_prefix = "96936" +process_only_synthetic_patients = true + +ecs_desired_count = 0 \ No newline at end of file diff --git a/stacks/suspension-service/terraform/configs/end-of-transfer-service/prod.tfvars b/stacks/suspension-service/terraform/configs/end-of-transfer-service/prod.tfvars new file mode 100644 index 00000000..fe701190 --- /dev/null +++ b/stacks/suspension-service/terraform/configs/end-of-transfer-service/prod.tfvars @@ -0,0 +1,6 @@ +environment = "prod" + +synthetic_patient_prefix = "999" +process_only_synthetic_patients = true + +ecs_desired_count = 0 \ No newline at end of file diff --git a/stacks/suspension-service/terraform/configs/suspension-service/suspension-service.tfvars b/stacks/suspension-service/terraform/configs/suspension-service/suspension-service.tfvars index ba2964c4..6f43650f 100644 --- a/stacks/suspension-service/terraform/configs/suspension-service/suspension-service.tfvars +++ b/stacks/suspension-service/terraform/configs/suspension-service/suspension-service.tfvars @@ -1,3 +1,5 @@ component_name = "suspension-service" repo_name = "suspension-service" metric_namespace = "SuspensionService" + +is_end_of_transfer_service = false diff --git a/stacks/suspension-service/terraform/dev.tfvars b/stacks/suspension-service/terraform/dev.tfvars index b5968e04..874c1f2d 100644 --- a/stacks/suspension-service/terraform/dev.tfvars +++ b/stacks/suspension-service/terraform/dev.tfvars @@ -1,8 +1,13 @@ -environment = "dev" -synthetic_patient_prefix = "96937" -component_name = "suspension-service" -repo_name = "suspension-service" -metric_namespace = "SuspensionService" -can_update_managing_organisation_to_repo = true -repo_process_only_safe_listed_ods_codes = true -process_only_synthetic_patients = false \ No newline at end of file +environment = "dev" + +synthetic_patient_prefix = "96937" +process_only_synthetic_patients = false + +ecs_desired_count = 0 +repo_process_only_safe_listed_ods_codes = true +component_name = "end-of-transfer-service" +repo_name = "end-of-transfer-service" +metric_namespace = "EndOfTransferService" + +can_update_managing_organisation_to_repo = false +is_end_of_transfer_service = true diff --git a/stacks/suspension-service/terraform/ecs-task.tf b/stacks/suspension-service/terraform/ecs-task.tf index 3a971052..1a37f219 100644 --- a/stacks/suspension-service/terraform/ecs-task.tf +++ b/stacks/suspension-service/terraform/ecs-task.tf @@ -9,10 +9,8 @@ locals { { name = "NHS_ENVIRONMENT", value = var.environment }, { name = "AWS_REGION", value = var.region }, { name = "LOG_LEVEL", value = var.log_level }, - { name = "INCOMING_QUEUE_NAME", value = module.suspension-service.suspension_queue_name }, + { name = "INCOMING_QUEUE_NAME", value = var.is_end_of_transfer_service ? module.end-of-transfer-service[0].transfer_complete_queue_name : module.suspension-service.suspension_queue_name }, { name = "NOT_SUSPENDED_SNS_TOPIC_ARN", value = aws_sns_topic.not_suspended.arn }, - { name = "NOT_SUSPENDED_QUEUE_NAME", value = aws_sqs_queue.not_suspended_observability.name }, - { name = "MOF_UPDATED_SNS_TOPIC_ARN", value = aws_sns_topic.mof_updated.arn }, { name = "ACTIVE_SUSPENSIONS_SNS_TOPIC_ARN", value = aws_sns_topic.active_suspensions.arn }, { name = "MOF_NOT_UPDATED_SNS_TOPIC_ARN", value = aws_sns_topic.mof_not_updated.arn }, { name = "EVENT_OUT_OF_ORDER_SNS_TOPIC_ARN", value = aws_sns_topic.event_out_of_order.arn }, @@ -22,7 +20,6 @@ locals { value = aws_sns_topic.invalid_suspension_audit_topic.arn }, { name = "DECEASED_PATIENT_SNS_TOPIC_ARN", value = aws_sns_topic.deceased_patient.arn }, - { name = "REPO_INCOMING_SNS_TOPIC_ARN", value = module.suspension-service.repo_incoming_sns_topic }, { name = "PDS_ADAPTOR_SUSPENSION_SERVICE_PASSWORD", value = data.aws_ssm_parameter.pds_adaptor_auth_key.value }, { name = "PROCESS_ONLY_SYNTHETIC_PATIENTS", value = tostring(var.process_only_synthetic_patients) }, { name = "SYNTHETIC_PATIENT_PREFIX", value = var.synthetic_patient_prefix }, diff --git a/stacks/suspension-service/terraform/iam.tf b/stacks/suspension-service/terraform/iam.tf index 2344c417..ea78b108 100644 --- a/stacks/suspension-service/terraform/iam.tf +++ b/stacks/suspension-service/terraform/iam.tf @@ -10,8 +10,8 @@ locals { aws_sns_topic.event_out_of_order.arn, aws_sns_topic.active_suspensions.arn, ] - sns_for_suspension_service = module.suspension-service.repo_incoming_sns_topic - sns_arns = concat(local.sns_base_arns, [local.sns_for_suspension_service]) + sns_for_suspension_service = [module.end-of-transfer-service[0].end_of_transfer_sns_topic] + sns_arns = concat(local.sns_base_arns, local.sns_for_suspension_service) } data "aws_iam_policy_document" "ecs-assume-role-policy" { @@ -107,16 +107,7 @@ data "aws_iam_policy_document" "sqs_suspensions_ecs_task" { ] # TODO: double check what queues should be here resources = [ - module.suspension-service.suspension_queue_arn, - aws_sqs_queue.not_suspended_observability.arn, - aws_sqs_queue.mof_updated.arn, - aws_sqs_queue.mof_not_updated.arn, - aws_sqs_queue.invalid_suspension.arn, - aws_sqs_queue.invalid_suspension_audit.arn, - aws_sqs_queue.not_suspended_audit.arn, - aws_sqs_queue.mof_not_updated_audit.arn, - aws_sqs_queue.mof_updated_audit.arn, - aws_sqs_queue.deceased_patient.arn + var.is_end_of_transfer_service ? module.end-of-transfer-service[0].transfer_complete_queue_arn : module.suspension-service.suspension_queue_arn, ] } } @@ -239,253 +230,6 @@ data "aws_iam_policy_document" "sns_service_assume_role_policy" { } } -resource "aws_sqs_queue_policy" "mof_updated_events_subscription" { - queue_url = aws_sqs_queue.mof_updated.id - policy = data.aws_iam_policy_document.mof_updated_events_policy_doc.json -} - -resource "aws_sqs_queue_policy" "mof_updated_events_audit_subscription" { - queue_url = aws_sqs_queue.mof_updated_audit.id - policy = data.aws_iam_policy_document.mof_updated_events_policy_doc.json -} - -resource "aws_sqs_queue_policy" "mof_not_updated_events_subscription" { - queue_url = aws_sqs_queue.mof_not_updated.id - policy = data.aws_iam_policy_document.mof_not_updated_events_policy_doc.json -} - -resource "aws_sqs_queue_policy" "mof_not_updated_events_audit_subscription" { - queue_url = aws_sqs_queue.mof_not_updated_audit.id - policy = data.aws_iam_policy_document.mof_not_updated_events_policy_doc.json -} - -resource "aws_sqs_queue_policy" "not_suspended_events_subscription" { - queue_url = aws_sqs_queue.not_suspended_observability.id - policy = data.aws_iam_policy_document.not_suspended_events_policy_doc.json -} - -resource "aws_sqs_queue_policy" "not_suspended_events_audit_subscription" { - queue_url = aws_sqs_queue.not_suspended_audit.id - policy = data.aws_iam_policy_document.not_suspended_events_policy_doc.json -} - -resource "aws_sqs_queue_policy" "invalid_suspension_subscription" { - queue_url = aws_sqs_queue.invalid_suspension.id - policy = data.aws_iam_policy_document.invalid_suspension_policy_doc.json -} - -resource "aws_sqs_queue_policy" "invalid_suspension_audit_subscription" { - queue_url = aws_sqs_queue.invalid_suspension_audit.id - policy = data.aws_iam_policy_document.invalid_suspension_audit_policy_doc.json -} - -resource "aws_sqs_queue_policy" "non_sensitive_deceased_subscription" { - queue_url = aws_sqs_queue.deceased_patient.id - policy = data.aws_iam_policy_document.non_sensitive_deceased_policy_doc.json -} - -resource "aws_sqs_queue_policy" "non_sensitive_deceased_audit_subscription" { - queue_url = aws_sqs_queue.deceased_patient_audit.id - policy = data.aws_iam_policy_document.non_sensitive_deceased_policy_doc.json -} - -resource "aws_sqs_queue_policy" "event_out_of_order_audit_subscription" { - queue_url = aws_sqs_queue.event_out_of_order_audit.id - policy = data.aws_iam_policy_document.event_out_of_order_policy_doc.json -} - -resource "aws_sqs_queue_policy" "event_out_of_order_observability_queue_subscription" { - queue_url = aws_sqs_queue.event_out_of_order_observability_queue.id - policy = data.aws_iam_policy_document.event_out_of_order_policy_doc.json -} - -data "aws_iam_policy_document" "not_suspended_events_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.not_suspended_observability.arn, - aws_sqs_queue.not_suspended_audit.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.not_suspended.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "mof_updated_events_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.mof_updated.arn, - aws_sqs_queue.mof_updated_audit.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.mof_updated.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "mof_not_updated_events_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.mof_not_updated.arn, - aws_sqs_queue.mof_not_updated_audit.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.mof_not_updated.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "invalid_suspension_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.invalid_suspension.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.invalid_suspension.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "invalid_suspension_audit_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.invalid_suspension_audit.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.invalid_suspension_audit_topic.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "non_sensitive_deceased_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.deceased_patient.arn, - aws_sqs_queue.deceased_patient_audit.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.deceased_patient.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "event_out_of_order_policy_doc" { - statement { - - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.event_out_of_order_observability_queue.arn, - aws_sqs_queue.event_out_of_order_audit.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.event_out_of_order.arn] - variable = "aws:SourceArn" - } - } -} - data "aws_iam_policy_document" "dynamodb-table-access" { statement { actions = [ diff --git a/stacks/suspension-service/terraform/main.tf b/stacks/suspension-service/terraform/main.tf index de1e9d18..9fe969b8 100644 --- a/stacks/suspension-service/terraform/main.tf +++ b/stacks/suspension-service/terraform/main.tf @@ -11,6 +11,17 @@ terraform { } } +module "end-of-transfer-service" { + count = 1 + source = "./modules/end-of-transfer-service/" + environment = var.environment + + component_name = var.component_name + metric_namespace = var.metric_namespace + repo_name = var.repo_name + ecs_desired_count = var.ecs_desired_count +} + module "suspension-service" { source = "./modules/suspension-service/" environment = var.environment diff --git a/stacks/suspension-service/terraform/modules/end-of-transfer-service/cloudwatch.tf b/stacks/suspension-service/terraform/modules/end-of-transfer-service/cloudwatch.tf new file mode 100644 index 00000000..0c709fae --- /dev/null +++ b/stacks/suspension-service/terraform/modules/end-of-transfer-service/cloudwatch.tf @@ -0,0 +1,24 @@ +locals { + sqs_namespace = "AWS/SQS" +} + +resource "aws_cloudwatch_metric_alarm" "transfer_complete_queue_age_of_message" { + alarm_name = "${var.environment}-${var.component_name}-transfer-complete-approx-age-of-oldest-message" + comparison_operator = "GreaterThanThreshold" + threshold = "1800" + evaluation_periods = "1" + metric_name = "ApproximateAgeOfOldestMessage" + namespace = local.sqs_namespace + alarm_description = "This alarm triggers when messages on the transfer complete queue is not polled by end of transfer service in last 30 mins" + statistic = "Maximum" + period = "300" + dimensions = { + QueueName = aws_sqs_queue.transfer_complete.name + } + alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] + ok_actions = [data.aws_sns_topic.alarm_notifications.arn] +} + +data "aws_sns_topic" "alarm_notifications" { + name = "${var.environment}-alarm-notifications-sns-topic" +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/end-of-transfer-service/data.tf b/stacks/suspension-service/terraform/modules/end-of-transfer-service/data.tf new file mode 100644 index 00000000..06565d02 --- /dev/null +++ b/stacks/suspension-service/terraform/modules/end-of-transfer-service/data.tf @@ -0,0 +1,6 @@ +data "aws_ssm_parameter" "transfer_complete_kms_key" { + name = "/repo/${var.environment}/output/ehr-transfer-service/transfer-complete-encryption-kms-key" +} +data "aws_ssm_parameter" "transfer_complete_topic_arn" { + name = "/repo/${var.environment}/output/ehr-transfer-service/transfer-complete-sns-topic-arn" +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/end-of-transfer-service/iam.tf b/stacks/suspension-service/terraform/modules/end-of-transfer-service/iam.tf new file mode 100644 index 00000000..4ee14a83 --- /dev/null +++ b/stacks/suspension-service/terraform/modules/end-of-transfer-service/iam.tf @@ -0,0 +1,35 @@ +data "aws_iam_policy_document" "transfer_complete_policy_doc" { + statement { + effect = "Allow" + + actions = [ + "sqs:SendMessage" + ] + + principals { + identifiers = ["sns.amazonaws.com"] + type = "Service" + } + + resources = [ + aws_sqs_queue.transfer_complete.arn, + aws_sqs_queue.transfer_complete_observability.arn + ] + + condition { + test = "ArnEquals" + values = [data.aws_ssm_parameter.transfer_complete_topic_arn.value] + variable = "aws:SourceArn" + } + } +} + +resource "aws_sqs_queue_policy" "transfer_complete_observability" { + queue_url = aws_sqs_queue.transfer_complete_observability.id + policy = data.aws_iam_policy_document.transfer_complete_policy_doc.json +} + +resource "aws_sqs_queue_policy" "transfer_complete" { + queue_url = aws_sqs_queue.transfer_complete.id + policy = data.aws_iam_policy_document.transfer_complete_policy_doc.json +} diff --git a/stacks/suspension-service/terraform/modules/end-of-transfer-service/output.tf b/stacks/suspension-service/terraform/modules/end-of-transfer-service/output.tf new file mode 100644 index 00000000..74f7bc45 --- /dev/null +++ b/stacks/suspension-service/terraform/modules/end-of-transfer-service/output.tf @@ -0,0 +1,11 @@ +output "end_of_transfer_sns_topic" { + value = data.aws_ssm_parameter.transfer_complete_topic_arn.value +} + +output "transfer_complete_queue_name" { + value = aws_sqs_queue.transfer_complete.name +} + +output "transfer_complete_queue_arn" { + value = aws_sqs_queue.transfer_complete.arn +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/end-of-transfer-service/queue.tf b/stacks/suspension-service/terraform/modules/end-of-transfer-service/queue.tf new file mode 100644 index 00000000..f8db1f45 --- /dev/null +++ b/stacks/suspension-service/terraform/modules/end-of-transfer-service/queue.tf @@ -0,0 +1,46 @@ +locals { + transfer_complete_queue_name = "${var.environment}-${var.component_name}-transfer-complete" + transfer_complete_observability_queue_name = "${var.environment}-${var.component_name}-transfer-complete-observability" +} + +resource "aws_sqs_queue" "transfer_complete" { + name = local.transfer_complete_queue_name + message_retention_seconds = 259200 + kms_master_key_id = data.aws_ssm_parameter.transfer_complete_kms_key.value + receive_wait_time_seconds = 20 + visibility_timeout_seconds = 240 + + tags = { + Name = local.transfer_complete_queue_name + CreatedBy = var.repo_name + Environment = var.environment + } +} + +resource "aws_sqs_queue" "transfer_complete_observability" { + name = local.transfer_complete_observability_queue_name + message_retention_seconds = 259200 + kms_master_key_id = data.aws_ssm_parameter.transfer_complete_kms_key.value + receive_wait_time_seconds = 20 + visibility_timeout_seconds = 240 + + tags = { + Name = local.transfer_complete_observability_queue_name + CreatedBy = var.repo_name + Environment = var.environment + } +} + +resource "aws_sns_topic_subscription" "transfer_complete_topic" { + protocol = "sqs" + raw_message_delivery = true + topic_arn = data.aws_ssm_parameter.transfer_complete_topic_arn.value + endpoint = aws_sqs_queue.transfer_complete.arn +} + +resource "aws_sns_topic_subscription" "transfer_complete_observability_topic" { + protocol = "sqs" + raw_message_delivery = true + topic_arn = data.aws_ssm_parameter.transfer_complete_topic_arn.value + endpoint = aws_sqs_queue.transfer_complete_observability.arn +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/end-of-transfer-service/variables.tf b/stacks/suspension-service/terraform/modules/end-of-transfer-service/variables.tf new file mode 100644 index 00000000..2e15cb96 --- /dev/null +++ b/stacks/suspension-service/terraform/modules/end-of-transfer-service/variables.tf @@ -0,0 +1,18 @@ +variable "region" { + type = string + default = "eu-west-2" +} + +variable "repo_name" { + type = string +} + +variable "environment" {} + +variable "component_name" {} + +variable "metric_namespace" {} + +variable "ecs_desired_count" { + default = 0 +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/suspension-service/cloudwatch.tf b/stacks/suspension-service/terraform/modules/suspension-service/cloudwatch.tf index e5ef27df..6aa57889 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/cloudwatch.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/cloudwatch.tf @@ -1,24 +1,3 @@ locals { sqs_namespace = "AWS/SQS" } - -resource "aws_cloudwatch_metric_alarm" "suspensions_queue_age_of_message" { - alarm_name = "${var.environment}-${var.component_name}-queue-age-of-message" - comparison_operator = "GreaterThanThreshold" - threshold = var.threshold_for_suspensions_queue_age_of_message - evaluation_periods = "1" - metric_name = "ApproximateAgeOfOldestMessage" - namespace = local.sqs_namespace - alarm_description = "Alarm to alert approximate time for message in the queue" - statistic = "Maximum" - period = var.period_of_age_of_message_metric - dimensions = { - QueueName = aws_sqs_queue.suspensions.name - } - alarm_actions = [data.aws_sns_topic.alarm_notifications.arn] - ok_actions = [data.aws_sns_topic.alarm_notifications.arn] -} - -data "aws_sns_topic" "alarm_notifications" { - name = "${var.environment}-alarm-notifications-sns-topic" -} diff --git a/stacks/suspension-service/terraform/modules/suspension-service/iam.tf b/stacks/suspension-service/terraform/modules/suspension-service/iam.tf index 0ef07334..e69de29b 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/iam.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/iam.tf @@ -1,59 +0,0 @@ -resource "aws_sqs_queue_policy" "repo_incoming_observability" { - queue_url = aws_sqs_queue.repo_incoming_observability_queue.id - policy = data.aws_iam_policy_document.repo_incoming_observability_topic_access_to_queue.json -} - -data "aws_iam_policy_document" "repo_incoming_observability_topic_access_to_queue" { - statement { - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.repo_incoming_observability_queue.arn - ] - - condition { - test = "ArnEquals" - values = [aws_sns_topic.repo_incoming.arn] - variable = "aws:SourceArn" - } - } -} - -data "aws_iam_policy_document" "suspensions_sns_topic_access_to_queue" { - statement { - effect = "Allow" - - actions = [ - "sqs:SendMessage" - ] - - principals { - identifiers = ["sns.amazonaws.com"] - type = "Service" - } - - resources = [ - aws_sqs_queue.suspensions.arn - ] - - condition { - test = "ArnEquals" - values = [data.aws_ssm_parameter.suspensions_sns_topic_arn.value] - variable = "aws:SourceArn" - } - } -} - -resource "aws_sqs_queue_policy" "suspensions_subscription" { - queue_url = aws_sqs_queue.suspensions.id - policy = data.aws_iam_policy_document.suspensions_sns_topic_access_to_queue.json -} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/suspension-service/kms.tf b/stacks/suspension-service/terraform/modules/suspension-service/kms.tf index 34a8449d..e69de29b 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/kms.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/kms.tf @@ -1,16 +0,0 @@ -resource "aws_kms_key" "repo_incoming" { - description = "Custom KMS Key to enable server side encryption for repo incoming topic" - policy = data.aws_iam_policy_document.kms_key_policy_doc.json - enable_key_rotation = true - - tags = { - Name = "${var.environment}-repo-incoming-kms-key" - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_kms_alias" "repo_incoming_encryption" { - name = "alias/${var.component_name}-repo-incoming-encryption-kms-key" - target_key_id = aws_kms_key.repo_incoming.id -} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/suspension-service/lambda.tf b/stacks/suspension-service/terraform/modules/suspension-service/lambda.tf index a7e80ff8..0dd8d683 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/lambda.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/lambda.tf @@ -3,29 +3,9 @@ locals { iam_role_policies = [ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", "arn:aws:iam::aws:policy/CloudWatchLambdaInsightsExecutionRolePolicy", - aws_iam_policy.suspensions_queue_send_message_policy.arn, - aws_iam_policy.ingestion_bucket_get_object_policy.arn ] } -resource "aws_lambda_function" "lambda" { - filename = data.archive_file.lambda.output_path - function_name = "${var.environment}_${local.ingestion_lambda_name}" - role = aws_iam_role.lambda_execution_role.arn - handler = "${local.ingestion_lambda_name}.lambda_handler" - source_code_hash = data.archive_file.lambda.output_base64sha256 - runtime = "python3.12" - timeout = 30 - memory_size = 128 - - environment { - variables = { - SUSPENSION_QUEUE_URL = aws_sqs_queue.suspensions.id - S3_BUCKET_NAME = aws_s3_bucket.ingestion_bucket.id - INGEST_FILE_NAME = "Patient-List-Test" - } - } -} data "aws_iam_policy_document" "assume_role" { statement { @@ -39,17 +19,6 @@ data "aws_iam_policy_document" "assume_role" { } } -resource "aws_iam_role" "lambda_execution_role" { - name = "${var.environment}_lambda_execution_role_${local.ingestion_lambda_name}" - assume_role_policy = data.aws_iam_policy_document.assume_role.json -} - -resource "aws_iam_role_policy_attachment" "lambda_execution_policy" { - count = length(local.iam_role_policies) - role = aws_iam_role.lambda_execution_role.name - policy_arn = local.iam_role_policies[count.index] -} - data "archive_file" "lambda" { type = "zip" source_file = "${path.root}/../../../lambdas/orc-ingestion-lambda/${local.ingestion_lambda_name}.py" diff --git a/stacks/suspension-service/terraform/modules/suspension-service/output.tf b/stacks/suspension-service/terraform/modules/suspension-service/output.tf index 3e4a3c3d..e69de29b 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/output.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/output.tf @@ -1,35 +0,0 @@ -output "repo_incoming_sns_topic" { - value = aws_sns_topic.repo_incoming.arn -} - -output "suspension_queue_name" { - value = aws_sqs_queue.suspensions.name -} - -output "suspension_queue_arn" { - value = aws_sqs_queue.suspensions.arn -} - -resource "aws_ssm_parameter" "repo_incoming_topic_arn" { - name = "/repo/${var.environment}/output/${var.component_name}/repo-incoming-topic-arn" - type = "String" - value = aws_sns_topic.repo_incoming.arn -} - -resource "aws_ssm_parameter" "repo_incoming_kms_key" { - name = "/repo/${var.environment}/output/${var.component_name}/repo-incoming-kms-key" - type = "String" - value = aws_kms_key.repo_incoming.id -} - -resource "aws_ssm_parameter" "suspensions_queue_arn" { - name = "/repo/${var.environment}/output/${var.component_name}/suspensions-queue-arn" - type = "String" - value = aws_sqs_queue.suspensions.arn -} - -resource "aws_ssm_parameter" "suspensions_queue_name" { - name = "/repo/${var.environment}/output/${var.component_name}/suspensions-queue-name" - type = "String" - value = aws_sqs_queue.suspensions.name -} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/suspension-service/queue.tf b/stacks/suspension-service/terraform/modules/suspension-service/queue.tf index 2b2c558f..ea79c32d 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/queue.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/queue.tf @@ -1,68 +1,4 @@ locals { suspensions_queue_name = "${var.environment}-${var.component_name}-suspensions" repo_incoming_observability_queue_name = "${var.environment}-${var.component_name}-repo-incoming-observability" -} -resource "aws_sqs_queue" "repo_incoming_observability_queue" { - name = local.repo_incoming_observability_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.repo_incoming.id - - tags = { - Name = local.repo_incoming_observability_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "repo_incoming_observability_queue" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.repo_incoming.arn - endpoint = aws_sqs_queue.repo_incoming_observability_queue.arn -} - -resource "aws_sqs_queue" "suspensions" { - name = local.suspensions_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = data.aws_ssm_parameter.suspensions_kms_key_id.value - receive_wait_time_seconds = 20 - visibility_timeout_seconds = 240 - - tags = { - Name = local.suspensions_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "suspensions_topic" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = data.aws_ssm_parameter.suspensions_sns_topic_arn.value - endpoint = aws_sqs_queue.suspensions.arn -} - -resource "aws_iam_policy" "suspensions_queue_send_message_policy" { - policy = jsonencode({ - Version = "2012-10-17" - Statement = [{ - "Sid" = "shsqsstatement", - "Effect" = "Allow", - "Action" = [ - "sqs:SendMessage", - ], - "Resource" = [ - aws_sqs_queue.suspensions.arn - ] - }, - { - "Effect" = "Allow", - "Action" = [ - "kms:GenerateDataKey", - "kms:Decrypt" - ], - "Resource" = [ - "*" - ] - }] }) -} +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/modules/suspension-service/s3.tf b/stacks/suspension-service/terraform/modules/suspension-service/s3.tf index 2c772b58..e69de29b 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/s3.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/s3.tf @@ -1,83 +0,0 @@ -locals { - ingestion_bucket_name = "${var.environment}-ehr-ingestion" -} - -resource "aws_s3_bucket" "ingestion_bucket" { - bucket = local.ingestion_bucket_name - - tags = { - Name = local.ingestion_bucket_name - Environment = var.environment - } - - lifecycle { - ignore_changes = [ - logging, - server_side_encryption_configuration - ] - } -} - -resource "aws_s3_bucket_logging" "ingestion_bucket" { - bucket = aws_s3_bucket.ingestion_bucket.id - - target_bucket = data.aws_s3_bucket.access_logs.id - target_prefix = "${local.ingestion_bucket_name}/" -} - -resource "aws_s3_bucket_server_side_encryption_configuration" "ingestion_bucket" { - bucket = aws_s3_bucket.ingestion_bucket.id - - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "AES256" - } - } -} - -resource "aws_s3_bucket_public_access_block" "ingestion_bucket" { - bucket = aws_s3_bucket.ingestion_bucket.bucket - - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} - -resource "aws_s3_bucket_policy" "ingestion_bucket_policy" { - bucket = aws_s3_bucket.ingestion_bucket.id - policy = jsonencode({ - "Version" : "2008-10-17", - "Statement" : [ - { - Effect : "Deny", - Principal : "*", - Action : "s3:*", - Resource : "${aws_s3_bucket.ingestion_bucket.arn}/*", - Condition : { - Bool : { - "aws:SecureTransport" : "false" - } - } - } - ] - } - ) -} - -resource "aws_iam_policy" "ingestion_bucket_get_object_policy" { - name = "${local.ingestion_bucket_name}_get_object_policy" - - policy = jsonencode({ - "Version" : "2012-10-17", - "Statement" : [ - { - "Effect" : "Allow", - "Action" : [ - "s3:GetObject", - ], - "Resource" : ["${aws_s3_bucket.ingestion_bucket.arn}/*"] - } - ] - }) -} diff --git a/stacks/suspension-service/terraform/modules/suspension-service/sns-topic.tf b/stacks/suspension-service/terraform/modules/suspension-service/sns-topic.tf index f4712c7d..f1580ee6 100644 --- a/stacks/suspension-service/terraform/modules/suspension-service/sns-topic.tf +++ b/stacks/suspension-service/terraform/modules/suspension-service/sns-topic.tf @@ -1,15 +1,3 @@ -resource "aws_sns_topic" "repo_incoming" { - name = "${var.environment}-${var.component_name}-repo-incoming" - kms_master_key_id = aws_kms_key.repo_incoming.id - sqs_failure_feedback_role_arn = var.sns_sqs_role_arn - - tags = { - Name = "${var.environment}-${var.component_name}-repo-incoming-sns-topic" - CreatedBy = var.repo_name - Environment = var.environment - } -} - data "aws_iam_policy_document" "kms_key_policy_doc" { statement { effect = "Allow" diff --git a/stacks/suspension-service/terraform/moved-3.0.1.tf b/stacks/suspension-service/terraform/moved-3.0.1.tf index d293c094..39d53cf2 100644 --- a/stacks/suspension-service/terraform/moved-3.0.1.tf +++ b/stacks/suspension-service/terraform/moved-3.0.1.tf @@ -1,4 +1,4 @@ moved { from = module.suspension-service[0] to = module.suspension-service -} +} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/output.tf b/stacks/suspension-service/terraform/output.tf index 3dbe379b..0dab6989 100644 --- a/stacks/suspension-service/terraform/output.tf +++ b/stacks/suspension-service/terraform/output.tf @@ -1,14 +1,3 @@ -resource "aws_ssm_parameter" "mof_updated_queue" { - name = "/repo/${var.environment}/output/${var.component_name}/mof-updated-queue-name" - type = "String" - value = aws_sqs_queue.mof_updated.name -} - -resource "aws_ssm_parameter" "ecs_tasks_sg" { - name = "/repo/${var.environment}/output/${var.component_name}/ecs-sg-id" - type = "String" - value = aws_security_group.ecs-tasks-sg.id -} resource "aws_ssm_parameter" "ecs-cluster-name" { name = "/repo/${var.environment}/output/${var.component_name}/suspension-service-ecs-cluster-name" diff --git a/stacks/suspension-service/terraform/pipeline.auto.tfvars b/stacks/suspension-service/terraform/pipeline.auto.tfvars new file mode 100644 index 00000000..bf1087ee --- /dev/null +++ b/stacks/suspension-service/terraform/pipeline.auto.tfvars @@ -0,0 +1,3 @@ +common_account_id="416874859154" +common_account_role="CiReadOnly" +task_image_tag="51-4e60390b" diff --git a/stacks/suspension-service/terraform/pre-prod.tfvars b/stacks/suspension-service/terraform/pre-prod.tfvars index 9db05361..a3bce36f 100644 --- a/stacks/suspension-service/terraform/pre-prod.tfvars +++ b/stacks/suspension-service/terraform/pre-prod.tfvars @@ -4,5 +4,6 @@ repo_name = "suspension-service" metric_namespace = "SuspensionService" synthetic_patient_prefix = "96936" +is_end_of_transfer_service = false process_only_synthetic_patients = false can_update_managing_organisation_to_repo = true \ No newline at end of file diff --git a/stacks/suspension-service/terraform/prod.tfvars b/stacks/suspension-service/terraform/prod.tfvars index eeb8d881..794598be 100644 --- a/stacks/suspension-service/terraform/prod.tfvars +++ b/stacks/suspension-service/terraform/prod.tfvars @@ -4,6 +4,7 @@ repo_name = "suspension-service" metric_namespace = "SuspensionService" synthetic_patient_prefix = "999" +is_end_of_transfer_service = false process_only_synthetic_patients = false repo_process_only_safe_listed_ods_codes = true can_update_managing_organisation_to_repo = true \ No newline at end of file diff --git a/stacks/suspension-service/terraform/queue.tf b/stacks/suspension-service/terraform/queue.tf index 0589fa5a..3e02d7d7 100644 --- a/stacks/suspension-service/terraform/queue.tf +++ b/stacks/suspension-service/terraform/queue.tf @@ -17,344 +17,8 @@ locals { deceased_patient_queue_name = "${var.environment}-${var.component_name}-deceased-patient" deceased_patient_audit_queue_name = "${var.environment}-${var.component_name}-deceased-patient-audit" deceased_patient_audit_splunk_dlq_queue_name = "${var.environment}-${var.component_name}-deceased-patient-audit-splunk-dlq" - repo_incoming_observability_queue_name = "${var.environment}-${var.component_name}-repo-incoming-observability" } -resource "aws_sqs_queue" "not_suspended_observability" { - name = local.not_suspended_observability_queue_name - message_retention_seconds = 1800 - kms_master_key_id = aws_kms_key.not_suspended.id - tags = { - Name = local.not_suspended_observability_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_ssm_parameter" "not_suspended_observability_queue" { - name = "/repo/${var.environment}/output/${var.component_name}/not-suspended-observability-queue-name" - type = "String" - value = aws_sqs_queue.not_suspended_observability.name -} - - -resource "aws_sns_topic_subscription" "not_suspended" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.not_suspended.arn - endpoint = aws_sqs_queue.not_suspended_observability.arn -} - -resource "aws_sqs_queue" "mof_not_updated" { - name = local.mof_not_updated_queue_name - message_retention_seconds = 1800 - kms_master_key_id = aws_kms_key.mof_not_updated.id - - tags = { - Name = local.mof_not_updated_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "mof_not_updated" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.mof_not_updated.arn - endpoint = aws_sqs_queue.mof_not_updated.arn -} - -resource "aws_sqs_queue" "mof_updated" { - name = local.mof_updated_queue_name - message_retention_seconds = 86400 - kms_master_key_id = aws_kms_key.mof_updated.id - - tags = { - Name = local.mof_updated_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "mof_updated" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.mof_updated.arn - endpoint = aws_sqs_queue.mof_updated.arn -} - -resource "aws_sqs_queue" "invalid_suspension" { - name = local.invalid_suspension_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.invalid_suspension.id - - tags = { - Name = local.invalid_suspension_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "invalid_suspension" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.invalid_suspension.arn - endpoint = aws_sqs_queue.invalid_suspension.arn -} - -resource "aws_sqs_queue" "invalid_suspension_audit" { - name = local.invalid_suspension_audit_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.invalid_suspension_audit.id - - redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.invalid_suspension_splunk_dlq.arn - maxReceiveCount = 4 - }) - tags = { - Name = local.invalid_suspension_audit_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sqs_queue" "invalid_suspension_splunk_dlq" { - name = local.invalid_suspension_splunk_dlq_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.invalid_suspension_audit.id - - - tags = { - Name = local.invalid_suspension_splunk_dlq_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "invalid_suspension_audit" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.invalid_suspension_audit_topic.arn - endpoint = aws_sqs_queue.invalid_suspension_audit.arn -} - -resource "aws_sqs_queue" "not_suspended_audit" { - name = local.not_suspended_audit_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.not_suspended.id - redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.not_suspended_audit_splunk_dlq.arn - maxReceiveCount = 4 - }) - - tags = { - Name = local.not_suspended_audit_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sqs_queue" "not_suspended_audit_splunk_dlq" { - name = local.not_suspended_audit_splunk_dlq_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.not_suspended.id - - tags = { - Name = local.not_suspended_audit_splunk_dlq_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "not_suspended_audit" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.not_suspended.arn - endpoint = aws_sqs_queue.not_suspended_audit.arn -} - -resource "aws_sqs_queue" "event_out_of_order_audit" { - name = local.event_out_of_order_audit_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.event_out_of_order.id - - redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.event_out_of_order_audit_splunk_dlq.arn - maxReceiveCount = 4 - }) - - tags = { - Name = local.event_out_of_order_audit_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sqs_queue" "event_out_of_order_audit_splunk_dlq" { - name = local.event_out_of_order_audit_splunk_dlq_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.event_out_of_order.id - - tags = { - Name = local.event_out_of_order_audit_splunk_dlq_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sqs_queue" "event_out_of_order_observability_queue" { - name = local.event_out_of_order_observability_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.event_out_of_order.id - - tags = { - Name = local.event_out_of_order_observability_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "event_out_of_order_audit" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.event_out_of_order.arn - endpoint = aws_sqs_queue.event_out_of_order_audit.arn -} - -resource "aws_sns_topic_subscription" "event_out_of_order_observability_queue" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.event_out_of_order.arn - endpoint = aws_sqs_queue.event_out_of_order_observability_queue.arn -} - -resource "aws_sqs_queue" "mof_not_updated_audit" { - name = local.mof_not_updated_audit_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.mof_not_updated.id - redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.mof_not_updated_audit_splunk_dlq.arn - maxReceiveCount = 4 - }) - - tags = { - Name = local.mof_not_updated_audit_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sqs_queue" "mof_not_updated_audit_splunk_dlq" { - name = local.mof_not_updated_audit_splunk_dlq_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.mof_not_updated.id - - tags = { - Name = local.mof_not_updated_audit_splunk_dlq_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "mof_not_updated_audit" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.mof_not_updated.arn - endpoint = aws_sqs_queue.mof_not_updated_audit.arn -} - -resource "aws_sqs_queue" "mof_updated_audit" { - name = local.mof_updated_audit_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.mof_updated.id - redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.mof_updated_audit_splunk_dlq.arn - maxReceiveCount = 4 - }) - - tags = { - Name = local.mof_updated_audit_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sqs_queue" "mof_updated_audit_splunk_dlq" { - name = local.mof_updated_audit_splunk_dlq_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.mof_updated.id - - tags = { - Name = local.mof_updated_audit_splunk_dlq_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "mof_updated_audit" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.mof_updated.arn - endpoint = aws_sqs_queue.mof_updated_audit.arn -} - -resource "aws_sqs_queue" "deceased_patient" { - name = local.deceased_patient_queue_name - message_retention_seconds = 1800 - kms_master_key_id = aws_kms_key.deceased_patient.id - receive_wait_time_seconds = 20 - visibility_timeout_seconds = 240 - - tags = { - Name = local.deceased_patient_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "deceased_patient" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.deceased_patient.arn - endpoint = aws_sqs_queue.deceased_patient.arn -} - -resource "aws_sqs_queue" "deceased_patient_audit" { - name = local.deceased_patient_audit_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.deceased_patient.id - receive_wait_time_seconds = 20 - visibility_timeout_seconds = 240 - - redrive_policy = jsonencode({ - deadLetterTargetArn = aws_sqs_queue.deceased_patient_audit_splunk_dlq.arn - maxReceiveCount = 4 - }) - tags = { - Name = local.deceased_patient_audit_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} - -resource "aws_sns_topic_subscription" "deceased_patient_audit" { - protocol = "sqs" - raw_message_delivery = true - topic_arn = aws_sns_topic.deceased_patient.arn - endpoint = aws_sqs_queue.deceased_patient_audit.arn -} -resource "aws_sqs_queue" "deceased_patient_audit_splunk_dlq" { - name = local.deceased_patient_audit_splunk_dlq_queue_name - message_retention_seconds = 1209600 - kms_master_key_id = aws_kms_key.deceased_patient.id - receive_wait_time_seconds = 20 - visibility_timeout_seconds = 240 - tags = { - Name = local.deceased_patient_audit_splunk_dlq_queue_name - CreatedBy = var.repo_name - Environment = var.environment - } -} \ No newline at end of file diff --git a/stacks/suspension-service/terraform/sns-topic.tf b/stacks/suspension-service/terraform/sns-topic.tf index c95b0ef7..e750445a 100644 --- a/stacks/suspension-service/terraform/sns-topic.tf +++ b/stacks/suspension-service/terraform/sns-topic.tf @@ -98,63 +98,3 @@ data "aws_sns_topic" "alarm_notifications" { name = "${var.environment}-alarm-notifications-sns-topic" } -resource "aws_sns_topic_policy" "deny_http" { - for_each = toset(local.sns_arns) - - arn = each.value - - policy = < tf-out.json +} + +############################ +# Docker Related Functions # +############################ + +function docker_login { + echo Logging in to Amazon ECR... + eval $(dojo -c Dojofile-infra "aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION") +} + +function configure_docker_repository_uri { + docker_login + get_aws_account_id + export REPOSITORY_URI=$AWS_ACCOUNT_ID.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/$IMAGE_REPO_NAME +} + +function build_docker_image() { + echo Build started on $(date) + set_image_tag + echo Building the Docker image... + docker build --build-arg UTILS_VERSION=$AWS_HELPERS_VERSION -t $REPOSITORY_URI:latest -t $REPOSITORY_URI:$IMAGE_TAG . + echo Build completed on `date` +} + +function configure_local_envs { + export LOG_LEVEL=debug + export NHS_ENVIRONMENT=local +} + +function die_localstack_die { + echo docker processes running: $(docker ps) + + DOCKER_CONTAINERS_ON_PORT=$(docker ps --filter publish=4566 -q) + + echo docker processes running on expected localstack port: $DOCKER_CONTAINERS_ON_PORT + + if [ -z "$DOCKER_CONTAINERS_ON_PORT" ]; then + echo no localstack nonsense going on, cool + else + echo trying to kill localstack... + docker stop $DOCKER_CONTAINERS_ON_PORT + fi +} + +########### +## TASKS ## +########### + +command="$1" +case "${command}" in + fetch_utils) + fetch_redaction_utils + ;; + die_localstack_die) + die_localstack_die + ;; + build_docker) + configure_envs + dojo "./tasks _build" + configure_docker_repository_uri + fetch_redaction_utils + build_docker_image + echo "Pushing the Docker image... $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG" + docker push $REPOSITORY_URI:$IMAGE_TAG + ;; + _build) + rm -rf build/ + gradle assemble + ;; + build) + dojo "./tasks _build" + ;; + _test_unit) + gradle test + ;; + test_unit) + dojo "./tasks _test_unit" + ;; + _test_integration) + gradle --info integration + ;; + test_integration) + configure_envs + die_localstack_die + dojo -c Dojofile-itest "./tasks _test_integration" + ;; + dojo_integration) + configure_envs + dojo -c Dojofile-itest "./tasks _test_integration" + ;; + _test_coverage) + gradle jacocoTestCoverageVerification + ;; + test_coverage) + configure_envs + die_localstack_die + dojo -c Dojofile-itest "./tasks _test_coverage" + ;; + _code_quality) + gradle check -x test -x integration + ;; + code_quality) + die_localstack_die + dojo -c Dojofile-itest "./tasks _code_quality" + ;; + _test_all) + gradle clean test integration jacocoTestCoverageVerification check + ;; + test_all) + configure_envs + die_localstack_die + dojo -c Dojofile-itest "./tasks _test_all" + ;; + run_local) + configure_envs + ./gradlew bootRun + ;; + run_localstack_local) + docker-compose -f docker-compose.localstack-local.yaml up -d + ;; + _tf) + _assume_environment_role $NHS_ENVIRONMENT + tf_init + bash + ;; + tf) + check_env + dojo -c Dojofile-infra "./tasks _tf" + ;; + _tf_plan_suspension) + export NHS_SERVICE=suspension-service + _assume_environment_role $NHS_ENVIRONMENT + tf_plan "$2" + ;; + tf_plan_suspension) + export NHS_SERVICE=suspension-service + check_env + dojo -c Dojofile-infra "./tasks _tf_plan $2" + ;; + _tf_plan_transfer) + export NHS_SERVICE=end-of-transfer-service + tf_plan "$2" + ;; + tf_plan_transfer) + export NHS_SERVICE=end-of-transfer-service + check_env + dojo -c Dojofile-infra "./tasks _tf_plan $2" + ;; + _tf_plan) + _assume_environment_role $NHS_ENVIRONMENT + tf_plan "$2" + ;; + tf_plan) + check_env + dojo -c Dojofile-infra "./tasks _tf_plan $2" + ;; + _tf_apply) + _assume_environment_role $NHS_ENVIRONMENT + tf_apply + ;; + tf_apply) + check_env + dojo -c Dojofile-infra "./tasks _tf_apply" + ;; + promote_docker_image) + check_env + set_image_tag + promote_docker_image "$IMAGE_REPO_NAME:$IMAGE_TAG" "$NHS_ENVIRONMENT" + ;; + _wait_ecs) + _assume_environment_role $NHS_ENVIRONMENT + aws ecs wait services-stable \ + --region $AWS_DEFAULT_REGION \ + --cluster $NHS_ENVIRONMENT-${NHS_SERVICE}-ecs-cluster \ + --service $NHS_ENVIRONMENT-${NHS_SERVICE} + ;; + wait_ecs) + check_env + dojo -c Dojofile-infra "./tasks _wait_ecs" + ;; + _run_sonar) + ./gradlew build sonar --info + ;; + run_sonar) + die_localstack_die + _assume_environment_role $NHS_ENVIRONMENT + configure_envs + configure_sonar_environment_variable + dojo -c Dojofile-itest "./tasks _run_sonar" + ;; + *) + echo "Invalid command: '${command}'" + exit 1 + ;; +esac +set +e \ No newline at end of file diff --git a/stacks/suspension-service/terraform/variables.tf b/stacks/suspension-service/terraform/variables.tf index 5eb02a64..5541eafd 100644 --- a/stacks/suspension-service/terraform/variables.tf +++ b/stacks/suspension-service/terraform/variables.tf @@ -44,6 +44,11 @@ variable "can_update_managing_organisation_to_repo" { default = false } +variable "is_end_of_transfer_service" { + type = bool + default = false +} + variable "image_name" { type = string default = "suspension-service"