Describe the bug
cdk migrate --from-scan (and the underlying CfnTemplateGeneratorProvider.listResourceScanResources / getResourceScanRelatedResources methods) can silently drop real resources from the generated CloudFormation template / migrate.json when two distinct scanned resources share the value of only the first key of a compound ResourceIdentifier.
The bug is in deduplicateResources() in packages/aws-cdk/lib/commands/migrate.ts:
function deduplicateResources(resources: ResourceDetail[]) {
let uniqueResources: { [key: string]: ResourceDetail } = {};
for (const resource of resources) {
const key = Object.keys(resource.ResourceIdentifier!)[0]; // <-- only the FIRST key
const uniqueIdentifer = `${resource.ResourceType}:${key}:${resource.ResourceIdentifier![key]}`;
uniqueResources[uniqueIdentifer] = resource;
}
return Object.values(uniqueResources);
}
ResourceIdentifier (returned by the CloudFormation ListResourceScanResources / ListResourceScanRelatedResources APIs) can legitimately contain more than one key for resource types with compound identifiers. For example AWS::Route53::KeySigningKey is identified by the pair (HostedZoneId, Name) — the CLI itself documents this elsewhere (packages/@aws-cdk/toolkit-lib/lib/api/resource-import/importer.ts).
Because deduplicateResources only reads Object.keys(resource.ResourceIdentifier!)[0] and ignores the remaining identifier components, two genuinely distinct resources that happen to share the value of just their first identifier key collide on the same synthetic dedup key and one silently overwrites the other in uniqueResources.
Impact
Any customer running cdk migrate --from-scan against an account that has multiple resources of a compound-identifier type sharing the leading identifier key (e.g. two AWS::Route53::KeySigningKey resources in the same hosted zone with different names) will have some of those resources silently dropped — no error, no warning — from the generated CDK app/template. The gap is only discovered later when resources turn out to be missing from the migrated stack.
Expected Behavior
deduplicateResources should use the entire ResourceIdentifier map (all key/value pairs) to determine resource uniqueness, not just the first key.
Reproduction
Unit-test level repro: call deduplicateResources (or exercise it via generateTemplate) with two ResourceDetail entries such as:
{ ResourceType: 'AWS::Route53::KeySigningKey', ResourceIdentifier: { HostedZoneId: 'Z1', Name: 'ksk-one' } }
{ ResourceType: 'AWS::Route53::KeySigningKey', ResourceIdentifier: { HostedZoneId: 'Z1', Name: 'ksk-two' } }
Both resources share HostedZoneId: 'Z1' as their first key, so today they collapse to a single entry in the deduplicated list even though they are two distinct resources.
CDK CLI Version
main (current)
Environment
N/A - code-level bug, not environment specific
Describe the bug
cdk migrate --from-scan(and the underlyingCfnTemplateGeneratorProvider.listResourceScanResources/getResourceScanRelatedResourcesmethods) can silently drop real resources from the generated CloudFormation template /migrate.jsonwhen two distinct scanned resources share the value of only the first key of a compoundResourceIdentifier.The bug is in
deduplicateResources()inpackages/aws-cdk/lib/commands/migrate.ts:ResourceIdentifier(returned by the CloudFormationListResourceScanResources/ListResourceScanRelatedResourcesAPIs) can legitimately contain more than one key for resource types with compound identifiers. For exampleAWS::Route53::KeySigningKeyis identified by the pair(HostedZoneId, Name)— the CLI itself documents this elsewhere (packages/@aws-cdk/toolkit-lib/lib/api/resource-import/importer.ts).Because
deduplicateResourcesonly readsObject.keys(resource.ResourceIdentifier!)[0]and ignores the remaining identifier components, two genuinely distinct resources that happen to share the value of just their first identifier key collide on the same synthetic dedup key and one silently overwrites the other inuniqueResources.Impact
Any customer running
cdk migrate --from-scanagainst an account that has multiple resources of a compound-identifier type sharing the leading identifier key (e.g. twoAWS::Route53::KeySigningKeyresources in the same hosted zone with different names) will have some of those resources silently dropped — no error, no warning — from the generated CDK app/template. The gap is only discovered later when resources turn out to be missing from the migrated stack.Expected Behavior
deduplicateResourcesshould use the entireResourceIdentifiermap (all key/value pairs) to determine resource uniqueness, not just the first key.Reproduction
Unit-test level repro: call
deduplicateResources(or exercise it viagenerateTemplate) with twoResourceDetailentries such as:Both resources share
HostedZoneId: 'Z1'as their first key, so today they collapse to a single entry in the deduplicated list even though they are two distinct resources.CDK CLI Version
main (current)
Environment
N/A - code-level bug, not environment specific