diff --git a/.github/workflows/preview-env.yml b/.github/workflows/preview-env.yml index 2c3b11cd..6cb7147e 100644 --- a/.github/workflows/preview-env.yml +++ b/.github/workflows/preview-env.yml @@ -168,7 +168,7 @@ jobs: with: mtls-secret-name: ${{ vars.PREVIEW_ENV_MTLS_SECRET_NAME}} target-url: ${{ steps.tf-output.outputs.preview_url }} - proxy-base-path: 'clinical-data-gateway-api-poc-pr-${{ github.event.pull_request.number }}' + proxy-base-path: "clinical-data-gateway-api-poc-pr-${{ github.event.pull_request.number }}" proxygen-key-secret: ${{ env._cds_gateway_dev_proxygen_proxygen_key_secret }} proxygen-key-id: ${{ vars.PREVIEW_ENV_PROXYGEN_KEY_ID }} proxygen-api-name: ${{ vars.PROXYGEN_API_NAME }} @@ -178,7 +178,7 @@ jobs: if: github.event.action == 'closed' uses: ./.github/actions/proxy/tear-down-proxy with: - proxy-base-path: 'clinical-data-gateway-api-poc-pr-${{ github.event.pull_request.number }}' + proxy-base-path: "clinical-data-gateway-api-poc-pr-${{ github.event.pull_request.number }}" proxygen-key-secret: ${{ env._cds_gateway_dev_proxygen_proxygen_key_secret }} proxygen-key-id: ${{ vars.PREVIEW_ENV_PROXYGEN_KEY_ID }} proxygen-api-name: ${{ vars.PROXYGEN_API_NAME }} @@ -348,6 +348,13 @@ jobs: }); # ---------- Security scanning ---------- + - name: Trivy IaC scan + if: github.event.action != 'closed' + uses: nhs-england-tools/trivy-action/iac-scan@3456c1657a37d500027fd782e6b08911725392da + with: + scan-ref: infrastructure/environments/preview + artifact-name: trivy-iac-scan-${{ steps.meta.outputs.branch_name }} + - name: Trivy filesystem scan if: github.event.action != 'closed' uses: nhs-england-tools/trivy-action/image-scan@3456c1657a37d500027fd782e6b08911725392da diff --git a/infrastructure/environments/preview/main.tf b/infrastructure/environments/preview/main.tf index faab12f0..1e269dc1 100644 --- a/infrastructure/environments/preview/main.tf +++ b/infrastructure/environments/preview/main.tf @@ -4,6 +4,8 @@ data "aws_region" "current" {} +data "aws_caller_identity" "current" {} + data "terraform_remote_state" "core" { backend = "s3" config = { @@ -38,6 +40,8 @@ locals { alb_listener_arn = data.terraform_remote_state.core.outputs.alb_listener_arn ecs_cluster_name = data.terraform_remote_state.core.outputs.ecs_cluster_name ecr_repository_url = data.terraform_remote_state.core.outputs.ecr_repository_url + + log_kms_key_id = var.log_kms_key_id != null ? var.log_kms_key_id : aws_kms_key.log_group[0].arn } ############################ @@ -141,6 +145,57 @@ resource "aws_iam_role_policy" "task_exec_command" { resource "aws_cloudwatch_log_group" "branch" { name = local.log_group_name retention_in_days = var.log_retention_days + kms_key_id = local.log_kms_key_id +} + +resource "aws_kms_key" "log_group" { + count = var.log_kms_key_id == null ? 1 : 0 + + description = "KMS key for preview CloudWatch Logs" + deletion_window_in_days = 30 + enable_key_rotation = true + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "EnableRootPermissions" + Effect = "Allow" + Principal = { + AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" + } + Action = "kms:*" + Resource = "*" + }, + { + Sid = "AllowCloudWatchLogs" + Effect = "Allow" + Principal = { + Service = "logs.${data.aws_region.current.name}.amazonaws.com" + } + Action = [ + "kms:Encrypt", + "kms:Decrypt", + "kms:ReEncrypt*", + "kms:GenerateDataKey*", + "kms:DescribeKey" + ] + Resource = "*" + Condition = { + ArnLike = { + "kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:${local.log_group_name}*" + } + } + } + ] + }) +} + +resource "aws_kms_alias" "log_group" { + count = var.log_kms_key_id == null ? 1 : 0 + + name = "alias/preview-logs-${local.branch_role_suffix}" + target_key_id = aws_kms_key.log_group[0].key_id } ############################ diff --git a/infrastructure/environments/preview/variables.tf b/infrastructure/environments/preview/variables.tf index 15ddaedb..4cbd1918 100644 --- a/infrastructure/environments/preview/variables.tf +++ b/infrastructure/environments/preview/variables.tf @@ -49,3 +49,9 @@ variable "log_retention_days" { type = number default = 14 } + +variable "log_kms_key_id" { + description = "KMS CMK ARN or ID used to encrypt the CloudWatch log group." + type = string + default = null +}