Apache APISIX aws-lambda 插件实战指南:将 AWS Lambda 与 API Gateway 接入为动态上游
【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix
aws-lambda是 Apache APISIX 中用于将 AWS Lambda 函数与 Amazon API Gateway 作为动态上游接入网关的核心插件:它拦截访问指定 URI 的请求,代表客户端向 AWS 发起携带授权信息的代理请求,并将响应原样返回。本文基于仓库中 aws-lambda 官方文档 展开,结合 插件源码、通用无服务器上游框架 与 测试用例,系统讲解插件属性、两种授权方案(API Key 与 IAM SigV4 签名)、HTTP/2 调用、路径转发与删除插件的完整实战流程。
插件概述与工作原理
根据 docs/zh/latest/plugins/aws-lambda.md 的定义,aws-lambda插件将 AWS Lambda 与 Amazon API Gateway 作为动态上游集成至 APISIX,用于把访问指定 URI 的请求代理到 AWS 云。
其工作流程可以概括为三步:
- 终止原始请求:当请求命中配置了该插件的路由时,插件终止对已配置 URI 的请求处理。
- 代表客户端发起新请求:插件基于配置中的
function_uri,向 AWS Lambda Gateway URI 发起一个新的 HTTP 请求。该新请求携带配置好的授权信息(API Key 或 IAM 签名)、请求头、请求体与参数,其中请求头、请求体和参数均从原始请求透传。 - 回传响应:插件将 AWS 返回的响应头、状态码和响应体返回给最初通过 APISIX 发起请求的客户端。
在实现层面,aws-lambda插件并非独立实现全部逻辑,而是复用了一个通用的"无服务器动态上游"框架。插件源码 apisix/plugins/aws-lambda.lua 的末尾直接调用了该框架的工厂函数:
local serverless_obj = require("apisix.plugins.serverless.generic-upstream") return serverless_obj(plugin_name, plugin_version, priority, request_processor, aws_authz_schema)从该调用可以推断,整个插件由两部分组成:
- 通用框架(apisix/plugins/serverless/generic-upstream.lua):负责声明插件 Schema、读取请求头/请求体/查询参数、拼接目标 URI、发起
resty.http请求、处理 HTTP/2 响应头兼容并回写响应; - 专属处理器(
request_processor):负责 AWS 特有的授权逻辑,包括注入x-api-key头以及实现 AWS Signature Version 4 请求签名。
插件的元信息同样定义在 apisix/plugins/aws-lambda.lua:插件名为aws-lambda,版本号0.1,执行优先级-1899(在 access 阶段中属于较后执行、靠近上游调用的插件)。
属性详解
下表完整列出了插件支持的配置属性(对应 官方文档 中的"属性"一节,并与 generic-upstream.lua 中的 Schema 相互印证):
| 名称 | 类型 | 必选项 | 默认值 | 有效值 | 描述 |
|---|---|---|---|---|---|
| function_uri | string | 是 | 触发 lambda serverless 函数的 AWS API Gateway 端点。 | ||
| authorization | object | 否 | 访问云函数的授权凭证。 | ||
| authorization.apikey | string | 否 | 生成的 API 密钥,用于授权对 AWS Gateway 端点的请求。 | ||
| authorization.iam | object | 否 | 用于通过 AWS v4 请求签名执行的基于 AWS IAM 角色的授权,详见下文"IAM 授权方案"小节。 | ||
| authorization.iam.accesskey | string | 是 | 从 AWS IAM 控制台生成的访问密钥 ID。 | ||
| authorization.iam.secretkey | string | 是 | 从 AWS IAM 控制台生成的访问密钥。 | ||
| authorization.iam.aws_region | string | 否 | "us-east-1" | 发出请求的 AWS 区域(如us-east-1、ap-southeast-1)。 | |
| authorization.iam.service | string | 否 | "execute-api" | 接收该请求的服务。使用 Amazon API Gateway 时设置为execute-api;直接调用 Lambda 函数时设置为lambda。 | |
| timeout | integer | 否 | 3000 | [100,...] | 代理请求超时(毫秒)。 |
| ssl_verify | boolean | 否 | true | true/false | 为true时执行 SSL 验证。 |
| keepalive | boolean | 否 | true | true/false | 为true时保持连接活动以便复用。 |
| keepalive_pool | integer | 否 | 5 | [1,...] | 关闭连接前,该连接上最多可发送的请求数。 |
| keepalive_timeout | integer | 否 | 60000 | [1000,...] | 连接空闲时保持活动状态的时间(毫秒)。 |
几点需要注意的细节:
function_uri是唯一必填项,且必须为完整的 AWS API Gateway 端点 URL;authorization整体为可选,但一旦配置了iam子对象,则accesskey与secretkey均为必填。这一约束在源码中体现为 aws_authz_schema 中的required = {"accesskey", "secretkey"},并有测试用例专门验证缺失字段时报错。timeout、keepalive_pool、keepalive_timeout的最小值约束(分别为 100ms、1、1000ms)同样来自 generic-upstream.lua 的 Schema,配置低于下限会被 Schema 校验直接拒绝。- 通过 conf/config.yaml.example 可以确认 APISIX 默认 HTTP 监听端口为
9080,Admin API 默认端口为9180(见 config.yaml.example 中 9180 端口配置)。
启用插件:API Key 授权方式
启用插件需要调用 Admin API 修改路由配置。在发起请求前,可以先从 conf/config.yaml 中取出admin_key并存入环境变量:
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')说明:Admin API 的密钥在 conf/config.yaml 的
deployment.admin.admin_key字段下配置,默认角色为admin。生产环境请务必替换为自定义密钥。
以下命令在路由/aws上启用aws-lambda插件,使用 AWS 控制台生成的 API Key 进行授权:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "aws-lambda": { "function_uri": "https://x9w6z07gb9.execute-api.us-east-1.amazonaws.com/default/test-apisix", "authorization": { "apikey": "<Generated API Key from aws console>" }, "ssl_verify":false } }, "uri": "/aws" }'配置完成后,任何对/awsURI 的请求(无论是HTTP/1.1、HTTPS还是HTTP/2)都会调用配置的 AWS 函数 URI,并将响应返回给客户端。假设 AWS Lambda 函数从查询参数中获取name并返回"Hello $name"消息,可以这样验证:
curl -i -XGET localhost:9080/aws\?name=APISIX正常返回结果:
HTTP/1.1 200 OK Content-Type: application/json ... "Hello, APISIX!"从源码看,API Key 授权的实现非常直接:在 request_processor 中,若客户端请求头中尚未携带x-api-key,插件会将其设置为配置中的apikey值;反之若客户端已显式设置x-api-key,插件遵循"不覆盖授权键"的原则,保留客户端传入的值。
通过 HTTP/2 与 APISIX 通信
客户端同样可以通过 HTTP/2 协议与 APISIX 通信并调用 AWS Lambda。由于 HTTP/2 默认处于禁用状态,需要先在 conf/config.yaml(或 conf/config.yaml.example 中取消对应注释)的apisix.node_listen下新增一个启用 HTTP/2 的监听端口,例如:
apisix: node_listen: # 支持监听多个端口 - 9080 - port: 9081 enable_http2: true # 该字段如果不设置,默认值为 `false`配置后使用curl的 HTTP/2 模式测试:
curl -i -XGET --http2 --http2-prior-knowledge localhost:9081/aws\?name=APISIX正常返回结果:
HTTP/2 200 content-type: application/json ... "Hello, APISIX!"值得说明的是,HTTP/2 场景并非只是协议层面的简单切换。在 generic-upstream.lua 的 access 阶段 中,插件在转发 AWS 响应时会检查ngx.var.http2,若为 HTTP/2 请求,则根据 RFC 7540 第 8.1.2.2 节的要求,移除Connection、Keep-Alive、Proxy-Connection、Upgrade、Transfer-Encoding等连接专用响应头,从而保证 HTTP/2 响应的协议合规性。
IAM 授权方案(AWS Signature Version 4 签名)
除了 API Key,插件还支持通过 AWS IAM 凭证进行授权,此时会在 HTTP 调用中自动完成AWS Signature Version 4(SigV4)请求签名。以下示例展示了通过 IAM 访问密钥配置授权:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "aws-lambda": { "function_uri": "https://ajycz5e0v9.execute-api.us-east-1.amazonaws.com/default/test-apisix", "authorization": { "iam": { "accesskey": "<access key>", "secretkey": "<access key secret>" } }, "ssl_verify": false } }, "uri": "/aws" }'注意:使用该方式前,需要确保你已拥有一个启用了程序化访问的 IAM 用户,并具备访问端点的必要权限(例如
AmazonAPIGatewayInvokeFullAccess)。aws_region与service均为可选参数,默认分别为"us-east-1"与"execute-api";若直接调用 Lambda 函数,应将service显式设置为"lambda"。
签名过程的源码级拆解
从 aws-lambda.lua 的 request_processor 后半段 可以完整还原 SigV4 签名的实现步骤,这有助于理解插件行为与排障:
- 生成时间戳:通过
ngx.time()与os.date生成X-Amz-Date请求头(格式%Y%m%dT%H%M%SZ)以及用于凭证范围的日期戳(%Y%m%d)。 - 构造 Canonical URI:对转发路径做规范化(
pl.path.normpath),统一处理首尾/。 - 构造 Canonical Query String:遍历查询参数,先
unescape再拼接为k=v,并按字典序排序(对应 aws-lambda.lua#L124-L132)。 - 构造 Canonical Headers 与 SignedHeaders:所有请求头小写化、剔除
connection头、去除首尾与多余空格、排序后拼装,并生成分号分隔的SignedHeaders列表(对应 aws-lambda.lua#L136-L154)。 - 构造 Canonical Request 与 StringToSign:按
AWS4-HMAC-SHA256算法组织签名串(对应 aws-lambda.lua#L157-L171)。 - 派生签名密钥并计算签名:
get_signature_key依次对AWS4+secretkey、日期戳、区域、服务名做 HMAC-SHA256 派生,最终生成authorization请求头,形如AWS4-HMAC-SHA256 Credential=..., SignedHeaders=..., Signature=...(对应 aws-lambda.lua#L46-L52 与 L174-L181)。
上述行为在测试 t/plugin/aws-lambda.t 的 TEST 6 中得到了验证:测试断言上游收到的Authorization头以AWS4-HMAC-SHA256开头、X-Amz-Date头符合数字T数字Z的时间格式。
配置路径转发
aws-lambda插件在代理请求到 AWS 上游时还支持URL 路径转发:基本请求路径的扩展部分会被追加到插件配置的function_uri上。
重要:由于 APISIX 路由是严格匹配的,要使路径转发正常工作,路由上配置的
uri字段必须以*结尾。*表示该 URI 的任何子路径都会匹配到同一条路由。
以下示例展示了路径转发的配置方式,function_uri只填写 API Gateway 的基础域名,具体路径由请求动态拼接:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "plugins": { "aws-lambda": { "function_uri": "https://x9w6z07gb9.execute-api.us-east-1.amazonaws.com", "authorization": { "apikey": "<Generate API key>" }, "ssl_verify":false } }, "uri": "/aws/*" }'配置完成后,任何访问aws/default/test-apisix的请求都会调用 AWS Lambda 函数,并转发附加的路径与参数:
curl -i -XGET http://127.0.0.1:9080/aws/default/test-apisix\?name\=APISIX正常返回结果:
HTTP/1.1 200 OK Content-Type: application/json ... "Hello, APISIX!"路径拼接的底层实现位于 generic-upstream.lua 的 access 阶段:插件解析function_uri得到基础路径,再通过ctx.curr_req_matched[":ext"]取出路由通配符*匹配到的扩展路径,拼接到基础路径之后(必要时自动补充/分隔符),从而实现"路由子路径即 AWS 函数路径"的动态转发。
删除插件
当需要删除该插件时,只需将路由中的插件配置置空即可,APISIX 会自动重新加载相关配置,无需重启服务:
curl http://127.0.0.1:9180/apisix/admin/routes/1 \ -H "X-API-KEY: $admin_key" -X PUT -d ' { "uri": "/aws", "plugins": {}, "upstream": { "type": "roundrobin", "nodes": { "127.0.0.1:1980": 1 } } }'执行后,路由/aws不再经过 AWS 代理,而是按新配置的upstream转发到本地127.0.0.1:1980。
测试用例对插件行为的验证
仓库中的 t/plugin/aws-lambda.t 为插件提供了完整的 Test::Nginx 测试套件,可用于理解插件各行为的预期结果:
| 测试 | 验证点 |
|---|---|
| TEST 1 | 合法 IAM 配置(accesskey+secretkey)通过 Schema 校验 |
| TEST 2 | IAM 配置缺失accesskey时返回明确的校验错误 |
| TEST 3 | 通过 Admin API 创建启用aws-lambda的路由 |
| TEST 4 | 请求/aws后成功代理到模拟上游并返回 "aws lambda invoked" |
| TEST 5 | 配置apikey后,上游收到的请求头包含x-api-key: test_key |
| TEST 6 | 配置 IAM 后,上游收到AWS4-HMAC-SHA256签名的Authorization头与格式正确的X-Amz-Date头 |
这些用例与本文介绍的两种授权方式一一对应,是排查授权类问题(如签名不匹配、缺少凭证)时的直接参考。
总结
aws-lambda插件以"通用无服务器上游框架 + AWS 专属授权处理器"的组合方式,为 APISIX 提供了将 AWS Lambda / API Gateway 作为动态上游的完整能力。本文覆盖了它的全部配置属性、API Key 与 IAM SigV4 两种授权方式、HTTP/2 通信、路径转发和插件下线流程。若需进一步深入,可查阅:英文版插件文档、插件源码、通用上游框架 与 插件测试,并结合 conf/config.yaml.example 核对监听端口与 HTTP/2 的默认配置。
【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考