-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(plugins): aws lambda serverless #5594
feat(plugins): aws lambda serverless #5594
Conversation
5331ab3
to
a8e6fd8
Compare
depends on: #5616 |
apisix/plugins/azure-functions.lua
Outdated
|
||
local schema = { | ||
local azure_authz_schema = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are developing a new feature "aws lambda serverless", so we should not update azure-functions.lua
, it is a different thing.
one for one thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
apisix/plugins/aws-lambda.lua
Outdated
local resty_sha256 = require("resty.sha256") | ||
|
||
|
||
local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bad style
good style:
local plugin_name = "aws-lambda"
local plugin_version = 0.1
local priority = -1899
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, updated
return kSigning | ||
end | ||
|
||
local aws_authz_schema = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we use schema
is fine, the file name is aws-lamda
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not the complete schema, rather it's the part of the schema (handling the plugin specific authorization details).
see:
authorization = authz_schema, |
apisix/plugins/aws-lambda.lua
Outdated
service = { | ||
type = "string", | ||
default = "execute-api", | ||
description = "The service that is receiving the request" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The service
or the service
?
we should use the same style with others.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
apisix/plugins/aws-lambda.lua
Outdated
|
||
local ngx = ngx | ||
local pairs = pairs | ||
local concat = table.concat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bad name, I think we should add a prefix tab_
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack
apisix/plugins/aws-lambda.lua
Outdated
local ngx = ngx | ||
local pairs = pairs | ||
local concat = table.concat | ||
local sort = table.sort |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
apisix/plugins/aws-lambda.lua
Outdated
end | ||
|
||
|
||
return require("apisix.plugins.serverless.generic-upstream")(plugin_name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is not easy to read.
another style:
local serverless_obj = require("apisix.plugins.serverless.generic-upstream")
local aws_obj = serverless_obj.new({
name = plugin_name,
version = plugin_version,
priority = priority,
... ...
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Updated accordingly
t/admin/plugins.t
Outdated
@@ -40,7 +40,7 @@ __DATA__ | |||
--- request | |||
GET /apisix/admin/plugins/list | |||
--- response_body_like eval | |||
qr/\["real-ip","client-control","ext-plugin-pre-req","zipkin","request-id","fault-injection","serverless-pre-function","batch-requests","cors","ip-restriction","ua-restriction","referer-restriction","uri-blocker","request-validation","openid-connect","authz-casbin","wolf-rbac","ldap-auth","hmac-auth","basic-auth","jwt-auth","key-auth","consumer-restriction","authz-keycloak","proxy-mirror","proxy-cache","proxy-rewrite","api-breaker","limit-conn","limit-count","limit-req","gzip","server-info","traffic-split","redirect","response-rewrite","grpc-transcode","prometheus","datadog","echo","http-logger","skywalking-logger","google-cloud-logging","sls-logger","tcp-logger","kafka-logger","syslog","udp-logger","example-plugin","azure-functions","openwhisk","serverless-post-function","ext-plugin-post-req"\]/ | |||
qr/\["real-ip","client-control","ext-plugin-pre-req","zipkin","request-id","fault-injection","serverless-pre-function","batch-requests","cors","ip-restriction","ua-restriction","referer-restriction","uri-blocker","request-validation","openid-connect","authz-casbin","wolf-rbac","ldap-auth","hmac-auth","basic-auth","jwt-auth","key-auth","consumer-restriction","authz-keycloak","proxy-mirror","proxy-cache","proxy-rewrite","api-breaker","limit-conn","limit-count","limit-req","gzip","server-info","traffic-split","redirect","response-rewrite","grpc-transcode","prometheus","datadog","echo","http-logger","skywalking-logger","google-cloud-logging","sls-logger","tcp-logger","kafka-logger","syslog","udp-logger","example-plugin","aws-lambda","azure-functions","openwhisk","serverless-post-function","ext-plugin-post-req"\]/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we split this into multiple lines? We can do it in the next PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, It's time to modify this to another easy-to-read format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guys, here it is: #5642
apisix/plugins/aws-lambda.lua
Outdated
if k ~= "connection" then | ||
signed_headers[#signed_headers+1] = k | ||
-- strip starting and trailing spaces including strip multiple spaces into single space | ||
canonical_headers[k] = v:gsub("^%s+", ""):gsub("%s+$", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
apisix/plugins/aws-lambda.lua
Outdated
headers["X-Amz-Date"] = amzdate | ||
|
||
-- computing canonical uri | ||
local canonical_uri = params.path:gsub("//", "/") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use pl.path
to do part of the normalized work?
https://refined-github-html-preview.kidonng.workers.dev/lunarmodules/Penlight/raw/master/docs/libraries/pl.path.html#normpath
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
apisix/plugins/aws-lambda.lua
Outdated
local serverless_obj = require("apisix.plugins.serverless.generic-upstream") | ||
|
||
return serverless_obj(plugin_name, | ||
plugin_version, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad indent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
apisix/plugins/aws-lambda.lua
Outdated
local tab_sort = table.sort | ||
local os = os | ||
local hmac = require("resty.hmac") | ||
local hexencode = require("resty.string").to_hex |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use underscore style for function name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack
apisix/plugins/aws-lambda.lua
Outdated
return hexencode(digest) | ||
end | ||
|
||
local function getSignatureKey(key, datestamp, region, service) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
docs/en/latest/plugins/aws-lambda.md
Outdated
"Hello, apisix!" | ||
``` | ||
|
||
For requests where the mode of communication between the client and the Apache APISIX gateway is HTTP/2, the example looks like ( make sure you are running APISIX agent with `enable_http2: true` for a port in conf.yaml or uncomment port 9081 of `node_listen` field inside [config-default.yaml](../../../../conf/config-default.yaml) ) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use config-default.yaml
directly, since people may read the doc on the doc's website. Please fix the azure-functions' doc too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
docs/en/latest/plugins/aws-lambda.md
Outdated
|
||
## How To Enable | ||
|
||
The following is an example of how to enable the aws-lambda faas plugin for a specific route URI. Calling the apisix route uri will make an invocation to the lambda function uri (the new upstream). We are assuming your cloud function is already up and running. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use APISIX route instead of apisix route
. Need to fix other similar places.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use APISIX
always
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. Got it. Thanks for letting me know : )
@shuaijinchao @tzssangglass pls review when you have time |
docs/en/latest/plugins/aws-lambda.md
Outdated
|
||
## How To Enable | ||
|
||
The following is an example of how to enable the aws-lambda faas plugin for a specific route URI. Calling the apisix route uri will make an invocation to the lambda function uri (the new upstream). We are assuming your cloud function is already up and running. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should use APISIX
always
t/admin/plugins.t
Outdated
@@ -40,7 +40,7 @@ __DATA__ | |||
--- request | |||
GET /apisix/admin/plugins/list | |||
--- response_body_like eval | |||
qr/\["real-ip","client-control","ext-plugin-pre-req","zipkin","request-id","fault-injection","serverless-pre-function","batch-requests","cors","ip-restriction","ua-restriction","referer-restriction","uri-blocker","request-validation","openid-connect","authz-casbin","wolf-rbac","ldap-auth","hmac-auth","basic-auth","jwt-auth","key-auth","consumer-restriction","authz-keycloak","proxy-mirror","proxy-cache","proxy-rewrite","api-breaker","limit-conn","limit-count","limit-req","gzip","server-info","traffic-split","redirect","response-rewrite","grpc-transcode","prometheus","datadog","echo","http-logger","skywalking-logger","google-cloud-logging","sls-logger","tcp-logger","kafka-logger","syslog","udp-logger","example-plugin","azure-functions","openwhisk","serverless-post-function","ext-plugin-post-req"\]/ | |||
qr/\["real-ip","client-control","ext-plugin-pre-req","zipkin","request-id","fault-injection","serverless-pre-function","batch-requests","cors","ip-restriction","ua-restriction","referer-restriction","uri-blocker","request-validation","openid-connect","authz-casbin","wolf-rbac","ldap-auth","hmac-auth","basic-auth","jwt-auth","key-auth","consumer-restriction","authz-keycloak","proxy-mirror","proxy-cache","proxy-rewrite","api-breaker","limit-conn","limit-count","limit-req","gzip","server-info","traffic-split","redirect","response-rewrite","grpc-transcode","prometheus","datadog","echo","http-logger","skywalking-logger","google-cloud-logging","sls-logger","tcp-logger","kafka-logger","syslog","udp-logger","example-plugin","aws-lambda","azure-functions","openwhisk","serverless-post-function","ext-plugin-post-req"\]/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, It's time to modify this to another easy-to-read format.
| authorization.apikey | string | optional | | | Field inside _authorization_. The generate API Key to authorize requests to that endpoint of the aws gateway. | | | ||
| authorization.iam | object | optional | | | Field inside _authorization_. AWS IAM role based authorization, performed via aws v4 request signing. See schema details below ([here](#iam-authorization-schema)). | | | ||
| timeout | integer | optional | 3000 | [100,...] | Proxy request timeout in milliseconds. | | ||
| ssl_verify | boolean | optional | true | true/false | If enabled performs SSL verification of the server. | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the ssl_verify
is true, do we need to specify a certificate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is generated from any trusted public CA, we don't have to specify the certificate of the CA as along the hierarchy chain eventually it will point to the root CA. But that's not the case with self signed certs. In that case, simply ssl_verify:false
will do or there is an option to specify the CA certificate file. see ref below
The optional ssl_verify argument takes a Lua boolean value to control whether to perform SSL verification. When set to true, the server certificate will be verified according to the CA certificates specified by the lua_ssl_trusted_certificate directive. You may also need to adjust the lua_ssl_verify_depth directive to control how deep we should follow along the certificate chain. Also, when the ssl_verify argument is true and the server_name argument is also specified, the latter will be used to validate the server name in the server certificate.
ref2: https://github.com/openresty/lua-nginx-module#lua_ssl_trusted_certificate
--- response_headers | ||
Content-Length: 19 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why check the Content-Length
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, thanks for the review.
It just checks if the headers that are being received from upstream lambda are being forwarded by the plugin. Not just Content-Length
specifically but all headers from the mock HTTP endpoint
if k ~= "connection" then | ||
signed_headers[#signed_headers+1] = k |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand here, do we just need to skip connection
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, I would like to specify, we are not tampering connection header for the request that is being sent to the lambda.
This section performs aws v4 request signing with aws iam secret key. As per the aws docs, to have the authenticity of the request (and to validate that the request has not been modified by any third party over the wire) it suggests generating hash digest from as many headers as we can (however host
and x-amz-date
is mandatory). In real-world testing what i have found that aws gateway doesn't include the connection
header value (keep-alive
, close
) for hash calculation. That's why I simply omitted it as it never was any hard requirement.
What this PR does / why we need it:
create a route
With API key-based authorization
With IAM v4 request signing
Pre-submission checklist: