Panorama系列--(2)AWS上搭建Panorama测试环境

Panorama系列--(2)AWS上搭建Panorama测试环境

一、注意事项

  • AWS上Paloalto防火墙默认版本是10.2.2h2,Panorama默认版本是10.2.0,需要将Panorama升级到与Paloalto相同版本,或者更高的版本,否则Panorama无法查看日志。
  • Paloalto防火墙VM-50型号只支持ESXi、Hyper-V和KVM平台,不支持AWS和其他云平台。

二、利用CloudFormation部署实验环境

Panorama主要用来管理多台防火墙,在AWS云上,对流量做集中安全检测一般会有多台防火墙,所以这里利用CloudFormation搭建了流量集中检测的LAB环境,然后利用Panorama管理这两台防火墙。

只启动两台防火墙和一台Panorama,也可以做大部分的测试,搭建流量集中检测环境是为了更加模拟真实环境。

利用CloudFormation创建实验环境,CloudFormation代码中不会创建Panorama,需要自行手动创建,也不会对Paloalto防火墙做初始化。

上传堆栈模板文件。image-20230131105703700

设置堆栈名称,选择EC2密钥。image-20230131105713286

允许创建IAM资源。image-20230131105723457

CloudFormation模板内容。堆栈需要七分钟左右创建完成,堆栈创建完成后,另外防火墙需要四分钟左右启动。

Mappings:
  RegionMap:
    cn-northwest-1:
      PA1022h2NWCD: ami-0738eadeed7e6b0fa

Parameters:
  EC2InstanceAmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2'
  Environment:
    Type: String
    AllowedValues:
      - dev
      - prod
    Default: dev
  MyKeyPair:
    Description: Amazon EC2 Key Pair
    Type: AWS::EC2::KeyPair::KeyName
    Default: CloudFormation-Test-Key
  PaloaltoVersion:
    Description: Choice Paloalto Firewall Version Type
    Type: String
    Default: PA1022h2NWCD
    AllowedValues:
      - PA1022h2NWCD
  PaloaltoInstanceType:
    Description: Choice Paloalto Instance Type
    Type: String
    Default: m5.large
    AllowedValues:
      - m5.large
      - m5.4xlarge
Resources:
  BastionSsmRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /

  BastionSsmPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: PrivatelianceInstanceAccess
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - ssm:DescribeAssociation
              - ssm:GetDeployablePatchSnapshotForInstance
              - ssm:GetDocument
              - ssm:DescribeDocument
              - ssm:GetManifest
              - ssm:GetParameter
              - ssm:GetParameters
              - ssm:ListAssociations
              - ssm:ListInstanceAssociations
              - ssm:PutInventory
              - ssm:PutComplianceItems
              - ssm:PutConfigurePackageResult
              - ssm:UpdateAssociationStatus
              - ssm:UpdateInstanceAssociationStatus
              - ssm:UpdateInstanceInformation
            Resource: "*"
          - Effect: Allow
            Action:
              - ssmmessages:CreateControlChannel
              - ssmmessages:CreateDataChannel
              - ssmmessages:OpenControlChannel
              - ssmmessages:OpenDataChannel
            Resource: "*"
          - Effect: Allow
            Action:
              - ec2messages:AcknowledgeMessage
              - ec2messages:DeleteMessage
              - ec2messages:FailMessage
              - ec2messages:GetEndpoint
              - ec2messages:GetMessages
              - ec2messages:SendReply
            Resource: "*"
      Roles:
        - !Ref BastionSsmRole

  BastionSsmProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref BastionSsmRole

#=============SecVpc============#
# 创建SecVpc
  SecVpc:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.100.10.0/16
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      Tags:
       - Key: Name
         Value: !Sub ${AWS::StackName}-SecVpc

# 创建IGW并且关联到VPC
  SecVpcIGW:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpcIGW

  SecVpcAttachIgw:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref SecVpc
      InternetGatewayId: !Ref SecVpcIGW

#-----------------SecVpc创建6个子网------------------#

# SecVpc AZ1内创建公有子网
  SecVpcAz1PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref SecVpc
      CidrBlock: 10.100.10.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Public-Subnet

# SecVpc AZ2内创建公有子网
  SecVpcAz2PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref SecVpc
      CidrBlock: 10.100.20.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Public-Subnet

# SecVpc AZ1内创建私有子网
  SecVpcAz1PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref SecVpc
      CidrBlock: 10.100.30.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Private-Subnet

# SecVpc AZ2内创建私有子网
  SecVpcAz2PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref SecVpc
      CidrBlock: 10.100.40.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Private-Subnet

# SecVpc AZ1内创建TGW子网
  SecVpcAz1TgwSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref SecVpc
      CidrBlock: 10.100.50.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-SecVpc-AZ1-TGW-Subnet

# SecVpc AZ2内创建TGW子网
  SecVpcAz2TgwSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref SecVpc
      CidrBlock: 10.100.60.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-SecVpc-AZ2-TGW-Subnet

#-----------------SecVpc创建路由表------------------#

# 公有子网路由表及关联
  SecVpcAz1PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Public-RouteTable

  SecVpcAz1PublicRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref SecVpcAz1PublicRouteTable
      SubnetId: !Ref SecVpcAz1PublicSubnet

  SecVpcAz2PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Public-RouteTable

  SecVpcAz2PublicRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref SecVpcAz2PublicRouteTable
      SubnetId: !Ref SecVpcAz2PublicSubnet

# Private子网路由表及关联
  SecVpcAz1PrivateRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Private-RouteTable

  SecVpcAz1PrivateRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref SecVpcAz1PrivateRouteTable
      SubnetId: !Ref SecVpcAz1PrivateSubnet

  SecVpcAz2PrivateRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Private-RouteTable

  SecVpcAz2PrivateRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref SecVpcAz2PrivateRouteTable
      SubnetId: !Ref SecVpcAz2PrivateSubnet


# Tgw路由表及关联
  SecVpcAz1TgwRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ1-Tgw-RouteTable

  SecVpcAz1TgwRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref SecVpcAz1TgwRouteTable
      SubnetId: !Ref SecVpcAz1TgwSubnet

  SecVpcAz2TgwRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ2-Tgw-RouteTable

  SecVpcAz2TgwRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref SecVpcAz2TgwRouteTable
      SubnetId: !Ref SecVpcAz2TgwSubnet

#-----------------NAT Gateway-----------------#

# AZ1 NAT GW
  SecVpcAz1NatGatewayEIP:
     Type: AWS::EC2::EIP
     Properties:
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ1-NatGateway-EIP

  SecVpcAz1NatGateway:
     Type: AWS::EC2::NatGateway
     Properties:
        AllocationId: !GetAtt SecVpcAz1NatGatewayEIP.AllocationId
        SubnetId: !Ref SecVpcAz1PublicSubnet
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ1-NatGateway

# AZ2 NAT GW
  SecVpcAz2NatGatewayEIP:
     Type: AWS::EC2::EIP
     Properties:
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ2-NatGateway-EIP

  SecVpcAz2NatGateway:
     Type: AWS::EC2::NatGateway
     Properties:
        AllocationId: !GetAtt SecVpcAz2NatGatewayEIP.AllocationId
        SubnetId: !Ref SecVpcAz2PublicSubnet
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-AZ2-NatGateway

  SecVpcAz1PrivateSubnetToInternetRoute:
     DependsOn: SecVpcAz1NatGateway
     Type: AWS::EC2::Route
     Properties:
        RouteTableId: !Ref SecVpcAz1PrivateRouteTable
        DestinationCidrBlock: '0.0.0.0/0'
        NatGatewayId: !Ref SecVpcAz1NatGateway

  SecVpcAz2PrivateSubnetToInternetRoute:
     DependsOn: SecVpcAz2NatGateway
     Type: AWS::EC2::Route
     Properties:
        RouteTableId: !Ref SecVpcAz2PrivateRouteTable
        DestinationCidrBlock: '0.0.0.0/0'
        NatGatewayId: !Ref SecVpcAz2NatGateway

#-----------------添加路由-----------------#

# 公有子网添加默认路由去往IGW
  SecVpcAz1PublicSubnetToInternetRoute:
    Type: "AWS::EC2::Route"
    DependsOn: SecVpcIGW
    Properties:
     RouteTableId: !Ref SecVpcAz1PublicRouteTable
     DestinationCidrBlock: 0.0.0.0/0
     GatewayId: !Ref SecVpcIGW

  SecVpcAz2PublicSubnetToInternetRoute:
    Type: "AWS::EC2::Route"
    DependsOn: SecVpcIGW
    Properties:
     RouteTableId: !Ref SecVpcAz2PublicRouteTable
     DestinationCidrBlock: 0.0.0.0/0
     GatewayId: !Ref SecVpcIGW

#-----------------SecVpc创建安全组-----------------#
  SecVpcSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SG to test ping
      VpcId: !Ref SecVpc
      SecurityGroupIngress:
      - IpProtocol: icmp
        FromPort: -1
        ToPort: -1
        CidrIp: 0.0.0.0/0
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 10.100.0.0/16
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 161.189.204.137/32
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpcSg


#-----------------SecVpc创建EC2实例-----------------#

#---IAM Instance Role and Profile---#
  ApplianceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "${AWS::StackName}-appliance-role"
      ManagedPolicyArns:
        - "arn:aws-cn:iam::aws:policy/AmazonSSMManagedInstanceCore"
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /

  AppliancePolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: AppServer
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - ec2:DescribeNetworkInterfaces
            Resource: '*'
      Roles:
        - !Ref ApplianceRole

  ApplianceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: /
      Roles:
        - !Ref ApplianceRole

#-----------------SecVpc创建GWLB-----------------#

# Gateway Load Balancer (GWLB), Target Group, Listener
  Gwlb:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      LoadBalancerAttributes:
        - Key: load_balancing.cross_zone.enabled
          Value: true
      Name: gwlb-panorama
      Type: gateway
      Subnets:
        - !Ref SecVpcAz1PrivateSubnet
        - !Ref SecVpcAz2PrivateSubnet
      Tags:
      - Key: Name
        Value: !Sub "${AWS::StackName}-gwlb-1"

  # Target Group:
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: target-group-panorama
      Port: 6081
      Protocol: GENEVE
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: "20"
      VpcId: !Ref SecVpc
      HealthCheckPort: 80
      HealthCheckProtocol: HTTP
      TargetType: instance
      Targets:
        - Id: !Ref Appliance1
        - Id: !Ref Appliance2
      Tags:
      - Key: Name
        Value: !Sub "${AWS::StackName}-tg-1"

  # Listener:
  Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
      - Type: forward
        TargetGroupArn: !Ref TargetGroup
      LoadBalancerArn: !Ref Gwlb

#-----------------SecVpc创建EC2实例-----------------#

#---SecVpc创建paloalto接口---#

  Pa1MgmtEip:
    Type: "AWS::EC2::EIP"
    Properties:
      Tags:
        - Key: Name
          Value: SecVpc-pa1-mgmt-eip

  Pa1MgmtEni:  # 创建PA1管理接口
    Type: "AWS::EC2::NetworkInterface"
    Properties:
      GroupSet:
        - !Ref SecVpcSg
      SubnetId:
        Ref: SecVpcAz1PublicSubnet
      Tags:
        - Key: Name
          Value: SecVpc-pa1-mgmt-eni

  Pa1MgmtEniAssociation:  # 关联公网IP到Mgt弹性接口
    Type: AWS::EC2::EIPAssociation
    DependsOn: Appliance1
    Properties:
      AllocationId: !GetAtt Pa1MgmtEip.AllocationId # 这里是EIP
      NetworkInterfaceId: !Ref Pa1MgmtEni

  Pa1DataEni:  # 创建PA1数据接口
    Type: "AWS::EC2::NetworkInterface"
    Properties:
      GroupSet:
        - Ref: SecVpcSg
      SubnetId:
        Ref: SecVpcAz1PrivateSubnet
      Tags:
        - Key: Name
          Value: SecVpc-pa1-data-eni

  Pa2MgmtEip:
    Type: "AWS::EC2::EIP"
    Properties:
      Tags:
        - Key: Name
          Value: SecVpc-pa2-mgmt-eip

  Pa2MgmtEni:  # 创建PA2管理接口
    Type: "AWS::EC2::NetworkInterface"
    Properties:
      GroupSet:
        - !Ref SecVpcSg
      SubnetId:
        Ref: SecVpcAz2PublicSubnet
      Tags:
        - Key: Name
          Value: SecVpc-pa2-mgmt-eni

  Pa2MgmtEniAssociation:  # 关联公网IP到Mgt弹性接口
    Type: AWS::EC2::EIPAssociation
    DependsOn: Appliance2
    Properties:
      AllocationId: !GetAtt Pa2MgmtEip.AllocationId # 这里是EIP
      NetworkInterfaceId: !Ref Pa2MgmtEni

  Pa2DataEni:  # 创建PA2数据接口
    Type: "AWS::EC2::NetworkInterface"
    Properties:
      GroupSet:
        - !Ref SecVpcSg
      SubnetId:
        Ref: SecVpcAz2PrivateSubnet
      Tags:
        - Key: Name
          Value: SecVpc-pa2-data-eni

# EC2 Instances (Appliances acting as target for GWLB):
  Appliance1:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", !Ref PaloaltoVersion]
      KeyName: !Ref MyKeyPair
      InstanceType: !Ref PaloaltoInstanceType
      NetworkInterfaces:
        -
          NetworkInterfaceId: !Ref Pa1DataEni
          DeviceIndex: 0
        -
          NetworkInterfaceId: !Ref Pa1MgmtEni
          DeviceIndex: 1
      UserData:
        Fn::Base64:
          !Sub |
          mgmt-interface-swap=enable
          plugin-op-commands=aws-gwlb-inspect:enable
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-PA-FW1

  Appliance2:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", !Ref PaloaltoVersion]
      KeyName: !Ref MyKeyPair
      InstanceType: !Ref PaloaltoInstanceType
      NetworkInterfaces:
        -
          NetworkInterfaceId: !Ref Pa2DataEni
          DeviceIndex: 0
        -
          NetworkInterfaceId: !Ref Pa2MgmtEni
          DeviceIndex: 1
      UserData:
        Fn::Base64:
          !Sub |
          mgmt-interface-swap=enable
          plugin-op-commands=aws-gwlb-inspect:enable
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-PA-FW2

  SecVpcBastionLinux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet:
            - Ref: SecVpcSg
          SubnetId: !Ref SecVpcAz1PublicSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-SecVpc-Bastion-Linux

# Create VPC Endpoint Service:

  VpcEndpointService:
    Type: AWS::EC2::VPCEndpointService
    Properties:
      GatewayLoadBalancerArns:
        - !Ref Gwlb
      AcceptanceRequired: false

# Create Lambda Custom Resource to retrieve VPC Endpoint Service Name:

  VpceServiceLambdaExecutionRole:
    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-cn:logs:*:*:*
              - Effect: Allow
                Action:
                  - ec2:DescribeVpcEndpointServiceConfigurations
                  - ec2:DescribeVpcEndpointServicePermissions
                  - ec2:DescribeVpcEndpointServices
                Resource: "*"


  VpceServiceLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
        LogGroupName: !Sub /aws/lambda/${AWS::StackName}-service
        RetentionInDays: 1

  VpceServiceName:
    Type: AWS::Lambda::Function
    DependsOn: VpceServiceLogGroup
    Properties:
      FunctionName: !Sub ${AWS::StackName}-service
      Handler: "index.handler"
      Role: !GetAtt VpceServiceLambdaExecutionRole.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:
                  serviceid = event["ResourceProperties"]["VpceServiceId"]
              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("Retrieving VPC Endpoint Service Name:")
                  try:
                      response = ec2.describe_vpc_endpoint_service_configurations(
                          Filters=[
                              {
                                  'Name': 'service-id',
                                  'Values': [serviceid]
                              }
                          ]
                      )
                  except Exception as e:
                      logger.info('ec2.describe_vpc_endpoint_service_configurations failure: {}'.format(e))

                  service_name = response['ServiceConfigurations'][0]['ServiceName']

                  time.sleep(120)

                  responseData['ServiceName'] = service_name
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
      Runtime: python3.7
      Timeout: 150

  RetrieveVpceServiceName:
    Type: Custom::RetrieveAttributes
    Properties:
      ServiceToken: !GetAtt VpceServiceName.Arn
      VpceServiceId: !Ref VpcEndpointService

# Create Gateway Load Balancer Endpoint:

  GwlbEndpoint1:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref SecVpc
      ServiceName: !GetAtt RetrieveVpceServiceName.ServiceName
      VpcEndpointType: GatewayLoadBalancer
      SubnetIds:
        - !Ref SecVpcAz1PrivateSubnet

  GwlbEndpoint2:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref SecVpc
      ServiceName: !GetAtt RetrieveVpceServiceName.ServiceName
      VpcEndpointType: GatewayLoadBalancer
      SubnetIds:
        - !Ref SecVpcAz2PrivateSubnet


#=============VpcA============#
# 创建VpcA
  VpcA:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.110.10.0/16
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      Tags:
       - Key: Name
         Value: !Sub ${AWS::StackName}-VpcA

# 创建IGW并且关联到VPC
  VpcAIGW:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcAIGW

  VpcAAttachIgw:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref VpcA
      InternetGatewayId: !Ref VpcAIGW

#-----------------VpcA创建6个子网------------------#

# VpcA AZ1内创建公有子网
  VpcAAz1PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcA
      CidrBlock: 10.110.10.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcA-AZ1-Public-Subnet

# VpcA AZ2内创建公有子网
  VpcAAz2PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcA
      CidrBlock: 10.110.20.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcA-AZ2-Public-Subnet

# VpcA AZ1内创建APP子网
  VpcAAz1AppSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcA
      CidrBlock: 10.110.30.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcA-AZ1-App-Subnet

# VpcA AZ2内创建APP子网
  VpcAAz2AppSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcA
      CidrBlock: 10.110.40.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcA-AZ2-App-Subnet


# VpcA AZ1内创建TGW子网
  VpcAAz1TgwSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcA
      CidrBlock: 10.110.50.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcA-AZ1-TGW-Subnet

# VpcA AZ2内创建TGW子网
  VpcAAz2TgwSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcA
      CidrBlock: 10.110.60.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcA-AZ2-TGW-Subnet

#-----------------VpcA创建路由表------------------#

# 公有子网路由表及关联
  VpcAAz1PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ1-Public-RouteTable

  VpcAAz1PublicRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcAAz1PublicRouteTable
      SubnetId: !Ref VpcAAz1PublicSubnet

  VpcAAz2PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ2-Public-RouteTable

  VpcAAz2PublicRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcAAz2PublicRouteTable
      SubnetId: !Ref VpcAAz2PublicSubnet

# App子网路由表及关联
  VpcAAz1AppRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ1-App-RouteTable

  VpcAAz1AppRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcAAz1AppRouteTable
      SubnetId: !Ref VpcAAz1AppSubnet

  VpcAAz2AppRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ2-App-RouteTable

  VpcAAz2AppRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcAAz2AppRouteTable
      SubnetId: !Ref VpcAAz2AppSubnet


# Tgw路由表及关联
  VpcAAz1TgwRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ1-Tgw-RouteTable

  VpcAAz1TgwRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcAAz1TgwRouteTable
      SubnetId: !Ref VpcAAz1TgwSubnet

  VpcAAz2TgwRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ2-Tgw-RouteTable

  VpcAAz2TgwRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcAAz2TgwRouteTable
      SubnetId: !Ref VpcAAz2TgwSubnet

#-----------------NAT Gateway-----------------#

# AZ1 NAT GW
  VpcAAz1NatGatewayEIP:
     Type: AWS::EC2::EIP
     Properties:
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ1-NatGateway-EIP

  VpcAAz1NatGateway:
     Type: AWS::EC2::NatGateway
     Properties:
        AllocationId: !GetAtt VpcAAz1NatGatewayEIP.AllocationId
        SubnetId: !Ref VpcAAz1PublicSubnet
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ1-NatGateway

# AZ2 NAT GW
  VpcAAz2NatGatewayEIP:
     Type: AWS::EC2::EIP
     Properties:
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ2-NatGateway-EIP

  VpcAAz2NatGateway:
     Type: AWS::EC2::NatGateway
     Properties:
        AllocationId: !GetAtt VpcAAz2NatGatewayEIP.AllocationId
        SubnetId: !Ref VpcAAz2PublicSubnet
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-AZ2-NatGateway


#-----------------添加路由-----------------#

# 公有子网添加默认路由去往IGW
  VpcAAz1PublicSubnetToInternetRoute:
    Type: "AWS::EC2::Route"
    DependsOn: VpcAIGW
    Properties:
     RouteTableId: !Ref VpcAAz1PublicRouteTable
     DestinationCidrBlock: 0.0.0.0/0
     GatewayId: !Ref VpcAIGW

  VpcAAz2PublicSubnetToInternetRoute:
    Type: "AWS::EC2::Route"
    DependsOn: VpcAIGW
    Properties:
     RouteTableId: !Ref VpcAAz2PublicRouteTable
     DestinationCidrBlock: 0.0.0.0/0
     GatewayId: !Ref VpcAIGW

#-----------------VpcA创建安全组-----------------#
  VpcABastionVpcSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SG to test ping
      VpcId: !Ref VpcA
      SecurityGroupIngress:
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 10.120.0.0/16
      - IpProtocol: icmp
        FromPort: -1
        ToPort: -1
        CidrIp: 0.0.0.0/0
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 10.110.0.0/16
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 161.189.204.137/32
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcASg


#-----------------VpcA创建EC2实例-----------------#

  VpcABastionLinux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet:
            - Ref: VpcABastionVpcSg
          SubnetId: !Ref VpcAAz1PublicSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-Bastion-Linux

  VpcAApp1Linux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - DeviceIndex: 0
          GroupSet:
            - Ref: VpcABastionVpcSg
          SubnetId: !Ref VpcAAz1AppSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-App1-Linux

  VpcAApp2Linux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - DeviceIndex: 0
          GroupSet:
            - Ref: VpcABastionVpcSg
          SubnetId: !Ref VpcAAz2AppSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcA-App2-Linux


#=============VpcB============#
# 创建VpcB
  VpcB:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.120.10.0/16
      EnableDnsSupport: 'true'
      EnableDnsHostnames: 'true'
      Tags:
       - Key: Name
         Value: !Sub ${AWS::StackName}-VpcB

# 创建IGW并且关联到VPC
  VpcBIGW:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcBIGW

  VpcBAttachIgw:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      VpcId: !Ref VpcB
      InternetGatewayId: !Ref VpcBIGW

#-----------------VpcB创建6个子网------------------#

# VpcB AZ1内创建公有子网
  VpcBAz1PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcB
      CidrBlock: 10.120.10.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcB-AZ1-Public-Subnet

# VpcB AZ2内创建公有子网
  VpcBAz2PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcB
      CidrBlock: 10.120.20.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcB-AZ2-Public-Subnet

# VpcB AZ1内创建APP子网
  VpcBAz1AppSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcB
      CidrBlock: 10.120.30.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcB-AZ1-App-Subnet

# VpcB AZ2内创建APP子网
  VpcBAz2AppSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcB
      CidrBlock: 10.120.40.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcB-AZ2-App-Subnet


# VpcB AZ1内创建TGW子网
  VpcBAz1TgwSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcB
      CidrBlock: 10.120.50.0/24
      AvailabilityZone:
        Fn::Select:
          - 0
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcB-AZ1-TGW-Subnet

# VpcB AZ2内创建TGW子网
  VpcBAz2TgwSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VpcB
      CidrBlock: 10.120.60.0/24
      AvailabilityZone:
        Fn::Select:
          - 1
          - Fn::GetAZs: ""
      Tags:
      - Key: Name
        Value: !Sub ${AWS::StackName}-VpcB-AZ2-TGW-Subnet

#-----------------VpcB创建路由表------------------#

# 公有子网路由表及关联
  VpcBAz1PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ1-Public-RouteTable

  VpcBAz1PublicRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcBAz1PublicRouteTable
      SubnetId: !Ref VpcBAz1PublicSubnet

  VpcBAz2PublicRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ2-Public-RouteTable

  VpcBAz2PublicRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcBAz2PublicRouteTable
      SubnetId: !Ref VpcBAz2PublicSubnet

# App子网路由表及关联
  VpcBAz1AppRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ1-App-RouteTable

  VpcBAz1AppRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcBAz1AppRouteTable
      SubnetId: !Ref VpcBAz1AppSubnet

  VpcBAz2AppRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ2-App-RouteTable

  VpcBAz2AppRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcBAz2AppRouteTable
      SubnetId: !Ref VpcBAz2AppSubnet


# Tgw路由表及关联
  VpcBAz1TgwRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ1-Tgw-RouteTable

  VpcBAz1TgwRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcBAz1TgwRouteTable
      SubnetId: !Ref VpcBAz1TgwSubnet

  VpcBAz2TgwRouteTable:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ2-Tgw-RouteTable

  VpcBAz2TgwRouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      RouteTableId: !Ref VpcBAz2TgwRouteTable
      SubnetId: !Ref VpcBAz2TgwSubnet

#-----------------NAT Gateway-----------------#

# AZ1 NAT GW
  VpcBAz1NatGatewayEIP:
     Type: AWS::EC2::EIP
     Properties:
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ1-NatGateway-EIP

  VpcBAz1NatGateway:
     Type: AWS::EC2::NatGateway
     Properties:
        AllocationId: !GetAtt VpcBAz1NatGatewayEIP.AllocationId
        SubnetId: !Ref VpcBAz1PublicSubnet
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ1-NatGateway

# AZ2 NAT GW
  VpcBAz2NatGatewayEIP:
     Type: AWS::EC2::EIP
     Properties:
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ2-NatGateway-EIP

  VpcBAz2NatGateway:
     Type: AWS::EC2::NatGateway
     Properties:
        AllocationId: !GetAtt VpcBAz2NatGatewayEIP.AllocationId
        SubnetId: !Ref VpcBAz2PublicSubnet
        Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-AZ2-NatGateway


#-----------------添加路由-----------------#

# 公有子网添加默认路由去往IGW
  VpcBAz1PublicSubnetToInternetRoute:
    Type: "AWS::EC2::Route"
    DependsOn: VpcBIGW
    Properties:
     RouteTableId: !Ref VpcBAz1PublicRouteTable
     DestinationCidrBlock: 0.0.0.0/0
     GatewayId: !Ref VpcBIGW

  VpcBAz2PublicSubnetToInternetRoute:
    Type: "AWS::EC2::Route"
    DependsOn: VpcBIGW
    Properties:
     RouteTableId: !Ref VpcBAz2PublicRouteTable
     DestinationCidrBlock: 0.0.0.0/0
     GatewayId: !Ref VpcBIGW

#-----------------VpcB创建安全组-----------------#
  VpcBBastionVpcSg:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SG to test ping
      VpcId: !Ref VpcB
      SecurityGroupIngress:
      - IpProtocol: icmp
        FromPort: -1
        ToPort: -1
        CidrIp: 0.0.0.0/0
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 10.110.0.0/16
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 10.120.0.0/16
      - IpProtocol: -1
        FromPort: -1
        ToPort: -1
        CidrIp: 161.189.204.137/32
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcBSg


#-----------------VpcB创建EC2实例-----------------#

  VpcBBastionLinux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          GroupSet:
            - Ref: VpcBBastionVpcSg
          SubnetId: !Ref VpcBAz1PublicSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-Bastion-Linux

  VpcBApp1Linux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - DeviceIndex: 0
          GroupSet:
            - Ref: VpcBBastionVpcSg
          SubnetId: !Ref VpcBAz1AppSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-App1-Linux

  VpcBApp2Linux:
    Type: AWS::EC2::Instance
    Properties:
      IamInstanceProfile: !Ref BastionSsmProfile
      ImageId: !Ref EC2InstanceAmiId
      KeyName: !Ref MyKeyPair
      InstanceType: t3.nano
      NetworkInterfaces:
        - DeviceIndex: 0
          GroupSet:
            - Ref: VpcBBastionVpcSg
          SubnetId: !Ref VpcBAz2AppSubnet
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-VpcB-App2-Linux



#=============TGW============#


#---创建TGW---#

  Tgw1:
    Type: AWS::EC2::TransitGateway
    Properties:
      AmazonSideAsn: 64512
      AutoAcceptSharedAttachments: enable
      DefaultRouteTableAssociation: disable
      DefaultRouteTablePropagation: disable
      Description: Transit Gateway 1 for GWLB Centralized Architecture
      DnsSupport: enable
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-tgw-1"
      VpnEcmpSupport: enable

#------创建TGW VPC挂载------#

  Tgw1VpcAAttachment:
    Type: AWS::EC2::TransitGatewayAttachment
    Properties:
      SubnetIds:
        - !Ref VpcAAz1TgwSubnet
        - !Ref VpcAAz2TgwSubnet
      TransitGatewayId: !Ref Tgw1
      VpcId: !Ref VpcA
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-VpcA-attachment"


  Tgw1VpcBAttachment:
    Type: AWS::EC2::TransitGatewayAttachment
    Properties:
      SubnetIds:
        - !Ref VpcBAz1TgwSubnet
        - !Ref VpcBAz2TgwSubnet
      TransitGatewayId: !Ref Tgw1
      VpcId: !Ref VpcB
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-VpcB-attachment"

  Tgw1SecVpcAttachment:
    Type: AWS::EC2::TransitGatewayAttachment
    Properties:
      SubnetIds:
        - !Ref SecVpcAz1TgwSubnet
        - !Ref SecVpcAz2TgwSubnet
      TransitGatewayId: !Ref Tgw1
      VpcId: !Ref SecVpc
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-appliance-vpc-attachment"

#-----------------------创建TGW路由表并关联VPC-----------------------#

  Tgw1VpcARtb:
    Type: AWS::EC2::TransitGatewayRouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-Tgw-VpcA-RTB"
      TransitGatewayId: !Ref Tgw1

  Tgw1VpcARtbAttachmentAssociation:
    Type: AWS::EC2::TransitGatewayRouteTableAssociation
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1VpcAAttachment
      TransitGatewayRouteTableId: !Ref Tgw1VpcARtb

  Tgw1VpcBRtb:
    Type: AWS::EC2::TransitGatewayRouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-Tgw-VpcB-RTB"
      TransitGatewayId: !Ref Tgw1

  Tgw1VpcBRtbAttachmentAssociation:
    Type: AWS::EC2::TransitGatewayRouteTableAssociation
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1VpcBAttachment
      TransitGatewayRouteTableId: !Ref Tgw1VpcBRtb

  Tgw1SecVpcRtb:
    Type: AWS::EC2::TransitGatewayRouteTable
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-SecVpc-RTB"
      TransitGatewayId: !Ref Tgw1

  Tgw1SecVpcRtbAttachmentAssociation:
    Type: AWS::EC2::TransitGatewayRouteTableAssociation
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1SecVpcAttachment
      TransitGatewayRouteTableId: !Ref Tgw1SecVpcRtb

#-----------------------创建TGW路由-----------------------#

# VpcA的TGW路由表
  Tgw1VpcARoute1:
    Type: AWS::EC2::TransitGatewayRoute
    DependsOn: Tgw1SecVpcAttachment
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1SecVpcAttachment
      DestinationCidrBlock: '0.0.0.0/0'
      TransitGatewayRouteTableId: !Ref Tgw1VpcARtb

# VpcB的TGW路由表
  Tgw1VpcBRoute1:
    Type: AWS::EC2::TransitGatewayRoute
    DependsOn: Tgw1SecVpcAttachment
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1SecVpcAttachment
      DestinationCidrBlock: '0.0.0.0/0'
      TransitGatewayRouteTableId: !Ref Tgw1VpcBRtb

# SecVpc的TGW路由表
  Tgw1SecVpcRoute1:
    Type: AWS::EC2::TransitGatewayRoute
    DependsOn: Tgw1VpcAAttachment
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1VpcAAttachment
      DestinationCidrBlock: '10.110.0.0/16'
      TransitGatewayRouteTableId: !Ref Tgw1SecVpcRtb

  Tgw1SecVpcRoute2:
    Type: AWS::EC2::TransitGatewayRoute
    DependsOn: Tgw1VpcBAttachment
    Properties:
      TransitGatewayAttachmentId: !Ref Tgw1VpcBAttachment
      DestinationCidrBlock: '10.120.0.0/16'
      TransitGatewayRouteTableId: !Ref Tgw1SecVpcRtb


#-----------------------VpcA VpcB Tgw相关路由-----------------------#

  VpcAPublicAz1TgwRoute1:
    DependsOn: Tgw1VpcAAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.100.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcAAz1PublicRouteTable

  VpcAPublicAz2TgwRoute1:
    DependsOn: Tgw1VpcAAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.100.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcAAz2PublicRouteTable

  VpcAPublicAz1TgwRoute2:
    DependsOn: Tgw1VpcAAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.120.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcAAz1PublicRouteTable

  VpcAPublicAz2TgwRoute2:
    DependsOn: Tgw1VpcAAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.120.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcAAz2PublicRouteTable

  VpcAAppAz1TgwRoute1:
    DependsOn: Tgw1VpcAAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcAAz1AppRouteTable

  VpcAAppAz2TgwRoute1:
    DependsOn: Tgw1VpcAAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcAAz2AppRouteTable

# ---VpcB路由表---

  VpcBPublicAz1TgwRoute1:
    DependsOn: Tgw1VpcBAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.100.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcBAz1PublicRouteTable

  VpcBPublicAz2TgwRoute1:
    DependsOn: Tgw1VpcBAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.100.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcBAz2PublicRouteTable

  VpcBPublicAz1TgwRoute2:
    DependsOn: Tgw1VpcBAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.110.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcBAz1PublicRouteTable

  VpcBPublicAz2TgwRoute2:
    DependsOn: Tgw1VpcBAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.110.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcBAz2PublicRouteTable

  VpcBAppAz1TgwRoute1:
    DependsOn: Tgw1VpcBAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcBAz1AppRouteTable

  VpcBAppAz2TgwRoute1:
    DependsOn: Tgw1VpcBAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref VpcBAz2AppRouteTable

#-----------------------SecVpc Tgw相关路由-----------------------#

  SecVpcPrivateAz1TgwRoute1:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.110.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref SecVpcAz1PrivateRouteTable

  SecVpcPrivateAz2TgwRoute1:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.110.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref SecVpcAz2PrivateRouteTable

  SecVpcPrivateAz1TgwRoute2:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.120.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref SecVpcAz1PrivateRouteTable

  SecVpcPrivateAz2TgwRoute2:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.120.0.0/16'
      TransitGatewayId: !Ref Tgw1
      RouteTableId: !Ref SecVpcAz2PrivateRouteTable


#-----------------------SecVpc Endpoint相关路由-----------------------#

  SecVpcPublicAz1Route1:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.110.0.0/16'
      VpcEndpointId: !Ref GwlbEndpoint1
      RouteTableId: !Ref SecVpcAz1PublicRouteTable

  SecVpcPublicAz2Route1:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.110.0.0/16'
      VpcEndpointId: !Ref GwlbEndpoint2
      RouteTableId: !Ref SecVpcAz2PublicRouteTable

  SecVpcPublicAz1Route2:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.120.0.0/16'
      VpcEndpointId: !Ref GwlbEndpoint1
      RouteTableId: !Ref SecVpcAz1PublicRouteTable

  SecVpcPublicAz2Route2:
    DependsOn: Tgw1SecVpcAttachment
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '10.120.0.0/16'
      VpcEndpointId: !Ref GwlbEndpoint2
      RouteTableId: !Ref SecVpcAz2PublicRouteTable

  SecVpcAz1TgwRoute1:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      VpcEndpointId: !Ref GwlbEndpoint1
      RouteTableId: !Ref SecVpcAz1TgwRouteTable

  SecVpcAz2TgwRoute1:
    Type: AWS::EC2::Route
    Properties:
      DestinationCidrBlock: '0.0.0.0/0'
      VpcEndpointId: !Ref GwlbEndpoint2
      RouteTableId: !Ref SecVpcAz2TgwRouteTable


#-----------------------修改TGW负载均衡模式-----------------------#

# Transit Gateway appliance mode Lambda Role:
  TgwLambdaExecutionRole:
    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: !GetAtt TgwApplianceModeLogGroup.Arn
              - Effect: Allow
                Action:
                  - ec2:ModifyTransitGatewayVpcAttachment
                  - ec2:DescribeTransitGatewayVpcAttachments
                Resource: "*"

# Enable Transit Gateway Appliance Mode Lambda Custom Resource:
  TgwApplianceModeLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
        LogGroupName: !Sub /aws/lambda/${AWS::StackName}-tgw-appliancemode
        RetentionInDays: 1

  TgwApplianceMode:
    Type: AWS::Lambda::Function
    DependsOn: TgwApplianceModeLogGroup
    Properties:
      FunctionName: !Sub ${AWS::StackName}-tgw-appliancemode
      Handler: "index.handler"
      Role: !GetAtt TgwLambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging

          def handler(event, context):
              logger = logging.getLogger()
              logger.setLevel(logging.INFO)
              responseData = {}
              responseStatus = cfnresponse.FAILED
              logger.info('Received event: {}'.format(json.dumps(event)))
              if event["RequestType"] == "Delete":
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
              if event["RequestType"] == "Create":
                  try:
                      TgwSecVpcAttachmentId = event["ResourceProperties"]["TgwSecVpcAttachmentId"]
                      ApplianceMode = event["ResourceProperties"]["ApplianceMode"]
                  except Exception as e:
                      logger.info('Key retrieval failure: {}'.format(e))
                  try:
                      ec2 = boto3.client('ec2')
                  except Exception as e:
                      logger.info('boto3.client failure: {}'.format(e))
                  try:
                      ec2.modify_transit_gateway_vpc_attachment(
                          TransitGatewayAttachmentId = TgwSecVpcAttachmentId,
                          Options = {'ApplianceModeSupport': ApplianceMode}
                      )
                      TgwResponse = ec2.describe_transit_gateway_vpc_attachments(
                          TransitGatewayAttachmentIds=[TgwSecVpcAttachmentId]
                      )
                      ApplianceModeStatus = TgwResponse['TransitGatewayVpcAttachments'][0]['Options']['ApplianceModeSupport']
                  except Exception as e:
                      logger.info('ec2.modify/describe_transit_gateway_vpc_attachment: {}'.format(e))

                  responseData['ApplianceModeStatus'] = ApplianceModeStatus
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
      Runtime: python3.7
      Timeout: 30

  ApplianceModeEnabled:
    Type: Custom::ModifyTransitGatewayVpcAttachment
    Properties:
      ServiceToken: !GetAtt TgwApplianceMode.Arn
      TgwSecVpcAttachmentId: !Ref Tgw1SecVpcAttachment
      ApplianceMode: enable

三、初始化Paloalto防火墙

使用EC2密钥登录防火墙CLI,修改admin用户的密码。

commitadmin@PA-VM> configure
Entering configuration mode
[edit]
admin@PA-VM# set mgt-config users admin password
Enter password   :
Confirm password :

[edit]
admin@PA-VM# commit

第一台防火墙初始化命令。

set network profiles interface-management-profile MgtProfile http yes
set network profiles interface-management-profile MgtProfile ssh yes
set network profiles interface-management-profile MgtProfile ping yes

set network interface ethernet ethernet1/1 layer3 ndp-proxy enabled no
set network interface ethernet ethernet1/1 layer3 sdwan-link-settings upstream-nat enable no
set network interface ethernet ethernet1/1 layer3 sdwan-link-settings upstream-nat static-ip
set network interface ethernet ethernet1/1 layer3 sdwan-link-settings enable no
set network interface ethernet ethernet1/1 layer3 interface-management-profile MgtProfile
set network interface ethernet ethernet1/1 layer3 lldp enable no
set network interface ethernet ethernet1/1 layer3 dhcp-client

set network virtual-router default interface ethernet1/1
set zone untrust network layer3 ethernet1/1

set rulebase default-security-rules rules intrazone-default action allow
set rulebase default-security-rules rules intrazone-default log-start yes
set rulebase default-security-rules rules intrazone-default log-end yes
set rulebase default-security-rules rules intrazone-default profile-setting profiles url-filtering default
set rulebase default-security-rules rules intrazone-default profile-setting profiles file-blocking "strict file blocking"
set rulebase default-security-rules rules intrazone-default profile-setting profiles virus default
set rulebase default-security-rules rules intrazone-default profile-setting profiles spyware strict
set rulebase default-security-rules rules intrazone-default profile-setting profiles vulnerability strict
set rulebase default-security-rules rules intrazone-default profile-setting profiles wildfire-analysis default

set deviceconfig system hostname PA1
set deviceconfig system locale zh_CN
set deviceconfig system timezone Asia/Shanghai

commit

第二台防火墙初始化命令,只有主机名不同。

set network profiles interface-management-profile MgtProfile http yes
set network profiles interface-management-profile MgtProfile ssh yes
set network profiles interface-management-profile MgtProfile ping yes

set network interface ethernet ethernet1/1 layer3 ndp-proxy enabled no
set network interface ethernet ethernet1/1 layer3 sdwan-link-settings upstream-nat enable no
set network interface ethernet ethernet1/1 layer3 sdwan-link-settings upstream-nat static-ip
set network interface ethernet ethernet1/1 layer3 sdwan-link-settings enable no
set network interface ethernet ethernet1/1 layer3 interface-management-profile MgtProfile
set network interface ethernet ethernet1/1 layer3 lldp enable no
set network interface ethernet ethernet1/1 layer3 dhcp-client

set network virtual-router default interface ethernet1/1
set zone untrust network layer3 ethernet1/1

set rulebase default-security-rules rules intrazone-default action allow
set rulebase default-security-rules rules intrazone-default log-start yes
set rulebase default-security-rules rules intrazone-default log-end yes
set rulebase default-security-rules rules intrazone-default profile-setting profiles url-filtering default
set rulebase default-security-rules rules intrazone-default profile-setting profiles file-blocking "strict file blocking"
set rulebase default-security-rules rules intrazone-default profile-setting profiles virus default
set rulebase default-security-rules rules intrazone-default profile-setting profiles spyware strict
set rulebase default-security-rules rules intrazone-default profile-setting profiles vulnerability strict
set rulebase default-security-rules rules intrazone-default profile-setting profiles wildfire-analysis default
Pr
set deviceconfig system hostname PA2
set deviceconfig system locale zh_CN
set deviceconfig system timezone Asia/Shanghai

commit

四、AWS上部署Panorama实例

搜索Panorama关键词,点击「亚马逊云科技Marketplace AMI」过滤,选择Panorama的镜像启动。image-20230131112225465

Panorama至少需要16vCPU,32GB内存。这个AMI设置了允许的实例类型,随意选择实例类型可能不受支持,从而启动失败,推荐使用m4.4xlarge实例即可。image-20230131110928855

选择EC2密钥,放置在SecVpc的公有子网,启动自动获取公网IP地址,选择现有安全组。添加一块2TB的存储卷,用于存储日志文件。最后启动实例,Panorama首次启动非常慢,大概需要20分钟才会完成启动。image-20230131110934839

使用EC2密钥登录Panorama防火墙,修改admin用户的密码。

admin@Panorama> configure
Entering configuration mode
[edit]
admin@Panorama# set mgt-config users admin password
Enter password   :
Confirm password :

[edit]
admin@Panorama# commit

五、Panorama与Paloalto激活

登录Paloalto网页:https://support.paloaltonetworks.com/SupportAccount/FirewallFlexDashboard,创建一个新的授权配置文件。

CN-Series是各类容器与容器管理平台中的容器版本防火墙。

Flexible vCPUs会根据系统分配的vCPU和内存,来决定防火墙的型号。

勾选For Management表示使用Panorama。

image-20230131145107662

生成Panorama的序列号。image-20230131145102468

输入序列号,激活Panorama。激活会重启Panorama,需要等待5分钟左右。image-20230131145630466

Panorama激活成功。image-20230131155953522

Paloalto防火墙激活成功。image-20230131160029141

六、Panorama版本升级

Panorama设置更新服务器域名、DNS服务器、NTP服务器,设置完成后,点击右上角Commit提交配置。image-20230131172429485

Panorama升级之前需要更新应用库。这里检查更新也需要花费较长时间。image-20230131170058297

Panorama升级到与Paloalto防火墙相同版本。下载比较快,安装需要等待较长时间。image-20230131155400536

Panorama升级完成。image-20230131170030113

七、Panorama添加Paloalto防火墙

在两台Paloalto防火墙上,配置DNS服务器和NTP服务器。image-20230103155723586

防火墙可以通过CLI查看NTP同步状态。

admin@PA1> show ntp

NTP state:
    NTP synched to ntp1.aliyun.com
    NTP server: ntp1.aliyun.com
        status: synched
        reachable: yes
        authentication-type: none
    NTP server: ntp2.aliyun.com
        status: available
        reachable: yes
        authentication-type: none

在Panorama上添加Paloalto防火墙,输入两台防火墙的序列号之后,拷贝认证密钥,最后提交配置到Panorama。image-20230131173933740

在两台Paloalto防火墙上添加Panorama的IP地址,以及认证密钥信息,最后提交配置到Paloalto。image-20230131173938840

Panorama上添加成功添加Paloalto防火墙。image-20230131174036445

八、文档链接