Skip to content

LEGO/kong-aws-request-signing

Repository files navigation

KONG-AWS-REQUEST-SIGNING

Build

About

This plugin will sign a request with AWS SIGV4 and temporary credentials from sts.amazonaws.com requested using an OAuth token.

It enables the secure use of AWS Lambdas as upstreams in Kong using Lambda URLs.

At the same time it drives down cost and complexity by excluding the AWS API Gateway and allowing to use AWS Lambdas directly.

The required AWS setup to make the plugin work with your Lambda HTTPS endpoint is described below.

Plugin configuration parameters

aws_assume_role_arn - ARN of the IAM role that the plugin will try to assume
type = "string"
required = true

aws_assume_role_name - Name of the role above.
type = "string"
required = true

aws_region - AWS region where your Lambda is deployed to
type = "string"
required = true

aws_service - AWS Service you are trying to access (lambda and s3 were tested)
type = "string"
required = true

override_target_host - To be used when deploying multiple lambdas on a single Kong service (because lambdas have differennt URLs)
type = "string"
required = false

override_target_port - To be used when deploying a Lambda on a Kong service that listens on a port other than `443`
type = "number"
required = false

override_target_protocol - To be used when deploying a Lambda on a Kong service that has a protocol different than `https`
type = "string"
one_of = "http", "https"
required = false

return_aws_sts_error - Whether to return the AWS STS response status and body when credentials fetching failed.
type = "boolean"
default = false
required = false

sign_query - Controls if the signature will be sent in the header or in the query. By default, header is used, if enabled will sign the query.
type = boolean
required = true
default = false

Using multiple Lambdas with the same Kong Service

The plugin can be enabled on a per-service and per-route basis. When enabled for a route, the plugin will direct traffic to the service's upstream Lambda target, unless override_target_host is specified.

If multiple Lambdas are needed for a single service, each route must have the plugin enabled with override_target_host configured, so that requests are correctly routed to the right Lambda.

If override_target_host is not specified and multiple Lambdas are used in the service, all routes will be served by the same service-level host.

You can also set the service protocol and host to something like http://example.com and then use override_target_protocol and override_target_host to changed it on the path level.

Installing the plugin

There are two things necessary to make a custom plugin work in Kong:

  1. Load the plugin files.

The easiest way to install the plugin is using luarocks.

luarocks install https://github.com/LEGO/kong-aws-request-signing/raw/main/rocks/kong-aws-request-signing-1.0.4-3.all.rock

You can substitute 1.0.0-3 in the command above with any other version you want to install.

If running Kong using the Helm chart, you will need to create a config map with the plugin files and mount it to /opt/kong/plugins/aws-request-signing. You can read more about this on Kong's website.

  1. Specify that you want to use the plugin by modifying the plugins property in the Kong configuration.

Add the custom plugin’s name to the list of plugins in your Kong configuration:

plugins = bundled, aws-request-signing

If you are using the Kong helm chart, create a configMap with the plugin files and add it to your values.yaml file:

# values.yaml
plugins:
  configMaps:
  - name: kong-plugin-aws-request-signing
    pluginName: aws-request-signing

AWS Setup required

  1. You have a Lambda function deployed with Function URL enabled and Auth type : AWS_IAM or you have an S3 bucket with public access disabled.
Show image

Lambda example

  1. Your OpenID Connect provider is added to AWS IAM
  2. You have a role with arn:aws:iam::aws:policy/AWSLambda_FullAccess and/or arn:aws:iam::aws:policy/AmazonS3FullAccess permision (or any other permision that grants access to your desired AWS service ) and the trust relationship below:
Show JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "${arn_of_the_open_id_connect_provider_step_1}"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "${the_open_id_connect_provider_step_1}:aud": "${audience_of_the_lambda_given_by_your_open_id_provider}"
                }
            }
        }
    ]
}

So if your provider is https://sts.windows.net/organization.onmicrosoft.com/ and your app identity is app_identity_1, the trust relationship above will look like:

Show JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::300000000000:oidc-provider/sts.windows.net/organization.onmicrosoft.com/"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "sts.windows.net/organization.onmicrosoft.com/:aud": "app_identity_1"
                }
            }
        }
    ]
}

About the code and differences from Kong Lambda Plugin

Some of the code was reused from Kong Lambda Plugin specifically the SIGV4 creation code and some parts for getting the temporary credentials from AWS STS. There are some considerable differences that will be outlined below:

  1. Unlike Kong-Lambda This plugin does not perform the Lambda invocation. But only signs the request coming from the consumer which Kong then forwards to the upstream that it is configured in the service that the plugin is bound to.
  2. The plugin works only with temporary credentials that are fetched from sts.amazonaws.com using AssumeRoleWithWebIdentity, this requires some configuration in AWS which can be found above.
  3. This plugin has a low priority and is compatible with the rest of Kong plugins because as mentioned above, it only performs SIGV4 on the request and then appends the necessary headers to be authorized in AWS.

Open Source Attribution

License

Modified Apache 2.0 (Section 6)