Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: consumer key duplication check #12040

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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
46 changes: 44 additions & 2 deletions apisix/admin/consumers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
local core = require("apisix.core")
local plugins = require("apisix.admin.plugins")
local resource = require("apisix.admin.resource")

local plugin = require("apisix.plugin")
local pairs = pairs
local consumer = require("apisix.consumer")

local function check_conf(username, conf, need_username, schema)
local ok, err = core.schema.check(schema, conf)
Expand All @@ -32,7 +34,47 @@ local function check_conf(username, conf, need_username, schema)
if conf.plugins then
ok, err = plugins.check_schema(conf.plugins, core.schema.TYPE_CONSUMER)
if not ok then
return nil, {error_msg = "invalid plugins configuration: " .. err}
return nil, {
error_msg = "invalid plugins configuration: " .. err
}
end

-- check duplicate key
for plugin_name, plugin_conf in pairs(conf.plugins or {}) do
local plugin_obj = plugin.get(plugin_name)
if not plugin_obj then
return nil, {error_msg = "unknown plugin " .. plugin_name}
end

if plugin_obj.type == "auth" then
local decrypted_conf = core.table.deepcopy(plugin_conf)
plugin.decrypt_conf(plugin_name, decrypted_conf, core.schema.TYPE_CONSUMER)

local plugin_key_map = {
["key-auth"] = "key",
["basic-auth"] = "username",
["jwt-auth"] = "key",
["hmac-auth"] = "key_id"
}

local key_field = plugin_key_map[plugin_name]

if key_field then
local key_value = decrypted_conf[key_field]

if key_value then
local consumer, _ = consumer
.find_consumer(plugin_name, key_field, key_value)

if consumer and consumer.username ~= conf.username then
return nil, {
error_msg = "duplicate key found with consumer: "
.. consumer.username
}
end
end
end
end
end
end

Expand Down
35 changes: 33 additions & 2 deletions apisix/admin/credentials.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ local core = require("apisix.core")
local plugins = require("apisix.admin.plugins")
local plugin = require("apisix.plugin")
local resource = require("apisix.admin.resource")
local consumer = require("apisix.consumer")
local pairs = pairs

local function check_conf(_id, conf, _need_id, schema)
local function check_conf(id, conf, _need_id, schema)
local ok, err = core.schema.check(schema, conf)
if not ok then
return nil, {error_msg = "invalid configuration: " .. err}
Expand All @@ -32,14 +33,44 @@ local function check_conf(_id, conf, _need_id, schema)
return nil, {error_msg = "invalid plugins configuration: " .. err}
end

for name, _ in pairs(conf.plugins) do
for name, plugin_conf in pairs(conf.plugins) do
local plugin_obj = plugin.get(name)
if not plugin_obj then
return nil, {error_msg = "unknown plugin " .. name}
end

if plugin_obj.type ~= "auth" then
return nil, {error_msg = "only supports auth type plugins in consumer credential"}
end

-- check duplicate key
local decrypted_conf = core.table.deepcopy(plugin_conf)
plugin.decrypt_conf(name, decrypted_conf, core.schema.TYPE_CONSUMER)

local plugin_key_map = {
["key-auth"] = "key",
["basic-auth"] = "username",
["jwt-auth"] = "key",
["hmac-auth"] = "key_id"
}

local key_field = plugin_key_map[name]
if key_field then
local key_value = decrypted_conf[key_field]

if key_value then
local consumer, _ = consumer
.find_consumer(name, key_field, key_value)

if consumer and consumer.credential_id ~= id then
return nil, {
error_msg = "duplicate key found with consumer: "
.. consumer.username
}
end
end
end

end
end

Expand Down
83 changes: 83 additions & 0 deletions t/admin/consumers2.t
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,86 @@ __DATA__
}
--- response_body
{"error_msg":"wrong username"}



=== TEST 6: create consumer
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers',
ngx.HTTP_PUT,
[[{
"username": "jack",
"desc": "key-auth for jack",
"plugins": {
"key-auth": {
"key": "the-key"
}
}
}]]
)
}
}
--- request
GET /t



=== TEST 7: duplicate consumer key, PUT
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers',
ngx.HTTP_PUT,
[[{
"username": "jack2",
"desc": "key-auth for jack2",
"plugins": {
"key-auth": {
"key": "the-key"
}
}
}]]
)

ngx.status = code
ngx.print(body)
}
}
--- request
GET /t
--- error_code: 400
--- response_body
{"error_msg":"duplicate key found with consumer: jack"}



=== TEST 8: update consumer jack
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers',
ngx.HTTP_PUT,
[[{
"username": "jack",
"desc": "key-auth for jack",
"plugins": {
"key-auth": {
"key": "the-key"
}
}
}]]
)

ngx.status = code
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
139 changes: 137 additions & 2 deletions t/admin/credentials.t
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ passed
"desc": "basic-auth for jack",
"plugins": {
"basic-auth": {
"username": "the-user",
"username": "the-new-user",
"password": "the-password"
}
}
Expand All @@ -119,7 +119,7 @@ passed
"value":{
"desc":"basic-auth for jack",
"id":"credential_a",
"plugins":{"basic-auth":{"username":"the-user","password":"WvF5kpaLvIzjuk4GNIMTJg=="}}
"plugins":{"basic-auth":{"username":"the-new-user","password":"WvF5kpaLvIzjuk4GNIMTJg=="}}
},
"key":"/apisix/consumers/jack/credentials/credential_a"
}]]
Expand Down Expand Up @@ -492,3 +492,138 @@ GET /t
--- error_code: 400
--- response_body
{"error_msg":"missing credential id"}



=== TEST 17: create a consumer bar
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers', ngx.HTTP_PUT, [[{ "username": "bar" }]])
}
}
--- request
GET /t



=== TEST 18: create a credential with key-auth for the consumer bar
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers/bar/credentials/credential_c',
ngx.HTTP_PUT,
[[{
"desc": "key-auth for bar",
"plugins": {
"key-auth": {
"key": "the-key-bar"
}
}
}]]
)
}
}
--- request
GET /t



=== TEST 19: can not create a credential with duplicate key
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers/bar/credentials/credential_d',
ngx.HTTP_PUT,
[[{
"desc": "key-auth for bar",
"plugins": {
"key-auth": {
"key": "the-key-bar"
}
}
}]]
)

ngx.status = code
ngx.print(body)
}
}
--- request
GET /t
--- error_code: 400
--- response_body
{"error_msg":"duplicate key found with consumer: bar"}



=== TEST 20: can update credential credential_c with same key
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test

-- update desc, keep same key
local code, body = t('/apisix/admin/consumers/bar/credentials/credential_c',
ngx.HTTP_PUT,
[[{
"desc": "new description",
"plugins": {
"key-auth": {
"key": "the-key-bar"
}
}
}]]
)

ngx.status = code
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
--- error_code: 200



=== TEST 21: delete credential credential_c
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers/bar/credentials/credential_c', ngx.HTTP_DELETE)
}
}
--- request
GET /t



=== TEST 22: delete consumer bar
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers/bar', ngx.HTTP_DELETE)
}
}
--- request
GET /t



=== TEST 23: delete consumer jack
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/consumers/jack', ngx.HTTP_DELETE)
}
}
--- request
GET /t
Loading