You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2021/11/23 19:13:37 UTC

[GitHub] [apisix] bisakhmondal opened a new pull request #5594: feat(plugins): aws lambda serverless with generic upstream refactoring

bisakhmondal opened a new pull request #5594:
URL: https://github.com/apache/apisix/pull/5594


   ### What this PR does / why we need it:
   <!--- Why is this change required? What problem does it solve? -->
   <!--- If it fixes an open issue, please link to the issue here. -->
   create a route
   ```json
   {
       "plugins": {
           "aws-lambda": {
               "function_uri": "https://x9w6z07gb9.execute-api.us-east-1.amazonaws.com/default/test-apisix",
               "authorization": {
                   "apikey": "<apikey>"
               },
               "ssl_verify":false
           }
       },
       "uri": "/aws"
   }
   ```
   ```shell
   curl -i -XGET localhost:9080/aws\?name=bisakh
   HTTP/1.1 200 OK
   Content-Type: application/json
   Connection: keep-alive
   X-Amzn-Trace-Id: Root=1-619d3cef-5a2070dc05d8cf4f37eb9877;Sampled=0
   x-amzn-RequestId: d74198ab-1cfd-4eb3-b4e5-a81095ddb6ba
   Date: Tue, 23 Nov 2021 19:11:43 GMT
   Content-Length: 16
   x-amz-apigw-id: JRZ1aHaHoAMFZmw=
   Server: APISIX/2.10.2
   
   "Hello, bisakh!"
   ```
   
   ### TODO: community dev-email, test cases, more authz methods, docs
   ### Pre-submission checklist:
   
   <!--
   Please follow the requirements:
   1. Use Draft if the PR is not ready to be reviewed
   2. Test is required for the feat/fix PR, unless you have a good reason
   3. Doc is required for the feat PR
   4. Use a new commit to resolve review instead of `push -f`
   5. Use "request review" to notify the reviewer once you have resolved the review
   -->
   
   * [x] Did you explain what problem does this PR solve? Or what new features have been added?
   * [ ] Have you added corresponding test cases?
   * [ ] Have you modified the corresponding document?
   * [x] Is this PR backward compatible? **If it is not backward compatible, please discuss on the [mailing list](https://github.com/apache/apisix/tree/master#community) first**
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758428555



##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |

Review comment:
       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




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758908789



##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.
+
+```shell
+# enable aws lambda for a route via api key authorization
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -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"
+}'
+```
+
+Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example ( here aws lambda function just take the `name` query param and returns `Hello $name` ) :

Review comment:
       thanks




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758908633



##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.
+
+```shell
+# enable aws lambda for a route via api key authorization
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -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"
+}'
+```
+
+Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example ( here aws lambda function just take the `name` query param and returns `Hello $name` ) :
+
+```shell
+$ curl -i -XGET localhost:9080/aws\?name=APISIX
+HTTP/1.1 200 OK
+Content-Type: application/json
+Connection: keep-alive
+Date: Sat, 27 Nov 2021 13:08:27 GMT
+x-amz-apigw-id: JdwXuEVxIAMFtKw=
+x-amzn-RequestId: 471289ab-d3b7-4819-9e1a-cb59cac611e0
+Content-Length: 16
+X-Amzn-Trace-Id: Root=1-61a22dca-600c552d1c05fec747fd6db0;Sampled=0
+Server: APISIX/2.10.2
+
+"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 [config-default.yaml](../../../../conf/config-default.yaml). You can do it by uncommenting the port 9081 from `apisix.node_listen` field ) :

Review comment:
       thanks




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758913144



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,183 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local hmac = require("resty.hmac")
+local hex_encode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+local str_strip = require("pl.stringx").strip
+local norm_path = require("pl.path").normpath
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex_encode(digest)
+end
+
+local function get_signature_key(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = norm_path(params.path)
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    tab_sort(canonical_qs)
+    canonical_qs = tab_concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        if k ~= "connection" then
+            signed_headers[#signed_headers+1] = k

Review comment:
       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.
   ![2021-11-30_09-27](https://user-images.githubusercontent.com/41498427/143983320-c20f1ac4-2d27-4e32-81dd-0c39d42e85b9.png)
   
   
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] membphis commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
membphis commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r757827479



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat

Review comment:
       bad name, I think we should add a prefix `tab_`

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899

Review comment:
       bad style
   
   good style:
   ```
   local plugin_name = "aws-lambda"
   local plugin_version = 0.1
   local priority = -1899
   ```

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex.to_hex(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "The service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    sort(canonical_qs)
+    canonical_qs = concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+    local url_decoded = url.parse(conf.function_uri)
+    headers["host"] = url_decoded.host
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        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+$", "")
+        end
+    end
+    sort(signed_headers)
+
+    for i = 1, #signed_headers do
+        local k = signed_headers[i]
+        canonical_headers[i] = k .. ":" .. canonical_headers[k] .. "\n"
+    end
+    canonical_headers = concat(canonical_headers, nil, 1, #signed_headers)
+    signed_headers = concat(signed_headers, ";")
+
+    -- combining elements to form the canonical request (step-1)
+    local canonical_request = params.method:upper() .. "\n"
+                        .. canonical_uri .. "\n"
+                        .. (canonical_qs or "") .. "\n"
+                        .. canonical_headers .. "\n"
+                        .. signed_headers .. "\n"
+                        .. sha256(params.body or "")
+
+    -- creating the string to sign for aws signature v4 (step-2)
+    local iam = conf.authorization.iam
+    local credential_scope = datestamp .. "/" .. iam.aws_region .. "/"
+                            .. iam.service .. "/aws4_request"
+    local string_to_sign = ALGO .. "\n"
+                        .. amzdate .. "\n"
+                        .. credential_scope .. "\n"
+                        .. sha256(canonical_request)
+
+    -- calculate the signature (step-3)
+    local signature_key = getSignatureKey(iam.secretkey, datestamp, iam.aws_region, iam.service)
+    local signature = hex.to_hex(hmac256(signature_key, string_to_sign))
+
+    -- add info to the headers (step-4)
+    headers["authorization"] = ALGO .. " Credential=" .. iam.accesskey
+                            .. "/" .. credential_scope
+                            .. ", SignedHeaders=" .. signed_headers
+                            .. ", Signature=" .. signature
+end
+
+
+return require("apisix.plugins.serverless.generic-upstream")(plugin_name,

Review comment:
       it is not easy to read.
   
   another style:
   
   ```lua
   local serverless_obj = require("apisix.plugins.serverless.generic-upstream")
   local aws_obj = serverless_obj.new({
       name = plugin_name,
       version = plugin_version,
       priority = priority,
       ... ...
   })
   ```

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex.to_hex(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {

Review comment:
       I think we use `schema` is fine, the file name is `aws-lamda`

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex.to_hex(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "The service that is receiving the request"

Review comment:
       `The service` or `the service`?
   
   we should use the same style with others.

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort

Review comment:
       ditto

##########
File path: apisix/plugins/azure-functions.lua
##########
@@ -14,30 +14,15 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-local core = require("apisix.core")
-local http = require("resty.http")
 local plugin = require("apisix.plugin")
-local ngx  = ngx
-local plugin_name = "azure-functions"
+local plugin_name, plugin_version, priority = "azure-functions", 0.1, -1900
 
-local schema = {
+local azure_authz_schema = {

Review comment:
       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. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758502099



##########
File path: t/admin/plugins.t
##########
@@ -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"\]/

Review comment:
       Guys, here it is: https://github.com/apache/apisix/pull/5642




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#issuecomment-979496919


   depends on: #5616 
   Need to be rebased once #5616 merges into master
   cc @spacewander for review


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758502099



##########
File path: t/admin/plugins.t
##########
@@ -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"\]/

Review comment:
       Guys, here's it: https://github.com/apache/apisix/pull/5642




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] spacewander commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
spacewander commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758852167



##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.

Review comment:
       ```suggestion
   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.
   ```

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.
+
+```shell
+# enable aws lambda for a route via api key authorization
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -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"
+}'
+```
+
+Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example ( here aws lambda function just take the `name` query param and returns `Hello $name` ) :
+
+```shell
+$ curl -i -XGET localhost:9080/aws\?name=APISIX
+HTTP/1.1 200 OK
+Content-Type: application/json
+Connection: keep-alive
+Date: Sat, 27 Nov 2021 13:08:27 GMT
+x-amz-apigw-id: JdwXuEVxIAMFtKw=
+x-amzn-RequestId: 471289ab-d3b7-4819-9e1a-cb59cac611e0
+Content-Length: 16
+X-Amzn-Trace-Id: Root=1-61a22dca-600c552d1c05fec747fd6db0;Sampled=0
+Server: APISIX/2.10.2
+
+"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 [config-default.yaml](../../../../conf/config-default.yaml). You can do it by uncommenting the port 9081 from `apisix.node_listen` field ) :

Review comment:
       Need to avoid using a link to `config-default.yaml`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] membphis commented on pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
membphis commented on pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#issuecomment-981615409


   @shuaijinchao @tzssangglass pls review when you have time


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758123078



##########
File path: apisix/plugins/azure-functions.lua
##########
@@ -14,30 +14,15 @@
 -- See the License for the specific language governing permissions and
 -- limitations under the License.
 
-local core = require("apisix.core")
-local http = require("resty.http")
 local plugin = require("apisix.plugin")
-local ngx  = ngx
-local plugin_name = "azure-functions"
+local plugin_name, plugin_version, priority = "azure-functions", 0.1, -1900
 
-local schema = {
+local azure_authz_schema = {

Review comment:
       I agree. This plugin depends on the refactoring proposed in #5616. For sake of fast development, I developed the feature on top of the branch ([ref](https://github.com/apache/apisix/pull/5594#issuecomment-979496919)). As the changes in 5616 has been merged into master, I have rebased it. Thanks : ) 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] juzhiyuan commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
juzhiyuan commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758873866



##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.
+
+```shell
+# enable aws lambda for a route via api key authorization
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -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"
+}'
+```
+
+Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example ( here aws lambda function just take the `name` query param and returns `Hello $name` ) :

Review comment:
       ```suggestion
   Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example (here AWS lambda function just take the `name` query param and returns `Hello $name` ) :
   ```

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.

Review comment:
       ```suggestion
   `aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the AWS lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params (all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758461816



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    tab_sort(canonical_qs)
+    canonical_qs = tab_concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        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+$", "")
+        end
+    end
+    tab_sort(signed_headers)
+
+    for i = 1, #signed_headers do
+        local k = signed_headers[i]
+        canonical_headers[i] = k .. ":" .. canonical_headers[k] .. "\n"
+    end
+    canonical_headers = tab_concat(canonical_headers, nil, 1, #signed_headers)
+    signed_headers = tab_concat(signed_headers, ";")
+
+    -- combining elements to form the canonical request (step-1)
+    local canonical_request = params.method:upper() .. "\n"
+                        .. canonical_uri .. "\n"
+                        .. (canonical_qs or "") .. "\n"
+                        .. canonical_headers .. "\n"
+                        .. signed_headers .. "\n"
+                        .. sha256(params.body or "")
+
+    -- creating the string to sign for aws signature v4 (step-2)
+    local iam = conf.authorization.iam
+    local credential_scope = datestamp .. "/" .. iam.aws_region .. "/"
+                            .. iam.service .. "/aws4_request"
+    local string_to_sign = ALGO .. "\n"
+                        .. amzdate .. "\n"
+                        .. credential_scope .. "\n"
+                        .. sha256(canonical_request)
+
+    -- calculate the signature (step-3)
+    local signature_key = getSignatureKey(iam.secretkey, datestamp, iam.aws_region, iam.service)
+    local signature = hexencode(hmac256(signature_key, string_to_sign))
+
+    -- add info to the headers (step-4)
+    headers["authorization"] = ALGO .. " Credential=" .. iam.accesskey
+                            .. "/" .. credential_scope
+                            .. ", SignedHeaders=" .. signed_headers
+                            .. ", Signature=" .. signature
+end
+
+
+local serverless_obj = require("apisix.plugins.serverless.generic-upstream")
+
+return serverless_obj(plugin_name,
+                    plugin_version,

Review comment:
       Updated

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex

Review comment:
       Ack

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.
+
+```shell
+# enable aws lambda for a route via api key authorization
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -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"
+}'
+```
+
+Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example ( here aws lambda function just take the `name` query param and returns `Hello $name` ) :
+
+```shell
+$ curl -i -XGET localhost:9080/aws\?name=apisix
+HTTP/1.1 200 OK
+Content-Type: application/json
+Connection: keep-alive
+Date: Sat, 27 Nov 2021 13:08:27 GMT
+x-amz-apigw-id: JdwXuEVxIAMFtKw=
+x-amzn-RequestId: 471289ab-d3b7-4819-9e1a-cb59cac611e0
+Content-Length: 16
+X-Amzn-Trace-Id: Root=1-61a22dca-600c552d1c05fec747fd6db0;Sampled=0
+Server: APISIX/2.10.2
+
+"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) ) :

Review comment:
       Updated

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.

Review comment:
       Okay. Got it

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.

Review comment:
       Okay. Got it. Thanks for letting me know : )




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] membphis commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
membphis commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758345571



##########
File path: t/admin/plugins.t
##########
@@ -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"\]/

Review comment:
       Yes, It's time to modify this to another easy-to-read format.

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.

Review comment:
       We should use `APISIX` always

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |

Review comment:
       if the `ssl_verify` is true, do we need to specify a certificate?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758461565



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    tab_sort(canonical_qs)
+    canonical_qs = tab_concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        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+$", "")

Review comment:
       Done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758123218



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex.to_hex(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "The service that is receiving the request"

Review comment:
       Done

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat

Review comment:
       Ack

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort

Review comment:
       Done

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899

Review comment:
       Thanks, updated

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex.to_hex(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "The service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    sort(canonical_qs)
+    canonical_qs = concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+    local url_decoded = url.parse(conf.function_uri)
+    headers["host"] = url_decoded.host
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        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+$", "")
+        end
+    end
+    sort(signed_headers)
+
+    for i = 1, #signed_headers do
+        local k = signed_headers[i]
+        canonical_headers[i] = k .. ":" .. canonical_headers[k] .. "\n"
+    end
+    canonical_headers = concat(canonical_headers, nil, 1, #signed_headers)
+    signed_headers = concat(signed_headers, ";")
+
+    -- combining elements to form the canonical request (step-1)
+    local canonical_request = params.method:upper() .. "\n"
+                        .. canonical_uri .. "\n"
+                        .. (canonical_qs or "") .. "\n"
+                        .. canonical_headers .. "\n"
+                        .. signed_headers .. "\n"
+                        .. sha256(params.body or "")
+
+    -- creating the string to sign for aws signature v4 (step-2)
+    local iam = conf.authorization.iam
+    local credential_scope = datestamp .. "/" .. iam.aws_region .. "/"
+                            .. iam.service .. "/aws4_request"
+    local string_to_sign = ALGO .. "\n"
+                        .. amzdate .. "\n"
+                        .. credential_scope .. "\n"
+                        .. sha256(canonical_request)
+
+    -- calculate the signature (step-3)
+    local signature_key = getSignatureKey(iam.secretkey, datestamp, iam.aws_region, iam.service)
+    local signature = hex.to_hex(hmac256(signature_key, string_to_sign))
+
+    -- add info to the headers (step-4)
+    headers["authorization"] = ALGO .. " Credential=" .. iam.accesskey
+                            .. "/" .. credential_scope
+                            .. ", SignedHeaders=" .. signed_headers
+                            .. ", Signature=" .. signature
+end
+
+
+return require("apisix.plugins.serverless.generic-upstream")(plugin_name,

Review comment:
       Nice. Updated accordingly




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] spacewander commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
spacewander commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758167136



##########
File path: t/admin/plugins.t
##########
@@ -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"\]/

Review comment:
       Can we split this into multiple lines? We can do it in the next PR.

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    tab_sort(canonical_qs)
+    canonical_qs = tab_concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        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+$", "")

Review comment:
       We can use https://refined-github-html-preview.kidonng.workers.dev/lunarmodules/Penlight/raw/master/docs/libraries/pl.stringx.html#strip?

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")

Review comment:
       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

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.

Review comment:
       Please use APISIX route instead of `apisix route`. Need to fix other similar places.

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |
+| secret_key       | string | required     |                |             | Genereated access key secret from aws IAM console.                                         |
+| aws_region       | string | optional     | "us-east-1"    |             | The aws region where the request is being sent.                                            |
+| service          | string | optional     | "execute-api"  |             | The service that is receiving the request (In case of Http Trigger it is "execute-api").   |
+
+## 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.
+
+```shell
+# enable aws lambda for a route via api key authorization
+curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -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"
+}'
+```
+
+Now any requests (HTTP/1.1, HTTPS, HTTP2) to URI `/aws` will trigger an HTTP invocation to the aforesaid function URI and response body along with the response headers and response code will be proxied back to the client. For example ( here aws lambda function just take the `name` query param and returns `Hello $name` ) :
+
+```shell
+$ curl -i -XGET localhost:9080/aws\?name=apisix
+HTTP/1.1 200 OK
+Content-Type: application/json
+Connection: keep-alive
+Date: Sat, 27 Nov 2021 13:08:27 GMT
+x-amz-apigw-id: JdwXuEVxIAMFtKw=
+x-amzn-RequestId: 471289ab-d3b7-4819-9e1a-cb59cac611e0
+Content-Length: 16
+X-Amzn-Trace-Id: Root=1-61a22dca-600c552d1c05fec747fd6db0;Sampled=0
+Server: APISIX/2.10.2
+
+"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) ) :

Review comment:
       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.

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)

Review comment:
       Ditto

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex

Review comment:
       Can we use underscore style for function name?

##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    tab_sort(canonical_qs)
+    canonical_qs = tab_concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        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+$", "")
+        end
+    end
+    tab_sort(signed_headers)
+
+    for i = 1, #signed_headers do
+        local k = signed_headers[i]
+        canonical_headers[i] = k .. ":" .. canonical_headers[k] .. "\n"
+    end
+    canonical_headers = tab_concat(canonical_headers, nil, 1, #signed_headers)
+    signed_headers = tab_concat(signed_headers, ";")
+
+    -- combining elements to form the canonical request (step-1)
+    local canonical_request = params.method:upper() .. "\n"
+                        .. canonical_uri .. "\n"
+                        .. (canonical_qs or "") .. "\n"
+                        .. canonical_headers .. "\n"
+                        .. signed_headers .. "\n"
+                        .. sha256(params.body or "")
+
+    -- creating the string to sign for aws signature v4 (step-2)
+    local iam = conf.authorization.iam
+    local credential_scope = datestamp .. "/" .. iam.aws_region .. "/"
+                            .. iam.service .. "/aws4_request"
+    local string_to_sign = ALGO .. "\n"
+                        .. amzdate .. "\n"
+                        .. credential_scope .. "\n"
+                        .. sha256(canonical_request)
+
+    -- calculate the signature (step-3)
+    local signature_key = getSignatureKey(iam.secretkey, datestamp, iam.aws_region, iam.service)
+    local signature = hexencode(hmac256(signature_key, string_to_sign))
+
+    -- add info to the headers (step-4)
+    headers["authorization"] = ALGO .. " Credential=" .. iam.accesskey
+                            .. "/" .. credential_scope
+                            .. ", SignedHeaders=" .. signed_headers
+                            .. ", Signature=" .. signature
+end
+
+
+local serverless_obj = require("apisix.plugins.serverless.generic-upstream")
+
+return serverless_obj(plugin_name,
+                    plugin_version,

Review comment:
       Bad indent




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] tzssangglass commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
tzssangglass commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758881212



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,183 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local hmac = require("resty.hmac")
+local hex_encode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+local str_strip = require("pl.stringx").strip
+local norm_path = require("pl.path").normpath
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex_encode(digest)
+end
+
+local function get_signature_key(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = norm_path(params.path)
+    if canonical_uri ~= "/" then
+        if canonical_uri:sub(-1, -1) == "/" then
+            canonical_uri = canonical_uri:sub(1, -2)
+        end
+        if canonical_uri:sub(1, 1) ~= "/" then
+            canonical_uri = "/" .. canonical_uri
+        end
+    end
+
+    -- computing canonical query string
+    local canonical_qs = {}
+    for k, v in pairs(params.query) do
+        canonical_qs[#canonical_qs+1] = ngx.unescape_uri(k) .. "=" .. ngx.unescape_uri(v)
+    end
+
+    tab_sort(canonical_qs)
+    canonical_qs = tab_concat(canonical_qs, "&")
+
+    -- computing canonical and signed headers
+
+    local canonical_headers, signed_headers = {}, {}
+    for k, v in pairs(headers) do
+        k = k:lower()
+        if k ~= "connection" then
+            signed_headers[#signed_headers+1] = k

Review comment:
       I don't understand here, do we just need to skip `connection`?

##########
File path: docs/en/latest/plugins/aws-lambda.md
##########
@@ -0,0 +1,156 @@
+---
+title: aws-lambda
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Summary
+
+- [Summary](#summary)
+- [Name](#name)
+- [Attributes](#attributes)
+  - [IAM Authorization Schema](#iam-authorization-schema)
+- [How To Enable](#how-to-enable)
+- [Disable Plugin](#disable-plugin)
+
+## Name
+
+`aws-lambda` is a serverless plugin built into Apache APISIX for seamless integration with [AWS Lambda](https://aws.amazon.com/lambda/), a widely used serverless solution, as a dynamic upstream to proxy all requests for a particular URI to the AWS cloud - one of the highly used public cloud platforms for production environment. If enabled, this plugin terminates the ongoing request to that particular URI and initiates a new request to the aws lambda gateway uri (the new upstream) on behalf of the client with the suitable authorization details set by the users, request headers, request body, params ( all these three components are passed from the original request ) and returns the response body, status code and the headers back to the original client that has invoked the request to the APISIX agent.
+At present, the plugin supports authorization via aws api key and aws IAM Secrets.
+
+## Attributes
+
+| Name             | Type   | Requirement  | Default      | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------      | -----       | ------------------------------------------------------------                               |
+| function_uri      | string | required    |          |   | The aws api gateway endpoint which triggers the lambda serverless function code.   |
+| authorization   | object | optional    |         |     |  Authorization credentials to access the cloud function.                                                             |
+| 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.                     |
+| keepalive  | boolean | optional    | true           | true/false     | To reuse the same proxy connection in near future. Set to false to disable keepalives and immediately close the connection.                    |
+| keepalive_pool  | integer | optional    | 5          | [1,...]     | The maximum number of connections in the pool.              |
+| keepalive_timeout  | integer | optional    | 60000           | [1000,...]     |  The maximal idle timeout (ms).                     |
+
+### IAM Authorization Schema
+
+| Name             | Type   | Requirement  | Default        | Valid       | Description                                                                                |
+| -----------      | ------ | -----------  | -------        | -----       | ------------------------------------------------------------                               |
+| accesskey        | string | required     |                |             | Genereated  access key ID from aws IAM console.                                            |

Review comment:
       ```suggestion
   | accesskey        | string | required     |                |             | Genereated access key ID from aws IAM console.                                            |
   ```

##########
File path: t/plugin/aws-lambda.t
##########
@@ -0,0 +1,299 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+repeat_each(1);
+no_long_string();
+no_root_location();
+no_shuffle();
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    my $inside_lua_block = $block->inside_lua_block // "";
+    chomp($inside_lua_block);
+    my $http_config = $block->http_config // <<_EOC_;
+
+    server {
+        listen 8765;
+
+        location /httptrigger {
+            content_by_lua_block {
+                ngx.req.read_body()
+                local msg = "aws lambda invoked"
+                ngx.header['Content-Length'] = #msg + 1
+                ngx.header['Connection'] = "Keep-Alive"
+                ngx.say(msg)
+            }
+        }
+
+        location /generic {
+            content_by_lua_block {
+                $inside_lua_block
+            }
+        }
+    }
+_EOC_
+
+    $block->set_value("http_config", $http_config);
+
+    if (!$block->request) {
+        $block->set_value("request", "GET /t");
+    }
+    if (!$block->no_error_log && !$block->error_log) {
+        $block->set_value("no_error_log", "[error]\n[alert]");
+    }
+});
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: checking iam schema
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.aws-lambda")
+            local ok, err = plugin.check_schema({
+                function_uri = "https://api.amazonaws.com",
+                authorization = {
+                    iam = {
+                        accesskey = "key1",
+                        secretkey = "key2"
+                    }
+                }
+            })
+            if not ok then
+                ngx.say(err)
+            else
+                ngx.say("done")
+            end
+        }
+    }
+--- response_body
+done
+
+
+
+=== TEST 2: missing fields in iam schema
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.aws-lambda")
+            local ok, err = plugin.check_schema({
+                function_uri = "https://api.amazonaws.com",
+                authorization = {
+                    iam = {
+                        secretkey = "key2"
+                    }
+                }
+            })
+            if not ok then
+                ngx.say(err)
+            else
+                ngx.say("done")
+            end
+        }
+    }
+--- response_body
+property "authorization" validation failed: property "iam" validation failed: property "accesskey" is required
+
+
+
+=== TEST 3: create route with aws plugin enabled
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+
+            local code, body = t('/apisix/admin/routes/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                        "plugins": {
+                            "aws-lambda": {
+                                "function_uri": "http://localhost:8765/httptrigger",
+                                "authorization": {
+                                    "apikey" : "testkey"
+                                }
+                            }
+                        },
+                        "uri": "/aws"
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "plugins": {
+                                "aws-lambda": {
+                                    "keepalive": true,
+                                    "timeout": 3000,
+                                    "ssl_verify": true,
+                                    "keepalive_timeout": 60000,
+                                    "keepalive_pool": 5,
+                                    "function_uri": "http://localhost:8765/httptrigger",
+                                    "authorization": {
+                                        "apikey": "testkey"
+                                    }
+                                }
+                            },
+                            "uri": "/aws"
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                ngx.say("fail")
+                return
+            end
+
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 4: Test plugin endpoint
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local core = require("apisix.core")
+
+            local code, _, body, headers = t("/aws", "GET")
+             if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            -- headers proxied 2 times -- one by plugin, another by this test case
+            core.response.set_header(headers)
+            ngx.print(body)
+        }
+    }
+--- response_body
+aws lambda invoked
+--- response_headers
+Content-Length: 19

Review comment:
       why check the `Content-Length` 

##########
File path: t/plugin/aws-lambda.t
##########
@@ -0,0 +1,299 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+repeat_each(1);
+no_long_string();
+no_root_location();
+no_shuffle();
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    my $inside_lua_block = $block->inside_lua_block // "";
+    chomp($inside_lua_block);
+    my $http_config = $block->http_config // <<_EOC_;
+
+    server {
+        listen 8765;
+
+        location /httptrigger {
+            content_by_lua_block {
+                ngx.req.read_body()
+                local msg = "aws lambda invoked"
+                ngx.header['Content-Length'] = #msg + 1
+                ngx.header['Connection'] = "Keep-Alive"
+                ngx.say(msg)
+            }
+        }
+
+        location /generic {
+            content_by_lua_block {
+                $inside_lua_block
+            }
+        }
+    }
+_EOC_
+
+    $block->set_value("http_config", $http_config);
+
+    if (!$block->request) {
+        $block->set_value("request", "GET /t");
+    }
+    if (!$block->no_error_log && !$block->error_log) {
+        $block->set_value("no_error_log", "[error]\n[alert]");
+    }
+});
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: checking iam schema
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.aws-lambda")
+            local ok, err = plugin.check_schema({
+                function_uri = "https://api.amazonaws.com",
+                authorization = {
+                    iam = {
+                        accesskey = "key1",
+                        secretkey = "key2"
+                    }
+                }
+            })
+            if not ok then
+                ngx.say(err)
+            else
+                ngx.say("done")
+            end
+        }
+    }
+--- response_body
+done
+
+
+
+=== TEST 2: missing fields in iam schema
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.aws-lambda")
+            local ok, err = plugin.check_schema({
+                function_uri = "https://api.amazonaws.com",
+                authorization = {
+                    iam = {
+                        secretkey = "key2"
+                    }
+                }
+            })
+            if not ok then
+                ngx.say(err)
+            else
+                ngx.say("done")
+            end
+        }
+    }
+--- response_body
+property "authorization" validation failed: property "iam" validation failed: property "accesskey" is required
+
+
+
+=== TEST 3: create route with aws plugin enabled
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+
+            local code, body = t('/apisix/admin/routes/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                        "plugins": {
+                            "aws-lambda": {
+                                "function_uri": "http://localhost:8765/httptrigger",
+                                "authorization": {
+                                    "apikey" : "testkey"
+                                }
+                            }
+                        },
+                        "uri": "/aws"
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "plugins": {
+                                "aws-lambda": {
+                                    "keepalive": true,
+                                    "timeout": 3000,
+                                    "ssl_verify": true,
+                                    "keepalive_timeout": 60000,
+                                    "keepalive_pool": 5,
+                                    "function_uri": "http://localhost:8765/httptrigger",
+                                    "authorization": {
+                                        "apikey": "testkey"
+                                    }
+                                }
+                            },
+                            "uri": "/aws"
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                ngx.say("fail")
+                return
+            end
+
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 4: Test plugin endpoint

Review comment:
       ```suggestion
   === TEST 4: test plugin endpoint
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758909397



##########
File path: t/plugin/aws-lambda.t
##########
@@ -0,0 +1,299 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+repeat_each(1);
+no_long_string();
+no_root_location();
+no_shuffle();
+
+add_block_preprocessor(sub {
+    my ($block) = @_;
+
+    my $inside_lua_block = $block->inside_lua_block // "";
+    chomp($inside_lua_block);
+    my $http_config = $block->http_config // <<_EOC_;
+
+    server {
+        listen 8765;
+
+        location /httptrigger {
+            content_by_lua_block {
+                ngx.req.read_body()
+                local msg = "aws lambda invoked"
+                ngx.header['Content-Length'] = #msg + 1
+                ngx.header['Connection'] = "Keep-Alive"
+                ngx.say(msg)
+            }
+        }
+
+        location /generic {
+            content_by_lua_block {
+                $inside_lua_block
+            }
+        }
+    }
+_EOC_
+
+    $block->set_value("http_config", $http_config);
+
+    if (!$block->request) {
+        $block->set_value("request", "GET /t");
+    }
+    if (!$block->no_error_log && !$block->error_log) {
+        $block->set_value("no_error_log", "[error]\n[alert]");
+    }
+});
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: checking iam schema
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.aws-lambda")
+            local ok, err = plugin.check_schema({
+                function_uri = "https://api.amazonaws.com",
+                authorization = {
+                    iam = {
+                        accesskey = "key1",
+                        secretkey = "key2"
+                    }
+                }
+            })
+            if not ok then
+                ngx.say(err)
+            else
+                ngx.say("done")
+            end
+        }
+    }
+--- response_body
+done
+
+
+
+=== TEST 2: missing fields in iam schema
+--- config
+    location /t {
+        content_by_lua_block {
+            local plugin = require("apisix.plugins.aws-lambda")
+            local ok, err = plugin.check_schema({
+                function_uri = "https://api.amazonaws.com",
+                authorization = {
+                    iam = {
+                        secretkey = "key2"
+                    }
+                }
+            })
+            if not ok then
+                ngx.say(err)
+            else
+                ngx.say("done")
+            end
+        }
+    }
+--- response_body
+property "authorization" validation failed: property "iam" validation failed: property "accesskey" is required
+
+
+
+=== TEST 3: create route with aws plugin enabled
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+
+            local code, body = t('/apisix/admin/routes/1',
+                 ngx.HTTP_PUT,
+                 [[{
+                        "plugins": {
+                            "aws-lambda": {
+                                "function_uri": "http://localhost:8765/httptrigger",
+                                "authorization": {
+                                    "apikey" : "testkey"
+                                }
+                            }
+                        },
+                        "uri": "/aws"
+                }]],
+                [[{
+                    "node": {
+                        "value": {
+                            "plugins": {
+                                "aws-lambda": {
+                                    "keepalive": true,
+                                    "timeout": 3000,
+                                    "ssl_verify": true,
+                                    "keepalive_timeout": 60000,
+                                    "keepalive_pool": 5,
+                                    "function_uri": "http://localhost:8765/httptrigger",
+                                    "authorization": {
+                                        "apikey": "testkey"
+                                    }
+                                }
+                            },
+                            "uri": "/aws"
+                        },
+                        "key": "/apisix/routes/1"
+                    },
+                    "action": "set"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+                ngx.say("fail")
+                return
+            end
+
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 4: Test plugin endpoint
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local core = require("apisix.core")
+
+            local code, _, body, headers = t("/aws", "GET")
+             if code >= 300 then
+                ngx.status = code
+                ngx.say(body)
+                return
+            end
+
+            -- headers proxied 2 times -- one by plugin, another by this test case
+            core.response.set_header(headers)
+            ngx.print(body)
+        }
+    }
+--- response_body
+aws lambda invoked
+--- response_headers
+Content-Length: 19

Review comment:
       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  




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] spacewander merged pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
spacewander merged pull request #5594:
URL: https://github.com/apache/apisix/pull/5594


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758121837



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,181 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local concat = table.concat
+local sort = table.sort
+local os = os
+local url = require("net.url")
+local hmac = require("resty.hmac")
+local hex = require("resty.string")
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name, plugin_version, priority = "aws-lambda", 0.1, -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hex.to_hex(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {

Review comment:
       This is not the complete schema, rather it's the part of the schema (handling the plugin specific authorization details).
   
   see: https://github.com/apache/apisix/blob/8f0b066c86257ad6af19f9b3b7e209ece95d17c9/apisix/plugins/serverless/generic-upstream.lua#L36




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] bisakhmondal commented on a change in pull request #5594: feat(plugins): aws lambda serverless

Posted by GitBox <gi...@apache.org>.
bisakhmondal commented on a change in pull request #5594:
URL: https://github.com/apache/apisix/pull/5594#discussion_r758463163



##########
File path: apisix/plugins/aws-lambda.lua
##########
@@ -0,0 +1,185 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+
+local ngx = ngx
+local pairs = pairs
+local tab_concat = table.concat
+local tab_sort = table.sort
+local os = os
+local hmac = require("resty.hmac")
+local hexencode = require("resty.string").to_hex
+local resty_sha256 = require("resty.sha256")
+
+
+local plugin_name = "aws-lambda"
+local plugin_version = 0.1
+local priority = -1899
+
+local ALGO = "AWS4-HMAC-SHA256"
+
+local function hmac256(key, msg)
+    return hmac:new(key, hmac.ALGOS.SHA256):final(msg)
+end
+
+local function sha256(msg)
+    local hash = resty_sha256:new()
+    hash:update(msg)
+    local digest = hash:final()
+    return hexencode(digest)
+end
+
+local function getSignatureKey(key, datestamp, region, service)
+    local kDate = hmac256("AWS4" .. key, datestamp)
+    local kRegion = hmac256(kDate, region)
+    local kService = hmac256(kRegion, service)
+    local kSigning = hmac256(kService, "aws4_request")
+    return kSigning
+end
+
+local aws_authz_schema = {
+    type = "object",
+    properties = {
+        -- API Key based authorization
+        apikey = {type = "string"},
+        -- IAM role based authorization, works via aws v4 request signing
+        -- more at https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
+        iam = {
+            type = "object",
+            properties = {
+                accesskey = {
+                    type = "string",
+                    description = "access key id from from aws iam console"
+                },
+                secretkey = {
+                    type = "string",
+                    description = "secret access key from from aws iam console"
+                },
+                aws_region = {
+                    type = "string",
+                    default = "us-east-1",
+                    description = "the aws region that is receiving the request"
+                },
+                service = {
+                    type = "string",
+                    default = "execute-api",
+                    description = "the service that is receiving the request"
+                }
+            },
+            required = {"accesskey", "secretkey"}
+        }
+    }
+}
+
+local function request_processor(conf, ctx, params)
+    local headers = params.headers
+    -- set authorization headers if not already set by the client
+    -- we are following not to overwrite the authz keys
+    if not headers["x-api-key"] then
+        if conf.authorization and conf.authorization.apikey then
+            headers["x-api-key"] = conf.authorization.apikey
+            return
+        end
+    end
+
+    -- performing aws v4 request signing for IAM authorization
+    -- visit https://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html
+    -- to look at the pseudocode in python.
+    if headers["authorization"] or not conf.authorization or not conf.authorization.iam then
+        return
+    end
+
+    -- create a date for headers and the credential string
+    local t = ngx.time()
+    local amzdate =  os.date("!%Y%m%dT%H%M%SZ", t)
+    local datestamp = os.date("!%Y%m%d", t) -- Date w/o time, used in credential scope
+    headers["X-Amz-Date"] = amzdate
+
+    -- computing canonical uri
+    local canonical_uri = params.path:gsub("//", "/")

Review comment:
       Done




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org