From 2c5639bf05bae67d29e4c755b3b98ae3abd2ec6f Mon Sep 17 00:00:00 2001 From: dongjunduo Date: Mon, 10 Apr 2023 22:31:13 +0800 Subject: [PATCH] feat(cli): support bypassing Admin API Auth by configuration (#9147) --- apisix/admin/init.lua | 13 +++++++ apisix/cli/ops.lua | 7 ++++ apisix/cli/schema.lua | 3 ++ conf/config-default.yaml | 4 ++ t/admin/api.t | 80 ++++++++++++++++++++++++++++++++++++++++ t/cli/test_admin.sh | 56 ++++++++++++++++++++++++++++ 6 files changed, 163 insertions(+) diff --git a/apisix/admin/init.lua b/apisix/admin/init.lua index 072a584350ee..ccea011fe23d 100644 --- a/apisix/admin/init.lua +++ b/apisix/admin/init.lua @@ -67,6 +67,12 @@ local router local function check_token(ctx) local local_conf = core.config.local_conf() + + -- check if admin_key is required + if local_conf.deployment.admin.admin_key_required == false then + return true + end + local admin_key = core.table.try_read_attr(local_conf, "deployment", "admin", "admin_key") if not admin_key then return true @@ -395,6 +401,13 @@ function _M.init_worker() events.register(reload_plugins, reload_event, "PUT") if ngx_worker_id() == 0 then + -- check if admin_key is required + if local_conf.deployment.admin.admin_key_required == false then + core.log.warn("Admin key is bypassed! ", + "If you are deploying APISIX in a production environment, ", + "please disable `admin_key_required` and set a secure admin key!") + end + local ok, err = ngx_timer_at(0, function(premature) if premature then return diff --git a/apisix/cli/ops.lua b/apisix/cli/ops.lua index 5ce51dab3b32..ebd3061e0c12 100644 --- a/apisix/cli/ops.lua +++ b/apisix/cli/ops.lua @@ -189,6 +189,13 @@ local function init(env) and #allow_admin == 1 and allow_admin[1] == "127.0.0.0/24" then checked_admin_key = true end + -- check if admin_key is required + if yaml_conf.deployment.admin.admin_key_required == false then + checked_admin_key = true + print("Warning! Admin key is bypassed! " + .. "If you are deploying APISIX in a production environment, " + .. "please disable `admin_key_required` and set a secure admin key!") + end if yaml_conf.apisix.enable_admin and not checked_admin_key then local help = [[ diff --git a/apisix/cli/schema.lua b/apisix/cli/schema.lua index 477e2ce7e56d..56d7e2f630cc 100644 --- a/apisix/cli/schema.lua +++ b/apisix/cli/schema.lua @@ -353,6 +353,9 @@ local admin_schema = { https_admin = { type = "boolean", }, + admin_key_required = { + type = "boolean", + }, } } diff --git a/conf/config-default.yaml b/conf/config-default.yaml index 2765afe9c43f..d61f745afc9a 100755 --- a/conf/config-default.yaml +++ b/conf/config-default.yaml @@ -588,6 +588,10 @@ deployment: role_traditional: config_provider: etcd admin: + # Admin API authentication is enabled by default. + # Set it false in the production environment will cause a serious security issue. + # admin_key_required: true + # Default token when use API to call for Admin API. # *NOTE*: Highly recommended to modify this value to protect APISIX's Admin API. # Disabling this configuration item means that the Admin API does not diff --git a/t/admin/api.t b/t/admin/api.t index 67d7344b6998..982becc79e7a 100644 --- a/t/admin/api.t +++ b/t/admin/api.t @@ -156,3 +156,83 @@ X-API-VERSION: v2 GET /t --- response_body passed + + + +=== TEST 10: Access with api key, and admin_key_required=true +--- yaml_config +deployment: + admin: + admin_key_required: true +--- more_headers +X-API-KEY: edd1c9f034335f136f87ad84b625c8f1 +--- request +GET /apisix/admin/routes +--- error_code: 200 + + + +=== TEST 11: Access with wrong api key, and admin_key_required=true +--- yaml_config +deployment: + admin: + admin_key_required: true +--- more_headers +X-API-KEY: wrong-key +--- request +GET /apisix/admin/routes +--- error_code: 401 + + + +=== TEST 12: Access without api key, and admin_key_required=true +--- yaml_config +deployment: + admin: + admin_key_required: true +--- request +GET /apisix/admin/routes +--- error_code: 401 + + + +=== TEST 13: Access with api key, but admin_key_required=false +--- yaml_config +deployment: + admin: + admin_key_required: false +--- more_headers +X-API-KEY: edd1c9f034335f136f87ad84b625c8f1 +--- request +GET /apisix/admin/routes +--- error_code: 200 +--- error_log +Admin key is bypassed! + + + +=== TEST 14: Access with wrong api key, but admin_key_required=false +--- yaml_config +deployment: + admin: + admin_key_required: false +--- more_headers +X-API-KEY: wrong-key +--- request +GET /apisix/admin/routes +--- error_code: 200 +--- error_log +Admin key is bypassed! + + + +=== TEST 15: Access without api key, but admin_key_required=false +--- yaml_config +deployment: + admin: + admin_key_required: false +--- request +GET /apisix/admin/routes +--- error_code: 200 +--- error_log +Admin key is bypassed! diff --git a/t/cli/test_admin.sh b/t/cli/test_admin.sh index 6f39ffae170a..aad049728176 100755 --- a/t/cli/test_admin.sh +++ b/t/cli/test_admin.sh @@ -189,6 +189,62 @@ fi echo "pass: missing admin key and only allow 127.0.0.0/24 to access admin api" +# allow any IP to access admin api with empty admin_key, when admin_key_required=true + +git checkout conf/config.yaml + +echo ' +deployment: + admin: + admin_key_required: true + admin_key: ~ + allow_admin: + - 0.0.0.0/0 +' > conf/config.yaml + +make init > output.log 2>&1 | true + +if ! grep -E "ERROR: missing valid Admin API token." output.log > /dev/null; then + echo "failed: should show 'ERROR: missing valid Admin API token.'" + exit 1 +fi + +echo ' +deployment: + admin: + admin_key_required: false + admin_key: ~ + allow_admin: + - 0.0.0.0/0 +' > conf/config.yaml + +make init > output.log 2>&1 | true + +if grep -E "ERROR: missing valid Admin API token." output.log > /dev/null; then + echo "failed: should not show 'ERROR: missing valid Admin API token.'" + exit 1 +fi + +if ! grep -E "Warning! Admin key is bypassed" output.log > /dev/null; then + echo "failed: should show 'Warning! Admin key is bypassed'" + exit 1 +fi + +echo ' +deployment: + admin: + admin_key_required: invalid-value +' > conf/config.yaml + +make init > output.log 2>&1 | true + +if grep -E "path[deployment->admin->admin_key_required] expect: boolean, but got: string" output.log > /dev/null; then + echo "check admin_key_required value failed: should show 'expect: boolean, but got: string'" + exit 1 +fi + +echo "pass: allow empty admin_key, when admin_key_required=false" + # admin api, allow any IP but use default key echo '