Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions infrastructure/terraform/components/dl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ No requirements.
| <a name="input_aws_account_id"></a> [aws\_account\_id](#input\_aws\_account\_id) | The AWS Account ID (numeric) | `string` | n/a | yes |
| <a name="input_component"></a> [component](#input\_component) | The variable encapsulating the name of this component | `string` | `"dl"` | no |
| <a name="input_core_notify_url"></a> [core\_notify\_url](#input\_core\_notify\_url) | The URL used to send requests to Notify | `string` | `"https://sandbox.api.service.nhs.uk"` | no |
| <a name="input_default_cloudwatch_event_bus_name"></a> [default\_cloudwatch\_event\_bus\_name](#input\_default\_cloudwatch\_event\_bus\_name) | The name of the default cloudwatch event bus. This is needed as GuardDuty Scan Result events are sent to the default bus | `string` | `"default"` | no |
| <a name="input_default_tags"></a> [default\_tags](#input\_default\_tags) | A map of default tags to apply to all taggable resources within the component | `map(string)` | `{}` | no |
| <a name="input_enable_dynamodb_delete_protection"></a> [enable\_dynamodb\_delete\_protection](#input\_enable\_dynamodb\_delete\_protection) | Enable DynamoDB Delete Protection on all Tables | `bool` | `true` | no |
| <a name="input_enable_mock_mesh"></a> [enable\_mock\_mesh](#input\_enable\_mock\_mesh) | Enable mock mesh access (dev only). Grants lambda permission to read mock-mesh prefix in non-pii bucket. | `bool` | `false` | no |
Expand Down Expand Up @@ -48,12 +49,14 @@ No requirements.
| <a name="module_lambda_lambda_apim_refresh_token"></a> [lambda\_lambda\_apim\_refresh\_token](#module\_lambda\_lambda\_apim\_refresh\_token) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_mesh_download"></a> [mesh\_download](#module\_mesh\_download) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_mesh_poll"></a> [mesh\_poll](#module\_mesh\_poll) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_move_scanned_files"></a> [move\_scanned\_files](#module\_move\_scanned\_files) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_pdm_mock"></a> [pdm\_mock](#module\_pdm\_mock) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_pdm_poll"></a> [pdm\_poll](#module\_pdm\_poll) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_pdm_uploader"></a> [pdm\_uploader](#module\_pdm\_uploader) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_print_analyser"></a> [print\_analyser](#module\_print\_analyser) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_print_status_handler"></a> [print\_status\_handler](#module\_print\_status\_handler) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <a name="module_s3bucket_cf_logs"></a> [s3bucket\_cf\_logs](#module\_s3bucket\_cf\_logs) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
| <a name="module_s3bucket_file_quarantine"></a> [s3bucket\_file\_quarantine](#module\_s3bucket\_file\_quarantine) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
| <a name="module_s3bucket_file_safe"></a> [s3bucket\_file\_safe](#module\_s3bucket\_file\_safe) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
| <a name="module_s3bucket_letters"></a> [s3bucket\_letters](#module\_s3bucket\_letters) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
| <a name="module_s3bucket_non_pii_data"></a> [s3bucket\_non\_pii\_data](#module\_s3bucket\_non\_pii\_data) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip | n/a |
Expand All @@ -62,6 +65,7 @@ No requirements.
| <a name="module_sqs_core_notifier"></a> [sqs\_core\_notifier](#module\_sqs\_core\_notifier) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
| <a name="module_sqs_event_publisher_errors"></a> [sqs\_event\_publisher\_errors](#module\_sqs\_event\_publisher\_errors) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
| <a name="module_sqs_mesh_download"></a> [sqs\_mesh\_download](#module\_sqs\_mesh\_download) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
| <a name="module_sqs_move_scanned_files"></a> [sqs\_move\_scanned\_files](#module\_sqs\_move\_scanned\_files) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
| <a name="module_sqs_pdm_poll"></a> [sqs\_pdm\_poll](#module\_sqs\_pdm\_poll) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
| <a name="module_sqs_pdm_uploader"></a> [sqs\_pdm\_uploader](#module\_sqs\_pdm\_uploader) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip | n/a |
| <a name="module_sqs_print_analyser"></a> [sqs\_print\_analyser](#module\_sqs\_print\_analyser) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.30/terraform-sqs.zip | n/a |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
resource "aws_cloudwatch_event_rule" "guardduty_scan_result" {
name = "${local.csi}-guardduty_scan_result"
description = "guardduty Scan Result event rule"
event_bus_name = var.default_cloudwatch_event_bus_name
event_pattern = jsonencode({
"source": ["aws.guardduty"]
"detail" : {
"resourceType": ["S3_OBJECT"],
"s3ObjectDetails": {
"bucketName": [ local.unscanned_files_bucket ],
"objectKey": [{ "prefix": "${local.csi}/" }]
}
}
})
}

resource "aws_cloudwatch_event_target" "guardduty_scan_result_move_scanned_files" {
rule = aws_cloudwatch_event_rule.guardduty_scan_result.name
arn = module.sqs_move_scanned_files.sqs_queue_arn
event_bus_name = var.default_cloudwatch_event_bus_name
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
resource "aws_lambda_event_source_mapping" "move_scanned_files_lambda" {
event_source_arn = module.sqs_move_scanned_files.sqs_queue_arn
function_name = module.move_scanned_files.function_arn
batch_size = var.queue_batch_size
maximum_batching_window_in_seconds = var.queue_batch_window_seconds

function_response_types = [
"ReportBatchItemFailures"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
module "move_scanned_files" {
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip"

function_name = "move-scanned-files"
description = "A function that handles GuardDuty Malware Protection Object Scan Result and depending on the result moves objects from the unscanned bucket to the file safe or quarantined bucket. "

aws_account_id = var.aws_account_id
component = local.component
environment = var.environment
project = var.project
region = var.region
group = var.group

log_retention_in_days = var.log_retention_in_days
kms_key_arn = module.kms.key_arn

iam_policy_document = {
body = data.aws_iam_policy_document.move_scanned_files.json
}

function_s3_bucket = local.acct.s3_buckets["lambda_function_artefacts"]["id"]
function_code_base_path = local.aws_lambda_functions_dir_path
function_code_dir = "move-scanned-files-lambda/dist"
function_include_common = true
handler_function_name = "handler"
runtime = "nodejs22.x"
memory = 128
timeout = 60
log_level = var.log_level

force_lambda_code_deploy = var.force_lambda_code_deploy
enable_lambda_insights = false

log_destination_arn = local.log_destination_arn
log_subscription_role_arn = local.acct.log_subscription_role_arn

lambda_env_vars = {
"EVENT_PUBLISHER_EVENT_BUS_ARN" = aws_cloudwatch_event_bus.main.arn
"EVENT_PUBLISHER_DLQ_URL" = module.sqs_event_publisher_errors.sqs_queue_url
"ENVIRONMENT" = var.environment
"KEY_PREFIX_UNSCANNED_FILES" = local.csi
"UNSCANNED_FILE_S3_BUCKET_NAME" = local.unscanned_files_bucket
"SAFE_FILE_S3_BUCKET_NAME" = module.s3bucket_file_safe.bucket
"QUARANTINE_FILE_S3_BUCKET_NAME" = module.s3bucket_file_quarantine.bucket
}
}

data "aws_iam_policy_document" "move_scanned_files" {
statement {
sid = "KMSPermissions"
effect = "Allow"

actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey",
]

resources = [
module.kms.key_arn,
]
}

statement {
sid = "SQSPermissionsFileScannerMoveScannedFiles"
effect = "Allow"

actions = [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
]

resources = [
module.sqs_move_scanned_files.sqs_queue_arn,
]
}

statement {
sid = "PutEvents"
effect = "Allow"

actions = [
"events:PutEvents",
]

resources = [
aws_cloudwatch_event_bus.main.arn,
]
}

statement {
sid = "SQSPermissionsDLQ"
effect = "Allow"

actions = [
"sqs:SendMessage",
"sqs:SendMessageBatch",
]

resources = [
module.sqs_event_publisher_errors.sqs_queue_arn,
]
}

statement {
sid = "PermissionsToUnscannedBucket"
effect = "Allow"

actions = [
"s3:GetObject",
"s3:GetObjectTagging",
"s3:DeleteObject",
]

resources = [
"arn:aws:s3:::${local.unscanned_files_bucket}/*",
]
}

statement {
sid = "PermissionsToSafeFileBucket"
effect = "Allow"

actions = [
"s3:PutObject",
"s3:PutObjectTagging",
]

resources = [
"${module.s3bucket_file_safe.arn}/*"
]
}

statement {
sid = "PermissionsToQuarantineFileBucket"
effect = "Allow"

actions = [
"s3:PutObject",
"s3:PutObjectTagging",
]

resources = [
"${module.s3bucket_file_quarantine.arn}/*"
]
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module "s3bucket_file_quarantine" {
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-s3bucket.zip"

name = "file-quarantine"

aws_account_id = var.aws_account_id
region = var.region
project = var.project
environment = var.environment
component = local.component

kms_key_arn = module.kms.key_arn

policy_documents = [data.aws_iam_policy_document.s3bucket_file_quarantine.json]

force_destroy = var.force_destroy

lifecycle_rules = [
{
enabled = true

expiration = {
days = "90"
}

noncurrent_version_transition = [
{
noncurrent_days = "30"
storage_class = "STANDARD_IA"
}
]

noncurrent_version_expiration = {
noncurrent_days = "90"
}

abort_incomplete_multipart_upload = {
days = "1"
}
}
]
}

data "aws_iam_policy_document" "s3bucket_file_quarantine" {
statement {
sid = "AllowManagedAccountsToList"
effect = "Allow"

actions = [
"s3:ListBucket",
]

resources = [
module.s3bucket_file_quarantine.arn,
]

principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${var.aws_account_id}:root"
]
}
}

statement {
sid = "AllowManagedAccountsToGetPut"
effect = "Allow"

actions = [
"s3:GetObject",
"s3:PutObject",
]

resources = [
"${module.s3bucket_file_quarantine.arn}/*",
]

principals {
type = "AWS"
identifiers = [
"arn:aws:iam::${var.aws_account_id}:root"
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module "sqs_move_scanned_files" {
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.24/terraform-sqs.zip"

aws_account_id = var.aws_account_id
component = local.component
environment = var.environment
project = var.project
region = var.region
name = "move-scanned-files"

sqs_kms_key_arn = module.kms.key_arn

visibility_timeout_seconds = 60

create_dlq = true

sqs_policy_overload = data.aws_iam_policy_document.sqs_move_scanned_files.json
}

data "aws_iam_policy_document" "sqs_move_scanned_files" {
statement {
sid = "AllowEventBridgeToSendMessage"
effect = "Allow"

principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}

actions = [
"sqs:SendMessage"
]

resources = [
"arn:aws:sqs:${var.region}:${var.aws_account_id}:${local.csi}-move-scanned-files-queue"
]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the events are coming from the "default" bus, which I referred as "default", so I don't have an ARN. I'll check with platform to see if there is something else we can put in here.


condition {
test = "ArnLike"
variable = "aws:SourceArn"
values = [ "arn:aws:events:${var.region}:${var.aws_account_id}:event-bus/${var.default_cloudwatch_event_bus_name}" ]
}
}
}
6 changes: 6 additions & 0 deletions infrastructure/terraform/components/dl/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,9 @@ variable "enable_pdm_mock" {
description = "Flag indicating whether to deploy PDM mock API (should be false in production environments)"
default = true
}

variable "default_cloudwatch_event_bus_name" {
type = string
description = "The name of the default cloudwatch event bus. This is needed as GuardDuty Scan Result events are sent to the default bus"
default = "default"
}
5 changes: 5 additions & 0 deletions lambdas/move-scanned-files-lambda/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { baseJestConfig } from '../../jest.config.base';

const config = baseJestConfig;

export default config;
26 changes: 26 additions & 0 deletions lambdas/move-scanned-files-lambda/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"dependencies": {
"aws-lambda": "^1.0.7",
"axios": "^1.13.2",
"digital-letters-events": "^0.0.1",
"utils": "^0.0.1"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.2",
"@types/aws-lambda": "^8.10.155",
"@types/jest": "^29.5.14",
"jest": "^29.7.0",
"jest-mock-extended": "^3.0.7",
"typescript": "^5.9.3"
},
"name": "nhs-notify-digital-move-scanned-files-lambda",
"private": true,
"scripts": {
"lambda-build": "rm -rf dist && npx esbuild --bundle --minify --sourcemap --target=es2020 --platform=node --loader:.node=file --entry-names=[name] --outdir=dist src/index.ts",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test:unit": "jest",
"typecheck": "tsc --noEmit"
},
"version": "0.0.1"
}
Loading
Loading