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(config) add control- and data-plane configuration #3147

Closed
wants to merge 1 commit into from
Closed
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
90 changes: 37 additions & 53 deletions kong.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -72,25 +72,31 @@
# NGINX
#------------------------------------------------------------------------------

#proxy_listen = 0.0.0.0:8000 # Address and port on which Kong will accept
# HTTP requests.
# This is the public-facing entrypoint of
# Kong, to which your consumers will make
# requests.
#proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssl
# Comma-separated list of addresses and ports on
# which the proxy server should listen to. The proxy
# server is the public entrypoint of Kong, which
# proxies traffic from your consumers. The `ssl`
# suffix requires that all connections through this
# port be made through SSL, and `http2` allows for
# HTTP/2 connections. And finally the `proxy_protocol`
# flag is allowed.
# If set to `off` the proxy will be disabled.
# Note: See http://nginx.org/en/docs/http/ngx_http_core_module.html#listen for
# a description of the accepted formats for this and other *_listen values.
#
# See https://www.nginx.com/resources/admin-guide/proxy-protocol/ for more
# details about the `proxy_protocol` parameter.

#proxy_listen_ssl = 0.0.0.0:8443 # Address and port on which Kong will accept
# HTTPS requests if `ssl` is enabled.

#admin_listen = 127.0.0.1:8001 # Address and port on which Kong will expose
# an entrypoint to the Admin API.
# This API lets you configure and manage Kong,
# and should be kept private and secured.

#admin_listen_ssl = 127.0.0.1:8444 # Address and port on which Kong will
# accept HTTPS requests to the admin API,
# if `admin_ssl` is enabled.
#admin_listen = 127.0.0.1:8000, 127.0.0.1:8443 ssl
# Comma-separated list of addresses and ports on
# which the admin interface is listening.
# This API lets you configure and manage Kong,
# and should be kept private and secured.
# The `ssl` suffix requires that all connections
# through this port be made through SSL, and `http2`
# allows for HTTP/2 connections.
# If set to `off` the Admin API will be disabled.

#nginx_user = nobody nobody # Defines user and group credentials used by
# worker processes. If group is omitted, a
Expand All @@ -110,12 +116,6 @@
# `m`, with a minimum recommended value of
# a few MBs.

#ssl = on # Determines if Nginx should be listening for
# HTTPS traffic on the `proxy_listen_ssl`
# address. If disabled, Nginx will only bind
# itself on `proxy_listen`, and all SSL
# settings will be ignored.

#ssl_cipher_suite = modern # Defines the TLS ciphers served by Nginx.
# Accepted values are `modern`, `intermediate`,
# `old`, or `custom`.
Expand All @@ -128,16 +128,13 @@
# This value is ignored if `ssl_cipher_suite`
# is not `custom`.

#ssl_cert = # If `ssl` is enabled, the absolute path to
#ssl_cert = # If ssl is enabled, the absolute path to
# the SSL certificate for the
# `proxy_listen_ssl` address.

#ssl_cert_key = # If `ssl` is enabled, the absolute path to
# the SSL key for the `proxy_listen_ssl`
# address.
# `proxy_listen` ssl addresses.

#http2 = off # Enables HTTP2 support for HTTPS traffic on
# the `proxy_listen_ssl` address.
#ssl_cert_key = # If ssl is enabled, the absolute path to
# the SSL key for the `proxy_listen` ssl
# addresses.

#client_ssl = off # Determines if Nginx should send client-side
# SSL certificates when proxying requests.
Expand All @@ -156,22 +153,13 @@
# and currently cannot be configured on a
# per-API basis.

#admin_ssl = on # Determines if Nginx should be listening for
# HTTPS traffic on the `admin_listen_ssl`
# address. If disabled, Nginx will only bind
# itself on `admin_listen`, and all SSL
# settings will be ignored.
#admin_ssl_cert = # If ssl is enabled on the admin interface,
# the absolute path to the SSL certificate
# for the `admin_listen` addresses.

#admin_ssl_cert = # If `admin_ssl` is enabled, the absolute path
# to the SSL certificate for the
# `admin_listen_ssl` address.

#admin_ssl_cert_key = # If `admin_ssl` is enabled, the absolute path
# to the SSL key for the `admin_listen_ssl`
# address.

#admin_http2 = off # Enables HTTP2 support for HTTPS traffic on
# the `admin_listen_ssl` address.
#admin_ssl_cert_key = # If ssl is enabled on the admin interface,
# the absolute path to the SSL key for the
# `admin_listen` addresses.

#upstream_keepalive = 60 # Sets the maximum number of idle keepalive
# connections to upstream servers that are
Expand Down Expand Up @@ -216,18 +204,13 @@
# This value sets the ngx_http_realip_module
# directive of the same name in the Nginx
# configuration.
#
# If this value receives `proxy_protocol`, the
# `proxy_protocol` parameter will be appended
# to the `listen` directive of the Nginx
# template.
# If set to `proxy_protocol` then at least one
# of the `proxy_listen` entries should have
# the `proxy_protocol` flag enabled.
# Note:
#
# See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
# for a description of this directive.
#
# See https://www.nginx.com/resources/admin-guide/proxy-protocol/ for more
# details about the `proxy_protocol` parameter.

#real_ip_recursive = off # This value sets the ngx_http_realip_module
# directive of the same name in the Nginx
Expand Down Expand Up @@ -492,3 +475,4 @@
#lua_socket_pool_size = 30 # Specifies the size limit for every cosocket
# connection pool associated with every remote
# server

19 changes: 11 additions & 8 deletions kong/cmd/utils/prefix_handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ local function get_ulimit()
end
end

local function gather_system_infos(compile_env)
local function gather_system_infos()
local infos = {}

local ulimit, err = get_ulimit()
Expand Down Expand Up @@ -110,10 +110,6 @@ local function compile_conf(kong_config, conf_template)
compile_env = pl_tablex.merge(compile_env, kong_config, true) -- union
compile_env.dns_resolver = table.concat(compile_env.dns_resolver, " ")

compile_env.http2 = kong_config.http2 and " http2" or ""
compile_env.admin_http2 = kong_config.admin_http2 and " http2" or ""
compile_env.proxy_protocol = kong_config.real_ip_header == "proxy_protocol" and " proxy_protocol" or ""

local post_template = pl_template.substitute(conf_template, compile_env)
return string.gsub(post_template, "(${%b{}})", function(w)
local name = w:sub(4, -3)
Expand Down Expand Up @@ -202,7 +198,8 @@ local function prepare_prefix(kong_config, nginx_custom_template_path)
end

-- generate default SSL certs if needed
if kong_config.ssl and not kong_config.ssl_cert and not kong_config.ssl_cert_key then
if kong_config.proxy_ssl_enabled and not kong_config.ssl_cert and
not kong_config.ssl_cert_key then
log.verbose("SSL enabled, no custom certificate set: using default certificate")
local ok, err = gen_default_ssl_cert(kong_config)
if not ok then
Expand All @@ -211,7 +208,8 @@ local function prepare_prefix(kong_config, nginx_custom_template_path)
kong_config.ssl_cert = kong_config.ssl_cert_default
kong_config.ssl_cert_key = kong_config.ssl_cert_key_default
end
if kong_config.admin_ssl and not kong_config.admin_ssl_cert and not kong_config.admin_ssl_cert_key then
if kong_config.admin_ssl_enabled and not kong_config.admin_ssl_cert and
not kong_config.admin_ssl_cert_key then
log.verbose("Admin SSL enabled, no custom certificate set: using default certificate")
local ok, err = gen_default_ssl_cert(kong_config, true)
if not ok then
Expand Down Expand Up @@ -266,7 +264,12 @@ local function prepare_prefix(kong_config, nginx_custom_template_path)

for k, v in pairs(kong_config) do
if type(v) == "table" then
v = table.concat(v, ",")
if (getmetatable(v) or {}).__tostring then
-- the 'tostring' meta-method knows how to serialize
v = tostring(v)
else
v = table.concat(v, ",")
end
end
if v ~= "" then
buf[#buf+1] = k .. " = " .. tostring(v)
Expand Down
145 changes: 117 additions & 28 deletions kong/conf_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ local PREFIX_PATHS = {
-- `array`: a comma-separated list
local CONF_INFERENCES = {
-- forced string inferences (or else are retrieved as numbers)
proxy_listen = {typ = "string"},
proxy_listen_ssl = {typ = "string"},
admin_listen = {typ = "string"},
admin_listen_ssl = {typ = "string"},
proxy_listen = {typ = "array"},
admin_listen = {typ = "array"},
db_update_frequency = { typ = "number" },
db_update_propagation = { typ = "number" },
db_cache_ttl = { typ = "number" },
Expand Down Expand Up @@ -102,11 +100,7 @@ local CONF_INFERENCES = {
dns_error_ttl = {typ = "number"},
dns_no_sync = {typ = "boolean"},

http2 = {typ = "boolean"},
admin_http2 = {typ = "boolean"},
ssl = {typ = "boolean"},
client_ssl = {typ = "boolean"},
admin_ssl = {typ = "boolean"},

proxy_access_log = {typ = "string"},
proxy_error_log = {typ = "string"},
Expand Down Expand Up @@ -230,7 +224,7 @@ local function check_and_infer(conf)
end
end

if conf.ssl then
if (table.concat(conf.proxy_listen, ",") .. " "):find("%sssl[%s,]") then
if conf.ssl_cert and not conf.ssl_cert_key then
errors[#errors+1] = "ssl_cert_key must be specified"
elseif conf.ssl_cert_key and not conf.ssl_cert then
Expand Down Expand Up @@ -260,7 +254,7 @@ local function check_and_infer(conf)
end
end

if conf.admin_ssl then
if (table.concat(conf.admin_listen, ",") .. " "):find("%sssl[%s,]") then
if conf.admin_ssl_cert and not conf.admin_ssl_cert_key then
errors[#errors+1] = "admin_ssl_cert_key must be specified"
elseif conf.admin_ssl_cert_key and not conf.admin_ssl_cert then
Expand Down Expand Up @@ -357,6 +351,85 @@ local function overrides(k, default_v, file_conf, arg_conf)
return value, k
end

-- @param value The options string to check for flags (whitespace separated)
-- @param flags List of boolean flags to check for.
-- @returns 1) remainder string after all flags removed, 2) table with flag
-- booleans, 3) sanitized flags string
local function parse_option_flags(value, flags)
assert(type(value) == "string")

value = " " .. value .. " "

local sanitized = ""
local result = { }

for _, flag in ipairs(flags) do
local count
local patt = "%s" .. flag .. "%s"

value, count = value:gsub(patt, " ")

if count > 0 then
result[flag] = true
sanitized = sanitized .. " " .. flag

else
result[flag] = false
end
end

return pl_stringx.strip(value), result, pl_stringx.strip(sanitized)
end

-- Parses a listener address line.
-- Supports multiple (comma separated) addresses, with 'ssl' and 'http2' flags.
-- Pre- and postfixed whitespace as well as comma's are allowed.
-- "off" as a first entry will return empty tables.
-- @value list of entries (strings)
-- @return list of parsed entries, each entry having fields `ip` (normalized string)
-- `port` (number), `ssl` (bool), `http2` (bool), `listener` (string, full listener)
local function parse_listeners(values)
local list = {}
local flags = { "ssl", "http2", "proxy_protocol" }
local usage = "must be of form: [off] | <ip>:<port> [" ..
table.concat(flags, "] [") .. "], [... next entry ...]"

if pl_stringx.strip(values[1]) == "off" then
return list
end

for _, entry in ipairs(values) do
-- parse the flags
local remainder, listener, cleaned_flags = parse_option_flags(entry, flags)

-- verify IP for remainder
local ip

if utils.hostname_type(remainder) == "name" then
-- it's not an IP address, so a name/wildcard/regex
ip = {}
ip.host, ip.port = remainder:match("(.+):([%d]+)$")

else
-- It's an IPv4 or IPv6, just normalize it
ip = utils.normalize_ip(remainder)
end

if not ip or not ip.port then
return nil, usage
end

listener.ip = ip.host
listener.port = ip.port
listener.listener = ip.host .. ":" .. ip.port ..
(#cleaned_flags == 0 and "" or " " .. cleaned_flags)

table.insert(list, listener)
end

return list
end

--- Load Kong configuration
-- The loaded configuration will have all properties from the default config
-- merged with the (optionally) specified config file, environment variables
Expand Down Expand Up @@ -478,24 +551,40 @@ local function load(path, custom_conf)

-- extract ports/listen ips
do
local ip_port_pat = "(.+):([%d]+)$"
local admin_ip, admin_port = string.match(conf.admin_listen, ip_port_pat)
local admin_ssl_ip, admin_ssl_port = string.match(conf.admin_listen_ssl, ip_port_pat)
local proxy_ip, proxy_port = string.match(conf.proxy_listen, ip_port_pat)
local proxy_ssl_ip, proxy_ssl_port = string.match(conf.proxy_listen_ssl, ip_port_pat)

if not admin_port then return nil, "admin_listen must be of form 'address:port'"
elseif not admin_ssl_port then return nil, "admin_listen_ssl must be of form 'address:port'"
elseif not proxy_port then return nil, "proxy_listen must be of form 'address:port'"
elseif not proxy_ssl_port then return nil, "proxy_listen_ssl must be of form 'address:port'" end
conf.admin_ip = admin_ip
conf.admin_ssl_ip = admin_ssl_ip
conf.proxy_ip = proxy_ip
conf.proxy_ssl_ip = proxy_ssl_ip
conf.admin_port = tonumber(admin_port)
conf.admin_ssl_port = tonumber(admin_ssl_port)
conf.proxy_port = tonumber(proxy_port)
conf.proxy_ssl_port = tonumber(proxy_ssl_port)
local err
-- this meta table will prevent the parsed table to be passed on in the
-- intermediate Kong config file in the prefix directory
local mt = { __tostring = function() return "" end }

conf.proxy_listeners, err = parse_listeners(conf.proxy_listen)
if err then
return nil, "proxy_listen " .. err
end

setmetatable(conf.proxy_listeners, mt) -- do not pass on, parse again
conf.proxy_ssl_enabled = false

for _, listener in ipairs(conf.proxy_listeners) do
if listener.ssl == true then
conf.proxy_ssl_enabled = true
break
end
end

conf.admin_listeners, err = parse_listeners(conf.admin_listen)
if err then
return nil, "admin_listen " .. err
end

setmetatable(conf.admin_listeners, mt) -- do not pass on, parse again
conf.admin_ssl_enabled = false

for _, listener in ipairs(conf.admin_listeners) do
if listener.ssl == true then
conf.admin_ssl_enabled = true
break
end
end
end

-- load absolute paths
Expand Down
Loading