aws / aws/aws-cdk

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

Open Beginner friendly
#37,783 5 comments 0 reactions 0 assignees View on GitHub
@aws-cdk/aws-cloudformation bug effort/small good first issue p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
1d 19h
Merged PRs (30d)
74

Description

### 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`](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-dynamodb-globaltable.html):
> 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](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts#L1447-L1463). `TableV2` in the same file [sets it here](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts#L853).

### 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_

Contributor guide

Open the contributing guide

Research direction

Start in packages/aws-cdk-lib/aws-dynamodb/lib/table-v2.ts, comparing TableV2's SSESpecification handling near line 853 with TableV2MultiAccountReplica near lines 1447-1463. Synthesize the reproduction stack and inspect the AWS::DynamoDB::GlobalTable resource; done means customer-managed-key replicas render top-level SSEEnabled true and SSEType KMS alongside the replica key settings.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, databases, infrastructure
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.