aws-cloudformation/vpc_routing_enhancement_architectures/templates/EgressVpcNatGw.yaml [629:809]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          touch /var/www/html/index.html
          echo "<html>" >> /var/www/html/index.html
          echo "  <head>" >> /var/www/html/index.html
          echo "    <title>Gateway Load Balancer Endpoint POC</title>" >> /var/www/html/index.html
          echo "    <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>" >> /var/www/html/index.html
          echo "  </head>" >> /var/www/html/index.html
          echo "  <body>" >> /var/www/html/index.html
          echo "    <h1>GWLB Endpoint POC:</h1>" >> /var/www/html/index.html
          echo "    <h2>Welcome to Ingress VPC: GWLB Endpoint + ALB + VPC Routing Enhancements POC:</h2>" >> /var/www/html/index.html
          echo "    <h3>This is server 2 running in $instance_az. Happy testing!</h3>" >> /var/www/html/index.html
          echo "  </body>" >> /var/www/html/index.html
          echo "</html>" >> /var/www/html/index.html

  BastionHost:
    DependsOn: ['GwlbeRtb1Route1', 'PublicRtb1EditLocalRoute']
    Type: AWS::EC2::Instance
    Condition: BastionHostCreate
    Properties:
      ImageId: !Ref ApplicationAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      IamInstanceProfile: !Ref InstanceSSMProfile
      SecurityGroupIds:
        - !Ref BastionSg
      SubnetId: !Ref PublicSubnet1
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-host"
      UserData:
        Fn::Base64: |
          #!/bin/bash -ex

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

          # Configure hostname:
          hostnamectl set-hostname gwlbe-ingress-vpc-bh;

          # 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 Lambda Custom Resource to edit existing route in an RTB:
  ReplaceRouteLambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - ec2:ReplaceRoute
                Resource: "*"

  # Lambda creates CloudWatch Log Group.
  # Since CF stack didn't explicitly create the Log Group, Log Group doesn't get deleted when stack is deleted.
  # Hence creating Log Group though the stack for Lambda specific funciton.
  # Their are few things to consider. For more details refer to: https://github.com/aws/serverless-application-model/issues/1216
  ReplaceRouteLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
        LogGroupName: !Sub /aws/lambda/${AWS::StackName}ReplaceRoute
        RetentionInDays: 1

  ReplaceRoute:
    Type: AWS::Lambda::Function
    DependsOn: ReplaceRouteLogGroup
    Properties:
      FunctionName: !Sub ${AWS::StackName}ReplaceRoute
      Handler: "index.handler"
      Role: !GetAtt ReplaceRouteLambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import json
          import logging
          import time

          import boto3
          import cfnresponse
          from botocore.exceptions import ClientError

          try:
              ec2 = boto3.client('ec2')
          except ClientError as e:
              logger.error(f"ERROR: failed to connect to EC2 client: {e}")
              sys.exit(1)              

          def handler(event, context):
              logger = logging.getLogger()
              logger.setLevel(logging.INFO)
              logger.info('Received event: {}'.format(json.dumps(event)))

              responseData = {}
              responseStatus = cfnresponse.FAILED

              try:
                  DestCidr = event["ResourceProperties"]["DestCidr"]
                  VpceId = event["ResourceProperties"]["VpceId"]
                  RtbId = event["ResourceProperties"]["RtbId"]
                    
              except Exception as e:
                  logger.info('Attribute retrival failure: {}'.format(e))

              try:
                  if event["RequestType"] == "Delete":    
                      responseStatus = cfnresponse.SUCCESS
                      cfnresponse.send(event, context, responseStatus, responseData)
              except Exception:
                  logger.exception("Signaling failure to CloudFormation.")
                  cfnresponse.send(event, context, cfnresponse.FAILED, {})

              if event["RequestType"] == "Create":
                  logger.info(f"Replacing target to {VpceId} for {DestCidr} for {RtbId}")
                  try:
                      response = ec2.replace_route(
                          DestinationCidrBlock = DestCidr,
                          VpcEndpointId = VpceId,
                          RouteTableId = RtbId
                      )
                  except Exception as e:
                      logger.info('ec2.describe_vpc_endpoint_service_configurations failure: {}'.format(e))
            
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
      Runtime: python3.7
      Timeout: 150

# Add routes to route tables:
  # AZ 1:
  # Public route table 1 routes:
  PublicRtb1Route1:
    Type: AWS::EC2::Route
    DependsOn: AttachInternetGateway
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PublicRouteTable1
  PublicRtb1EditLocalRoute:
    Type: Custom::ReplaceRoute
    Properties:
      ServiceToken: !GetAtt ReplaceRoute.Arn
      DestCidr: !Ref VpcCidr
      VpceId: !Ref GwlbVpcEndpoint1
      RtbId: !Ref PublicRouteTable1
  # GWLBE route table 1 routes:
  GwlbeRtb1Route1:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NATGW1
      RouteTableId: !Ref GwlbeRouteTable1
  # Application route table 1 routes:
  AppRtb1Route1:
    Type: AWS::EC2::Route
    Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



aws-cloudformation/vpc_routing_enhancement_architectures/templates/IngressVpcElb.yaml [723:906]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          touch /var/www/html/index.html
          echo "<html>" >> /var/www/html/index.html
          echo "  <head>" >> /var/www/html/index.html
          echo "    <title>Gateway Load Balancer Endpoint POC</title>" >> /var/www/html/index.html
          echo "    <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>" >> /var/www/html/index.html
          echo "  </head>" >> /var/www/html/index.html
          echo "  <body>" >> /var/www/html/index.html
          echo "    <h1>GWLB Endpoint POC:</h1>" >> /var/www/html/index.html
          echo "    <h2>Welcome to Ingress VPC: GWLB Endpoint + ALB + VPC Routing Enhancements POC:</h2>" >> /var/www/html/index.html
          echo "    <h3>This is server 2 running in $instance_az. Happy testing!</h3>" >> /var/www/html/index.html
          echo "  </body>" >> /var/www/html/index.html
          echo "</html>" >> /var/www/html/index.html

  BastionHost:
    DependsOn: ['GwlbeRtb1Route1', 'PublicRtb1EditLocalRoute']
    Type: AWS::EC2::Instance
    Condition: BastionHostCreate
    Properties:
      ImageId: !Ref ApplicationAmiId
      KeyName: !Ref KeyPairName
      InstanceType: !Ref ApplicationInstanceType
      IamInstanceProfile: !Ref InstanceSSMProfile
      SecurityGroupIds:
        - !Ref BastionSg
      SubnetId: !Ref PublicSubnet1
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeSize: !Ref ApplicationInstanceDiskSize
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-bastion-host"
      UserData:
        Fn::Base64: |
          #!/bin/bash -ex

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

          # Configure hostname:
          hostnamectl set-hostname gwlbe-ingress-vpc-bh;

          # 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 Lambda Custom Resource to edit existing route in an RTB:
  ReplaceRouteLambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - ec2:ReplaceRoute
                Resource: "*"

  # Lambda creates CloudWatch Log Group.
  # Since CF stack didn't explicitly create the Log Group, Log Group doesn't get deleted when stack is deleted.
  # Hence creating Log Group though the stack for Lambda specific funciton.
  # Their are few things to consider. For more details refer to: https://github.com/aws/serverless-application-model/issues/1216
  ReplaceRouteLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
        LogGroupName: !Sub /aws/lambda/${AWS::StackName}ReplaceRoute
        RetentionInDays: 1

  ReplaceRoute:
    Type: AWS::Lambda::Function
    DependsOn: ReplaceRouteLogGroup
    Properties:
      FunctionName: !Sub ${AWS::StackName}ReplaceRoute
      Handler: "index.handler"
      Role: !GetAtt ReplaceRouteLambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import json
          import logging
          import time

          import boto3
          import cfnresponse
          from botocore.exceptions import ClientError

          try:
              ec2 = boto3.client('ec2')
          except ClientError as e:
              logger.error(f"ERROR: failed to connect to EC2 client: {e}")
              sys.exit(1)              

          def handler(event, context):
              logger = logging.getLogger()
              logger.setLevel(logging.INFO)
              logger.info('Received event: {}'.format(json.dumps(event)))

              responseData = {}
              responseStatus = cfnresponse.FAILED

              try:
                  DestCidr = event["ResourceProperties"]["DestCidr"]
                  VpceId = event["ResourceProperties"]["VpceId"]
                  RtbId = event["ResourceProperties"]["RtbId"]
                    
              except Exception as e:
                  logger.info('Attribute retrival failure: {}'.format(e))

              try:
                  if event["RequestType"] == "Delete":    
                      responseStatus = cfnresponse.SUCCESS
                      cfnresponse.send(event, context, responseStatus, responseData)
              except Exception:
                  logger.exception("Signaling failure to CloudFormation.")
                  cfnresponse.send(event, context, cfnresponse.FAILED, {})

              if event["RequestType"] == "Create":
                  logger.info(f"Replacing target to {VpceId} for {DestCidr} for {RtbId}")
                  try:
                      response = ec2.replace_route(
                          DestinationCidrBlock = DestCidr,
                          VpcEndpointId = VpceId,
                          RouteTableId = RtbId
                      )
                  except Exception as e:
                      logger.info('ec2.describe_vpc_endpoint_service_configurations failure: {}'.format(e))
            
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
      Runtime: python3.7
      Timeout: 150

# Add routes to route tables:
  # AZ 1:
  # Public route table 1 routes:
  PublicRtb1Route1:
    Type: AWS::EC2::Route
    DependsOn: AttachInternetGateway
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
      RouteTableId: !Ref PublicRouteTable1
  PublicRtb1EditLocalRoute:
    Type: Custom::ReplaceRoute
    # DependsOn: GwlbVpcEndpoint1
    Properties:
      ServiceToken: !GetAtt ReplaceRoute.Arn
      DestCidr: !Ref VpcCidr
      VpceId: !Ref GwlbVpcEndpoint1
      RtbId: !Ref PublicRouteTable1
  # GWLBE route table 1 routes:
  GwlbeRtb1Route1:
    Type: AWS::EC2::Route
    # DependsOn: NATGW1
    Properties:
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NATGW1
      RouteTableId: !Ref GwlbeRouteTable1
  # Application route table 1 routes:
  AppRtb1Route1:
    Type: AWS::EC2::Route
    # DependsOn: GwlbVpcEndpoint1
    Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



