Description: This template deploys a VPC, with a pair of public and private subnets in a single Availability Zones. It deploys an internet gateway, with a default route on the public subnets. It also deploys a NAT gateway, and default route private subnets. Mappings: RegionMap: us-east-1: #North Virginia DvwaAMI: ami-09e67e426f25ce0d7 BastionLinuxAMI: ami-09e67e426f25ce0d7 PrivateLinuxAMI: ami-09e67e426f25ce0d7 BastionWinAMI: ami-0cff7528ff583bf9a PrivateWinAMI: ami-0cff7528ff583bf9a us-east-2: #Ohio DvwaAMI: ami-00399ec92321828f5 BastionLinuxAMI: ami-00399ec92321828f5 PrivateLinuxAMI: ami-00399ec92321828f5 BastionWinAMI: ami-029c4a9e6f0a6b9e3 PrivateWinAMI: ami-029c4a9e6f0a6b9e3 us-west-1: #North California DvwaAMI: ami-0d382e80be7ffdae5 BastionLinuxAMI: ami-0d382e80be7ffdae5 PrivateLinuxAMI: ami-0d382e80be7ffdae5 BastionWinAMI: ami-063f1c4fb6e4c511a PrivateWinAMI: ami-063f1c4fb6e4c511a us-west-2: #Oregon DvwaAMI: ami-03d5c68bab01f3496 BastionLinuxAMI: ami-03d5c68bab01f3496 PrivateLinuxAMI: ami-03d5c68bab01f3496 BastionWinAMI: ami-098e42ae54c764c35 PrivateWinAMI: ami-098e42ae54c764c35 Parameters: EnvironmentName: Description: An environment name that is prefixed to resource names Type: String Default: C1NS-labenvironment InspectionVPCCIDR: Description: Please enter the IP range (CIDR notation) for this INSPECTION VPC Type: String Default: 10.10.0.0/16 ProtectedPublicSubnetCIDR: Description: Please enter the IP range (CIDR notation) for the PROTECTED-PUBLIC subnet Type: String Default: 10.10.10.0/24 ProtectedPublicSubnetAZ: Description: Please enter the Availability Zone that you want to use for the PROTECTED-PUBLIC subnet Type: String Default: us-east-1a ProtectedPrivateSubnetCIDR: Description: Please enter the IP range (CIDR notation) for the PROTECTED-PRIVATE subnet Type: String Default: 10.10.20.0/24 ProtectedPrivateSubnetAZ: Description: Please enter the Availability Zone that you want to use for the PROTECTED-PRIVATE subnet Type: String Default: us-east-1a KeyPair: Description: Please enter the valid Key Pair for your region Type: String MyPublicIP: Description: Please enter your public IP with CIDR (e.g. 191.162.228.91/32). As a example you can use https://wtfismyip.com/text or https://ipinfo.io/ip . It will be use to allow you to access the DVWA through HTTP (TCP/80). Type: String Resources: #Creating VPC that will be using in the demo environment VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref InspectionVPCCIDR EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub Inpection VPC - ${EnvironmentName} - Key: VPC Name Value: Inpection VPC - Key: Service Value: Cloud One Network Security #creating an Internet Gateway InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Sub IGW - ${EnvironmentName} - Key: Service Value: Cloud One #Attaching the Internet Gateway to the VPC that we create InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC #Creating the Protected-Public Subnet ProtectedPublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref ProtectedPublicSubnetCIDR MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub Protected-Public Subnet ${EnvironmentName} #Creating the Protected-Private Subnet ProtectedPrivateSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref ProtectedPrivateSubnetCIDR MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub Protected-Private Subnet ${EnvironmentName} #Creating the Elastic IP for the NAT Gateway NatGatewayEIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc #Creating the NAT Gateway that will be use in the Protected-Public Subnet NatGateway: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGatewayEIP.AllocationId SubnetId: !Ref ProtectedPublicSubnet #Creating the Public Route table PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub Protected Public Routes - ${EnvironmentName} #Add a default route in the Public Route table DefaultPublicRoute: Type: AWS::EC2::Route DependsOn: InternetGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway #Associating the Protected-Public Subnet in the Public Route Table (Edge Association) ProtectedPublicSubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref ProtectedPublicSubnet #Creating the Private Route table PrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub Private Routes - ${EnvironmentName} #Add a default route in the Private Route table DefaultPrivateRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway #Associating the Protected-Private Subnet in the Private Route Table ProtectedPrivateSubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable SubnetId: !Ref ProtectedPrivateSubnet #Creating the Security Gorup for Allowing only inbound traffic from the VPC CIDR and any outbound traffic. NoIngressSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: "no-ingress-sg" GroupDescription: "Security group with no ingress rule" VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 10.10.0.0/16 - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: 10.10.0.0/16 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 #Creating the Security Gorup for Allowing SSH and RDP inbound traffic from any source IP, but for HTTP only if the source IP are in the VPC CIDR. Allowing any outbound traffic. #Note: If you want to acess the DVWA Application you can add a new entry here for your Public IP or you can add it later in the AWS Console. PublicAccessSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: "public-ingress-sg" GroupDescription: "Security group with no ingress rule" VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 10.10.0.0/16 - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: !Ref MyPublicIP - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 #EC2 Role to be assumed and use to create the EC2 resources. EC2Role: Type: 'AWS::IAM::Role' Properties: RoleName: !Sub "EC2Role-${EnvironmentName}" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - "sts:AssumeRole" #Instance profile EC2InstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref EC2Role #Creating the instance that will be a Linux Bastion Host. BastionLinux: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - BastionLinuxAMI InstanceType: t3.micro KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: BastionLinux - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPublicSubnet SecurityGroupIds: - Ref: PublicAccessSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 #Creating the instance that will be a Windows Bastion Host. BastionWin: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - BastionWinAMI InstanceType: t3.small KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: BastionWin - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPublicSubnet SecurityGroupIds: - Ref: PublicAccessSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 #Creating the instance that will the DVWA host. Note that the DVWA will run as container. DVWA: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - DvwaAMI InstanceType: t3.micro KeyName: !Ref KeyPair Tags: - Key: Name Value: DVWA - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPublicSubnet SecurityGroupIds: - Ref: PublicAccessSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 UserData: !Base64 | #!/bin/bash apt update sleep 10 apt install -y apt-transport-https ca-certificates curl gnupg python3-pip lsb-release sleep 60 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg sleep 10 echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null apt update sleep 10 apt install -y docker-ce docker-ce-cli containerd.io sleep 60 docker run --rm -it -d -p 80:80 vulnerables/web-dvwa #Creating the instance that will be a Windows machine in the Protected-Private Subnet. PrivateWin: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - PrivateWinAMI InstanceType: t3.small KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: PrivateWin - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPrivateSubnet SecurityGroupIds: - Ref: NoIngressSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 #Creating the instance that will be a Linux machine in the Protected-Private Subnet. PrivateLinux: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - PrivateLinuxAMI InstanceType: t3.small KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: PrivateLinux - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPrivateSubnet SecurityGroupIds: - Ref: NoIngressSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 #Outputs to be presented in the CloudFormation Stack Outputs: VPC: Description: A reference to the created VPC Value: !Ref VPC ProtectedPublicSubnet: Description: A reference to the public subnet in the 1st Availability Zone Value: !Ref ProtectedPublicSubnet ProtectedPrivateSubnet: Description: A reference to the private subnet in the 1st Availability Zone Value: !Ref ProtectedPrivateSubnet NoIngressSecurityGroup: Description: Security group with no ingress rule Value: !Ref NoIngressSecurityGroup DVWAPublicDNSName: Description: Export the DVWA instance Public DNS Name Value: !GetAtt DVWA.PublicDnsName BastionLinuxPublicDNSName: Description: Export the Bastion instance Public DNS Name Value: !GetAtt BastionLinux.PublicDnsName BastionWindownsPublicDNSName: Description: Export the Attacker instance Public DNS Name Value: !GetAtt BastionWin.PublicDnsName