aws-cloudformation/centralized_architecture/CentralizedArchitectureSpokeVpc2Az.yaml [144:535]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  ApplicationInstanceDiskSize:
    Description: Application instance disk size in GB. Default is set to 8GB
    Default: 8
    AllowedValues: [8]
    Type: Number
    ConstraintDescription: Should be a valid instance size in GB
  KeyPairName:
    Description: EC2 KeyPair required for accessing EC2 instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: Must be the name of an existing EC2 KeyPair
  AccessLocation:
    Description: >-
      Enter desired Network CIDR to access Bastion Host. Default is set to
      access from anywhere (0.0.0.0/0) and it is not recommended
    AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
    MinLength: "9"
    MaxLength: "18"
    Default: 0.0.0.0/0
    Type: String
    ConstraintDescription: Must be a valid Network CIDR of the form x.x.x.x/y

Resources:
# Create VPC:
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Join
            - ""
            - - !Ref AWS::StackName
              - "-vpc"

# Create IGW and attach to the VPC:  
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-igw"
  
  AttachInternetGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref Vpc
      InternetGatewayId: !Ref InternetGateway

# Create Subnets:
  # AZ1:
  BastionSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      CidrBlock: !Ref BastionSubnet1Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-subnet-1"

  ApplicationSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      CidrBlock: !Ref ApplicationSubnet1Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-subnet-1"
  
  TgwAttachSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      CidrBlock: !Ref TgwAttachSubnet1Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-tgw-attach-subnet-1"

  # AZ2:
  BastionSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      CidrBlock: !Ref BastionSubnet2Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-subnet-2"

  ApplicationSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      CidrBlock: !Ref ApplicationSubnet2Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-subnet-2"

  TgwAttachSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      CidrBlock: !Ref TgwAttachSubnet2Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-tgw-attach-subnet-2"

# Create Route Tables:
  ApplicationRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-applicaiton-rtb"

  BastionRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-rtb"

# Associate Subnets with Route Tables:
  # AZ1:
  ApplicationSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref ApplicationSubnet1
      RouteTableId: !Ref ApplicationRouteTable

  TgwAttachSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref TgwAttachSubnet1
      RouteTableId: !Ref ApplicationRouteTable

  BastionSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref BastionSubnet1
      RouteTableId: !Ref BastionRouteTable

  # AZ2:
  ApplicationSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref ApplicationSubnet2
      RouteTableId: !Ref ApplicationRouteTable
  
  TgwAttachSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref TgwAttachSubnet2
      RouteTableId: !Ref ApplicationRouteTable

  BastionSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref BastionSubnet2
      RouteTableId: !Ref BastionRouteTable

# Create Routes. Routes with TGW as the target are created through TGW template:
  BastionRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachInternetGateway
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref BastionRouteTable

# Create Security Group:
  ApplicationSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref Vpc
      GroupName: !Sub "${AWS::StackName}-application-sg"
      GroupDescription: >-
        Access to application instance: allow TCP, UDP and ICMP from appropriate
        location. Allow all traffic from VPC CIDR.
      SecurityGroupIngress:
        - CidrIp: !Ref AccessLocation
          IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
        - CidrIp: !Ref AccessLocation
          IpProtocol: ICMP
          FromPort: -1
          ToPort: -1
        - CidrIp: !Ref AccessLocation
          IpProtocol: udp
          FromPort: 0
          ToPort: 65535
        - CidrIp: !Ref VpcCidr
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1       
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-sg"

# Create Application Instances:

  Application1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ApplicationInstanceAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      SecurityGroupIds:
        - !Ref ApplicationSg
      SubnetId: !Ref ApplicationSubnet1
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-instance-1"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex

          # Configure hostname:
          hostnamectl set-hostname ${AWS::StackName}-application1;

          # Configure SSH client alive interval for ssh session timeout:
          echo 'ClientAliveInterval 60' | sudo tee --append /etc/ssh/sshd_config;
          service sshd restart;
          
          # Set dark background for vim:
          touch /home/ec2-user/.vimrc;
          echo "set background=dark" >> /home/ec2-user/.vimrc;

  Application2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ApplicationInstanceAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      SecurityGroupIds:
        - !Ref ApplicationSg
      SubnetId: !Ref ApplicationSubnet2
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-instance-2"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex

          # Configure hostname:
          hostnamectl set-hostname ${AWS::StackName}-application2;

          # Configure SSH client alive interval for ssh session timeout:
          echo 'ClientAliveInterval 60' | sudo tee --append /etc/ssh/sshd_config;
          service sshd restart;
          
          # Set dark background for vim:
          touch /home/ec2-user/.vimrc;
          echo "set background=dark" >> /home/ec2-user/.vimrc;

# Create security group for bastion host:
  BastionSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref Vpc
      GroupName: !Sub "${AWS::StackName}-bastion-sg"
      GroupDescription: >-
        Access to bastion instance: allow SSH and ICMP access from appropriate
        location. Allow all traffic from VPC CIDR
      SecurityGroupIngress:
        - CidrIp: !Ref AccessLocation
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - CidrIp: !Ref AccessLocation
          IpProtocol: ICMP
          FromPort: -1
          ToPort: -1
        - CidrIp: !Ref VpcCidr
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1          
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-sg"

# Create Bastion Host (creates only one bastion host in one AZ):
  BastionHost:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ApplicationInstanceAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      SecurityGroupIds:
        - !Ref BastionSg
      SubnetId: !Ref BastionSubnet1
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-host-1"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex

          # Install packages:
          yum update -y;
          yum install htop -y;

          # Configure hostname:
          hostnamectl set-hostname ${AWS::StackName}-bastion-host1;

          # Configure SSH client alive interval for ssh session timeout:
          echo 'ClientAliveInterval 60' | sudo tee --append /etc/ssh/sshd_config;
          service sshd restart;
          
          # Set dark background for vim:
          touch /home/ec2-user/.vimrc;
          echo "set background=dark" >> /home/ec2-user/.vimrc;

# Edit applicaiton security group to allow access from bastion host:
  ApplicationSgIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref ApplicationSg
      IpProtocol: tcp
      FromPort: 22
      ToPort: 22
      SourceSecurityGroupId: !GetAtt BastionSg.GroupId

Outputs:
  SpokeVpcCidr:
    Description: Spoke VPC CIDR
    Value: !Ref VpcCidr
  SpokeVpcId:
    Description: Spoke VPC ID
    Value: !Ref Vpc
  SpokeApplication1PrivateIp:
    Description: Spoke VPC Application Instance Private IP
    Value: !GetAtt Application1.PrivateIp
  SpokeApplication2PrivateIp:
    Description: Spoke VPC Application Instance Private IP
    Value: !GetAtt Application2.PrivateIp      
  SpokeApplication1PublicIp:
    Description: Spoke VPC Application Instance Public IP
    Value: !GetAtt Application1.PublicIp
  SpokeApplication2PublicIp:
    Description: Spoke VPC Application Instance Public IP
    Value: !GetAtt Application2.PublicIp    
  SpokeBastionHostPublicIp:
    Description: Spoke VPC Bastion Instance Public IP
    Value: !GetAtt BastionHost.PublicIp
  SpokeTgwAttachSubnet1Id:
    Description: Spoke VPC TgwAttachSubnet1 ID
    Value: !Ref TgwAttachSubnet1
  SpokeTgwAttachSubnet2Id:
    Description: Spoke VPC TgwAttachSubnet2 ID
    Value: !Ref TgwAttachSubnet2  
  SpokeApplicationRouteTableId:
    Description: Application Route Table ID
    Value: !Ref ApplicationRouteTable
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



aws-cloudformation/centralized_architecture/nested-stack/SpokeVpc2Az.yaml [144:535]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  ApplicationInstanceDiskSize:
    Description: Application instance disk size in GB. Default is set to 8GB
    Default: 8
    AllowedValues: [8]
    Type: Number
    ConstraintDescription: Should be a valid instance size in GB
  KeyPairName:
    Description: EC2 KeyPair required for accessing EC2 instance
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: Must be the name of an existing EC2 KeyPair
  AccessLocation:
    Description: >-
      Enter desired Network CIDR to access Bastion Host. Default is set to
      access from anywhere (0.0.0.0/0) and it is not recommended
    AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
    MinLength: "9"
    MaxLength: "18"
    Default: 0.0.0.0/0
    Type: String
    ConstraintDescription: Must be a valid Network CIDR of the form x.x.x.x/y

Resources:
# Create VPC:
  Vpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: "true"
      EnableDnsHostnames: "true"
      InstanceTenancy: default
      Tags:
        - Key: Name
          Value: !Join
            - ""
            - - !Ref AWS::StackName
              - "-vpc"

# Create IGW and attach to the VPC:  
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-igw"
  
  AttachInternetGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref Vpc
      InternetGatewayId: !Ref InternetGateway

# Create Subnets:
  # AZ1:
  BastionSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      CidrBlock: !Ref BastionSubnet1Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-subnet-1"

  ApplicationSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      CidrBlock: !Ref ApplicationSubnet1Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-subnet-1"
  
  TgwAttachSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone1
      CidrBlock: !Ref TgwAttachSubnet1Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-tgw-attach-subnet-1"

  # AZ2:
  BastionSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      CidrBlock: !Ref BastionSubnet2Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-subnet-2"

  ApplicationSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      CidrBlock: !Ref ApplicationSubnet2Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-subnet-2"

  TgwAttachSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      AvailabilityZone: !Ref AvailabilityZone2
      CidrBlock: !Ref TgwAttachSubnet2Cidr
      VpcId: !Ref Vpc
      MapPublicIpOnLaunch: "true"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-tgw-attach-subnet-2"

# Create Route Tables:
  ApplicationRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-applicaiton-rtb"

  BastionRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref Vpc
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-rtb"

# Associate Subnets with Route Tables:
  # AZ1:
  ApplicationSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref ApplicationSubnet1
      RouteTableId: !Ref ApplicationRouteTable

  TgwAttachSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref TgwAttachSubnet1
      RouteTableId: !Ref ApplicationRouteTable

  BastionSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref BastionSubnet1
      RouteTableId: !Ref BastionRouteTable

  # AZ2:
  ApplicationSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref ApplicationSubnet2
      RouteTableId: !Ref ApplicationRouteTable
  
  TgwAttachSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref TgwAttachSubnet2
      RouteTableId: !Ref ApplicationRouteTable

  BastionSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref BastionSubnet2
      RouteTableId: !Ref BastionRouteTable

# Create Routes. Routes with TGW as the target are created through TGW template:
  BastionRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachInternetGateway
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref BastionRouteTable

# Create Security Group:
  ApplicationSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref Vpc
      GroupName: !Sub "${AWS::StackName}-application-sg"
      GroupDescription: >-
        Access to application instance: allow TCP, UDP and ICMP from appropriate
        location. Allow all traffic from VPC CIDR.
      SecurityGroupIngress:
        - CidrIp: !Ref AccessLocation
          IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
        - CidrIp: !Ref AccessLocation
          IpProtocol: ICMP
          FromPort: -1
          ToPort: -1
        - CidrIp: !Ref AccessLocation
          IpProtocol: udp
          FromPort: 0
          ToPort: 65535
        - CidrIp: !Ref VpcCidr
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1       
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-sg"

# Create Application Instances:

  Application1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ApplicationInstanceAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      SecurityGroupIds:
        - !Ref ApplicationSg
      SubnetId: !Ref ApplicationSubnet1
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-instance-1"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex

          # Configure hostname:
          hostnamectl set-hostname ${AWS::StackName}-application1;

          # Configure SSH client alive interval for ssh session timeout:
          echo 'ClientAliveInterval 60' | sudo tee --append /etc/ssh/sshd_config;
          service sshd restart;
          
          # Set dark background for vim:
          touch /home/ec2-user/.vimrc;
          echo "set background=dark" >> /home/ec2-user/.vimrc;

  Application2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ApplicationInstanceAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      SecurityGroupIds:
        - !Ref ApplicationSg
      SubnetId: !Ref ApplicationSubnet2
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-application-instance-2"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex

          # Configure hostname:
          hostnamectl set-hostname ${AWS::StackName}-application2;

          # Configure SSH client alive interval for ssh session timeout:
          echo 'ClientAliveInterval 60' | sudo tee --append /etc/ssh/sshd_config;
          service sshd restart;
          
          # Set dark background for vim:
          touch /home/ec2-user/.vimrc;
          echo "set background=dark" >> /home/ec2-user/.vimrc;

# Create security group for bastion host:
  BastionSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref Vpc
      GroupName: !Sub "${AWS::StackName}-bastion-sg"
      GroupDescription: >-
        Access to bastion instance: allow SSH and ICMP access from appropriate
        location. Allow all traffic from VPC CIDR
      SecurityGroupIngress:
        - CidrIp: !Ref AccessLocation
          IpProtocol: tcp
          FromPort: 22
          ToPort: 22
        - CidrIp: !Ref AccessLocation
          IpProtocol: ICMP
          FromPort: -1
          ToPort: -1
        - CidrIp: !Ref VpcCidr
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1          
      SecurityGroupEgress:
        - CidrIp: 0.0.0.0/0
          IpProtocol: "-1"
          FromPort: -1
          ToPort: -1
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-sg"

# Create Bastion Host (creates only one bastion host in one AZ):
  BastionHost:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref ApplicationInstanceAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      SecurityGroupIds:
        - !Ref BastionSg
      SubnetId: !Ref BastionSubnet1
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-host-1"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -ex

          # Install packages:
          yum update -y;
          yum install htop -y;

          # Configure hostname:
          hostnamectl set-hostname ${AWS::StackName}-bastion-host1;

          # Configure SSH client alive interval for ssh session timeout:
          echo 'ClientAliveInterval 60' | sudo tee --append /etc/ssh/sshd_config;
          service sshd restart;
          
          # Set dark background for vim:
          touch /home/ec2-user/.vimrc;
          echo "set background=dark" >> /home/ec2-user/.vimrc;

# Edit applicaiton security group to allow access from bastion host:
  ApplicationSgIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref ApplicationSg
      IpProtocol: tcp
      FromPort: 22
      ToPort: 22
      SourceSecurityGroupId: !GetAtt BastionSg.GroupId

Outputs:
  SpokeVpcCidr:
    Description: Spoke VPC CIDR
    Value: !Ref VpcCidr
  SpokeVpcId:
    Description: Spoke VPC ID
    Value: !Ref Vpc
  SpokeApplication1PrivateIp:
    Description: Spoke VPC Application Instance Private IP
    Value: !GetAtt Application1.PrivateIp
  SpokeApplication2PrivateIp:
    Description: Spoke VPC Application Instance Private IP
    Value: !GetAtt Application2.PrivateIp      
  SpokeApplication1PublicIp:
    Description: Spoke VPC Application Instance Public IP
    Value: !GetAtt Application1.PublicIp
  SpokeApplication2PublicIp:
    Description: Spoke VPC Application Instance Public IP
    Value: !GetAtt Application2.PublicIp    
  SpokeBastionHostPublicIp:
    Description: Spoke VPC Bastion Instance Public IP
    Value: !GetAtt BastionHost.PublicIp
  SpokeTgwAttachSubnet1Id:
    Description: Spoke VPC TgwAttachSubnet1 ID
    Value: !Ref TgwAttachSubnet1
  SpokeTgwAttachSubnet2Id:
    Description: Spoke VPC TgwAttachSubnet2 ID
    Value: !Ref TgwAttachSubnet2  
  SpokeApplicationRouteTableId:
    Description: Application Route Table ID
    Value: !Ref ApplicationRouteTable
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



