Skip to content

Eli 704/adding cloudwatch metric filter cloudtrail#613

Draft
robbailiff2 wants to merge 5 commits intomainfrom
ELI-704/adding-cloudwatch-metric-filter-cloudtrail
Draft

Eli 704/adding cloudwatch metric filter cloudtrail#613
robbailiff2 wants to merge 5 commits intomainfrom
ELI-704/adding-cloudwatch-metric-filter-cloudtrail

Conversation

@robbailiff2
Copy link
Contributor

Description

Context

Type of changes

  • Refactoring (non-breaking change)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would change existing functionality)
  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I am familiar with the contributing guidelines
  • I have followed the code style of the project
  • I have added tests to cover my changes
  • I have updated the documentation accordingly
  • This PR is a result of pair or mob programming

Sensitive Information Declaration

To ensure the utmost confidentiality and protect your and others privacy, we kindly ask you to NOT including PII (Personal Identifiable Information) / PID (Personal Identifiable Data) or any other sensitive data in this PR (Pull Request) and the codebase changes. We will remove any PR that do contain any sensitive information. We really appreciate your cooperation in this matter.

  • I confirm that neither PII/PID nor sensitive data are included in this PR and the codebase changes.

@robbailiff2
Copy link
Contributor Author

Terraform plan on 20/03/26:

Terraform will perform the following actions:

  # data.aws_iam_policy_document.cloudtrail_cloudwatch_policy will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "cloudtrail_cloudwatch_policy" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions   = [
              + "logs:CreateLogGroup",
              + "logs:CreateLogStream",
              + "logs:PutLogEvents",
            ]
          + effect    = "Allow"
          + resources = [
              + (known after apply),
              + (known after apply),
            ]
        }
    }

  # data.aws_iam_policy_document.s3_cloudtrail_bucket_policy will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "s3_cloudtrail_bucket_policy" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions   = [
              + "s3:GetBucketLocation",
              + "s3:GetObject",
              + "s3:ListBucket",
              + "s3:PutObject",
            ]
          + resources = [
              + (known after apply),
              + (known after apply),
            ]
          + sid       = "AllowSSLRequestsOnly"

          + condition {
              + test     = "Bool"
              + values   = [
                  + "true",
                ]
              + variable = "aws:SecureTransport"
            }
        }
    }

  # data.aws_iam_policy_document.s3_cloudtrail_kms_access_policy will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "s3_cloudtrail_kms_access_policy" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions   = [
              + "kms:Decrypt",
              + "kms:DescribeKey",
              + "kms:Encrypt",
              + "kms:GenerateDataKey*",
              + "kms:ReEncrypt*",
            ]
          + resources = [
              + (known after apply),
            ]
        }
    }

  # aws_cloudtrail.data_events_trail will be created
  + resource "aws_cloudtrail" "data_events_trail" {
      + arn                           = (known after apply)
      + cloud_watch_logs_group_arn    = (known after apply)
      + cloud_watch_logs_role_arn     = (known after apply)
      + enable_log_file_validation    = true
      + enable_logging                = true
      + home_region                   = (known after apply)
      + id                            = (known after apply)
      + include_global_service_events = true
      + is_multi_region_trail         = false
      + is_organization_trail         = false
      + kms_key_id                    = (known after apply)
      + name                          = "eligibility-signposting-api-dev-data-events-trail"
      + s3_bucket_name                = "eligibility-signposting-api-dev-eli-cloudwatch-logs"
      + sns_topic_arn                 = (known after apply)
      + tags_all                      = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }

      + event_selector {
          + include_management_events = false
          + read_write_type           = "ReadOnly"

          + data_resource {
              + type   = "AWS::DynamoDB::Table"
              + values = [
                  + "arn:aws:dynamodb:eu-west-2:448049830832:table/eligibility-signposting-api-dev-eligibility_datastore",
                ]
            }
        }
    }

  # aws_cloudwatch_log_group.cloudtrail_log_group will be created
  + resource "aws_cloudwatch_log_group" "cloudtrail_log_group" {
      + arn               = (known after apply)
      + id                = (known after apply)
      + kms_key_id        = (known after apply)
      + log_group_class   = (known after apply)
      + name              = "elid-aws-cloudtrail-logs"
      + name_prefix       = (known after apply)
      + retention_in_days = 365
      + skip_destroy      = false
      + tags_all          = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }
    }

  # aws_cloudwatch_log_metric_filter.cloudtrail_custom_metrics["DynamoDBTableReadOutsideLambdaRole"] must be replaced
-/+ resource "aws_cloudwatch_log_metric_filter" "cloudtrail_custom_metrics" {
      ~ id             = "DynamoDBTableReadOutsideLambdaRole" -> (known after apply)
      ~ log_group_name = "test-dynamodb-aws-cloudtrail-logs-448049830832-2e96053a" -> "elid-aws-cloudtrail-logs" # forces replacement
        name           = "DynamoDBTableReadOutsideLambdaRole"
      ~ pattern        = "{($.eventSource=dynamodb.amazonaws.com) && (($.eventName=GetItem) || ($.eventName=Query) || ($.eventName=Scan)) && ($.requestParameters.tableName=\"eligibility-signposting-api-dev-eligibility_datastore
\") && (($.userIdentity.sessionContext.sessionIssuer.arn != \"arn:aws:iam::448049830832:role/eligibility_lambda-role\") || ($.userIdentity.sessionContext.sessionIssuer.arn NOT EXISTS))}" -> "{($.eventSource=dynamodb.amazonaws.c
om) && (($.eventName=GetItem) || ($.eventName=Query) || ($.eventName=Scan)) && ($.requestParameters.tableName=\"eligibility-signposting-api-dev-eligibility_datastore\") && ($.userIdentity.sessionContext.sessionIssuer.arn != \"arn:aws:iam::448049830832:role/eligibility_lambda-role\")}"

      ~ metric_transformation {
          - dimensions    = {} -> null
            name          = "DynamoDBTableReadOutsideLambdaRole"
            # (4 unchanged attributes hidden)
        }
    }

  # aws_cloudwatch_metric_alarm.cloudtrail_custom_metric_alarms["DynamoDBTableReadOutsideLambdaRole"] will be created
  + resource "aws_cloudwatch_metric_alarm" "cloudtrail_custom_metric_alarms" {
      + actions_enabled                       = true
      + alarm_actions                         = [
          + "arn:aws:sns:eu-west-2:448049830832:cloudwatch-security-alarms",
        ]
      + alarm_description                     = "DynamoDB table read detected from non-Lambda execution role"
      + alarm_name                            = "SecurityAlert-DynamoDBTableReadOutsideLambdaRole"
      + arn                                   = (known after apply)
      + comparison_operator                   = "GreaterThanOrEqualToThreshold"
      + evaluate_low_sample_count_percentiles = (known after apply)
      + evaluation_periods                    = 1
      + id                                    = (known after apply)
      + metric_name                           = "DynamoDBTableReadOutsideLambdaRole"
      + namespace                             = "security"
      + period                                = 300
      + statistic                             = "Sum"
      + tags                                  = {
          + "AlertType"   = "security"
          + "Environment" = "production"
          + "ManagedBy"   = "terraform"
          + "Severity"    = "high"
        }
      + tags_all                              = {
          + "AlertType"           = "security"
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "production"
          + "FinOpsTagVersion"    = "1"
          + "ManagedBy"           = "terraform"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Severity"            = "high"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }
      + threshold                             = 1
      + treat_missing_data                    = "notBreaching"
    }

  # aws_iam_role.cloudtrail_cloudwatch_role will be created
  + resource "aws_iam_role" "cloudtrail_cloudwatch_role" {
      + arn                   = (known after apply)
      + assume_role_policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "sts:AssumeRole"
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "cloudtrail.amazonaws.com"
                        }
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + create_date           = (known after apply)
      + force_detach_policies = false
      + id                    = (known after apply)
      + managed_policy_arns   = (known after apply)
      + max_session_duration  = 3600
      + name                  = "cloudtrail-cloudwatch-role"
      + name_prefix           = (known after apply)
      + path                  = "/"
      + permissions_boundary  = "arn:aws:iam::448049830832:policy/api-layer-ELIGIBILITY-SIGNPOSTING-API-PermissionsBoundary"
      + tags_all              = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }
      + unique_id             = (known after apply)

      + inline_policy (known after apply)
    }

  # aws_iam_role_policy.cloudtrail_cloudwatch_policy will be created
  + resource "aws_iam_role_policy" "cloudtrail_cloudwatch_policy" {
      + id          = (known after apply)
      + name        = "CloudTrailCloudWatchLogsAccess"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.s3_cloudtrail_bucket_policy will be created
  + resource "aws_iam_role_policy" "s3_cloudtrail_bucket_policy" {
      + id          = (known after apply)
      + name        = "S3CloudTrailBucketAccess"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_iam_role_policy.s3_cloudtrail_kms_access_policy will be created
  + resource "aws_iam_role_policy" "s3_cloudtrail_kms_access_policy" {
      + id          = (known after apply)
      + name        = "S3CloudTrailKMSAccess"
      + name_prefix = (known after apply)
      + policy      = (known after apply)
      + role        = (known after apply)
    }

  # aws_kms_alias.cloudtrail_kms_alias will be created
  + resource "aws_kms_alias" "cloudtrail_kms_alias" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name           = "alias/-cloudtrail-cmk"
      + name_prefix    = (known after apply)
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

  # aws_kms_key.cloudtrail_kms_key will be created
  + resource "aws_kms_key" "cloudtrail_kms_key" {
      + arn                                = (known after apply)
      + bypass_policy_lockout_safety_check = false
      + customer_master_key_spec           = "SYMMETRIC_DEFAULT"
      + deletion_window_in_days            = 14
      + description                        = "KMS key for CloudTrail log file encryption"
      + enable_key_rotation                = true
      + id                                 = (known after apply)
      + is_enabled                         = true
      + key_id                             = (known after apply)
      + key_usage                          = "ENCRYPT_DECRYPT"
      + multi_region                       = (known after apply)
      + policy                             = jsonencode(
            {
              + Statement = [
                  + {
                      + Action    = "kms:*"
                      + Effect    = "Allow"
                      + Principal = {
                          + AWS = "arn:aws:iam::448049830832:root"
                        }
                      + Resource  = "*"
                      + Sid       = "EnableRootPermissions"
                    },
                  + {
                      + Action    = [
                          + "kms:GenerateDataKey*",
                          + "kms:DescribeKey",
                          + "kms:Encrypt",
                        ]
                      + Effect    = "Allow"
                      + Principal = {
                          + Service = "cloudtrail.amazonaws.com"
                        }
                      + Resource  = "*"
                      + Sid       = "AllowCloudTrailEncryptLogs"
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + rotation_period_in_days            = (known after apply)
      + tags                               = {
          + "environment"  = "dev"
          + "project_name" = "eligibility-signposting-api"
          + "stack_name"   = "api-layer"
          + "workspace"    = "default"
        }
      + tags_all                           = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "environment"         = "dev"
          + "project_name"        = "eligibility-signposting-api"
          + "stack_name"          = "api-layer"
          + "workspace"           = "default"
        }
    }

  # aws_sns_topic_subscription.email_targets["adam.waller1@nhs.net"] will be destroyed
  # (because key ["adam.waller1@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:6c4ce0ab-9fa5-4b61-a4b0-834b30b893f4" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "adam.waller1@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:6c4ce0ab-9fa5-4b61-a4b0-834b30b893f4" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = false -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["ayesh.alshukri3@nhs.net"] will be destroyed
  # (because key ["ayesh.alshukri3@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:0cadf2b8-d0c5-4db8-9f9e-1664ef106dc9" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "ayesh.alshukri3@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:0cadf2b8-d0c5-4db8-9f9e-1664ef106dc9" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["edd.almond1@nhs.net"] will be destroyed
  # (because key ["edd.almond1@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:95fef6ab-017f-4849-ae0c-033281152123" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "edd.almond1@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:95fef6ab-017f-4849-ae0c-033281152123" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["karthikeyan.thangavel1@nhs.net"] will be destroyed
  # (because key ["karthikeyan.thangavel1@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:607f6498-06f0-4031-904b-18d1b47a5a86" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "karthikeyan.thangavel1@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:607f6498-06f0-4031-904b-18d1b47a5a86" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["rob.bailiff1@nhs.net"] will be destroyed
  # (because key ["rob.bailiff1@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:08927928-84e4-40a1-a183-de81691250ef" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "rob.bailiff1@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:08927928-84e4-40a1-a183-de81691250ef" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["sean.steberis3@nhs.net"] will be destroyed
  # (because key ["sean.steberis3@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:40eea2e5-dabf-4df2-ad82-c44e6d323a6b" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "sean.steberis3@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:40eea2e5-dabf-4df2-ad82-c44e6d323a6b" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["shweta.dongare1@nhs.net"] will be destroyed
  # (because key ["shweta.dongare1@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:07efeed8-b738-42ba-8f0a-fda3ae095309" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "shweta.dongare1@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:07efeed8-b738-42ba-8f0a-fda3ae095309" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # aws_sns_topic_subscription.email_targets["tom.eldridge1@nhs.net"] will be destroyed
  # (because key ["tom.eldridge1@nhs.net"] is not in for_each map)
  - resource "aws_sns_topic_subscription" "email_targets" {
      - arn                             = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:5161a497-9c5e-48e7-b2f9-d69529f1df88" -> null
      - confirmation_timeout_in_minutes = 1 -> null
      - confirmation_was_authenticated  = false -> null
      - endpoint                        = "tom.eldridge1@nhs.net" -> null
      - endpoint_auto_confirms          = false -> null
      - id                              = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications:5161a497-9c5e-48e7-b2f9-d69529f1df88" -> null
      - owner_id                        = "448049830832" -> null
      - pending_confirmation            = true -> null
      - protocol                        = "email" -> null
      - raw_message_delivery            = false -> null
      - topic_arn                       = "arn:aws:sns:eu-west-2:448049830832:secret-rotation-notifications" -> null
        # (6 unchanged attributes hidden)
    }

  # module.eligibility_signposting_lambda_function.aws_lambda_function.eligibility_signposting_lambda will be updated in-place
  ~ resource "aws_lambda_function" "eligibility_signposting_lambda" {
        id                             = "eligibility_signposting_api"
      ~ last_modified                  = "2026-03-19T15:11:30.000+0000" -> (known after apply)
      ~ qualified_arn                  = "arn:aws:lambda:eu-west-2:448049830832:function:eligibility_signposting_api:442" -> (known after apply)
      ~ qualified_invoke_arn           = "arn:aws:apigateway:eu-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-west-2:448049830832:function:eligibility_signposting_api:442/invocations" -> (known after apply)
      ~ source_code_hash               = "UlKkMZn3Oxc4Roa1P/bnsH63KLAGe4EzNjvBd8mc5Gg=" -> "MIe9/NElnfMlxFYQcbVXDrNOYASCdDOJa9Y0iVqOctk="
        tags                           = {}
      ~ version                        = "442" -> (known after apply)
        # (24 unchanged attributes hidden)

        # (5 unchanged blocks hidden)
    }

  # module.eligibility_status_table.aws_dynamodb_table.dynamodb_table will be updated in-place
  ~ resource "aws_dynamodb_table" "dynamodb_table" {
        id                          = "eligibility-signposting-api-dev-eligibility_datastore"
        name                        = "eligibility-signposting-api-dev-eligibility_datastore"
        tags                        = {
            "ApplicationRole"     = "API"
            "CostCentre"          = "129117"
            "Customer"            = "NHS England"
            "DataType"            = "PII"
            "Environment"         = "dev"
            "FinOpsTagVersion"    = "1"
            "OnOffPattern"        = "AlwaysOn"
            "Owner"               = "edd.almond1@nhs.net"
            "Product"             = "EligibilitySignpostingAPI"
            "Programme"           = "Vaccinations"
            "ProjectType"         = "Production"
            "PublicFacing"        = "Y"
            "ServiceCategory"     = "Silver"
            "Stack"               = "api-layer"
            "Tool"                = "Terraform"
            "data_classification" = "5"
            "workspace"           = "default"
        }
        # (13 unchanged attributes hidden)

      + server_side_encryption {
          + enabled     = true
          + kms_key_arn = "arn:aws:kms:eu-west-2:448049830832:key/1f42fe69-c28e-4edb-ad03-af06908fb200"
        }

        # (4 unchanged blocks hidden)
    }

  # module.s3_cloudtrail_bucket.data.aws_iam_policy_document.access_logs_s3_bucket_policy will be read during apply
  # (config refers to values not yet known)
 <= data "aws_iam_policy_document" "access_logs_s3_bucket_policy" {
      + id            = (known after apply)
      + json          = (known after apply)
      + minified_json = (known after apply)

      + statement {
          + actions   = [
              + "s3:*",
            ]
          + effect    = "Deny"
          + resources = [
              + (known after apply),
              + (known after apply),
            ]
          + sid       = "AllowSslRequestsOnly"

          + condition {
              + test     = "Bool"
              + values   = [
                  + "false",
                ]
              + variable = "aws:SecureTransport"
            }

          + principals {
              + identifiers = [
                  + "*",
                ]
              + type        = "*"
            }
        }
      + statement {
          + actions   = [
              + "s3:PutObject",
            ]
          + effect    = "Allow"
          + resources = [
              + (known after apply),
            ]
          + sid       = "S3ServerAccessLogsPolicy"

          + condition {
              + test     = "ArnEquals"
              + values   = [
                  + (known after apply),
                ]
              + variable = "aws:SourceArn"
            }

          + principals {
              + identifiers = [
                  + "logging.s3.amazonaws.com",
                ]
              + type        = "Service"
            }
        }
      + statement {
          + actions   = [
              + "s3:GetBucketAcl",
              + "s3:ListBucket",
            ]
          + effect    = "Allow"
          + resources = [
              + (known after apply),
            ]
          + sid       = "S3ServerAccessLogsDeliveryRootAccess"

          + condition {
              + test     = "ArnEquals"
              + values   = [
                  + (known after apply),
                ]
              + variable = "aws:SourceArn"
            }

          + principals {
              + identifiers = [
                  + "logging.s3.amazonaws.com",
                ]
              + type        = "Service"
            }
        }
    }

  # module.s3_cloudtrail_bucket.aws_kms_alias.storage_bucket_cmk will be created
  + resource "aws_kms_alias" "storage_bucket_cmk" {
      + arn            = (known after apply)
      + id             = (known after apply)
      + name           = "alias/eli-cloudwatch-logs-cmk"
      + name_prefix    = (known after apply)
      + target_key_arn = (known after apply)
      + target_key_id  = (known after apply)
    }

  # module.s3_cloudtrail_bucket.aws_kms_key.storage_bucket_cmk will be created
  + resource "aws_kms_key" "storage_bucket_cmk" {
      + arn                                = (known after apply)
      + bypass_policy_lockout_safety_check = false
      + customer_master_key_spec           = "SYMMETRIC_DEFAULT"
      + deletion_window_in_days            = 14
      + description                        = "eli-cloudwatch-logs Master Key"
      + enable_key_rotation                = true
      + id                                 = (known after apply)
      + is_enabled                         = true
      + key_id                             = (known after apply)
      + key_usage                          = "ENCRYPT_DECRYPT"
      + multi_region                       = (known after apply)
      + policy                             = (known after apply)
      + rotation_period_in_days            = (known after apply)
      + tags_all                           = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket.storage_bucket will be created
  + resource "aws_s3_bucket" "storage_bucket" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "eligibility-signposting-api-dev-eli-cloudwatch-logs"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags_all                    = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket.storage_bucket_access_logs will be created
  + resource "aws_s3_bucket" "storage_bucket_access_logs" {
      + acceleration_status         = (known after apply)
      + acl                         = (known after apply)
      + arn                         = (known after apply)
      + bucket                      = "eligibility-signposting-api-dev-eli-cloudwatch-logs-access-logs"
      + bucket_domain_name          = (known after apply)
      + bucket_prefix               = (known after apply)
      + bucket_regional_domain_name = (known after apply)
      + force_destroy               = false
      + hosted_zone_id              = (known after apply)
      + id                          = (known after apply)
      + object_lock_enabled         = (known after apply)
      + policy                      = (known after apply)
      + region                      = (known after apply)
      + request_payer               = (known after apply)
      + tags_all                    = {
          + "ApplicationRole"     = "API"
          + "CostCentre"          = "129117"
          + "Customer"            = "NHS England"
          + "DataType"            = "PII"
          + "Environment"         = "dev"
          + "FinOpsTagVersion"    = "1"
          + "OnOffPattern"        = "AlwaysOn"
          + "Owner"               = "edd.almond1@nhs.net"
          + "Product"             = "EligibilitySignpostingAPI"
          + "Programme"           = "Vaccinations"
          + "ProjectType"         = "Production"
          + "PublicFacing"        = "Y"
          + "ServiceCategory"     = "Silver"
          + "Stack"               = "api-layer"
          + "Tool"                = "Terraform"
          + "data_classification" = "5"
          + "workspace"           = "default"
        }
      + website_domain              = (known after apply)
      + website_endpoint            = (known after apply)

      + cors_rule (known after apply)

      + grant (known after apply)

      + lifecycle_rule (known after apply)

      + logging (known after apply)

      + object_lock_configuration (known after apply)

      + replication_configuration (known after apply)

      + server_side_encryption_configuration (known after apply)

      + versioning (known after apply)

      + website (known after apply)
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_lifecycle_configuration.storage_bucket will be created
  + resource "aws_s3_bucket_lifecycle_configuration" "storage_bucket" {
      + bucket                                 = (known after apply)
      + expected_bucket_owner                  = (known after apply)
      + id                                     = (known after apply)
      + transition_default_minimum_object_size = "all_storage_classes_128K"

      + rule {
          + id     = "StorageBucketExpirationTransferToIa"
          + status = "Enabled"
            # (1 unchanged attribute hidden)

          + abort_incomplete_multipart_upload {
              + days_after_initiation = 7
            }

          + expiration {
              + days                         = 1200
              + expired_object_delete_marker = false
            }

          + filter {
                # (1 unchanged attribute hidden)
            }

          + noncurrent_version_transition {
              + noncurrent_days = 30
              + storage_class   = "STANDARD_IA"
            }
        }
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_lifecycle_configuration.storage_bucket_access_logs_object_expiry_lifecycle_rule_config will be created
  + resource "aws_s3_bucket_lifecycle_configuration" "storage_bucket_access_logs_object_expiry_lifecycle_rule_config" {
      + bucket                                 = (known after apply)
      + expected_bucket_owner                  = (known after apply)
      + id                                     = (known after apply)
      + transition_default_minimum_object_size = "all_storage_classes_128K"

      + rule {
          + id     = "StorageBucketLogsExpiration"
          + status = "Enabled"
            # (1 unchanged attribute hidden)

          + expiration {
              + days                         = 5
              + expired_object_delete_marker = false
            }

          + filter {
                # (1 unchanged attribute hidden)
            }

          + noncurrent_version_expiration {
              + noncurrent_days = 5
            }
        }
      + rule {
          + id     = "StorageBucketLogsMultipartUploadExpiration"
          + status = "Enabled"
            # (1 unchanged attribute hidden)

          + abort_incomplete_multipart_upload {
              + days_after_initiation = 7
            }

          + filter {
                # (1 unchanged attribute hidden)
            }
        }
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_logging.storage_bucket_logging_config will be created
  + resource "aws_s3_bucket_logging" "storage_bucket_logging_config" {
      + bucket        = (known after apply)
      + id            = (known after apply)
      + target_bucket = "eligibility-signposting-api-dev-eli-cloudwatch-logs-access-logs"
      + target_prefix = "bucket_logs/"
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_policy.storage_bucket_access_logs will be created
  + resource "aws_s3_bucket_policy" "storage_bucket_access_logs" {
      + bucket = (known after apply)
      + id     = (known after apply)
      + policy = (known after apply)
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_public_access_block.storage_bucket_access_logs_public_access_block will be created
  + resource "aws_s3_bucket_public_access_block" "storage_bucket_access_logs_public_access_block" {
      + block_public_acls       = true
      + block_public_policy     = true
      + bucket                  = (known after apply)
      + id                      = (known after apply)
      + ignore_public_acls      = true
      + restrict_public_buckets = true
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_public_access_block.storage_bucket_block_public_access will be created
  + resource "aws_s3_bucket_public_access_block" "storage_bucket_block_public_access" {
      + block_public_acls       = true
      + block_public_policy     = true
      + bucket                  = (known after apply)
      + id                      = (known after apply)
      + ignore_public_acls      = true
      + restrict_public_buckets = true
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_server_side_encryption_configuration.storage_bucket_access_logs_server_side_encryption_config will be created
  + resource "aws_s3_bucket_server_side_encryption_configuration" "storage_bucket_access_logs_server_side_encryption_config" {
      + bucket = (known after apply)
      + id     = (known after apply)

      + rule {
          + apply_server_side_encryption_by_default {
              + kms_master_key_id = (known after apply)
              + sse_algorithm     = "aws:kms"
            }
        }
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_server_side_encryption_configuration.storage_bucket_server_side_encryption_config will be created
  + resource "aws_s3_bucket_server_side_encryption_configuration" "storage_bucket_server_side_encryption_config" {
      + bucket = (known after apply)
      + id     = (known after apply)

      + rule {
          + bucket_key_enabled = true

          + apply_server_side_encryption_by_default {
              + kms_master_key_id = (known after apply)
              + sse_algorithm     = "aws:kms"
            }
        }
    }

  # module.s3_cloudtrail_bucket.aws_s3_bucket_versioning.storage_bucket_versioning_config will be created
  + resource "aws_s3_bucket_versioning" "storage_bucket_versioning_config" {
      + bucket = (known after apply)
      + id     = (known after apply)

      + versioning_configuration {
          + mfa_delete = (known after apply)
          + status     = "Enabled"
        }
    }

Plan: 23 to add, 2 to change, 9 to destroy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants