В настоящее время логический идентификатор ресурса формируется путем объединения имен всех конструкций в пути к ресурсу и добавления восьмисимвольного хэша MD5.
Это создает мусор, такой как VpcPrivateSubnet1DefaultRouteBE02A9ED, и, к сожалению, делает невозможным запрос ресурсов по их логическому идентификатору.
Есть ли способ контролировать, как называются логические идентификаторы?

В TypeScript метод, который вы ищете, это overrideLogicalId. Но вы должны сначала получить конструкцию CfnVpc более низкого уровня, используя следующий код (снова TypeScript):
let vpc = new ec2.Vpc(this, 'vpc', { natGateways: 1 })
let cfnVpc = vpc.node.defaultChild as ec2.CfnVPC
cfnVpc.overrideLogicalId('MainVpc')
Результаты в следующем yaml:
MainVpc:
Type: AWS::EC2::VPC
Немного опоздал на вечеринку, но вот моя реализация. Я удалил случайные символы в конце строки и заменил их логическим идентификатором, уникальным для всего проекта.
protected allocateLogicalId(cfnElement: CfnElement): string {
return cfnElement.logicalId.split('.')[1];
}