diff --git a/apisix/admin/consumers.lua b/apisix/admin/consumers.lua index e02789069c64..d78800767c44 100644 --- a/apisix/admin/consumers.lua +++ b/apisix/admin/consumers.lua @@ -17,7 +17,7 @@ local core = require("apisix.core") local plugins = require("apisix.admin.plugins") local resource = require("apisix.admin.resource") - +local utils = require("apisix.admin.utils") local function check_conf(username, conf, need_username, schema) local ok, err = core.schema.check(schema, conf) @@ -30,10 +30,17 @@ local function check_conf(username, conf, need_username, schema) end if conf.plugins then + -- check_schema encrypts the key in the plugin. + -- check duplicate key require the original key. + local conf_plugins_copy = core.table.deepcopy(conf.plugins) ok, err = plugins.check_schema(conf.plugins, core.schema.TYPE_CONSUMER) if not ok then return nil, {error_msg = "invalid plugins configuration: " .. err} end + local ok, err = utils.check_duplicate_key(conf_plugins_copy, conf.username) + if not ok then + return nil, {error_msg = err} + end end if conf.group_id then diff --git a/apisix/admin/credentials.lua b/apisix/admin/credentials.lua index 3622867528d8..73e877d8b0e8 100644 --- a/apisix/admin/credentials.lua +++ b/apisix/admin/credentials.lua @@ -18,20 +18,29 @@ local core = require("apisix.core") local plugins = require("apisix.admin.plugins") local plugin = require("apisix.plugin") local resource = require("apisix.admin.resource") +local utils = require("apisix.admin.utils") 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} end if conf.plugins then + -- check_schema encrypts the key in the plugin. + -- check duplicate key require the original key. + local conf_plugins_copy = core.table.deepcopy(conf.plugins) ok, err = plugins.check_schema(conf.plugins, core.schema.TYPE_CONSUMER) if not ok then return nil, {error_msg = "invalid plugins configuration: " .. err} end + local ok, err = utils.check_duplicate_key(conf_plugins_copy, nil, id) + if not ok then + return nil, {error_msg = err} + end + for name, _ in pairs(conf.plugins) do local plugin_obj = plugin.get(name) if not plugin_obj then diff --git a/apisix/admin/utils.lua b/apisix/admin/utils.lua index eee2787f0540..594840a1075e 100644 --- a/apisix/admin/utils.lua +++ b/apisix/admin/utils.lua @@ -19,6 +19,8 @@ local ngx_time = ngx.time local tonumber = tonumber local ipairs = ipairs local pairs = pairs +local consumer = require("apisix.consumer") +local plugin = require("apisix.plugin") local _M = {} @@ -110,4 +112,51 @@ function _M.decrypt_params(decrypt_func, body, schema_type) end end + +local plugin_key_map = { + ["key-auth"] = "key", + ["basic-auth"] = "username", + ["jwt-auth"] = "key", + ["hmac-auth"] = "key_id" +} + + +function _M.check_duplicate_key(plugins_conf, username, credential_id) + if not plugins_conf then + return true + end + + for plugin_name, plugin_conf in pairs(plugins_conf) do + local plugin_obj = plugin.get(plugin_name) + if not plugin_obj then + return nil, "unknown plugin " .. plugin_name + end + + if plugin_obj.type ~= "auth" then + goto continue + end + + local key_field = plugin_key_map[plugin_name] + if not key_field then + goto continue + end + + local key_value = plugin_conf[key_field] + if not key_value then + goto continue + end + + local consumer = consumer.find_consumer(plugin_name, key_field, key_value) + if consumer and + ((username and consumer.username ~= username) or + (credential_id and consumer.credential_id ~= credential_id)) then + return nil, "duplicate key found with consumer: " .. consumer.username + end + + ::continue:: + end + + return true +end + return _M diff --git a/t/admin/consumers2.t b/t/admin/consumers2.t index 6e351d02be96..ac9adb04a6fc 100644 --- a/t/admin/consumers2.t +++ b/t/admin/consumers2.t @@ -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 diff --git a/t/admin/credentials.t b/t/admin/credentials.t index 15119829c2e3..6d15f9288cc7 100644 --- a/t/admin/credentials.t +++ b/t/admin/credentials.t @@ -110,7 +110,7 @@ passed "desc": "basic-auth for jack", "plugins": { "basic-auth": { - "username": "the-user", + "username": "the-new-user", "password": "the-password" } } @@ -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" }]] @@ -492,3 +492,99 @@ 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 diff --git a/t/secret/aws.t b/t/secret/aws.t index ae0e09b63398..c0d7266da762 100644 --- a/t/secret/aws.t +++ b/t/secret/aws.t @@ -314,3 +314,5 @@ GET /t } --- response_body all done +--- error_log +failed to fetch secret value: no secret conf, secret_uri: $secret://aws/mysecret/jack/key diff --git a/t/secret/gcp.t b/t/secret/gcp.t index b7fc5331cf37..dc28ab56ec65 100644 --- a/t/secret/gcp.t +++ b/t/secret/gcp.t @@ -247,6 +247,8 @@ kEJQcmfVew5mFXyxuEn3zA== } --- response_body all done +--- error_log +failed to fetch secret value: no secret conf, secret_uri: $secret://gcp/mysecret/jack/key diff --git a/t/secret/secret_lru.t b/t/secret/secret_lru.t index 3ff3386fcf15..9f320ae2883e 100644 --- a/t/secret/secret_lru.t +++ b/t/secret/secret_lru.t @@ -96,3 +96,5 @@ GET /t } --- response_body nil +--- error_log +failed to fetch secret value: no secret conf, secret_uri: $secret://vault/mysecret/jack/auth-key