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

如何替换CfnInclude导入CloudFormation栈中的Lambda授权函数?

问题描述

我通过以下代码将CloudFormation模板导入AWS CDK:

const template = new include.CfnInclude(this, "Include", {
  templateFile: "../cloudformation-template/serverless.template.generated",
  parameters: {}
});

导入的模板包含一个API Gateway REST API资源,该资源引用S3托管的Swagger文件。Swagger中定义了名为MyCustomAuthorizer的自定义授权器,其authorizerUri引用旧Lambda函数MyCustomAuthorizerLambda的ARN:

"securityDefinitions": {
    "MyCustomAuthorizer": {
      "type": "apiKey",
      "name": "Authorization",
      "in": "header",
      "x-amazon-apigateway-authtype": "custom",
      "x-amazon-apigateway-authorizer": {
        "authorizerUri": {
          "Fn::Join": [
            "",
            [
              "arn:aws:apigateway:",
              {
                "Ref": "AWS::Region"
              },
              ":lambda:path/2015-03-31/functions/",
              {
                "Fn::GetAtt": ["MyCustomAuthorizerLambda", "Arn"]
              },
              "/invocations"
            ]
          ]
        },
        "authorizerResultTtlInSeconds": 300,
        "identitySource": "method.request.header.Authorization, context.path, context.httpMethod",
        "type": "request"
      }
    }
  }

Swagger中的API方法均通过security字段引用该授权器:

"/MyGETMethod.json": {
  "get": {
    "security": [{
      "MyCustomAuthorizer": []
    }],
    ....
  }
}

我已通过CDK创建了新的Lambda函数:

var myNewAuthorizerLambda = new lambda.Function(this, 'MyNewAuthorizerLambda', {
  runtime: ...,
  code: lambda.Code.fromAsset(...),
  description: `An API Gateway Authorizer.`,
  handler: ...
});

尝试过replaceDependency方法和遍历节点等方式,但未能将所有API方法的授权器引用从旧Lambda切换到新Lambda,请问该如何操作?此需求是否可行?

解决方案

完全可行,以下是两种可靠的实现方式:

方式一:直接修改导入的RestApi资源的Swagger定义

这种方式直接更新Swagger中的授权器配置,无需重新关联每个API方法:

  1. 获取导入的RestApi资源:
    找到原CloudFormation模板中API Gateway资源的逻辑ID(比如MyRestApi),通过CfnInclude获取该资源:
    import * as apigateway from 'aws-cdk-lib/aws-apigateway';
    
    const restApi = template.getResource("MyRestApi") as apigateway.CfnRestApi;
    
  2. 更新Swagger中的授权器URI:
    • 如果原RestApi的Swagger定义直接写在body字段中:
      // 解析原Swagger JSON
      const swaggerContent = JSON.parse(restApi.body as string);
      // 替换授权器的Lambda ARN为新函数的ARN
      swaggerContent.securityDefinitions.MyCustomAuthorizer["x-amazon-apigateway-authorizer"].authorizerUri = `arn:aws:apigateway:${this.region}:lambda:path/2015-03-31/functions/${myNewAuthorizerLambda.functionArn}/invocations`;
      // 重新设置RestApi的body
      restApi.body = JSON.stringify(swaggerContent);
      
    • 如果原RestApi通过s3Location引用S3托管的Swagger文件:
      先将S3中的Swagger文件下载到本地,修改其中的authorizerUri为新Lambda的ARN,然后在CDK中读取修改后的本地文件并更新RestApi:
      import * as fs from 'fs';
      
      // 读取本地修改后的Swagger文件
      const modifiedSwagger = fs.readFileSync("../path/to/modified-swagger.json", "utf-8");
      // 更新RestApi的body,同时移除S3Location引用
      restApi.body = modifiedSwagger;
      restApi.s3Location = undefined;
      

方式二:删除原授权器,重新创建并关联新授权器

这种方式适合需要完全替换授权器配置的场景:

  1. 移除原授权器的关联:
    遍历栈中所有API方法资源,清除原授权器的引用:
    // 遍历当前栈的所有子节点,找到所有CfnMethod资源
    this.node.children.forEach(child => {
      if (child instanceof apigateway.CfnMethod) {
        child.authorizerId = undefined;
        child.security = undefined;
      }
    });
    
  2. 创建新的自定义授权器:
    使用CDK的L2构造创建符合原配置的新授权器:
    import { Duration } from 'aws-cdk-lib';
    
    const newAuthorizer = new apigateway.RequestAuthorizer(this, "MyNewCustomAuthorizer", {
      handler: myNewAuthorizerLambda,
      identitySources: [
        apigateway.IdentitySource.header("Authorization"),
        apigateway.IdentitySource.context("path"),
        apigateway.IdentitySource.context("httpMethod")
      ],
      resultsCacheTtl: Duration.seconds(300)
    });
    
  3. 关联新授权器到所有API方法:
    找到所有API方法,设置授权类型和新授权器ID:
    // 假设已收集到所有CfnMethod实例(可通过遍历或getResource方法获取)
    const methods = [/* 所有API方法资源实例 */];
    methods.forEach(method => {
      method.authorizationType = "CUSTOM";
      method.authorizerId = newAuthorizer.authorizerId;
    });
    

注意事项

  • 若不再需要旧Lambda函数MyCustomAuthorizerLambda,可通过template.getResource("MyCustomAuthorizerLambda")获取后,调用node.remove()移除该资源,同时清理相关依赖。
  • 操作完成后,使用cdk diff查看变更,确认授权器的URI或关联的Lambda函数已更新为新资源。
  • 确保新Lambda函数具备API Gateway调用它的权限(CDK的RequestAuthorizer会自动创建该权限,手动关联时需额外配置)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:27:19