Invoke an AWS Lambda function from Kong. It can be used in combination with other request plugins to secure, manage or extend the function.


Terminology

  • plugin: a plugin executing actions inside Kong before or after a request has been proxied to the upstream API.
  • API: (deprecated) the Kong entity representing your upstream service placed behind Kong, for which Kong proxies requests to.
  • Service: the Kong entity representing an external upstream API or microservice.
  • Route: the Kong entity representing a way to map downstream requests to upstream services.
  • Consumer: the Kong entity representing a developer or machine using the API. When using Kong, a Consumer only communicates with Kong which proxies every call to the said upstream API.
  • Credential: a unique string associated with a Consumer, also referred to as an API key.
  • upstream service: this refers to your own API/service sitting behind Kong, to which client requests are forwarded.

Configuration

Enabling the plugin for a Service

Configure on top of a Service by executing the following request on your Kong server:

$ curl -X POST http://kong:8001/services/{service}/plugins \
    --data "name=aws-lambda"  \
    --data-urlencode "config.aws_key=AWS_KEY" \
    --data-urlencode "config.aws_secret=AWS_SECRET" \
    --data "config.aws_region=AWS_REGION" \
    --data "config.function_name=LAMBDA_FUNCTION_NAME"
  • service: the id or name of the Service that this plugin configuration will target.

Enabling the plugin for a Route

Configure on top of a Route with:

$ curl -X POST http://kong:8001/routes/{route_id}/plugins \
    --data "name=aws-lambda"  \
    --data-urlencode "config.aws_key=AWS_KEY" \
    --data-urlencode "config.aws_secret=AWS_SECRET" \
    --data "config.aws_region=AWS_REGION" \
    --data "config.function_name=LAMBDA_FUNCTION_NAME"
  • route_id: the id of the Route that this plugin configuration will target.

Enabling the plugin for an API

If you are using the deprecated API entity, you can configure on top of an API by executing the following request on your Kong server:

$ curl -X POST http://kong:8001/apis/{api}/plugins \
    --data "name=aws-lambda"  \
    --data-urlencode "config.aws_key=AWS_KEY" \
    --data-urlencode "config.aws_secret=AWS_SECRET" \
    --data "config.aws_region=AWS_REGION" \
    --data "config.function_name=LAMBDA_FUNCTION_NAME"
  • api: either id or name of the API that this plugin configuration will target.

Enabling the plugin for a Consumer

You can use the http://localhost:8001/plugins endpoint to target Consumers:

$ curl -X POST http://kong:8001/plugins \
    --data "name=aws-lambda" \
    --data "consumer_id={consumer_id}"  \
    --data-urlencode "config.aws_key=AWS_KEY" \
    --data-urlencode "config.aws_secret=AWS_SECRET" \
    --data "config.aws_region=AWS_REGION" \
    --data "config.function_name=LAMBDA_FUNCTION_NAME"

Where consumer_id: The id of the Consumer we want to associate with this plugin.

You can combine adding consumer_id and service_id in the same request.

Once applied, any user with a valid credential can access the Service/API. To restrict usage to only some of the authenticated users, also add the ACL plugin (not covered here) and create whitelist or blacklist groups of users.

Global plugins

All plugins can be configured using the http:/kong:8001/plugins/ endpoint. A plugin which is not associated to any API, Service, Route or Consumer is considered "global", and will be run on every request. Read the Plugin Reference and the Plugin Precedence sections for more information.

Parameters

Here's a list of all the parameters which can be used in this plugin's configuration:

form parameterdefaultdescription
nameThe name of the plugin to use, in this case aws-lambda
api_idThe id of the API which this plugin will target.
service_idThe id of the Service which this plugin will target.
route_idThe id of the Route which this plugin will target.
consumer_idThe id of the Consumer which this plugin will target.
config.aws_key

The AWS key credential to be used when invoking the function

config.aws_secret

The AWS secret credential to be used when invoking the function

config.aws_region

The AWS region where the Lambda function is located. Regions supported are: us-east-1, us-east-2, ap-northeast-1, ap-northeast-2, ap-southeast-1, ap-southeast-2, eu-central-1, eu-west-1

config.function_name

The AWS Lambda function name to invoke

config.qualifier
optional

The Qualifier to use when invoking the function.

config.invocation_type
optional

RequestResponse

The InvocationType to use when invoking the function. Available types are RequestResponse, Event, DryRun

config.log_type
optional

Tail

The LogType to use when invoking the function. By default None and Tail are supported

config.timeout
optional

60000

An optional timeout in milliseconds when invoking the function

config.keepalive
optional

60000

An optional value in milliseconds that defines how long an idle connection will live before being closed

config.unhandled_status
optional

200, 202 or 204

The response status code to use (instead of the default 200, 202, or 204) in the case of an Unhandled Function Error

config.forward_request_body
optional

false

An optional value that defines whether the request body is to be sent in the request_body field of the JSON-encoded request. If the body arguments can be parsed, they will be sent in the separate request_body_args field of the request. The body arguments can be parsed for application/json, application/x-www-form-urlencoded, and multipart/form-data content types.

config.forward_request_headers
optional

false

An optional value that defines whether the original HTTP request headers are to be sent as a map in the request_headers field of the JSON-encoded request.

config.forward_request_method
optional

false

An optional value that defines whether the original HTTP request method verb is to be sent in the request_method field of the JSON-encoded request.

config.forward_request_uri
optional

false

An optional value that defines whether the original HTTP request URI is to be sent in the request_uri field of the JSON-encoded request. Request URI arguments (if any) will be sent in the separate request_uri_args field of the JSON body.

Reminder: curl by default sends payloads with an application/x-www-form-urlencoded MIME type, which will naturally be URL- decoded by Kong. To ensure special characters that are likely to appear in your AWS key or secret (like +) are correctly decoded, you must URL-encode them, hence use --date-urlencode if you are using curl. Alternatives to this approach would be to send your payload with a different MIME type (like application/json), or to use a different HTTP client.

Sending parameters

Any form parameter sent along with the request, will be also sent as an argument to the AWS Lambda function.

Known Issues

Use a fake upstream service

When using the AWS Lambda plugin, the response will be returned by the plugin itself without proxying the request to any upstream service. This means that a Service's host, port, path properties will be ignored, but must still be specified for the entity to be validated by Kong. The host property in particular must either be an IP address, or a hostname that gets resolved by your nameserver.

When the plugin is added to an API entity (which is deprecated as of 0.13.0), it is the upsream_url property which must be specified and resolvable as well (but ignored).

Response plugins

There is a known limitation in the system that prevents some response plugins from being executed. We are planning to remove this limitation in the future.


Step By Step Guide

The Steps

  1. Access to AWS Console as user allowed to operate with lambda functions and create user and roles.
  2. Create an Execution role in AWS
  3. Create an user which will be invoke the function via Kong, test it.
  4. Create an API in Kong, add the aws-lambda plugin linked to our aws function and execute it.

Configure:

  1. First, let's create an execution role called LambdaExecutor for our lambda function.

    In IAM Console create a new Role choosing the AWS Lambda service, there will be no policies as our function in this example will simply execute itself giving us back an hardcoded JSON as response without accessing other AWS resources.

  2. Now let's create a user named KongInvoker, used by our Kong API gateway to invoke the function.

    In IAM Console create a new user, must be provided to it programmatic access via Access and Secret keys; then will attach existing policies directly particularly the AWSLambdaRole predefined. Once the user creation is confirmed, store Access Key and Secret Key in a safe place.

  3. Now we need to create the lambda function itself, will do so in N.Virginia Region (code us-east-1).

    In Lambda Management, create a new function Mylambda, there will be no blueprint as we are going to paste the code below; for the execution role let's choose an existing role specifically LambdaExecutor created previously

    Use the inline code below to have a simple JSON response in return, note this is code for Python 3.6 interpreter.

    import json
    def lambda_handler(event, context):
        jsonbody='''{"response": "yes"}'''
        return json.loads(jsonbody)
    

    Test the lambda function from the AWS console and make sure the execution succeeds.

  4. Finally we setup the api in Kong and link it to the function just created.

    The api that we are going to create doesn't really need a real upstream_url since we are not going to have an HTTP call to upstream but rather a response generated by our function.

    curl -i -X POST http://{kong_hostname}:8001/apis \
    --data 'name=lambda1' \
    --data 'upstream_url=http://localhost:8000' \
    --data 'uris=/lambda1'
    

    Add the plugin:

    curl -i -X POST http://{kong_hostname}:8001/apis/lambda1/plugins \
    --data 'name=aws-lambda' \
    --data 'config.aws_key={KongInvoker user key}' \
    --data 'config.aws_secret={KongInvoker user secret}' \
    --data 'config.aws_region=us-east-1' \
    --data 'config.function_name=MyLambda'
    

    Call the Api and verify the correct invocation, execution and response:

    curl http://{kong_hostname}:8000/lambda1
    

    Additional headers:

    x-amzn-Remapped-Content-Length, X-Amzn-Trace-Id, x-amzn-RequestId
    

    JSON response:

    {"response": "yes"}
    

Have fun leveraging the power of AWS Lambda in Kong!

Keep up with the latest features