aws/aws-cdk

TableV2MultiAccountReplica: does not set top-level SSESpecification when using TableEncryptionV2.customerManagedKey(), causing deployment failure

Open

#37.783 aperta il 6 mag 2026

Vedi su GitHub
 (5 commenti) (0 reazioni) (0 assegnatari)TypeScript (3530 fork)batch import
@aws-cdk/aws-cloudformationbugeffort/smallgood first issuep2

Metriche repository

Star
 (10.710 star)
Metriche merge PR
 (Merge medio 14g 11h) (68 PR mergiate in 30 g)

Descrizione

Describe the bug

When using TableV2MultiAccountReplica with TableEncryptionV2.customerManagedKey(), the generated CloudFormation template is missing the top-level SSESpecification property on the AWS::DynamoDB::GlobalTable resource. This causes CloudFormation to fail with:

Resource handler returned message: "Invalid request provided: ReplicaSSESpecification and SSEType must be null when SSE is set to default."

Regression Issue

  • Select this option if this issue appears to be a regression.

Last Known Working CDK Library Version

No response

Expected Behavior

The TableV2MultiAccountReplica construct should render a top-level SSESpecification with SSEEnabled: true and SSEType: "KMS" when using customer-managed key encryption, matching the behavior of TableV2:

 {
   "Type": "AWS::DynamoDB::GlobalTable",
   "Properties": {
     "TableName": "MyGlobalTable",
     "GlobalTableSourceArn": "arn:aws:dynamodb:us-west-2:111111111111:table/MyGlobalTable",
     "SSESpecification": { /* <=== this */
       "SSEEnabled": true,
       "SSEType": "KMS"
     },
     "Replicas": [{
       "Region": "us-east-2",
       "SSESpecification": {
         "KMSMasterKeyId": "arn:aws:kms:us-east-2:222222222222:key/..."
       }
     }]
   }
 }

Current Behavior

TableV2MultiAccountReplica only sets SSESpecification.KMSMasterKeyId at the replica level, but omits the top-level SSESpecification entirely:

{
 "Type": "AWS::DynamoDB::GlobalTable",
 "Properties": {
   "TableName": "MyGlobalTable",
   "GlobalTableSourceArn": "arn:aws:dynamodb:us-west-2:111111111111:table/MyGlobalTable",
   "Replicas": [{
     "Region": "us-east-2",
     "SSESpecification": {
       "KMSMasterKeyId": "arn:aws:kms:us-east-2:222222222222:key/..."
     }
   }]
 }
}

DDB's CFN validator has a rule that says "all settings must be null if SSE is disabled". This lack of SSESpecification at the top-level is being interpreted as SSEEnabled: false. Because the replicas themselves have encryption info, the validator fails.

This seems to be backed up in the docs for SSESpecification:

Specifies the settings to enable server-side encryption. These settings will be applied to all replicas. If you plan to use customer-managed KMS keys, you must provide a key for each replica using the ReplicaSpecification.ReplicaSSESpecification property.

Reproduction Steps

import * as cdk from 'aws-cdk-lib';
import { Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import {
  AttributeType,
  Billing,
  TableEncryptionV2,
  TableV2,
  TableV2MultiAccountReplica,
} from 'aws-cdk-lib/aws-dynamodb';
import { Key } from 'aws-cdk-lib/aws-kms';

const PRIMARY_ACCOUNT = '111111111111';
const PRIMARY_REGION = 'us-west-2';
const REPLICA_ACCOUNT = '222222222222';
const REPLICA_REGION = 'us-east-2';

class PrimaryTableStack extends Stack {
  public readonly table: TableV2;

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const kmsKey = new Key(this, 'TableKey', { enableKeyRotation: true });

    this.table = new TableV2(this, 'GlobalTable', {
      tableName: 'MyGlobalTable',
      partitionKey: { name: 'pk', type: AttributeType.STRING },
      billing: Billing.onDemand(),
      encryption: TableEncryptionV2.customerManagedKey(kmsKey),
    });
  }
}

class ReplicaTableStack extends Stack {
  constructor(scope: Construct, id: string, primaryTable: TableV2, props?: cdk.StackProps) {
    super(scope, id, props);

    const kmsKey = new Key(this, 'TableKey', { enableKeyRotation: true });

    // BUG: This generates CloudFormation without top-level SSESpecification
    new TableV2MultiAccountReplica(this, 'GlobalTableReplica', {
      replicaSourceTable: primaryTable,
      encryption: TableEncryptionV2.customerManagedKey(kmsKey),
    });
  }
}

const app = new cdk.App();

const primaryStack = new PrimaryTableStack(app, 'PrimaryTableStack', {
  env: { account: PRIMARY_ACCOUNT, region: PRIMARY_REGION },
});

new ReplicaTableStack(app, 'ReplicaTableStack', primaryStack.table, {
  env: { account: REPLICA_ACCOUNT, region: REPLICA_REGION },
});

app.synth();

Possible Solution

The TableV2MultiAccountReplica doesn't have anything setting sseSpecification. TableV2 in the same file sets it here.

Additional Information/Context

I've been able to mitigate this with an escape hatch:

 const cfnTable = replicaTable.node.defaultChild as CfnGlobalTable;
 cfnTable.addPropertyOverride('SSESpecification', {
   SSEEnabled: true,
   SSEType: 'KMS',
 })

AWS CDK Library version (aws-cdk-lib)

2.241.0

AWS CDK CLI version

2.241.0

Node.js Version

20.x

OS

macOs

Language

TypeScript

Language Version

No response

Other information

No response

Guida contributor