From 9f14124b8b356be5c77dd03d781f7f5718c1541b Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Tue, 9 Jun 2026 11:59:27 -0400 Subject: [PATCH] feat(exec-aide): CMK SSE on exec-aide DynamoDB table (INFRA-95 / M-3) Switch the exec-aide table from the AWS-owned key to the shared customer-managed CMK (alias/seahaven-dynamodb, imported via SSM /seahaven/dynamodb/cmk-arn). In-place UpdateTable, no replacement. CDK auto-grants kms to the 5 in-stack consumer roles (4 pipeline Lambdas + SocketMode Fargate task role). Deployed + verified: SSEType=KMS, scan decrypts, ECS service healthy. INFRA-95 --- lib/constructs/email-pipeline.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/constructs/email-pipeline.ts b/lib/constructs/email-pipeline.ts index b25ad66..2dca042 100644 --- a/lib/constructs/email-pipeline.ts +++ b/lib/constructs/email-pipeline.ts @@ -1,6 +1,8 @@ import { Construct } from 'constructs'; import * as cdk from 'aws-cdk-lib'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as ssm from 'aws-cdk-lib/aws-ssm'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as events from 'aws-cdk-lib/aws-events'; import * as targets from 'aws-cdk-lib/aws-events-targets'; @@ -22,12 +24,29 @@ export class EmailPipelineConstruct extends Construct { // ── DynamoDB ────────────────────────────────────────────── + // Shared customer-managed CMK for sensitive DynamoDB SSE (INFRA-95 / M-3). + // The key is owned by the seahaven-dynamodb-cmk stack (account-baseline + // repo); its ARN is published to SSM and imported here. The exec-aide table + // holds inbox PII (email senders/subjects/bodies, conversation state). + // CDK's grantReadWriteData/grantReadData auto-add the matching KMS actions + // to every consumer role (the 4 pipeline Lambdas + the socket-mode Fargate + // task role) when the table carries an encryptionKey, so no manual KMS grant + // is needed. SSE change is an in-place UpdateTable (no downtime). + const dynamodbCmk = kms.Key.fromKeyArn( + this, + 'DynamoDbCmk', + ssm.StringParameter.valueForStringParameter(this, '/seahaven/dynamodb/cmk-arn'), + ); + this.table = new dynamodb.Table(this, 'Table', { tableName: 'exec-aide', billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, partitionKey: { name: 'pk', type: dynamodb.AttributeType.STRING }, sortKey: { name: 'sk', type: dynamodb.AttributeType.STRING }, timeToLiveAttribute: 'ttl', + // INFRA-95 / M-3: customer-managed CMK SSE (was AWS-owned key). + encryption: dynamodb.TableEncryption.CUSTOMER_MANAGED, + encryptionKey: dynamodbCmk, removalPolicy: cdk.RemovalPolicy.RETAIN, });