Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/unreleased/kong/feat-aws-lambda-max-uri-args.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message: "**aws-lambda**: Add `max_uri_args` configuration to override the default limit of 100 query string parameters, and `reject_if_max_uri_args_exceeded` to return 414 when the limit is exceeded."
type: feature
scope: Plugin
12 changes: 12 additions & 0 deletions kong/plugins/aws-lambda/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ local AWSLambdaHandler = {


function AWSLambdaHandler:access(conf)
-- Reject early if query string parameter count exceeds the configured limit
if conf.reject_if_max_uri_args_exceeded then
local args = ngx.req.get_uri_args(conf.max_uri_args)
local count = 0
for _ in pairs(args) do
count = count + 1
end
if count >= conf.max_uri_args then
return kong.response.exit(414, { message = "URI Too Long" })
end
end

-- TRACING: set KONG_WAITING_TIME start
local kong_wait_time_start = get_now()

Expand Down
3 changes: 2 additions & 1 deletion kong/plugins/aws-lambda/request-util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ local function aws_serializer(ctx, config)
end

-- query parameters
local queryStringParameters = ngx_req_get_uri_args()
local max_args = config and config.max_uri_args or nil
local queryStringParameters = ngx_req_get_uri_args(max_args)
local multiValueQueryStringParameters = {}
for qname, qvalue in pairs(queryStringParameters) do
if type(qvalue) == "table" then
Expand Down
11 changes: 11 additions & 0 deletions kong/plugins/aws-lambda/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ return {
default = "v1",
one_of = { "v1", "v2" }
} },
{ max_uri_args = {
description = "The maximum number of query string parameters to parse from the request URI. Nginx's default limit is 100.",
type = "integer",
default = 100,
between = { 1, 1000 },
} },
{ reject_if_max_uri_args_exceeded = {
description = "If enabled, the plugin returns a 414 URI Too Long response when the number of query string parameters exceeds max_uri_args, instead of forwarding the request to Lambda with truncated parameters.",
type = "boolean",
default = false,
} },
{ empty_arrays_mode = { -- TODO: this config field is added for backward compatibility and will be removed in next major version
description = "An optional value that defines whether Kong should send empty arrays (returned by Lambda function) as `[]` arrays or `{}` objects in JSON responses. The value `legacy` means Kong will send empty arrays as `{}` objects in response",
type = "string",
Expand Down
72 changes: 72 additions & 0 deletions spec/03-plugins/27-aws-lambda/02-schema_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,76 @@ describe("Plugin: AWS Lambda (schema)", function()
assert.is_nil(err)
assert.truthy(ok)
end)

describe("max_uri_args", function()
it("defaults to 100", function()
local ok, err = v({
aws_region = "us-east-1",
function_name = "my-function"
}, schema_def)

assert.is_nil(err)
assert.truthy(ok)
assert.equal(100, ok.config.max_uri_args)
end)

it("accepts a valid value", function()
local ok, err = v({
aws_region = "us-east-1",
function_name = "my-function",
max_uri_args = 1000,
}, schema_def)

assert.is_nil(err)
assert.truthy(ok)
assert.equal(1000, ok.config.max_uri_args)
end)

it("errors with a value less than 1", function()
local ok, err = v({
aws_region = "us-east-1",
function_name = "my-function",
max_uri_args = 0,
}, schema_def)

assert.equal("value should be between 1 and 1000", err.config.max_uri_args)
assert.falsy(ok)
end)

it("errors with a value greater than 1000", function()
local ok, err = v({
aws_region = "us-east-1",
function_name = "my-function",
max_uri_args = 1001,
}, schema_def)

assert.equal("value should be between 1 and 1000", err.config.max_uri_args)
assert.falsy(ok)
end)
end)

describe("reject_if_max_uri_args_exceeded", function()
it("defaults to false", function()
local ok, err = v({
aws_region = "us-east-1",
function_name = "my-function"
}, schema_def)

assert.is_nil(err)
assert.truthy(ok)
assert.is_false(ok.config.reject_if_max_uri_args_exceeded)
end)

it("accepts true", function()
local ok, err = v({
aws_region = "us-east-1",
function_name = "my-function",
reject_if_max_uri_args_exceeded = true,
}, schema_def)

assert.is_nil(err)
assert.truthy(ok)
assert.is_true(ok.config.reject_if_max_uri_args_exceeded)
end)
end)
end)
48 changes: 48 additions & 0 deletions spec/03-plugins/27-aws-lambda/05-aws-serializer_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,52 @@ describe("[AWS Lambda] aws-gateway input", function()
end
end

it("passes max_uri_args to ngx.req.get_uri_args", function()
local captured_max_args

mock_request = {
http_version = "1.1",
start_time = 1662436514,
headers = {
["user-agent"] = "curl/7.54.0",
},
query = {
foo = "bar",
},
body = "",
var = {
request_method = "GET",
upstream_uri = "/test?foo=bar",
kong_request_id = "1234567890",
host = "abc.myhost.test",
remote_addr = "123.123.123.123"
},
ctx = {
router_matches = {
uri = "/test"
},
},
}

-- patch get_uri_args to capture the argument
local orig_get_uri_args = _G.ngx.req.get_uri_args
_G.ngx.req.get_uri_args = function(max_args)
captured_max_args = max_args
return orig_get_uri_args()
end

reload_module()

aws_serialize(nil, { max_uri_args = 500 })
assert.equal(500, captured_max_args)

-- verify default (nil config) passes nil
captured_max_args = "not called"
aws_serialize()
assert.is_nil(captured_max_args)

-- restore
_G.ngx.req.get_uri_args = orig_get_uri_args
end)

end)
79 changes: 79 additions & 0 deletions spec/03-plugins/27-aws-lambda/99-access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ for _, strategy in helpers.each_strategy() do
service = null,
}

local route30 = bp.routes:insert {
hosts = { "lambda30.test" },
protocols = { "http", "https" },
service = null,
}

local route31 = bp.routes:insert {
hosts = { "lambda31.test" },
protocols = { "http", "https" },
service = null,
}

bp.plugins:insert {
name = "aws-lambda",
route = { id = route1.id },
Expand Down Expand Up @@ -603,6 +615,34 @@ for _, strategy in helpers.each_strategy() do
}
}

bp.plugins:insert {
name = "aws-lambda",
route = { id = route30.id },
config = {
port = 10001,
aws_key = "mock-key",
aws_secret = "mock-secret",
aws_region = "us-east-1",
function_name = "kongLambdaTest",
max_uri_args = 3,
reject_if_max_uri_args_exceeded = true,
}
}

bp.plugins:insert {
name = "aws-lambda",
route = { id = route31.id },
config = {
port = 10001,
aws_key = "mock-key",
aws_secret = "mock-secret",
aws_region = "us-east-1",
function_name = "kongLambdaTest",
max_uri_args = 3,
reject_if_max_uri_args_exceeded = false,
}
}

fixtures.dns_mock:A({
name = "custom.lambda.endpoint",
address = "127.0.0.1",
Expand Down Expand Up @@ -1344,6 +1384,45 @@ for _, strategy in helpers.each_strategy() do
assert.equals("https", req.vars.scheme)
end)

it("returns 414 when reject_if_max_uri_args_exceeded is true and args exceed max_uri_args", function()
-- route30 has max_uri_args=3, reject_if_max_uri_args_exceeded=true
local res = assert(proxy_client:send {
method = "GET",
path = "/get?a=1&b=2&c=3&d=4",
headers = {
["Host"] = "lambda30.test"
}
})
assert.res_status(414, res)
local body = assert.response(res).has.jsonbody()
assert.equal("URI Too Long", body.message)
end)

it("passes request through when reject_if_max_uri_args_exceeded is true and args are within limit", function()
-- route30 has max_uri_args=3, reject_if_max_uri_args_exceeded=true
local res = assert(proxy_client:send {
method = "GET",
path = "/get?a=1&b=2",
headers = {
["Host"] = "lambda30.test"
}
})
assert.res_status(200, res)
end)

it("does not return 414 when reject_if_max_uri_args_exceeded is false even if args exceed max_uri_args", function()
-- route31 has max_uri_args=3, reject_if_max_uri_args_exceeded=false
local res = assert(proxy_client:send {
method = "GET",
path = "/get?a=1&b=2&c=3&d=4",
headers = {
["Host"] = "lambda31.test"
}
})
-- should NOT be 414, should pass through to Lambda
assert.res_status(200, res)
end)

it("#test2 works normally by removing transfer encoding header when proxy integration mode", function ()
proxy_client:set_timeout(3000)
assert.eventually(function ()
Expand Down