fix: grant KMS on seahaven-dynamodb CMK to PaymentsDashboard consumers (INFRA-104) (#44)
Some checks are pending
Deploy / deploy (push) Waiting to run

The PaymentsDashboard table was migrated to SSE-KMS (alias/seahaven-dynamodb,
INFRA-95/M-3) out-of-band, but no function role had kms perms. fetchBoaTransactions
failed 6/6 daily runs with kms:Decrypt AccessDeniedException, taking the BoA
transaction feed 100% down; the other 3 table consumers were latently broken too.

- Add kms:Decrypt/GenerateDataKey/DescribeKey to processPayrollEmail,
  processPaymentCsv, fetchBoaTransactions (read-write) and kms:Decrypt/DescribeKey
  to slackAppHome (read-only). Actions match the lambda permissions boundary.
- Declare SSESpecification on the table to reconcile out-of-band drift (idempotent).
- Resolve the CMK arn from SSM /seahaven/dynamodb/cmk-arn.

GPT-4.1 cross-review: no blockers.
This commit is contained in:
Adam Moussa 2026-06-10 19:31:59 -04:00 • committed by GitHub
parent ea64f27f2c
commit edf681c4ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,6 +2,16 @@ AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Payments Dashboard - S3 CSV ingestion to Slack App Home
Parameters:
DynamoDbCmkArn:
Type: AWS::SSM::Parameter::Value<String>
Default: /seahaven/dynamodb/cmk-arn
Description: >-
ARN of the shared customer-managed CMK (alias/seahaven-dynamodb) that
encrypts the PaymentsDashboard table. Functions that read/write the table
need kms:Decrypt/GenerateDataKey/DescribeKey on this key (the boundary
permits exactly these), or DynamoDB calls fail with AccessDeniedException.
Globals:
Function:
Runtime: nodejs22.x
@ -167,6 +177,14 @@ Resources:
TimeToLiveSpecification:
AttributeName: ttl
Enabled: true
# SSE-KMS with the shared CMK (alias/seahaven-dynamodb, INFRA-95 / M-3).
# The table was migrated to this key out-of-band, so declaring it here
# reconciles the template drift (no-op against the live table). Consumer
# roles still need explicit kms perms below (SAM policies do not auto-add).
SSESpecification:
SSEEnabled: true
SSEType: KMS
KMSMasterKeyId: !Ref DynamoDbCmkArn
PayrollEmailBucket:
Type: AWS::S3::Bucket
@ -385,6 +403,14 @@ Resources:
BucketName: !Sub seahaven-payroll-emails-${AWS::AccountId}
- DynamoDBCrudPolicy:
TableName: !Ref DashboardTable
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- kms:Decrypt
- kms:GenerateDataKey
- kms:DescribeKey
Resource: !Ref DynamoDbCmkArn
- Version: "2012-10-17"
Statement:
- Effect: Allow
@ -433,6 +459,14 @@ Resources:
BucketName: !Sub seahaven-payments-csv-${AWS::AccountId}
- DynamoDBCrudPolicy:
TableName: !Ref DashboardTable
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- kms:Decrypt
- kms:GenerateDataKey
- kms:DescribeKey
Resource: !Ref DynamoDbCmkArn
- Version: "2012-10-17"
Statement:
- Effect: Allow
@ -469,6 +503,13 @@ Resources:
Policies:
- DynamoDBReadPolicy:
TableName: !Ref DashboardTable
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- kms:Decrypt
- kms:DescribeKey
Resource: !Ref DynamoDbCmkArn
- Version: "2012-10-17"
Statement:
- Effect: Allow
@ -508,6 +549,14 @@ Resources:
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref DashboardTable
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- kms:Decrypt
- kms:GenerateDataKey
- kms:DescribeKey
Resource: !Ref DynamoDbCmkArn
- Version: "2012-10-17"
Statement:
- Effect: Allow