From e92d8dcf8f58456262405a2de8297c7610bead55 Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:02:48 +0100 Subject: [PATCH 1/5] CCM-16644: Update .gitleaksignore --- .gitleaksignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitleaksignore b/.gitleaksignore index 969beb5d..456cd8b8 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -19,3 +19,9 @@ e44436c05bb859820c89b241df2e589ab760595b:infrastructure/terraform/components/rep 056d713eefe2305444059e99d707bd902ed6f532:infrastructure/terraform/components/reporting/variables.tf:ipv4:109 d38af4e4f6c36ca9c3d843193b434386a9bad5ee:infrastructure/terraform/etc/env_eu-west-2_int.tfvars:generic-api-key:29 d38af4e4f6c36ca9c3d843193b434386a9bad5ee:infrastructure/terraform/etc/env_eu-west-2_prod.tfvars:generic-api-key:43 +e4f41f458ca66d94f1fcebdff9579e2ce81d1d5e:infrastructure/terraform/etc/env_eu-west-2_int.tfvars:generic-api-key:29 +e4f41f458ca66d94f1fcebdff9579e2ce81d1d5e:infrastructure/terraform/etc/env_eu-west-2_prod.tfvars:generic-api-key:43 +9469a5a10e20b5c3275ba055e65ba98e7d11e9d2:infrastructure/terraform/components/reporting/README.md:ipv4:16 +9469a5a10e20b5c3275ba055e65ba98e7d11e9d2:infrastructure/terraform/components/reporting/README.md:ipv4:16 +9469a5a10e20b5c3275ba055e65ba98e7d11e9d2:infrastructure/terraform/components/reporting/variables.tf:ipv4:109 +9469a5a10e20b5c3275ba055e65ba98e7d11e9d2:infrastructure/terraform/components/reporting/variables.tf:ipv4:109 From 22ceb743e4ab0bef4a44a9e51196f6f9bcdcc94c Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Fri, 1 May 2026 10:44:04 +0100 Subject: [PATCH 2/5] CCM-16644: Fix request_item_plan_read_status_smsnudge dependencies --- .../null_resource_request_item_plan_read_status_smsnudge.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/terraform/components/reporting/null_resource_request_item_plan_read_status_smsnudge.tf b/infrastructure/terraform/components/reporting/null_resource_request_item_plan_read_status_smsnudge.tf index 08b3e434..cde63f7e 100644 --- a/infrastructure/terraform/components/reporting/null_resource_request_item_plan_read_status_smsnudge.tf +++ b/infrastructure/terraform/components/reporting/null_resource_request_item_plan_read_status_smsnudge.tf @@ -15,6 +15,6 @@ resource "null_resource" "request_item_plan_read_status_smsnudge" { depends_on = [ null_resource.request_item_plan_status_table, - null_resource.request_item_status_smsnudge_staging_view + null_resource.request_item_plan_status_smsnudge_view ] } From c208c0a230c84168e63c75d93ff8ff1114c54c90 Mon Sep 17 00:00:00 2001 From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com> Date: Wed, 29 Apr 2026 16:07:37 +0100 Subject: [PATCH 3/5] CCM-16644: Add Firehose Stream --- .../terraform/components/reporting/README.md | 1 + ...watch_log_group_kinesis_firehose_events.tf | 9 ++ .../reporting/iam_role_firehose_events.tf | 107 ++++++++++++++++++ ...elivery_stream_eventsub_to_s3_reporting.tf | 50 ++++++++ .../terraform/components/reporting/locals.tf | 3 + .../components/reporting/s3_bucket_events.tf | 73 ++++++++++++ .../reporting/s3_bucket_policy_events.tf | 28 +++++ .../components/reporting/variables.tf | 12 ++ .../terraform/etc/env_eu-west-2_main.tfvars | 7 +- .../terraform/etc/env_eu-west-2_ref.tfvars | 7 +- 10 files changed, 295 insertions(+), 2 deletions(-) create mode 100644 infrastructure/terraform/components/reporting/cloudwatch_log_group_kinesis_firehose_events.tf create mode 100644 infrastructure/terraform/components/reporting/iam_role_firehose_events.tf create mode 100644 infrastructure/terraform/components/reporting/kinesis_firehose_delivery_stream_eventsub_to_s3_reporting.tf create mode 100644 infrastructure/terraform/components/reporting/s3_bucket_events.tf create mode 100644 infrastructure/terraform/components/reporting/s3_bucket_policy_events.tf diff --git a/infrastructure/terraform/components/reporting/README.md b/infrastructure/terraform/components/reporting/README.md index 82985d40..9a2b26e9 100644 --- a/infrastructure/terraform/components/reporting/README.md +++ b/infrastructure/terraform/components/reporting/README.md @@ -31,6 +31,7 @@ No requirements. | [enable\_spot](#input\_enable\_spot) | run Power BI On-Premises Gateway as spot instances | `bool` | `false` | no | | [enable\_vault\_lock\_configuration](#input\_enable\_vault\_lock\_configuration) | Enable vault lock, preventing the deletion of a vault that contains 1 or more Recovery Points | `bool` | `false` | no | | [environment](#input\_environment) | The name of the environment | `string` | n/a | yes | +| [event\_staging\_retention\_config](#input\_event\_staging\_retention\_config) | The number of days for data retention policy for events in the staging table |
object({
current_days = number,
non_current_days = number,
}) | {
"current_days": 534,
"non_current_days": 14
} | no |
| [group](#input\_group) | The group variables are being inherited from (often synonmous with account short-name) | `string` | `"n/a"` | no |
| [instance\_type](#input\_instance\_type) | The EC2 instance type. | `string` | `"t3.medium"` | no |
| [log\_retention\_days](#input\_log\_retention\_days) | How many days to retain the logs generated by the step function | `number` | `30` | no |
diff --git a/infrastructure/terraform/components/reporting/cloudwatch_log_group_kinesis_firehose_events.tf b/infrastructure/terraform/components/reporting/cloudwatch_log_group_kinesis_firehose_events.tf
new file mode 100644
index 00000000..ca348f74
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/cloudwatch_log_group_kinesis_firehose_events.tf
@@ -0,0 +1,9 @@
+resource "aws_cloudwatch_log_group" "kinesis_firehose_events" {
+ name = "/aws/kinesisfirehose/${local.csi}-events"
+ retention_in_days = var.log_retention_days
+}
+
+resource "aws_cloudwatch_log_stream" "kinesis_firehose_events_extended_s3" {
+ name = "${local.csi}-events-extended-s3"
+ log_group_name = aws_cloudwatch_log_group.kinesis_firehose_events.name
+}
diff --git a/infrastructure/terraform/components/reporting/iam_role_firehose_events.tf b/infrastructure/terraform/components/reporting/iam_role_firehose_events.tf
new file mode 100644
index 00000000..0761117d
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/iam_role_firehose_events.tf
@@ -0,0 +1,107 @@
+resource "aws_iam_role" "firehose_events" {
+ name = "${local.csi}-firehose-events-role"
+ description = "Role used by Firehose to deliver events into the event staging S3 bucket"
+ assume_role_policy = data.aws_iam_policy_document.firehose_events_assume_role.json
+}
+
+data "aws_iam_policy_document" "firehose_events_assume_role" {
+ statement {
+ effect = "Allow"
+
+ principals {
+ type = "Service"
+ identifiers = ["firehose.amazonaws.com"]
+ }
+
+ actions = ["sts:AssumeRole"]
+ }
+}
+
+resource "aws_iam_role_policy_attachment" "firehose_events" {
+ role = aws_iam_role.firehose_events.name
+ policy_arn = aws_iam_policy.firehose_events.arn
+}
+
+resource "aws_iam_policy" "firehose_events" {
+ name = "${local.csi}-firehose-events-policy"
+ description = "Permissions for Firehose delivery to the event staging S3 bucket"
+ policy = data.aws_iam_policy_document.firehose_events.json
+}
+
+data "aws_iam_policy_document" "firehose_events" {
+ statement {
+ sid = "AllowS3BucketMeta"
+ effect = "Allow"
+
+ actions = [
+ "s3:GetBucketLocation",
+ "s3:ListBucket",
+ "s3:ListBucketMultipartUploads"
+ ]
+
+ resources = [
+ aws_s3_bucket.events.arn,
+ ]
+ }
+
+ statement {
+ sid = "AllowS3ObjectWrite"
+ effect = "Allow"
+
+ actions = [
+ "s3:AbortMultipartUpload",
+ "s3:GetObject",
+ "s3:PutObject"
+ ]
+
+ resources = [
+ "${aws_s3_bucket.events.arn}/${local.firehose_output_path_prefix}/*",
+ ]
+ }
+
+ statement {
+ sid = "AllowCloudWatchLogging"
+ effect = "Allow"
+
+ actions = [
+ "logs:CreateLogStream",
+ "logs:PutLogEvents"
+ ]
+
+ resources = [
+ aws_cloudwatch_log_group.kinesis_firehose_events.arn,
+ aws_cloudwatch_log_stream.kinesis_firehose_events_extended_s3.arn,
+ ]
+ }
+
+ statement {
+ sid = "AllowGlueSchemaAccess"
+ effect = "Allow"
+
+ actions = [
+ "glue:GetTable",
+ "glue:GetTableVersion",
+ "glue:GetTableVersions"
+ ]
+
+ resources = [
+ "arn:aws:glue:${var.region}:${var.aws_account_id}:catalog"
+ ]
+ }
+
+ statement {
+ sid = "AllowKMSEncryption"
+ effect = "Allow"
+
+ actions = [
+ "kms:Decrypt",
+ "kms:DescribeKey",
+ "kms:Encrypt",
+ "kms:GenerateDataKey"
+ ]
+
+ resources = [
+ aws_kms_key.s3.arn,
+ ]
+ }
+}
diff --git a/infrastructure/terraform/components/reporting/kinesis_firehose_delivery_stream_eventsub_to_s3_reporting.tf b/infrastructure/terraform/components/reporting/kinesis_firehose_delivery_stream_eventsub_to_s3_reporting.tf
new file mode 100644
index 00000000..f140e55a
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/kinesis_firehose_delivery_stream_eventsub_to_s3_reporting.tf
@@ -0,0 +1,50 @@
+resource "aws_kinesis_firehose_delivery_stream" "events" {
+ name = "${local.csi}-events"
+ destination = "extended_s3"
+
+ server_side_encryption {
+ enabled = true
+ key_type = "CUSTOMER_MANAGED_CMK"
+ key_arn = aws_kms_key.s3.arn
+ }
+
+ extended_s3_configuration {
+ role_arn = aws_iam_role.firehose_events.arn
+ bucket_arn = aws_s3_bucket.events.arn
+ kms_key_arn = aws_kms_key.s3.arn
+
+ buffering_interval = 300
+ buffering_size = 128
+
+ prefix = "${local.firehose_output_path_events}/!{partitionKeyFromQuery:type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"
+ error_output_prefix = "${local.firehose_output_path_prefix}/firehose-errors/!{firehose:error-output-type}/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/"
+
+ dynamic_partitioning_configuration {
+ enabled = true
+ }
+
+ processing_configuration {
+ enabled = true
+
+ processors {
+ type = "MetadataExtraction"
+
+ parameters {
+ parameter_name = "JsonParsingEngine"
+ parameter_value = "JQ-1.6"
+ }
+
+ parameters {
+ parameter_name = "MetadataExtractionQuery"
+ parameter_value = "{type:.type}"
+ }
+ }
+ }
+
+ cloudwatch_logging_options {
+ enabled = true
+ log_group_name = aws_cloudwatch_log_group.kinesis_firehose_events.name
+ log_stream_name = aws_cloudwatch_log_stream.kinesis_firehose_events_extended_s3.name
+ }
+ }
+}
diff --git a/infrastructure/terraform/components/reporting/locals.tf b/infrastructure/terraform/components/reporting/locals.tf
index 3d4c48ab..0fadb4bf 100644
--- a/infrastructure/terraform/components/reporting/locals.tf
+++ b/infrastructure/terraform/components/reporting/locals.tf
@@ -87,4 +87,7 @@ locals {
sms_nudge_client_id = format("'%s'", var.sms_nudge_client_id)
log_destination_arn = "arn:aws:logs:${var.region}:${var.shared_infra_account_id}:destination:nhs-main-obs-firehose-logs"
+
+ firehose_output_path_prefix = "kinesis-firehose-output"
+ firehose_output_path_events = "${local.firehose_output_path_prefix}/events"
}
diff --git a/infrastructure/terraform/components/reporting/s3_bucket_events.tf b/infrastructure/terraform/components/reporting/s3_bucket_events.tf
new file mode 100644
index 00000000..f1cd7404
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/s3_bucket_events.tf
@@ -0,0 +1,73 @@
+resource "aws_s3_bucket" "events" {
+ bucket = "${local.csi_global}-events"
+ force_destroy = "false"
+}
+
+resource "aws_s3_bucket_ownership_controls" "events" {
+ bucket = aws_s3_bucket.events.id
+
+ rule {
+ object_ownership = "BucketOwnerPreferred"
+ }
+}
+
+resource "aws_s3_bucket_server_side_encryption_configuration" "events" {
+ bucket = aws_s3_bucket.events.id
+
+ rule {
+ apply_server_side_encryption_by_default {
+ sse_algorithm = "aws:kms"
+ kms_master_key_id = aws_kms_alias.s3.id
+ }
+ bucket_key_enabled = true
+ }
+}
+
+resource "aws_s3_bucket_versioning" "events" {
+ bucket = aws_s3_bucket.events.id
+
+ versioning_configuration {
+ status = "Enabled"
+ }
+}
+
+resource "aws_s3_bucket_public_access_block" "events" {
+ depends_on = [
+ aws_s3_bucket_policy.events
+ ]
+
+ bucket = aws_s3_bucket.events.id
+
+ block_public_acls = true
+ block_public_policy = true
+ ignore_public_acls = true
+ restrict_public_buckets = true
+}
+
+resource "aws_s3_bucket_logging" "events" {
+ bucket = aws_s3_bucket.events.id
+
+ target_bucket = aws_s3_bucket.access_logs.bucket
+ target_prefix = "nhs-notify/${aws_s3_bucket.events.bucket}/"
+}
+
+resource "aws_s3_bucket_lifecycle_configuration" "events" {
+ bucket = aws_s3_bucket.events.id
+ expected_bucket_owner = local.this_account
+
+ rule {
+ id = "events"
+ status = "Enabled"
+
+ filter {
+ }
+
+ expiration {
+ days = var.event_staging_retention_config.current_days
+ }
+
+ noncurrent_version_expiration {
+ noncurrent_days = var.event_staging_retention_config.non_current_days
+ }
+ }
+}
diff --git a/infrastructure/terraform/components/reporting/s3_bucket_policy_events.tf b/infrastructure/terraform/components/reporting/s3_bucket_policy_events.tf
new file mode 100644
index 00000000..a54bb90b
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/s3_bucket_policy_events.tf
@@ -0,0 +1,28 @@
+resource "aws_s3_bucket_policy" "events" {
+ bucket = aws_s3_bucket.events.id
+ policy = data.aws_iam_policy_document.events.json
+}
+
+data "aws_iam_policy_document" "events" {
+ statement {
+ effect = "Deny"
+ actions = ["s3:*"]
+ resources = [
+ aws_s3_bucket.events.arn,
+ "${aws_s3_bucket.events.arn}/*",
+ ]
+
+ principals {
+ type = "AWS"
+ identifiers = ["*"]
+ }
+
+ condition {
+ test = "Bool"
+ variable = "aws:SecureTransport"
+ values = [
+ false
+ ]
+ }
+ }
+}
diff --git a/infrastructure/terraform/components/reporting/variables.tf b/infrastructure/terraform/components/reporting/variables.tf
index 3a1c983a..7ef0a2d2 100644
--- a/infrastructure/terraform/components/reporting/variables.tf
+++ b/infrastructure/terraform/components/reporting/variables.tf
@@ -252,3 +252,15 @@ variable "parent_acct_environment" {
description = "Name of the environment responsible for the acct resources used, affects things like DNS zone. Useful for named dev environments"
default = "main"
}
+
+variable "event_staging_retention_config" {
+ description = "The number of days for data retention policy for events in the staging table"
+ type = object({
+ current_days = number,
+ non_current_days = number,
+ })
+ default = {
+ current_days = 534,
+ non_current_days = 14,
+ }
+}
diff --git a/infrastructure/terraform/etc/env_eu-west-2_main.tfvars b/infrastructure/terraform/etc/env_eu-west-2_main.tfvars
index d3662737..b2c17b24 100644
--- a/infrastructure/terraform/etc/env_eu-west-2_main.tfvars
+++ b/infrastructure/terraform/etc/env_eu-west-2_main.tfvars
@@ -28,6 +28,11 @@ private_subnet_cidrs = [
"10.0.6.0/24"
]
-shared_infra_account_id = "099709604300"
+shared_infra_account_id = "099709604300"
destination_backup_vault_arn = "arn:aws:backup:eu-west-2:390844765011:backup-vault:nhs-notify-reporting-dev-backup-vault"
+
+event_staging_retention_config = {
+ current_days = 30,
+ non_current_days = 14
+}
diff --git a/infrastructure/terraform/etc/env_eu-west-2_ref.tfvars b/infrastructure/terraform/etc/env_eu-west-2_ref.tfvars
index 609bbaa5..3cd309cc 100644
--- a/infrastructure/terraform/etc/env_eu-west-2_ref.tfvars
+++ b/infrastructure/terraform/etc/env_eu-west-2_ref.tfvars
@@ -34,4 +34,9 @@ email_filter_client_ids = [
enable_s3_backup = false
-shared_infra_account_id = "099709604300"
+shared_infra_account_id = "099709604300"
+
+event_staging_retention_config = {
+ current_days = 7,
+ non_current_days = 14
+}
From 10b406e05d52857fd006ebdca145fcf0f52f1c94 Mon Sep 17 00:00:00 2001
From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com>
Date: Thu, 30 Apr 2026 17:22:00 +0100
Subject: [PATCH 4/5] CCM-16644: Add event staging table
---
.../glue_catalog_table_event_staging.tf | 140 ++++++++++++++++++
1 file changed, 140 insertions(+)
create mode 100644 infrastructure/terraform/components/reporting/glue_catalog_table_event_staging.tf
diff --git a/infrastructure/terraform/components/reporting/glue_catalog_table_event_staging.tf b/infrastructure/terraform/components/reporting/glue_catalog_table_event_staging.tf
new file mode 100644
index 00000000..6e33bd39
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/glue_catalog_table_event_staging.tf
@@ -0,0 +1,140 @@
+resource "aws_glue_catalog_table" "event_staging" {
+ name = "event_staging"
+ description = "Staging table for all event records."
+ database_name = aws_glue_catalog_database.reporting.name
+
+ table_type = "EXTERNAL_TABLE"
+
+ storage_descriptor {
+ location = "s3://${aws_s3_bucket.events.bucket}/${local.firehose_output_path_events}"
+
+ input_format = "org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat"
+ output_format = "org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat"
+
+ # additional columns must be added at the end of the list
+ columns {
+ name = "specversion"
+ type = "string"
+ }
+ columns {
+ name = "id"
+ type = "string"
+ }
+ columns {
+ name = "source"
+ type = "string"
+ }
+ columns {
+ name = "subject"
+ type = "string"
+ }
+ columns {
+ name = "type"
+ type = "string"
+ }
+ columns {
+ name = "time"
+ type = "string"
+ }
+ columns {
+ name = "datacontenttype"
+ type = "string"
+ }
+ columns {
+ name = "dataschema"
+ type = "string"
+ }
+ columns {
+ name = "data"
+ type = "string"
+ }
+ columns {
+ name = "traceparent"
+ type = "string"
+ }
+ columns {
+ name = "tracestate"
+ type = "string"
+ }
+ columns {
+ name = "partitionkey"
+ type = "string"
+ }
+ columns {
+ name = "recordedtime"
+ type = "string"
+ }
+ columns {
+ name = "sampledrate"
+ type = "string"
+ }
+ columns {
+ name = "sampledrate"
+ type = "int"
+ }
+ columns {
+ name = "sequence"
+ type = "string"
+ }
+ columns {
+ name = "severitytext"
+ type = "string"
+ }
+ columns {
+ name = "severitynumber"
+ type = "int"
+ }
+ columns {
+ name = "dataclassification"
+ type = "string"
+ }
+ columns {
+ name = "dataregulation"
+ type = "string"
+ }
+ columns {
+ name = "datacategory"
+ type = "string"
+ }
+ }
+
+ partition_keys {
+ name = "type"
+ type = "string"
+ }
+
+ partition_keys {
+ name = "year"
+ type = "int"
+ }
+ partition_keys {
+ name = "month"
+ type = "int"
+ }
+ partition_keys {
+ name = "day"
+ type = "int"
+ }
+
+ parameters = {
+ EXTERNAL = "TRUE"
+ "parquet.compression" = "SNAPPY"
+ compressionType = "none"
+ classification = "parquet"
+ }
+}
+
+resource "aws_glue_partition_index" "event_record" {
+ database_name = aws_glue_catalog_database.reporting.name
+ table_name = aws_glue_catalog_table.event_staging.name
+
+ partition_index {
+ index_name = "data"
+ keys = ["type", "year", "month", "day"]
+ }
+
+ timeouts {
+ create = "60m"
+ delete = "60m"
+ }
+}
From a52503b5be460d6d55658c15b1d5791f6e3ae193 Mon Sep 17 00:00:00 2001
From: Gareth Allan <157592212+gareth-allan@users.noreply.github.com>
Date: Fri, 1 May 2026 16:43:57 +0100
Subject: [PATCH 5/5] CCM-16644: Add a temporary SNS topic
---
.../reporting/iam_role_sns_events_firehose.tf | 44 +++++++++++++++++++
.../components/reporting/kms_key_s3.tf | 20 +++++++++
.../components/reporting/sns_topic_events.tf | 40 +++++++++++++++++
3 files changed, 104 insertions(+)
create mode 100644 infrastructure/terraform/components/reporting/iam_role_sns_events_firehose.tf
create mode 100644 infrastructure/terraform/components/reporting/sns_topic_events.tf
diff --git a/infrastructure/terraform/components/reporting/iam_role_sns_events_firehose.tf b/infrastructure/terraform/components/reporting/iam_role_sns_events_firehose.tf
new file mode 100644
index 00000000..af5f0e31
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/iam_role_sns_events_firehose.tf
@@ -0,0 +1,44 @@
+resource "aws_iam_role" "sns_events_firehose" {
+ name = "${local.csi}-sns-events-firehose-role"
+ assume_role_policy = data.aws_iam_policy_document.sns_events_firehose_assume_role.json
+}
+
+data "aws_iam_policy_document" "sns_events_firehose_assume_role" {
+ statement {
+ effect = "Allow"
+
+ principals {
+ type = "Service"
+ identifiers = ["sns.amazonaws.com"]
+ }
+
+ actions = ["sts:AssumeRole"]
+ }
+}
+
+resource "aws_iam_policy" "sns_events_firehose_delivery" {
+ name = "${local.csi}-sns-events-firehose-delivery"
+ description = "Allows SNS to publish events to the events Firehose stream"
+ policy = data.aws_iam_policy_document.sns_events_firehose_delivery.json
+}
+
+data "aws_iam_policy_document" "sns_events_firehose_delivery" {
+ statement {
+ sid = "AllowFirehoseDelivery"
+ effect = "Allow"
+
+ actions = [
+ "firehose:PutRecord",
+ "firehose:PutRecordBatch",
+ ]
+
+ resources = [
+ aws_kinesis_firehose_delivery_stream.events.arn,
+ ]
+ }
+}
+
+resource "aws_iam_role_policy_attachment" "sns_events_firehose_delivery" {
+ role = aws_iam_role.sns_events_firehose.name
+ policy_arn = aws_iam_policy.sns_events_firehose_delivery.arn
+}
diff --git a/infrastructure/terraform/components/reporting/kms_key_s3.tf b/infrastructure/terraform/components/reporting/kms_key_s3.tf
index 4387b6f2..2b8f7e9e 100644
--- a/infrastructure/terraform/components/reporting/kms_key_s3.tf
+++ b/infrastructure/terraform/components/reporting/kms_key_s3.tf
@@ -71,4 +71,24 @@ data "aws_iam_policy_document" "s3" {
]
}
}
+
+ statement {
+ sid = "AllowUsageFromSharedInfraAccount"
+ effect = "Allow"
+
+ principals {
+ type = "AWS"
+ identifiers = ["arn:aws:iam::${var.shared_infra_account_id}:root"]
+ }
+
+ actions = [
+ "kms:Encrypt",
+ "kms:Decrypt",
+ "kms:GenerateDataKey"
+ ]
+
+ resources = [
+ "*",
+ ]
+ }
}
diff --git a/infrastructure/terraform/components/reporting/sns_topic_events.tf b/infrastructure/terraform/components/reporting/sns_topic_events.tf
new file mode 100644
index 00000000..7ab63faa
--- /dev/null
+++ b/infrastructure/terraform/components/reporting/sns_topic_events.tf
@@ -0,0 +1,40 @@
+resource "aws_sns_topic" "events" {
+ name = "${local.csi}-events-topic"
+ kms_master_key_id = aws_kms_key.s3.arn
+}
+
+resource "aws_sns_topic_policy" "events" {
+ arn = aws_sns_topic.events.arn
+ policy = data.aws_iam_policy_document.sns_topic_events.json
+}
+
+data "aws_iam_policy_document" "sns_topic_events" {
+ policy_id = "__default_policy_ID"
+
+ statement {
+ sid = "AllowAllSNSActionsFromSharedAccount"
+ effect = "Allow"
+ actions = [
+ "SNS:Publish",
+ ]
+
+ principals {
+ type = "AWS"
+ identifiers = [
+ "arn:aws:iam::${var.shared_infra_account_id}:root"
+ ]
+ }
+
+ resources = [
+ aws_sns_topic.events.arn,
+ ]
+ }
+}
+
+resource "aws_sns_topic_subscription" "events_firehose" {
+ topic_arn = aws_sns_topic.events.arn
+ protocol = "firehose"
+ subscription_role_arn = aws_iam_role.sns_events_firehose.arn
+ endpoint = aws_kinesis_firehose_delivery_stream.events.arn
+ raw_message_delivery = true
+}