From 681a1bffac777f6a7b29d0e504b838c0d71a4810 Mon Sep 17 00:00:00 2001 From: heidi Date: Thu, 12 Sep 2024 06:10:54 +0000 Subject: [PATCH] Completed the 6 tasks in READEME.md --- src/index.ts | 2 +- src/stack.ts | 163 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 123 insertions(+), 42 deletions(-) diff --git a/src/index.ts b/src/index.ts index 6264d4d..d32feb5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node -import { App } from '@aws-cdk/core' +import { App } from 'aws-cdk-lib/core' import { LoadBalancerStack } from './stack' const app = new App() diff --git a/src/stack.ts b/src/stack.ts index 766b172..a7f6d8e 100644 --- a/src/stack.ts +++ b/src/stack.ts @@ -1,47 +1,128 @@ #!/usr/bin/env node -import autoscaling = require('aws-cdk-lib/aws-autoscaling') -import ec2 = require('aws-cdk-lib/aws-ec2') -import { ApplicationLoadBalancer } from 'aws-cdk-lib/aws-elasticloadbalancingv2' -import { App, Stack } from 'aws-cdk-lib/core' +import autoscaling = require("aws-cdk-lib/aws-autoscaling"); +import ec2 = require("aws-cdk-lib/aws-ec2"); +import { ApplicationLoadBalancer } from "aws-cdk-lib/aws-elasticloadbalancingv2"; +import { App, Stack } from "aws-cdk-lib/core"; +import iam = require("aws-cdk-lib/aws-iam"); +import { Construct } from "constructs"; + +//Allow outbound traffic from anyIpv4 to port +function addEgressRule(sg: ec2.SecurityGroup, port: number) { + sg.addEgressRule( + ec2.Peer.anyIpv4(), + ec2.Port.tcp(port), + `Allow outbound traffic on port ${port}`, + ); +} + +// Create a security group with egress rules for pot 443, 5432, 6379 adn 12001 +function createSecurityGroup(scope: Construct, vpc: ec2.Vpc) { + const sg = new ec2.SecurityGroup(scope, "instanceSg", { + vpc, + allowAllOutbound: false, + }); + + sg.addEgressRule(ec2.Peer.ipv4("0.0.0.0/0"), ec2.Port.tcp(443)); + + const ports = [5432, 6379, 12001]; + + ports.forEach((port) => { + addEgressRule(sg, port); + }); + + return sg; +} + +// Create an AutoScaling group +function createAutoScalingGroup( + scope: Construct, + vpc: ec2.Vpc, + sg: ec2.SecurityGroup, + bucketArn: string, +) { + const asg = new autoscaling.AutoScalingGroup(scope, "ASG", { + vpc, + instanceType: ec2.InstanceType.of( + ec2.InstanceClass.T3A, + ec2.InstanceSize.MICRO, + ), + machineImage: new ec2.AmazonLinuxImage(), + securityGroup: sg, + }); + + asg.scaleOnCpuUtilization("ScaleOnCpu", { + targetUtilizationPercent: 40, + }); + + // Add a script in userdata to copy the `testFile.txt` file from s3 to the new instance. + asg.addUserData( + `#!/bin/bash + aws s3 cp ${bucketArn}/testFile.txt /home/ec2-user/`, + ); + + return asg; +} + +// Create an Application Load Balancer with port 80 open to the world +function createLoadBalancer( + scope: Construct, + vpc: ec2.Vpc, + sg: ec2.SecurityGroup, + asg: autoscaling.AutoScalingGroup, +) { + const lb = new ApplicationLoadBalancer(scope, "LB", { + vpc, + internetFacing: true, + }); + + sg.connections.allowFrom(lb, ec2.Port.tcp(80), "Load balancer to target"); + + const listener = lb.addListener("Listener", { + port: 80, + }); + + listener.addTargets("Target", { + port: 80, + targets: [asg], + }); + + listener.connections.allowDefaultPortFromAnyIpv4("Open to the world"); + + return lb; +} + +// Create an S3 read-only role +function createS3ReadRole(scope: Construct, bucketArn: string) { + const s3ReadRole = new iam.Role(scope, "S3ReadOnlyRole", { + assumedBy: new iam.ArnPrincipal("arn_for_trusted_principal"), + }); + + s3ReadRole.addToPolicy( + new iam.PolicyStatement({ + effect: iam.Effect.ALLOW, + actions: ["s3:GetObject"], + resources: [`${bucketArn}/*`], + }), + ); + + return s3ReadRole; +} export class LoadBalancerStack extends Stack { constructor(app: App, id: string) { - super(app, id) - - const vpc = new ec2.Vpc(this, 'VPC') - - const lb = new ApplicationLoadBalancer(this, 'LB', { - vpc, - internetFacing: true - }) - - const sg = new ec2.SecurityGroup(this, 'instanceSg', { - vpc, - allowAllOutbound: false - }) - sg.connections.allowFrom(lb, ec2.Port.tcp(80), 'Load balancer to target') - sg.addEgressRule(ec2.Peer.ipv4('0.0.0.0/0'), ec2.Port.tcp(443)) - - const asg = new autoscaling.AutoScalingGroup(this, 'ASG', { - vpc, - instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO), - machineImage: new ec2.AmazonLinuxImage(), - securityGroup: sg - }) - - const listener = lb.addListener('Listener', { - port: 80 - }) - - listener.addTargets('Target', { - port: 80, - targets: [asg] - }) - - listener.connections.allowDefaultPortFromAnyIpv4('Open to the world') - - asg.scaleOnRequestCount('AModestLoad', { - targetRequestsPerMinute: 1 - }) + super(app, id); + + const vpc = new ec2.Vpc(this, "VPC"); + + //create security group ports wiht outbound on the ec2 ('443`. `5432`, `6379`, `12001`) + const sg = createSecurityGroup(this, vpc); + + const s3BuckeArn = "arn:aws:s3:::cdk-alb-test"; + const asg = createAutoScalingGroup(this, vpc, sg, s3BuckeArn); + + //create ALB with port 80 open to the world and target on ASG + createLoadBalancer(this, vpc, sg, asg); + + createS3ReadRole(this, s3BuckeArn); } }