Skip to content

Instantly share code, notes, and snippets.

@richard-gibson
Created February 8, 2023 20:53
Show Gist options
  • Save richard-gibson/6de838c4daa691fafdc975f66c2e23cc to your computer and use it in GitHub Desktop.
Save richard-gibson/6de838c4daa691fafdc975f66c2e23cc to your computer and use it in GitHub Desktop.
import {Template} from '@hexlabs/kloudformation-ts';
import {join, joinWith, Value, Base64Fn} from '@hexlabs/kloudformation-ts/dist/kloudformation/Value';
import {AWS} from '@hexlabs/kloudformation-ts/dist/kloudformation/aws';
import {InternetGateway} from '@hexlabs/kloudformation-ts/dist/aws/ec2/InternetGateway';
import {VPC} from '@hexlabs/kloudformation-ts/dist/aws/ec2/VPC';
import {VPCGatewayAttachment} from '@hexlabs/kloudformation-ts/dist/aws/ec2/VPCGatewayAttachment';
import {RouteTable} from '@hexlabs/kloudformation-ts/dist/aws/ec2/RouteTable';
import {SecurityGroup} from '@hexlabs/kloudformation-ts/dist/aws/ec2/SecurityGroup';
import {NatGateway} from '@hexlabs/kloudformation-ts/dist/aws/ec2/NatGateway';
import {Subnet} from '@hexlabs/kloudformation-ts/dist/aws/ec2/Subnet';
import {Instance} from '@hexlabs/kloudformation-ts/dist/aws/ec2/Instance';
const nameTag = (value: string) => ({key: 'Name', value})
function ec2Vpc(aws: AWS): VPC {
return aws.ec2VPC({
cidrBlock: '10.0.0.0/16',
instanceTenancy: 'default',
tags: [nameTag('DEMO-VPC')],
});
}
function subnet(aws: AWS, vpc: VPC, az: string, cidr: string, isPublic: boolean) {
const subnetName = `${cidr}-${az}`;
return aws.ec2Subnet({
vpcId: vpc,
availabilityZone: az,
cidrBlock: cidr,
mapPublicIpOnLaunch: isPublic,
tags: [nameTag(subnetName)],
});
}
function publicRoute(aws: AWS, vpcGateWayAttachment: VPCGatewayAttachment, internetGateWay: InternetGateway, routeTable: RouteTable) {
return aws.ec2Route({
_dependsOn: [vpcGateWayAttachment],
routeTableId: routeTable,
destinationCidrBlock: '0.0.0.0/0',
gatewayId: internetGateWay,
});
}
function privateRoute(aws: AWS, natGateway: NatGateway, routeTable: RouteTable) {
return aws.ec2Route({
routeTableId: routeTable,
destinationCidrBlock: '0.0.0.0/0',
natGatewayId: natGateway,
});
}
function publicSecurityGroup(aws: AWS, vpc: VPC) {
return aws.ec2SecurityGroup({
_logicalName: 'PublicSecurityGroup',
groupName: join(vpc.attributes.VpcId, '-WEB-SG'),
groupDescription: 'SSH and Port 80',
securityGroupIngress: ['22', '80'].map(port =>
({ipProtocol: 'tcp', fromPort: port, toPort: port, cidrIp: '0.0.0.0/0'}),
),
vpcId: vpc,
});
}
function privateSecurityGroup(aws: AWS, vpc: VPC, pubSubnetCidr: string) {
return aws.ec2SecurityGroup({
_logicalName: 'PrivateSecurityGroup',
groupName: join(vpc.attributes.VpcId, '-APP-PRIV-SG'),
groupDescription: 'priv SG',
securityGroupIngress: [...['22', '80']
.map(port => ({ipProtocol: 'tcp', fromPort: port, toPort: port, cidrIp: pubSubnetCidr})),
{ipProtocol: 'icmp', fromPort: '-1', toPort: '-1', cidrIp: pubSubnetCidr} //ping
],
vpcId: vpc,
});
}
function ec2Instance(
aws: AWS,
instanceName: string,
ec2SecurityGroup: SecurityGroup,
subNet: Subnet,
imageId: Value<string>,
keyName?: Value<string>,
userData?: Base64Fn,
): Instance {
return aws.ec2Instance({
instanceType: 't2.micro',
securityGroupIds: [ec2SecurityGroup.attributes.GroupId],
subnetId: subNet,
imageId,
...(keyName ? {keyName} : {}),
...(userData ? {userData} : {}),
blockDeviceMappings: [
{
deviceName: '/dev/sdc',
virtualName: 'ephemeral0',
},
],
tags: [nameTag(instanceName)],
});
}
export default Template.createWithParams({
KeyName: {type: 'String', default: 'vpc-demo-kp'},
LatestAmiId: {
type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>',
default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2',
},
}, {},
(aws, params) => {
const az1 = 'eu-west-1a';
// const az2 = 'eu-west-1b';
const vpc = ec2Vpc(aws);
const publicSubnetCidr = '10.0.1.0/24';
const privateSubnetCidr = '10.0.3.0/24';
const publicSubnet = subnet(aws, vpc, az1, publicSubnetCidr, true);
const privateSubnet = subnet(aws, vpc, az1, privateSubnetCidr, false);
const internetGateway = aws.ec2InternetGateway({tags: [nameTag('DEMO-VPC-IGW')]});
const vpcGateWayAttachment = aws.ec2VPCGatewayAttachment({vpcId: vpc, internetGatewayId: internetGateway});
const publicRouteTable = aws.ec2RouteTable({vpcId: vpc});
publicRoute(aws, vpcGateWayAttachment, internetGateway, publicRouteTable);
aws.ec2SubnetRouteTableAssociation({subnetId: publicSubnet, routeTableId: publicRouteTable});
const privateRouteTable = aws.ec2RouteTable({vpcId: vpc});
const natPublicIp = aws.ec2EIP({_dependsOn: [vpc], domain: vpc});
const natGateway = aws.ec2NatGateway({
_dependsOn: [natPublicIp],
subnetId: publicSubnet,
allocationId: natPublicIp.attributes.AllocationId,
tags:[nameTag('DEMO-VPC-NGW')]
});
//route out to internet from priv instance
privateRoute(aws, natGateway, privateRouteTable);
aws.ec2SubnetRouteTableAssociation({subnetId: privateSubnet, routeTableId: privateRouteTable});
// const nacl = aws.ec2NetworkAcl({
//
// })
const publicSG = publicSecurityGroup(aws, vpc);
ec2Instance(aws, 'WebServerPub', publicSG, publicSubnet, params.LatestAmiId(), params.KeyName(), {
'Fn::Base64': joinWith('\n',
"#!/bin/bash -xe",
"sudo yum update -y",
"sudo yum install httpd -y",
"sudo /etc/init.d/httpd start",
"echo \"<html><body><h1>Hello !!!</h1>\" > /var/www/html/index.html",
"echo \"</body></html>\" >> /var/www/html/index.html"
)
});
const privSG = privateSecurityGroup(aws, vpc, publicSubnetCidr);
ec2Instance(aws, 'AppServerPriv', privSG, privateSubnet, params.LatestAmiId(), params.KeyName());
}, `vpc.json`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment