{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "CloudLabs demo - network infrastructure for ECS Fargate plus an EC2 Linux lab VM",
  "Parameters": {
    "CloudLabsDeploymentID": {
      "Description": "DeploymentID Value",
      "Type": "String"
    },
    "VpcName": {
      "Description": "VPC Name",
      "Type": "String",
      "Default": "clgVpc"
    },
    "VpcCidr": {
      "Description": "VPC CIDR Block",
      "Type": "String",
      "Default": "10.10.0.0/16"
    },
    "VMSubnetName": {
      "Description": "VM Subnet Name",
      "Type": "String",
      "Default": "vmSubnet"
    },
    "VMSubnetCidr": {
      "Description": "VM Subnet CIDR",
      "Type": "String",
      "Default": "10.10.0.0/24"
    },
    "ClusterSubnetName": {
      "Description": "Cluster Subnet Name",
      "Type": "String",
      "Default": "clgClusterSubnet"
    },
    "ClusterSubnetCidr": {
      "Description": "Cluster Subnet CIDR",
      "Type": "String",
      "Default": "10.10.1.0/24"
    },
    "InternetGatewayName": {
      "Description": "Internet Gateway Name",
      "Type": "String",
      "Default": "clgInternetGateway"
    },
    "RouteTableName": {
      "Description": "Route Table Name",
      "Type": "String",
      "Default": "RouteTable"
    },
    "VMName": {
      "Description": "EC2 Instance Name",
      "Type": "String",
      "Default": "labvm"
    },
    "InstanceType": {
      "Description": "EC2 Instance Type",
      "Type": "String",
      "Default": "t2.micro",
      "AllowedValues": ["t2.micro", "t2.small", "t3.micro", "t3.small", "t3.medium"]
    },
    "KeyPairName": {
      "Description": "Key Pair Name",
      "Type": "String",
      "Default": "labkeypair"
    },
    "VMSecurityGroupName": {
      "Description": "VM Security Group Name",
      "Type": "String",
      "Default": "vmSecurityGroup"
    },
    "ClusterSecurityGroupName": {
      "Description": "Cluster Security Group Name",
      "Type": "String",
      "Default": "clgSg"
    },
    "TaskExecutionRoleName": {
      "Description": "ECS Task Execution Role Name",
      "Type": "String",
      "Default": "TaskExecutionRole"
    },
    "AmazonECSTaskExecutionRolePolicy": {
      "Description": "ECS Task Execution Role Policy ARN",
      "Type": "String",
      "Default": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
    },
    "VMUserName": {
      "Description": "VM Username",
      "Type": "String",
      "Default": "labuser"
    },
    "VMPassword": {
      "Description": "VM Password",
      "Type": "String",
      "Default": "Chkp!234"
    },
    "SSHLocation": {
      "Description": "SSH Allowed CIDR",
      "Type": "String",
      "Default": "0.0.0.0/0"
    },
    "HTTPSLocation": {
      "Description": "HTTPS Allowed CIDR",
      "Type": "String",
      "Default": "0.0.0.0/0"
    },
    "SSHPort": {
      "Description": "SSH Port",
      "Type": "Number",
      "Default": 22
    },
    "HTTPSPort": {
      "Description": "HTTPS Port",
      "Type": "Number",
      "Default": 443
    },
    "CheckAcknowledgement": {
      "Description": "Acknowledgement",
      "Type": "String",
      "Default": "TRUE",
      "AllowedValues": ["TRUE", "FALSE"]
    },
    "linuxami": {
      "Type": "AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>",
      "Default": "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64"
    }
  },
  "Rules": {
    "AcknowledgementRequired": {
      "Assertions": [
        {
          "Assert": { "Fn::Equals": [{ "Ref": "CheckAcknowledgement" }, "TRUE"] },
          "AssertDescription": "CheckAcknowledgement must be TRUE to deploy this lab."
        }
      ]
    }
  },
  "Resources": {
    "TaskExecutionRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": { "Service": ["ecs-tasks.amazonaws.com"] },
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [{ "Ref": "AmazonECSTaskExecutionRolePolicy" }],
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "TaskExecutionRoleName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "clgVpc": {
      "Type": "AWS::EC2::VPC",
      "Properties": {
        "CidrBlock": { "Ref": "VpcCidr" },
        "EnableDnsSupport": true,
        "EnableDnsHostnames": true,
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "VpcName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "clgInternetGateway": {
      "Type": "AWS::EC2::InternetGateway",
      "Properties": {
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "InternetGatewayName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "attachInternetGateway": {
      "Type": "AWS::EC2::VPCGatewayAttachment",
      "Properties": {
        "InternetGatewayId": { "Ref": "clgInternetGateway" },
        "VpcId": { "Ref": "clgVpc" }
      }
    },
    "vmSubnet": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "MapPublicIpOnLaunch": true,
        "AvailabilityZone": { "Fn::Select": [0, { "Fn::GetAZs": "" }] },
        "VpcId": { "Ref": "clgVpc" },
        "CidrBlock": { "Ref": "VMSubnetCidr" },
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "VMSubnetName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "clgClusterSubnet": {
      "Type": "AWS::EC2::Subnet",
      "Properties": {
        "MapPublicIpOnLaunch": true,
        "AvailabilityZone": { "Fn::Select": [1, { "Fn::GetAZs": "" }] },
        "VpcId": { "Ref": "clgVpc" },
        "CidrBlock": { "Ref": "ClusterSubnetCidr" },
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "ClusterSubnetName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "RouteTable": {
      "Type": "AWS::EC2::RouteTable",
      "Properties": {
        "VpcId": { "Ref": "clgVpc" },
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "RouteTableName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "routesToInternetGateway": {
      "Type": "AWS::EC2::Route",
      "DependsOn": "attachInternetGateway",
      "Properties": {
        "RouteTableId": { "Ref": "RouteTable" },
        "DestinationCidrBlock": "0.0.0.0/0",
        "GatewayId": { "Ref": "clgInternetGateway" }
      }
    },
    "vmSubnetRouteTableAssociation": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Properties": {
        "SubnetId": { "Ref": "vmSubnet" },
        "RouteTableId": { "Ref": "RouteTable" }
      }
    },
    "clusterSubnetRouteTableAssociation": {
      "Type": "AWS::EC2::SubnetRouteTableAssociation",
      "Properties": {
        "SubnetId": { "Ref": "clgClusterSubnet" },
        "RouteTableId": { "Ref": "RouteTable" }
      }
    },
    "vmSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "Lab VM access - SSH and HTTPS",
        "VpcId": { "Ref": "clgVpc" },
        "SecurityGroupIngress": [
          { "IpProtocol": "tcp", "FromPort": { "Ref": "SSHPort" }, "ToPort": { "Ref": "SSHPort" }, "CidrIp": { "Ref": "SSHLocation" } },
          { "IpProtocol": "tcp", "FromPort": { "Ref": "HTTPSPort" }, "ToPort": { "Ref": "HTTPSPort" }, "CidrIp": { "Ref": "HTTPSLocation" } }
        ],
        "SecurityGroupEgress": [
          { "IpProtocol": "-1", "CidrIp": "0.0.0.0/0" }
        ],
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "VMSecurityGroupName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "clgSg": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "this is for container",
        "GroupName": { "Fn::Join": ["", [{ "Ref": "ClusterSecurityGroupName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] },
        "VpcId": { "Ref": "clgVpc" },
        "SecurityGroupIngress": [
          { "IpProtocol": "tcp", "FromPort": { "Ref": "HTTPSPort" }, "ToPort": { "Ref": "HTTPSPort" }, "CidrIp": { "Ref": "HTTPSLocation" } },
          { "IpProtocol": "tcp", "FromPort": { "Ref": "HTTPSPort" }, "ToPort": { "Ref": "HTTPSPort" }, "CidrIpv6": "::/0" }
        ],
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "ClusterSecurityGroupName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    },
    "vmKeyPair": {
      "Type": "AWS::EC2::KeyPair",
      "Properties": {
        "KeyName": { "Fn::Join": ["", [{ "Ref": "KeyPairName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] }
      }
    },
    "vmInstance": {
      "Type": "AWS::EC2::Instance",
      "DependsOn": "routesToInternetGateway",
      "Properties": {
        "ImageId": { "Ref": "linuxami" },
        "InstanceType": { "Ref": "InstanceType" },
        "SecurityGroupIds": [{ "Ref": "vmSecurityGroup" }],
        "KeyName": { "Ref": "vmKeyPair" },
        "SubnetId": { "Ref": "vmSubnet" },
        "UserData": {
          "Fn::Base64": {
            "Fn::Sub": "#!/bin/bash\nexec > /var/log/userdata-logs.txt 2>&1\nuseradd -m ${VMUserName}\necho '${VMUserName}:${VMPassword}' | chpasswd\nusermod -aG wheel ${VMUserName}\necho 'PasswordAuthentication yes' > /etc/ssh/sshd_config.d/00-lab-password.conf\nsystemctl restart sshd\n"
          }
        },
        "Tags": [
          { "Key": "Name", "Value": { "Fn::Join": ["", [{ "Ref": "VMName" }, "-", { "Ref": "CloudLabsDeploymentID" }]] } }
        ]
      }
    }
  },
  "Outputs": {
    "CloudLabsDeploymentID": {
      "Description": "DeploymentID Value",
      "Value": { "Ref": "CloudLabsDeploymentID" }
    },
    "VpcId": {
      "Description": "The ID of the VPC",
      "Value": { "Ref": "clgVpc" }
    },
    "vmSubnetId": {
      "Description": "The ID of the VM Subnet",
      "Value": { "Ref": "vmSubnet" }
    },
    "clusterSubnetId": {
      "Description": "The ID of the ClusterSubnet",
      "Value": { "Ref": "clgClusterSubnet" }
    },
    "clusterSecurityGroupId": {
      "Description": "The SG ID of the Cluster",
      "Value": { "Ref": "clgSg" }
    },
    "TaskExecutionRole": {
      "Description": "The Arn of Role that is utilised by ECS Task Definition",
      "Value": { "Fn::GetAtt": ["TaskExecutionRole", "Arn"] }
    },
    "VMPublicDNSName": {
      "Description": "public dns name",
      "Value": { "Fn::GetAtt": ["vmInstance", "PublicDnsName"] }
    },
    "VMPrivateDNSName": {
      "Description": "private dns name",
      "Value": { "Fn::GetAtt": ["vmInstance", "PrivateDnsName"] }
    },
    "VMPublicIP": {
      "Description": "VM Public IP",
      "Value": { "Fn::GetAtt": ["vmInstance", "PublicIp"] }
    },
    "VMPrivateIP": {
      "Description": "VM Private IP",
      "Value": { "Fn::GetAtt": ["vmInstance", "PrivateIp"] }
    },
    "VMUserName": {
      "Description": "VM Username",
      "Value": { "Ref": "VMUserName" }
    },
    "VMPassword": {
      "Description": "VM Password",
      "Value": { "Ref": "VMPassword" }
    },
    "KeyPairName": {
      "Description": "Key pair name; private key is in SSM Parameter Store at /ec2/keypair/<KeyPairId>",
      "Value": { "Ref": "vmKeyPair" }
    }
  }
}