Wie füge ich mit CloudFormation Routen zur Haupt-Routing-Tabelle in meiner Amazon VPC hinzu?

Lesedauer: 3 Minute
0

Ich möchte der Haupt-Routing-Tabelle Routen hinzufügen, wenn ich meine Amazon Virtual Private Cloud (Amazon VPC) in AWS CloudFormation erstelle.

Behebung

Wenn Sie CloudFormation verwenden, um eine Amazon VPC zu erstellen, erkennt CloudFormation die standardmäßig erstellte Haupt-Routing-Tabelle nicht. Sie können der Haupt-Routing-Tabelle keine Routen hinzufügen oder aus ihr entfernen, da Sie in Ihrer CloudFormation-Vorlage nicht auf die Routing-Tabelle verweisen können.

Um dieses Problem zu lösen, verwenden Sie eine AWS Lambda-unterstützte benutzerdefinierte Ressource in der CloudFormation-Vorlage.

Verwenden Sie die folgende RouteTable-template.yml-Vorlage, um einen CloudFormation-Stack mit einer benutzerdefinierten Ressource zu erstellen:

AWSTemplateFormatVersion: 2010-09-09
Description: Template to add routes to default/main routetable of VPC
Resources:
  MyVPC:
    Type: 'AWS::EC2::VPC'
    Properties:
      CidrBlock: 10.0.0.0/16
      Tags:
        - Key: Env
          Value: Test
  LambdaIAMRole:
    Type: 'AWS::IAM::Role'
    DependsOn: MyVPC
    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:
                  - 'ec2:Describe*'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'
  LambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt LambdaIAMRole.Arn
      Runtime: python3.9
      Timeout: 50
      Code:
        ZipFile: |
            from __future__ import print_function
            import json
            import boto3
            import urllib3
            import cfnresponse

            SUCCESS = "SUCCESS"
            FAILED = "FAILED"

            http = urllib3.PoolManager()

            print('Loading function')
            ec2 = boto3.client('ec2')

            def lambda_handler(event, context):
                print("Received event: " + json.dumps(event, indent=2))
                responseData={}
                try:
                    if event['RequestType'] == 'Delete':
                        print("Request Type:",event['RequestType'])
                        print("Delete Request - No Physical resources to delete")
                    elif event['RequestType'] == 'Create':
                        print("Request Type:",event['RequestType'])
                        VPCID=event['ResourceProperties']['VPCID']
                        RouteTableID=get_vpc(VPCID)
                        responseData={'RouteTableID':RouteTableID}
                        print("Sending response to custom resource")
                    elif event['RequestType'] == 'Update':
                        print("Request Type:",event['RequestType'])
                        VPCID=event['ResourceProperties']['VPCID']
                        RouteTableID=get_vpc(VPCID)
                        responseData={'RouteTableID':RouteTableID}
                        print("Sending response to custom resource")
                    responseStatus = 'SUCCESS'
                    print("responseStatus: " + responseStatus)
                    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
                except Exception as e:
                    print('Failed to process:', e)
                    responseStatus = 'FAILURE'
                    responseData = {'Failure': 'Something bad happened.'}
                    cfnresponse.send(event, context, cfnresponse.FAILURE, responseData, "CustomResourcePhysicalID")

            def get_vpc(VPCID):
                response = ec2.describe_route_tables (
                  Filters=[
                    {
                      'Name': 'association.main',
                      'Values': [ 'true' ]
                    },
                    {
                      'Name': 'vpc-id',
                      'Values': [ VPCID ]
                    }
                  ]
                )
                print("Printing the VPC Route Table ID ....")
                RouteTableID=response['RouteTables'][0]['RouteTableId']
                print(RouteTableID)
                return RouteTableID

            def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False):
                responseUrl = event['ResponseURL']
                print(responseUrl)
                responseBody = {'Status': responseStatus,
                                'Reason': 'See the details in CloudWatch Log Stream: ' + context.log_stream_name,
                                'PhysicalResourceId': physicalResourceId or context.log_stream_name,
                                'StackId': event['StackId'],
                                'RequestId': event['RequestId'],
                                'LogicalResourceId': event['LogicalResourceId'],
                                'Data': responseData}
                json_responseBody = json.dumps(responseBody)
                print("Response body:\n" + json_responseBody)
                headers = {
                    'content-type' : '',
                    'content-length' : str(len(json_responseBody))
                }
                try:
                    response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody)
                    print("Status code: " + response.reason)
                except Exception as e:
                    print("send(..) failed executing requests.put(..): " + str(e))


  Lambdatrigger:
    Type: 'Custom::RouteTableLambda'
    Properties:
      ServiceToken: !GetAtt LambdaFunction.Arn
      VPCID: !Ref MyVPC
  MyInternetGateway:
    Type: 'AWS::EC2::InternetGateway'
    Properties:
      Tags:
        - Key: Env
          Value: Test
  AttachGateway:
    Type: 'AWS::EC2::VPCGatewayAttachment'
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref MyInternetGateway
  MyRoute:
    Type: 'AWS::EC2::Route'
    Properties:
      RouteTableId: !GetAtt Lambdatrigger.RouteTableID

      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref MyInternetGateway
Outputs:
  RouteTableID:
    Value: !GetAtt Lambdatrigger.RouteTableID

Die benutzerdefinierte Ressource verwendet eine Lambda-Funktion, um die Haupt-Routing-Tabellen-ID abzurufen. Um auf die ID zu verweisen, verwenden Sie die Funktion GetAtt AWS::EC2::Route, um der Haupt-Routing-Tabelle Routen hinzuzufügen. Oder öffnen Sie die CloudFormation-Konsole und wählen Sie dann Output aus. Sie finden die Informationen unter RouteTableID.

Das folgende Beispiel zeigt den SUCCESS-Antworttext, den die benutzerdefinierte Ressource an den CloudFormation-Stack sendet:

{  "Status": "SUCCESS",
  "Reason": "See the details in CloudWatch Log Stream: 2022/08/31/[$LATEST]c48b90efb3944c11ad3fb6e1ce5e1f45",
  "PhysicalResourceId": "CustomResourcePhysicalID",
  "StackId": "arn:aws:cloudformation:us-west-1:abcd:stack/VPC-RT/06c957b0-297e-11ed-afb5-02ca6fd67f8d",
  "RequestId": "55c0f2b8-3044-47f7-aba4-84502b4ef632",
  "LogicalResourceId": "Lambdatrigger",
  "NoEcho": false,
  "Data": {
    "RouteTableID": "rtb-0fba8d15701234567a"
  }
}
AWS OFFICIAL
AWS OFFICIALAktualisiert vor 7 Monaten