Skip to content

Instantly share code, notes, and snippets.

@clstokes

clstokes/index.ts

Forked from kevink/index.ts
Created Mar 26, 2020
Embed
What would you like to do?
Test Script for AWS infra
// Copyright 2016-2019, Pulumi Corporation. All rights reserved.
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
import * as pulumi from "@pulumi/pulumi";
//import { VpcEndpointService } from "@pulumi/aws/ec2";
// ****************************************************************************************************************************************
// Grab some secrets from our config file
// ****************************************************************************************************************************************
// Get the config ready to go.
const config = new pulumi.Config();
// If keyName is provided, an existing KeyPair is used, else if publicKey is provided a new KeyPair derived from the publicKey is created.
let keyName: pulumi.Input<string> | string | undefined = config.get("keyName");
const publicKey = config.get("publicKey");
// The privateKey associated with the selected key must be provided (either directly or base64 encoded), along with an optional passphrase if needed.
const privateKey = config.requireSecret("privateKey").apply(key => {
if (key.startsWith("-----BEGIN RSA PRIVATE KEY-----")) {
return key;
} else {
return Buffer.from(key, "base64").toString("ascii");
}
});
const privateKeyPassphrase = config.getSecret("privateKeyPassphrase");
// ****************************************************************************************************************************************
// Setup VPC, Security Groups
// ****************************************************************************************************************************************
const vpc = new awsx.ec2.Vpc("api-vpc", {
cidrBlock: "10.1.0.0/16",
//enableDnsHostnames: true,
//enableDnsSupport: true,
numberOfAvailabilityZones: 2,
subnets: [
{ type: "public" },
{ type: "private" },
// { type: "isolated", name: "db" },
// { type: "isolated", name: "redis" },
],
tags: { Name: "api-vpc" }
});
// Create a new security group that permits SSH and web access.
const secgrp = new aws.ec2.SecurityGroup("api-secgrp", {
vpcId: vpc.id,
description: "api-secgrp",
ingress: [
{ protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["0.0.0.0/0"] },
{ protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] },
{ protocol: "tcp", fromPort: 443, toPort: 443, cidrBlocks: ["0.0.0.0/0"] },
{ protocol: "tcp", fromPort: 3306, toPort: 3306, cidrBlocks: ["216.160.116.174/32"] }, // whitelist my home network
{ protocol: "tcp", fromPort: 3306, toPort: 3306, cidrBlocks: [vpc.vpc.cidrBlock] }, // whitelist internal network
{ protocol: "tcp", fromPort: 3306, toPort: 3306, cidrBlocks: ["172.31.0.0/16"] }, // whitelist internal network
],
egress: [
{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: [ "0.0.0.0/0" ] },
],
tags: { Name: "api-secgrp" },
});
// ****************************************************************************************************************************************
// Setup our EC2 Instance
// ****************************************************************************************************************************************
// Get our Debian AMI
const amiId = aws.getAmi({
owners: ["379101102735"],
mostRecent: true,
filters: [{
name: "name",
values: ["debian-stretch-hvm-x86_64-gp2-2020-02-10-73984"],
}],
}, { async: true }).then(ami => ami.id);
// Create a small EC2 server that we'll then provision stuff onto.
const size = "t2.micro";
if (!keyName) {
const key = new aws.ec2.KeyPair("key", { publicKey: publicKey! });
keyName = key.keyName;
}
// Launch it in the sec group we made above
const apiserver = new aws.ec2.Instance("api-server", {
instanceType: size,
// availabilityZone: "us-west-2a", // not needed when specifying the subnet
subnetId: vpc.publicSubnetIds[0], // use the subnet(s) from awsx.ec2.Vpc
ami: amiId,
keyName: keyName,
vpcSecurityGroupIds: [ secgrp.id ],
tags: {
Name: "api-server",
},
ebsBlockDevices: [
{
volumeSize: 15,
encrypted: true,
deviceName: "/dev/xvdh"
}
],
volumeTags: {
snapshotable: "true"
},
// TODO: Remove - this is just for testing http connectivity.
userData: `#!/bin/bash
apt update
apt install -y nginx `
});
// make sure we can ssh in
const conn = {
host: apiserver.publicIp,
username: "ec2-user",
privateKey,
privateKeyPassphrase,
};
// ****************************************************************************************************************************************
// Create our database instance
// ****************************************************************************************************************************************
// Create a new subnet group for the database from our subnets
const dbSubnetGroup = new aws.rds.SubnetGroup("api-dbsubnets", {
subnetIds: vpc.privateSubnetIds, // use the subnet(s) from awsx.ec2.Vpc
});
const db = new aws.rds.Instance("api-mysqldb", {
engine: "mysql",
// availabilityZone: "us-west-2a", // not needed when specifying the subnet
instanceClass: "db.t2.micro",
allocatedStorage: 20,
publiclyAccessible: true,
dbSubnetGroupName: dbSubnetGroup.name,
vpcSecurityGroupIds: [ secgrp.id ],
name: "absdata",
username: "absdata",
password: config.getSecret("dbPassword"),
skipFinalSnapshot: true,
});
// ****************************************************************************************************************************************
// Create our application load balancer, TargetGroups and Listener
// ****************************************************************************************************************************************
const alb = new aws.lb.LoadBalancer("api-lb", {
// accessLogs: {
// bucket: aws_s3_bucket_lb_logs.bucket,
// enabled: true,
// prefix: "test-lb",
// },
//enableDeletionProtection: true,
internal: false,
loadBalancerType: "application",
securityGroups: [secgrp.id],
subnets: vpc.publicSubnetIds,
tags: {
Environment: "production",
},
});
const tg1 = new aws.lb.TargetGroup("api-tg1", {
port: 80,
protocol: "HTTP",
vpcId: vpc.id,
});
const tg1attachment = new aws.lb.TargetGroupAttachment("api-tg1", {
targetGroupArn: tg1.arn,
targetId: apiserver.id,
});
const tg2 = new aws.lb.TargetGroup("api-tg2", {
port: 80,
protocol: "HTTP",
vpcId: vpc.id,
});
const tg2attachment = new aws.lb.TargetGroupAttachment("api-tg2", {
targetGroupArn: tg2.arn,
targetId: apiserver.id,
});
// Fixed-response Listener
const listener = new aws.lb.Listener("api-listener", {
// certificateArn: "arn:aws:acm:us-west-2:353450002364:certificate/ebcfcee2-883d-4667-ac80-911bb99e8c93",
defaultActions: [{
targetGroupArn: tg1.arn,
type: "forward",
}],
loadBalancerArn: alb.arn,
port: 80,
protocol: "HTTP",
// sslPolicy: "ELBSecurityPolicy-2016-08",
});
const generateListenerRule = (
name: string,
path: string,
tg: aws.lb.TargetGroup,
listener: aws.lb.Listener,
priority: number,
) => {
return new aws.lb.ListenerRule(name, {
actions: [{
targetGroupArn: tg.arn,
type: "forward",
}],
conditions: [
{
pathPattern: {
values: [path],},
},
//{
//hostHeader: {
// values: ["example.com"], },
//},
],
listenerArn: listener.arn,
priority: priority,
});
};
let priority=100;
const listenerRule1 = generateListenerRule("api-listener1", "/bigotpp", tg1, listener, priority++);
const listenerRule2 = generateListenerRule("api-listener2", "/tiregurus", tg2, listener, priority++);
// Export the resulting URL so that it's easy to access.
export const albIp = alb.dnsName;
//export const endpoint = listener.endpoint.hostname;
export const publicIp = apiserver.publicIp;
//export const publicHostName = apiserver.publicDns;
export const database = db.endpoint;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment