in src/construct-hub.ts [419:521]
private createVpc(isolation: Isolation, codeArtifact: Repository | undefined) {
if (isolation === Isolation.UNLIMITED_INTERNET_ACCESS) {
return { vpc: undefined, vpcEndpoints: undefined, vpcSubnets: undefined };
}
const subnetType = isolation === Isolation.NO_INTERNET_ACCESS
? ec2.SubnetType.ISOLATED
: ec2.SubnetType.PRIVATE_WITH_NAT;
const vpcSubnets = { subnetType };
const vpc = new ec2.Vpc(this, 'VPC', {
enableDnsHostnames: true,
enableDnsSupport: true,
// Provision no NAT gateways if we are running ISOLATED (we wouldn't have a public subnet)
natGateways: subnetType === ec2.SubnetType.ISOLATED ? 0 : undefined,
// Pre-allocating PUBLIC / PRIVATE / INTERNAL subnets, regardless of use, so we don't create
// a whole new VPC if we ever need to introduce subnets of these types.
subnetConfiguration: [
// If there is a PRIVATE subnet, there must also have a PUBLIC subnet (for NAT gateways).
{ name: 'Public', subnetType: ec2.SubnetType.PUBLIC, reserved: subnetType === ec2.SubnetType.ISOLATED },
{ name: 'Private', subnetType: ec2.SubnetType.PRIVATE_WITH_NAT, reserved: subnetType === ec2.SubnetType.ISOLATED },
{ name: 'Isolated', subnetType: ec2.SubnetType.ISOLATED, reserved: subnetType !== ec2.SubnetType.ISOLATED },
],
});
Tags.of(vpc.node.defaultChild!).add('Name', vpc.node.path);
const securityGroups = subnetType === ec2.SubnetType.PRIVATE_WITH_NAT
? createRestrictedSecurityGroups(this, vpc)
: undefined;
// Creating the CodeArtifact endpoints only if a repository is present.
const codeArtifactEndpoints = codeArtifact && {
codeArtifactApi: vpc.addInterfaceEndpoint('CodeArtifact.API', {
privateDnsEnabled: false,
service: new ec2.InterfaceVpcEndpointAwsService('codeartifact.api'),
subnets: vpcSubnets,
securityGroups,
}),
codeArtifact: vpc.addInterfaceEndpoint('CodeArtifact', {
privateDnsEnabled: true,
service: new ec2.InterfaceVpcEndpointAwsService('codeartifact.repositories'),
subnets: vpcSubnets,
securityGroups,
}),
};
// We'll only use VPC endpoints if we are configured to run in an ISOLATED subnet.
const vpcEndpoints = {
...codeArtifactEndpoints,
// This is needed so that ECS workloads can use the awslogs driver
cloudWatchLogs: vpc.addInterfaceEndpoint('CloudWatch.Logs', {
privateDnsEnabled: true,
service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS,
subnets: vpcSubnets,
securityGroups,
}),
// These are needed for ECS workloads to be able to pull images
ecrApi: vpc.addInterfaceEndpoint('ECR.API', {
privateDnsEnabled: true,
service: ec2.InterfaceVpcEndpointAwsService.ECR,
subnets: vpcSubnets,
securityGroups,
}),
ecr: vpc.addInterfaceEndpoint('ECR.Docker', {
privateDnsEnabled: true,
service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
subnets: vpcSubnets,
securityGroups,
}),
// This is needed (among others) for CodeArtifact registry usage
s3: vpc.addGatewayEndpoint('S3', {
service: ec2.GatewayVpcEndpointAwsService.S3,
subnets: [vpcSubnets],
}),
// This is useful for getting results from ECS tasks within workflows
stepFunctions: vpc.addInterfaceEndpoint('StepFunctions', {
privateDnsEnabled: true,
service: ec2.InterfaceVpcEndpointAwsService.STEP_FUNCTIONS,
subnets: vpcSubnets,
securityGroups,
}),
};
// The S3 access is necessary for the CodeArtifact Repository and ECR Docker
// endpoints to be used (they serve objects from S3).
vpcEndpoints.s3.addToPolicy(new PolicyStatement({
effect: Effect.ALLOW,
actions: ['s3:GetObject'],
resources: [
// The in-region CodeArtifact S3 Bucket
...codeArtifact ? [`${codeArtifact.s3BucketArn}/*`] : [],
// The in-region ECR layer bucket
`arn:aws:s3:::prod-${Stack.of(this).region}-starport-layer-bucket/*`,
],
// It doesn't seem we can constrain principals for these grants (unclear
// which principal those calls are made from, or if that is something we
// could name here).
principals: [new AnyPrincipal()],
sid: 'Allow-CodeArtifact-and-ECR',
}));
return { vpc, vpcEndpoints, vpcSubnets, vpcSecurityGroups: securityGroups };
}