Come faccio ad aggiungere percorsi alla tabella di routing principale del mio Amazon VPC con CloudFormation?

3 minuti di lettura
0

Desidero aggiungere percorsi alla tabella di routing principale quando creo il mio Amazon Virtual Private Cloud (Amazon VPC) in AWS CloudFormation.

Risoluzione

Quando usi CloudFormation per creare un Amazon VPC, CloudFormation non riconosce la tabella di routing principale creata per impostazione predefinita. Non puoi aggiungere né rimuovere percorsi dalla tabella di routing principale perché non puoi fare riferimento alla tabella di routing dal tuo modello di CloudFormation.

Per risolvere questo problema, usa una risorsa personalizzata supportata da AWS Lambda nel modello di CloudFormation.

Per creare uno stack CloudFormation con una risorsa personalizzata, usa il seguente modello RouteTable-Template.yml:

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

La risorsa personalizzata utilizza una funzione Lambda per recuperare l'ID della tabella di routing principale. Per fare riferimento all'ID, usa la funzione GetAtt in AWS::EC2::Route per aggiungere percorsi alla tabella di routing principale. In alternativa, apri la console CloudFormation e scegli Output. Puoi trovare le informazioni in RouteTableID.

Di seguito è riportato un esempio del corpo di risposta SUCCESS che la risorsa personalizzata invia allo stack CloudFormation:

{  "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 UFFICIALE
AWS UFFICIALEAggiornata 7 mesi fa