Skip to content

fix(asea): handle duplicate vpc names #1286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
"globals": "15.0.0",
"prettier": "3.0.3",
"typescript-eslint": "^7.6.0"
}
}
},
"packageManager": "[email protected]+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* and limitations under the License.
*/
import * as t from './types';
import * as crypto from 'crypto';

export const MandatoryAccountType = t.enums('MandatoryAccountType', [
'master',
Expand Down Expand Up @@ -1323,10 +1324,12 @@ export class AcceleratorConfig {
// Add mandatory account VPC configuration first
for (const [accountKey, accountConfig] of this.getMandatoryAccountConfigs()) {
for (const vpcConfig of accountConfig.vpc || []) {
const lzaVpcName = createLzaVpcName(vpcConfig.name, accountKey, vpcConfig.region);
vpcConfigs.push({
accountKey,
vpcConfig,
ouKey: accountConfig.ou,
lzaVpcName
});
}
}
Expand All @@ -1346,13 +1349,14 @@ export class AcceleratorConfig {
continue;
}
}
vpcConfig.lzaVpcName = `${vpcConfig.name}_${accountKey}`;
vpcConfig.lzaVpcName = createLzaVpcName(vpcConfig.name, accountKey, vpcConfig.region);
if (vpcConfig['cidr-src'] === 'dynamic') {
const lzaVpcName = createLzaVpcName(vpcConfig.name, accountKey, vpcConfig.region);
vpcConfigs.push({
ouKey,
accountKey,
vpcConfig,
lzaVpcName: `${vpcConfig.name}_${accountKey}`,
lzaVpcName,
});
}
}
Expand All @@ -1361,6 +1365,7 @@ export class AcceleratorConfig {
ouKey,
vpcConfig,
excludeAccounts,
lzaVpcName: createLzaVpcName(vpcConfig.name, ouKey, vpcConfig.region),
});
}
} else {
Expand All @@ -1369,6 +1374,7 @@ export class AcceleratorConfig {
ouKey,
accountKey: destinationAccountKey,
vpcConfig,
lzaVpcName: createLzaVpcName(vpcConfig.name, destinationAccountKey, vpcConfig.region)
});
}
}
Expand All @@ -1381,6 +1387,7 @@ export class AcceleratorConfig {
accountKey,
vpcConfig,
ouKey: accountConfig.ou,
lzaVpcName: createLzaVpcName(vpcConfig.name, accountKey, vpcConfig.region),
});
}
}
Expand All @@ -1406,3 +1413,10 @@ export class AcceleratorConfig {
}));
}
}

export function createLzaVpcName(vpcName: string, accountKey: string, region: string): string {
const md5Hash = crypto.createHash('md5').update(`${vpcName}_${accountKey}_${region}`).digest('hex');
const vpcNameWithType = vpcName.endsWith('_vpc') ? vpcName : `${vpcName}_vpc`;
const lzaVpcName = `${vpcNameWithType}..${md5Hash.substring(0,5)}`;
return lzaVpcName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
TransitGatewayRouteConfig,
VpcConfig,
VpcFlowLogsDestinationConfig,
createLzaVpcName,
} from './asea-config';
import { loadAseaConfig } from './asea-config/load';
import * as WriteToSourcesTypes from './common//utils/types/writeToSourcesTypes';
Expand Down Expand Up @@ -539,9 +540,9 @@ export class ConvertAseaConfig {
name: createNetworkFirewallName(firewallConfigName, this.aseaPrefix),
subnetChangeProtection: false,
tags: [],
vpc: createVpcName(lzaVpcName ?? vpcConfig.name),
vpc: lzaVpcName!,
subnets: this.getAzSubnets(vpcConfig, networkFirewallConfig.subnet.name).map((subnet) =>
createSubnetName(lzaVpcName ?? vpcConfig.name, subnet.subnetName, subnet.az),
createSubnetName(vpcConfig.name, subnet.subnetName, subnet.az),
),
});
}
Expand Down Expand Up @@ -1776,7 +1777,7 @@ export class ConvertAseaConfig {
name: instanceNameWithAz,
account,
launchTemplate,
vpc: `${vpcName}_vpc`,
vpc: firewallScopedVpcConfig?.lzaVpcName!,
terminationProtection,
detailedMonitoring,
tags,
Expand Down Expand Up @@ -2432,7 +2433,7 @@ export class ConvertAseaConfig {
const setConfigRulesConfig = async () => {
if (!globalOptions['aws-config']) return;
// TODO: Consider account regions for deploymentTargets
const currentNodeRuntime = 'nodejs18.x';
const currentNodeRuntime = 'nodejs20.x';
const rulesWithTarget: (AwsConfigRule & {
deployTo?: string[];
excludedAccounts?: string[];
Expand Down Expand Up @@ -2800,7 +2801,7 @@ export class ConvertAseaConfig {
if (route['target-vpc']) {
return {
account: this.getAccountKeyforLza(globalOptions, route['target-account'] || accountKey),
vpcName: createVpcName(route['target-vpc']),
vpcName: this.getLzaVpcName(route['target-vpc']),
};
} else if (route['target-vpn']) {
return {
Expand Down Expand Up @@ -2967,27 +2968,27 @@ export class ConvertAseaConfig {
sources: [],
};
for (const source of rule.source) {
let sourceVpcAccountKey: string | undefined = undefined;
let sourceVpcConfig: ResolvedVpcConfig | undefined;
if (SubnetSourceConfig.is(source)) {
sourceVpcAccountKey = this.vpcConfigs.find(({ vpcConfig }) => vpcConfig.name === source.vpc)?.accountKey;
sourceVpcConfig = this.vpcConfigs.find(({ vpcConfig }) => vpcConfig.name === source.vpc);
}
if (SecurityGroupSourceConfig.is(source)) {
lzaRule.sources.push({
lzaRule.sources.push({
securityGroups: source['security-group'].map(securityGroupName),
});
} else if (SubnetSourceConfig.is(source)) {
lzaRule.sources.push({
//account: this.getAccountKeyforLza(globalOptions, source.account || accountKey || ''),
account: this.getAccountKeyforLza(
globalOptions,
sourceVpcAccountKey || source.account || accountKey || '',
sourceVpcConfig?.accountKey || source.account || accountKey || '',
),
subnets: source.subnet.flatMap((sourceSubnet) =>
aseaConfig
.getAzSubnets(sourceVpcAccountKey || source.account || accountKey || '', source.vpc, sourceSubnet)
.getAzSubnets(sourceVpcConfig?.accountKey || source.account || accountKey || '', source.vpc, sourceSubnet)
.map((s) => createSubnetName(source.vpc, s.subnetName, s.az)),
),
vpc: createVpcName(source.vpc),
vpc: sourceVpcConfig?.lzaVpcName ?? source.vpc,
});
} else {
lzaRule.sources.push(source);
Expand All @@ -3011,7 +3012,6 @@ export class ConvertAseaConfig {
rules: NaclConfig[],
vpcConfig: VpcConfig,
accountKey?: string,
lzaVpcName?: string,
) => {
const lzaRules: (ConvertConfigTypes.LzaNaclInboundRuleType | ConvertConfigTypes.LzaNaclOutboundRuleType)[] = [];
for (const rule of rules) {
Expand Down Expand Up @@ -3055,18 +3055,17 @@ export class ConvertAseaConfig {
});
} else {
// determine which vpc the nacl rule references
// use the lzaVpcName when the config is from ou
let destination: string;
if (dest.vpc === vpcConfig.name) {
destination = createVpcName(lzaVpcName ?? vpcConfig.name);
destination = vpcConfig.name;
} else {
destination = createVpcName(dest.vpc);
destination = dest.vpc;
}
const destinationAccountKey = destinationVpcKey ? this.getAccountKeyforLza(globalOptions, destinationVpcKey): undefined;
target = {
account: destinationVpcKey ? this.getAccountKeyforLza(globalOptions, destinationVpcKey) : undefined,
account: destinationAccountKey,
subnet: createSubnetName(dest.vpc, ruleSubnet.subnetName, ruleSubnet.az),
//vpc: createVpcName(dest.vpc),
vpc: destination,
vpc: createLzaVpcName(destination, destinationAccountKey!, vpcConfig.region),
region: targetRegion,
};
}
Expand All @@ -3086,7 +3085,7 @@ export class ConvertAseaConfig {
}
return lzaRules;
};
const prepareNaclConfig = (vpcConfig: VpcConfig, accountKey?: string, lzaVpcName?: string) => {
const prepareNaclConfig = (vpcConfig: VpcConfig, accountKey?: string) => {
const naclSubnetConfigs = vpcConfig.subnets?.filter((s) => !!s.nacls);
if (!naclSubnetConfigs) return;
const nacls = [];
Expand All @@ -3100,8 +3099,8 @@ export class ConvertAseaConfig {
subnetAssociations: this.getAzSubnets(vpcConfig, subnetConfig.name).map((s) =>
createSubnetName(vpcConfig.name, s.subnetName, s.az),
),
inboundRules: prepareNaclRules(inboundRules, vpcConfig, accountKey, lzaVpcName),
outboundRules: prepareNaclRules(outboundRules, vpcConfig, accountKey, lzaVpcName),
inboundRules: prepareNaclRules(inboundRules, vpcConfig, accountKey),
outboundRules: prepareNaclRules(outboundRules, vpcConfig, accountKey),
});
}
return nacls;
Expand Down Expand Up @@ -3205,14 +3204,15 @@ export class ConvertAseaConfig {
vpcConfig: VpcConfig,
lzaEndpointsConfig: ConvertConfigTypes.ResolverEndpointsType[],
lzaEndpointsRulesConfig: ConvertConfigTypes.ResolverEndpointRulesType[],
accountKey: string | undefined,
): ConvertConfigTypes.ResolverEndpointsType[] => {
let inboundResolver = vpcConfig.resolvers!.inbound;
let outboundResolver = vpcConfig.resolvers!.outbound;
if (vpcConfig.resolvers) {
if (inboundResolver) {
lzaEndpointsConfig.push({
name: `${vpcConfig.name}InboundEndpoint`,
vpc: createVpcName(vpcConfig.lzaVpcName ?? vpcConfig.name),
vpc: createLzaVpcName(vpcConfig.name, accountKey!, vpcConfig.region),
subnets:
vpcConfig.subnets
?.find((subnetItem) => subnetItem.name === vpcConfig.resolvers?.subnet)
Expand All @@ -3226,7 +3226,7 @@ export class ConvertAseaConfig {
if (outboundResolver) {
lzaEndpointsConfig.push({
name: `${vpcConfig.name}OutboundEndpoint`,
vpc: createVpcName(vpcConfig.lzaVpcName ?? vpcConfig.name),
vpc: createLzaVpcName(vpcConfig.name, accountKey!, vpcConfig.region),
subnets:
vpcConfig.subnets
?.find((subnetItem) => subnetItem.name === vpcConfig.resolvers?.subnet)
Expand Down Expand Up @@ -3262,7 +3262,7 @@ export class ConvertAseaConfig {
return lzaEndpointsRulesConfig;
};

const prepareResolverConfig = (vpcConfig: VpcConfig) => {
const prepareResolverConfig = (vpcConfig: VpcConfig, accountKey: string | undefined) => {
let lzaResolverConfig: {
endpoints: ConvertConfigTypes.ResolverEndpointsType[] | undefined;
queryLogs: { name: string; destinations: string[] } | undefined;
Expand All @@ -3274,7 +3274,7 @@ export class ConvertAseaConfig {
let endpoints: any[] = [];
if (vpcConfig.resolvers) {
rules = prepareRulesConfig(vpcConfig, lzaEndpointsRulesConfig);
endpoints = prepareEndpointsConfig(vpcConfig, lzaEndpointsConfig, rules!);
endpoints = prepareEndpointsConfig(vpcConfig, lzaEndpointsConfig, rules!, accountKey);
}

lzaResolverConfig = {
Expand Down Expand Up @@ -3419,7 +3419,7 @@ export class ConvertAseaConfig {

const prepareVpcConfig = ({ accountKey, ouKey, vpcConfig, excludeAccounts, lzaVpcName }: ResolvedVpcConfig) => {
return {
name: createVpcName(lzaVpcName ?? vpcConfig.name),
name: lzaVpcName ?? createVpcName(vpcConfig.name),
account: accountKey ? this.getAccountKeyforLza(globalOptions, accountKey) : undefined,
deploymentTargets: !accountKey
? {
Expand Down Expand Up @@ -3458,13 +3458,13 @@ export class ConvertAseaConfig {
useCentralEndpoints: vpcConfig['use-central-endpoints'],
natGateways: prepareNatGatewayConfig(vpcConfig),
securityGroups: prepareSecurityGroupsConfig(vpcConfig, accountKey),
networkAcls: prepareNaclConfig(vpcConfig, accountKey, lzaVpcName),
networkAcls: prepareNaclConfig(vpcConfig, accountKey),
vpcFlowLogs: prepareVpcFlowLogs(vpcConfig['flow-logs']),
subnets: prepareSubnetConfig(vpcConfig, ouKey, accountKey),
transitGatewayAttachments: prepareTgwAttachConfig(vpcConfig),
virtualPrivateGateway: vpcConfig.vgw,
routeTables: prepareRouteTableConfig(vpcConfig, accountKey),
vpcRoute53Resolver: prepareResolverConfig(vpcConfig),
vpcRoute53Resolver: prepareResolverConfig(vpcConfig, accountKey),
};
};

Expand Down Expand Up @@ -3493,7 +3493,7 @@ export class ConvertAseaConfig {
.filter(({ vpcConfig }) => !!vpcConfig.pcx)
.map(({ vpcConfig }) => ({
name: peeringConnectionName(vpcConfig.name, vpcConfig.pcx!['source-vpc']),
vpcs: [createVpcName(vpcConfig.lzaVpcName ?? vpcConfig.name), createVpcName(vpcConfig.pcx!['source-vpc'])],
vpcs: [this.getLzaVpcName(vpcConfig.name), this.getLzaVpcName(vpcConfig.pcx!['source-vpc'])],
}));
};
await setCertificatesConfig();
Expand Down Expand Up @@ -3660,6 +3660,10 @@ export class ConvertAseaConfig {
);
}

private getLzaVpcName(vpcName: string): string {
return this.vpcConfigs.find((vc) => vc.vpcConfig.name === vpcName )?.lzaVpcName!
}

private getVpcCidr({ accountKey, vpcConfig, ouKey }: { accountKey?: string; vpcConfig: VpcConfig; ouKey?: string }) {
const cidrs: string[] = [];
if (vpcConfig['cidr-src'] === 'provided') {
Expand Down
2 changes: 1 addition & 1 deletion src/installer/cdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ class Installer extends cdk.Stack {
nodejs: 22,
},
commands: [
'npm install --global pnpm@10.4.1',
'npm install --global pnpm@10.11.0',
'pnpm install --frozen-lockfile',
'pnpm recursive run build',
],
Expand Down
4 changes: 2 additions & 2 deletions src/lib/cdk-accelerator/src/codebuild/cdk-deploy-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class PrebuiltCdkDeployProject extends CdkDeployProjectBase {
fs.writeFileSync(
path.join(this.projectTmpDir, 'Dockerfile'),
[
'FROM public.ecr.aws/bitnami/node:18',
'FROM public.ecr.aws/bitnami/node:22',
// Install the package manager
...installPackageManagerCommands(props.packageManager).map(cmd => `RUN ${cmd}`),
`WORKDIR ${appDir}`,
Expand Down Expand Up @@ -194,7 +194,7 @@ export class PrebuiltCdkDeployProject extends CdkDeployProjectBase {
*/
function installPackageManagerCommands(packageManager: PackageManager) {
if (packageManager === 'pnpm') {
return ['npm install --global pnpm@10.4.1'];
return ['npm install --global pnpm@10.11.0'];
}
throw new Error(`Unsupported package manager ${packageManager}`);
}
Expand Down