feat(exec-aide): CMK SSE on exec-aide DynamoDB table (INFRA-95 / M-3) (#53)

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
This commit is contained in:
Adam Moussa 2026-06-09 12:41:55 -04:00 • committed by GitHub
parent 5052849725
commit 34e4634a9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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,
});