Skip to content

Commit 1538517

Browse files
nowNickkevwilliams
authored andcommitted
fix(admin): reject AdminAPI call with empty tags (#13723)
(cherry picked from commit d1069e6)
1 parent 36a6a3d commit 1538517

File tree

7 files changed

+70
-5
lines changed

7 files changed

+70
-5
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
message: Fix for querying admin API entities with empty tags
2+
type: bugfix
3+
scope: Admin API

kong/api/endpoints.lua

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ local function handle_error(err_t)
137137
end
138138

139139

140-
local function extract_options(args, schema, context)
140+
local function extract_options(db, args, schema, context)
141141
local options = {
142142
nulls = true,
143143
pagination = {
@@ -156,6 +156,11 @@ local function extract_options(args, schema, context)
156156
end
157157

158158
if schema.fields.tags and args.tags ~= nil and context == "page" then
159+
if args.tags == null or #args.tags == 0 then
160+
local error_message = "cannot be null"
161+
return nil, error_message, db[schema.name].errors:invalid_options({tags = error_message})
162+
end
163+
159164
local tags = args.tags
160165
if type(tags) == "table" then
161166
tags = tags[1]
@@ -207,7 +212,11 @@ local function query_entity(context, self, db, schema, method)
207212
args = self.args.uri
208213
end
209214

210-
local opts = extract_options(args, schema, context)
215+
local opts, err, err_t = extract_options(db, args, schema, context)
216+
if err then
217+
return nil, err, err_t
218+
end
219+
211220
local schema_name = schema.name
212221
local dao = db[schema_name]
213222

kong/api/routes/consumers.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ return {
2020

2121
-- Search by custom_id: /consumers?custom_id=xxx
2222
if custom_id then
23-
local opts = endpoints.extract_options(args, db.consumers.schema, "select")
23+
local opts, _, err_t = endpoints.extract_options(db, args, db.consumers.schema, "select")
24+
if err_t then
25+
return endpoints.handle_error(err_t)
26+
end
27+
2428
local consumer, _, err_t = db.consumers:select_by_custom_id(custom_id, opts)
2529
if err_t then
2630
return endpoints.handle_error(err_t)

kong/api/routes/upstreams.lua

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ local function set_target_health(self, db, is_healthy)
2525
target, _, err_t = endpoints.select_entity(self, db, db.targets.schema)
2626

2727
else
28-
local opts = endpoints.extract_options(self.args.uri, db.targets.schema, "select")
28+
local opts
29+
opts, _, err_t = endpoints.extract_options(db, self.args.uri, db.targets.schema, "select")
30+
if err_t then
31+
return endpoints.handle_error(err_t)
32+
end
33+
2934
local upstream_pk = db.upstreams.schema:extract_pk_values(upstream)
3035
local filter = { target = unescape_uri(self.params.targets) }
3136
target, _, err_t = db.targets:select_by_upstream_filter(upstream_pk, filter, opts)
@@ -94,7 +99,11 @@ local function target_endpoint(self, db, callback)
9499
target, _, err_t = endpoints.select_entity(self, db, db.targets.schema)
95100

96101
else
97-
local opts = endpoints.extract_options(self.args.uri, db.targets.schema, "select")
102+
local opts
103+
opts, _, err_t = endpoints.extract_options(db, self.args.uri, db.targets.schema, "select")
104+
if err_t then
105+
return endpoints.handle_error(err_t)
106+
end
98107
local upstream_pk = db.upstreams.schema:extract_pk_values(upstream)
99108
local filter = { target = unescape_uri(self.params.targets) }
100109
target, _, err_t = db.targets:select_by_upstream_filter(upstream_pk, filter, opts)

spec/02-integration/04-admin_api/03-consumers_routes_spec.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,16 @@ describe("Admin API (#" .. strategy .. "): ", function()
282282
local body = assert.response(res).has.status(200)
283283
assert.match('"data":%[%]', body)
284284
end)
285+
it("returns bad request for empty tags", function()
286+
local res = assert(client:send {
287+
method = "GET",
288+
path = "/consumers",
289+
query = { tags = ngx.null}
290+
})
291+
res = assert.res_status(400, res)
292+
local json = cjson.decode(res)
293+
assert.same("invalid option (tags: cannot be null)", json.message)
294+
end)
285295
end)
286296
it("returns 405 on invalid method", function()
287297
local methods = {"DELETE", "PATCH"}

spec/02-integration/04-admin_api/07-upstreams_routes_spec.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,16 @@ describe("Admin API: #" .. strategy, function()
637637
})
638638
assert.res_status(200, res)
639639
end)
640+
it("returns bad request for empty tags", function()
641+
local res = assert(client:send {
642+
method = "GET",
643+
path = "/upstreams",
644+
query = { tags = ngx.null}
645+
})
646+
res = assert.res_status(400, res)
647+
local json = cjson.decode(res)
648+
assert.same("invalid option (tags: cannot be null)", json.message)
649+
end)
640650

641651
describe("empty results", function()
642652
lazy_setup(function()

spec/02-integration/04-admin_api/14-tags_spec.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ describe("Admin API - tags", function()
7373
end
7474
end)
7575

76+
it("filter by empty tag", function()
77+
local res = assert(client:send {
78+
method = "GET",
79+
path = "/consumers?tags="
80+
})
81+
local body = assert.res_status(400, res)
82+
local json = cjson.decode(body)
83+
assert.same("invalid option (tags: cannot be null)", json.message)
84+
end)
85+
86+
it("filter by empty string tag", function()
87+
local res = assert(client:send {
88+
method = "GET",
89+
path = "/consumers?tags=''"
90+
})
91+
local body = assert.res_status(200, res)
92+
local json = cjson.decode(body)
93+
assert.equals(0, #json.data)
94+
end)
95+
7696
it("filter by multiple tags with AND", function()
7797
local res = assert(client:send {
7898
method = "GET",

0 commit comments

Comments
 (0)