CloudFormation中如何获取子网关联的路由表ID?

0

【以下的问题经过翻译处理】 我的 CloudFormation 模板包括创建一个 S3 AWS::EC2::VPCEndpoint。在参数中,用户选择一个已创建的 VPC、子网和可用区。S3 endpoint的一个必需参数是路由表ID。目前,我将其设置为请求一个路由表 ID("rtb-xxxxxx")的字符串,但希望通过编程方式使其对用户更简化。

问题是,我如何根据选择的子网ID获取路由表ID?AWS::EC2::Subnet不支持返回与其关联的路由表ID。我知道我也可以通过调用Lambda来实现,但我希望找到一个更道地的解决方案。

我要查找的路由表ID不是VPC的主路由表。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html

profile picture
专家
已提问 7 个月前8 查看次数
1 回答
0

【以下的回答经过翻译处理】 自定义资源(或Macro宏)是唯一的解决方法。正如你所提到的,AWS::EC2::Subnet并不支持将其作为返回值,而且你还在尝试引用一个CloudFormation模板未创建的现有资源。

以下是一个快速示例,但请注意 - DescribeRouteTables只在子网已明确关联时才能工作,而对于默认路由表则不行。这将需要额外的编码/逻辑。

AWSTemplateFormatVersion: "2010-09-09" Description: Subnet Custom Resource Parameters: TheSubnet: Description: Subnet ID Type: AWS::EC2::Subnet::Id Default: subnet-32432943294

Resources: CustomFunction: Type: AWS::Lambda::Function Properties: Handler: index.lambda_handler Timeout: 30 Role: !GetAtt 'CustomResourceRole.Arn' Runtime: python3.7 Code: ZipFile: | import boto3 import json import urllib

      def sendResponse(event, context, responseData, responseStatus="FAILED"):
        response_body = json.dumps({
          "Status": responseStatus,
          "Reason": "See the details in CloudWatch Log Stream: " + context.log_stream_name,
          "PhysicalResourceId": context.log_stream_name,
          "StackId": event["StackId"],
          "RequestId": event["RequestId"],
          "LogicalResourceId": event["LogicalResourceId"],
          "Data":responseData
        })

        # Not using the old .put (deprecated)
        enc_body = response_body.encode('utf-8')
        opener = urllib.request.build_opener(urllib.request.HTTPHandler)
        request = urllib.request.Request(event['ResponseURL'], data=enc_body)
        request.add_header('Content-Type', '')
        request.add_header('Content-Length', len(response_body))
        request.get_method = lambda: 'PUT'
        response = opener.open(request)
        print("RESPONSE {}: {}".format(response.getcode(), response.msg))


      def lambda_handler(event, context):
        # Delete...
        if event['RequestType'] == 'Delete':
          sendResponse(event, context, {"Message": "DELETE"}, "SUCCESS")
          return '{}'
        
        try:
          ec2 = boto3.client('ec2')
          subnet = event["ResourceProperties"].get("SubnetId")
          resp = ec2.describe_route_tables(
            Filters=
              [
                {
                  'Name': 'association.subnet-id',
                  'Values': [subnet]
                }
              ]
          )
          print(resp['RouteTables'][0])
          sendResponse(event, context, resp['RouteTables'][0], "SUCCESS")
        except:
          print("ERROR")
          sendResponse(event, context, {"Value": "ERROR"})

CustomResourceRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole Condition: {} Path: / Policies: - PolicyName: QuerySubnet PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Resource: arn:aws:logs:::* - Effect: Allow Action: - ec2:DescribeSubnets - ec2:DescribeRouteTables Resource: '*'

SubnetQuery: Type: Custom::CustomResource Properties: ServiceToken: !GetAtt CustomFunction.Arn SubnetId: !Ref TheSubnet

Outputs: RouteTableId: Description: Discovered Route Table ID Value: !GetAtt SubnetQuery.RouteTableId

profile picture
专家
已回答 7 个月前

您未登录。 登录 发布回答。

一个好的回答可以清楚地解答问题和提供建设性反馈,并能促进提问者的职业发展。

回答问题的准则