From c6acb4f3be06446811edf2a3e671f8dfb8eb1ac1 Mon Sep 17 00:00:00 2001 From: Xiaoyan Rao <270668624@qq.com> Date: Sun, 29 Sep 2024 14:50:33 +0800 Subject: [PATCH] feat(gui): added a new feature to support proxy Admin API via `Gui`. --- kong.conf.default | 11 +++++++---- kong/admin_gui/init.lua | 9 --------- kong/init.lua | 16 ++++++++++++++++ kong/templates/nginx_kong.lua | 10 ++++++++++ kong/templates/nginx_kong_gui_include.lua | 19 +++++++++++++++++++ .../02-admin_gui_template_spec.lua | 8 -------- 6 files changed, 52 insertions(+), 21 deletions(-) diff --git a/kong.conf.default b/kong.conf.default index 447efb3c0a67..5e8a245a58cb 100644 --- a/kong.conf.default +++ b/kong.conf.default @@ -2034,10 +2034,13 @@ #admin_gui_api_url = # Hierarchical part of a URI which is composed # optionally of a host, port, and path at which the - # Admin API accepts HTTP or HTTPS traffic. When - # this config is disabled, Kong Manager will - # use the window protocol + host and append the - # resolved admin_listen HTTP/HTTPS port. + # Admin API accepts HTTP or HTTPS traffic. + # + # Examples: + # - http://localhost:8001 + # - http://127.0.0.1:8001 + # - https://admin.konghq.com:8444 + # - https://127.0.0.1:8444 #admin_gui_ssl_cert = # The SSL certificate for `admin_gui_listen` values # with SSL enabled. diff --git a/kong/admin_gui/init.lua b/kong/admin_gui/init.lua index f1c32500b620..352749a9ef6c 100644 --- a/kong/admin_gui/init.lua +++ b/kong/admin_gui/init.lua @@ -4,24 +4,15 @@ local fmt = string.format local insert = table.insert local concat = table.concat -local select_listener = utils.select_listener local prepare_variable = utils.prepare_variable local _M = {} function _M.generate_kconfig(kong_config) - local api_listen = select_listener(kong_config.admin_listeners, {ssl = false}) - local api_port = api_listen and api_listen.port - - local api_ssl_listen = select_listener(kong_config.admin_listeners, {ssl = true}) - local api_ssl_port = api_ssl_listen and api_ssl_listen.port - local configs = { ADMIN_GUI_URL = prepare_variable(kong_config.admin_gui_url), ADMIN_GUI_PATH = prepare_variable(kong_config.admin_gui_path), ADMIN_API_URL = prepare_variable(kong_config.admin_gui_api_url), - ADMIN_API_PORT = prepare_variable(api_port), - ADMIN_API_SSL_PORT = prepare_variable(api_ssl_port), ANONYMOUS_REPORTS = prepare_variable(kong_config.anonymous_reports), } diff --git a/kong/init.lua b/kong/init.lua index 70abad8b59c0..247413fa6929 100644 --- a/kong/init.lua +++ b/kong/init.lua @@ -77,6 +77,7 @@ local certificate = require "kong.runloop.certificate" local concurrency = require "kong.concurrency" local cache_warmup = require "kong.cache.warmup" local balancer = require "kong.runloop.balancer" +local utils = require "kong.admin_gui.utils" local kong_error_handlers = require "kong.error_handlers" local plugin_servers = require "kong.runloop.plugin_servers" local lmdb_txn = require "resty.lmdb.transaction" @@ -124,6 +125,7 @@ local set_current_peer = ngx_balancer.set_current_peer local set_timeouts = ngx_balancer.set_timeouts local set_more_tries = ngx_balancer.set_more_tries local enable_keepalive = ngx_balancer.enable_keepalive +local select_listener = utils.select_listener local time_ns = kong_time.time_ns @@ -1938,6 +1940,20 @@ function Kong.admin_gui_kconfig_content() end end +function Kong.admin_gui_api_balancer() + local admin_listeners = kong.configuration.admin_listeners + local listener = select_listener(admin_listeners, { ssl = true }) + if not listener then + listener = select_listener(admin_listeners, { ssl = false }) + end + + local ok, err = set_current_peer(listener.ip, listener.port) + if not ok then + ngx.log(ngx.ERR, "failed to set the Admin Api balancer: ", err) + return ngx.exit(500) + end +end + function Kong.admin_gui_log() if kong.configuration.anonymous_reports then reports.admin_gui_log(ngx.ctx) diff --git a/kong/templates/nginx_kong.lua b/kong/templates/nginx_kong.lua index 184ba9370c16..da5ac917ba0a 100644 --- a/kong/templates/nginx_kong.lua +++ b/kong/templates/nginx_kong.lua @@ -84,6 +84,16 @@ upstream kong_upstream { } } +> if (role == "control_plane" or role == "traditional") and #admin_listeners > 0 then +upstream kong_admin_gui_api { + server 0.0.0.1; + + balancer_by_lua_block { + Kong.admin_gui_api_balancer() + } +} +> end + server { server_name kong; > for _, entry in ipairs(proxy_listeners) do diff --git a/kong/templates/nginx_kong_gui_include.lua b/kong/templates/nginx_kong_gui_include.lua index 28f44a5fc626..644d7ce02dfb 100644 --- a/kong/templates/nginx_kong_gui_include.lua +++ b/kong/templates/nginx_kong_gui_include.lua @@ -23,6 +23,25 @@ location = $(admin_gui_path_prefix)/kconfig.js { } } +> if (role == "control_plane" or role == "traditional") and #admin_listeners > 0 then +location ~* $(admin_gui_path_prefix)/gateway/api { + set_by_lua_block $backend { + local utils = require "kong.admin_gui.utils" + local listener = utils.select_listener(kong.configuration.admin_listeners, { ssl = true }) + if listener then + return "https://kong_admin_gui_api" + else + return "http://kong_admin_gui_api" + end + } + rewrite ^$(admin_gui_path_prefix)/gateway/api(/.*)$ $1 break; + proxy_pass $backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +} +> end + location = $(admin_gui_path_prefix)/favicon.ico { root gui; diff --git a/spec/01-unit/29-admin_gui/02-admin_gui_template_spec.lua b/spec/01-unit/29-admin_gui/02-admin_gui_template_spec.lua index de4c337fda36..0e644f708f47 100644 --- a/spec/01-unit/29-admin_gui/02-admin_gui_template_spec.lua +++ b/spec/01-unit/29-admin_gui/02-admin_gui_template_spec.lua @@ -67,8 +67,6 @@ describe("admin_gui template", function() assert.matches("'ADMIN_GUI_URL': 'http://0.0.0.0:8002'", kconfig_content, nil, true) assert.matches("'ADMIN_GUI_PATH': '/manager'", kconfig_content, nil, true) assert.matches("'ADMIN_API_URL': 'https://admin-reference.kong-cloud.test'", kconfig_content, nil, true) - assert.matches("'ADMIN_API_PORT': '8001'", kconfig_content, nil, true) - assert.matches("'ADMIN_API_SSL_PORT': '8444'", kconfig_content, nil, true) end) it("should regenerates the appropriate kconfig from another call", function() @@ -86,8 +84,6 @@ describe("admin_gui template", function() assert.matches("'ADMIN_GUI_URL': 'http://admin-test.example.com'", new_content, nil, true) assert.matches("'ADMIN_GUI_PATH': '/manager'", new_content, nil, true) assert.matches("'ADMIN_API_URL': 'http://localhost:8001'", new_content, nil, true) - assert.matches("'ADMIN_API_PORT': '8001'", new_content, nil, true) - assert.matches("'ADMIN_API_SSL_PORT': '8444'", new_content, nil, true) end) end) @@ -148,8 +144,6 @@ describe("admin_gui template", function() assert.matches("'ADMIN_GUI_URL': 'http://0.0.0.0:8002'", kconfig_content, nil, true) assert.matches("'ADMIN_API_URL': '0.0.0.0:8001'", kconfig_content, nil, true) - assert.matches("'ADMIN_API_PORT': '8001'", kconfig_content, nil, true) - assert.matches("'ADMIN_API_SSL_PORT': '8444'", kconfig_content, nil, true) assert.matches("'ANONYMOUS_REPORTS': 'false'", kconfig_content, nil, true) end) @@ -166,8 +160,6 @@ describe("admin_gui template", function() -- test configuration values against template assert.matches("'ADMIN_GUI_URL': 'http://admin-test.example.com'", new_content, nil, true) assert.matches("'ADMIN_API_URL': '0.0.0.0:8001'", new_content, nil, true) - assert.matches("'ADMIN_API_PORT': '8001'", new_content, nil, true) - assert.matches("'ADMIN_API_SSL_PORT': '8444'", new_content, nil, true) assert.matches("'ANONYMOUS_REPORTS': 'true'", new_content, nil, true) end) end)