You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS CDK中通过标签名查找NAT网关并获取其公网IP

获取VPC关联NAT网关公网IP并添加到API Gateway白名单

核心思路

由于CDK的Vpc.fromLookup()不会自动返回关联的NAT网关信息,且NAT Gateway构造没有fromLookup()方法,我们需要通过自定义资源(CustomResource)结合EC2 API来查询指定VPC下的NAT网关公网IP,再将其集成到API Gateway的资源策略中。

实现步骤(TypeScript示例)

  1. 导入目标VPC
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as iam from 'aws-cdk-lib/aws-iam';
import { CustomResource, Provider } from 'aws-cdk-lib/custom-resources';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'NatIpToApiGatewayStack');

// 导入已存在的VPC(可通过VPC ID或标签匹配)
const vpc = ec2.Vpc.fromLookup(stack, 'ExistingVpc', {
  vpcId: 'vpc-xxxxxx', // 替换为你的VPC ID
});
  1. 创建Lambda函数查询NAT网关IP
    编写一个Lambda函数,调用EC2的describeNatGateways接口过滤指定VPC下的NAT网关,提取公网IP:
const getNatIpLambda = new lambda.Function(stack, 'GetNatIpLambda', {
  runtime: lambda.Runtime.NODEJS_18_X,
  handler: 'index.handler',
  code: lambda.Code.fromInline(`
    const AWS = require('aws-sdk');
    const ec2 = new AWS.EC2();

    exports.handler = async (event) => {
      if (event.RequestType === 'Create' || event.RequestType === 'Update') {
        try {
          const result = await ec2.describeNatGateways({
            Filters: [{ Name: 'vpc-id', Values: [event.ResourceProperties.VpcId] }]
          }).promise();
          
          // 提取所有NAT网关的公网IP
          const natIps = result.NatGateways.flatMap(nat => 
            nat.NatGatewayAddresses.map(addr => addr.PublicIp)
          );

          return {
            PhysicalResourceId: Date.now().toString(),
            Data: { NatPublicIps: natIps.join(',') }
          };
        } catch (err) {
          throw new Error(\`获取NAT网关IP失败: \${err.message}\`);
        }
      }
      return { PhysicalResourceId: event.PhysicalResourceId };
    };
  `),
});

// 赋予Lambda查询NAT网关的权限
getNatIpLambda.addToRolePolicy(new iam.PolicyStatement({
  actions: ['ec2:DescribeNatGateways'],
  resources: ['*'],
}));
  1. 通过自定义资源获取IP列表
    用Provider封装Lambda,再创建CustomResource来触发IP查询:
const natIpProvider = new Provider(stack, 'NatIpProvider', {
  onEventHandler: getNatIpLambda,
});

const natIpResource = new CustomResource(stack, 'NatIpResource', {
  serviceToken: natIpProvider.serviceToken,
  properties: { VpcId: vpc.vpcId },
});

// 解析出NAT网关公网IP数组
const natPublicIps = natIpResource.getAtt('NatPublicIps').toString().split(',');
  1. 将IP添加到API Gateway资源策略
    创建或更新API Gateway的资源策略,限制仅允许这些NAT网关IP访问:
// 创建或导入你的API Gateway
const api = new apigateway.RestApi(stack, 'MyProtectedApi', {
  description: '仅允许指定NAT网关IP访问的API',
});

// 构建资源策略
const apiPolicy = new iam.PolicyDocument({
  statements: [
    new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      principals: [new iam.AnyPrincipal()],
      actions: ['execute-api:Invoke'],
      resources: [api.arnForExecuteApi('*')],
      conditions: {
        IpAddress: { 'aws:SourceIp': natPublicIps },
      },
    }),
  ],
});

// 为API Gateway附加策略
api.addToResourcePolicy(apiPolicy);

注意事项

  • 如果VPC下有多个NAT网关,上述代码会自动收集所有公网IP并加入白名单;
  • 若NAT网关发生变更(如新增/替换),需触发CDK部署更新CustomResource,以刷新IP列表;
  • 确保Lambda角色拥有ec2:DescribeNatGateways权限,否则无法查询NAT网关信息。

内容的提问来源于stack exchange,提问作者Nikita Voronin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:24:58