local default_nginx_template = require "kong.templates.nginx" local kong_nginx_template = require "kong.templates.nginx_kong" local kong_nginx_gui_include_template = require "kong.templates.nginx_kong_gui_include" local kong_nginx_stream_template = require "kong.templates.nginx_kong_stream" local nginx_main_inject_template = require "kong.templates.nginx_inject" local nginx_http_inject_template = require "kong.templates.nginx_kong_inject" local nginx_stream_inject_template = require "kong.templates.nginx_kong_stream_inject" local wasmtime_cache_template = require "kong.templates.wasmtime_cache_config" local system_constants = require "lua_system_constants" local process_secrets = require "kong.cmd.utils.process_secrets" local openssl_bignum = require "resty.openssl.bn" local openssl_rand = require "resty.openssl.rand" local openssl_pkey = require "resty.openssl.pkey" local x509 = require "resty.openssl.x509" local x509_extension = require "resty.openssl.x509.extension" local x509_name = require "resty.openssl.x509.name" local pl_template = require "pl.template" local pl_tablex = require "pl.tablex" local pl_utils = require "pl.utils" local pl_file = require "pl.file" local pl_path = require "pl.path" local pl_dir = require "pl.dir" local log = require "kong.cmd.utils.log" local ffi = require "ffi" local bit = require "bit" local nginx_signals = require "kong.cmd.utils.nginx_signals" local admin_gui_utils = require "kong.admin_gui.utils" local strip = require("kong.tools.string").strip local isplitn = require("kong.tools.string").isplitn local shallow_copy = require("kong.tools.table").shallow_copy local getmetatable = getmetatable local makepath = pl_dir.makepath local tonumber = tonumber local tostring = tostring local assert = assert local string = string local exists = pl_path.exists local ipairs = ipairs local pairs = pairs local table = table local type = type local math = math local join = pl_path.join local io = io local os = os local fmt = string.format local function pre_create_private_file(file) local flags = bit.bor(system_constants.O_RDONLY(), system_constants.O_CREAT()) local mode = ffi.new("int", bit.bor(system_constants.S_IRUSR(), system_constants.S_IWUSR())) local fd = ffi.C.open(file, flags, mode) if fd == -1 then log.warn("unable to pre-create '%s' file: %s", file, ffi.string(ffi.C.strerror(ffi.errno()))) else ffi.C.close(fd) end end local function gen_default_dhparams(kong_config) for _, name in ipairs({ kong_config.nginx_http_ssl_dhparam, kong_config.nginx_stream_ssl_dhparam }) do local pem if name then pem = openssl_pkey.paramgen({ type = "DH", group = name, }) end if pem then local ssl_path = join(kong_config.prefix, "ssl") if not exists(ssl_path) then local ok, err = makepath(ssl_path) if not ok then return nil, err end end local param_file = join(ssl_path, name .. ".pem") if not exists(param_file) then log.verbose("generating %s DH parameters", name) local fd = assert(io.open(param_file, "w+b")) assert(fd:write(pem)) fd:close() end end end return true end local function gen_default_ssl_cert(kong_config, target) -- create SSL folder local ok, err = makepath(join(kong_config.prefix, "ssl")) if not ok then return nil, err end for _, suffix in ipairs({ "", "_ecdsa" }) do local ssl_cert, ssl_cert_key if target == "admin" then ssl_cert = kong_config["admin_ssl_cert_default" .. suffix] ssl_cert_key = kong_config["admin_ssl_cert_key_default" .. suffix] elseif target == "admin_gui" then ssl_cert = kong_config["admin_gui_ssl_cert_default" .. suffix] ssl_cert_key = kong_config["admin_gui_ssl_cert_key_default" .. suffix] elseif target == "status" then ssl_cert = kong_config["status_ssl_cert_default" .. suffix] ssl_cert_key = kong_config["status_ssl_cert_key_default" .. suffix] else ssl_cert = kong_config["ssl_cert_default" .. suffix] ssl_cert_key = kong_config["ssl_cert_key_default" .. suffix] end if not exists(ssl_cert) and not exists(ssl_cert_key) then log.verbose("generating %s SSL certificate (%s) and key (%s) for listener", target or "proxy", ssl_cert, ssl_cert_key) local key if suffix == "_ecdsa" then key = openssl_pkey.new { type = "EC", curve = "prime256v1" } else key = openssl_pkey.new { bits = 2048 } end local crt = x509.new() assert(crt:set_pubkey(key)) assert(crt:set_version(3)) assert(crt:set_serial_number(openssl_bignum.from_binary(openssl_rand.bytes(16)))) -- last for 20 years local now = os.time() assert(crt:set_not_before(now)) assert(crt:set_not_after(now + 86400 * 20 * 365)) local name = assert(x509_name.new() :add("C", "US") :add("ST", "California") :add("L", "San Francisco") :add("O", "Kong") :add("OU", "IT Department") :add("CN", "localhost")) assert(crt:set_subject_name(name)) assert(crt:set_issuer_name(name)) -- Not a CA assert(crt:set_basic_constraints { CA = false }) assert(crt:set_basic_constraints_critical(true)) -- Only allowed to be used for TLS connections (client or server) assert(crt:add_extension(x509_extension.new("extendedKeyUsage", "serverAuth,clientAuth"))) -- RFC-3280 4.2.1.2 assert(crt:add_extension(x509_extension.new("subjectKeyIdentifier", "hash", { subject = crt }))) -- All done; sign assert(crt:sign(key)) do -- write key out pre_create_private_file(ssl_cert_key) local fd = assert(io.open(ssl_cert_key, "w+b")) local pem = assert(key:to_PEM("private")) assert(fd:write(pem)) fd:close() end do -- write cert out local fd = assert(io.open(ssl_cert, "w+b")) local pem = assert(crt:to_PEM()) assert(fd:write(pem)) fd:close() end else log.verbose("%s SSL certificate found at %s", target or "default", ssl_cert) end end return true end local function write_ssl_cert(path, ssl_cert) local fd = assert(io.open(path, "w+b")) assert(fd:write(ssl_cert)) fd:close() end local function write_ssl_cert_key(path, ssl_cert_key) pre_create_private_file(path) local fd = assert(io.open(path, "w+b")) assert(fd:write(ssl_cert_key)) fd:close() end local function gen_trusted_certs_combined_file(combined_filepath, paths) log.verbose("generating trusted certs combined file in %s", combined_filepath) local fd = assert(io.open(combined_filepath, "w")) for _, path in ipairs(paths) do fd:write(assert(pl_file.read(path))) fd:write("\n") end io.close(fd) end local function get_ulimit() local ok, _, stdout, stderr = pl_utils.executeex "ulimit -n" if not ok then return nil, stderr end local sanitized_limit = strip(stdout) if sanitized_limit:lower():match("unlimited") then return 65536 else return tonumber(sanitized_limit) end end local function quote(s) return fmt("%q", s) end local function compile_conf(kong_config, conf_template, template_env_inject) -- computed config properties for templating local compile_env = { _escape = ">", pairs = pairs, ipairs = ipairs, tostring = tostring, os = { getenv = os.getenv, }, quote = quote, } local kong_proxy_access_log = kong_config.proxy_access_log if kong_proxy_access_log ~= "off" then compile_env.proxy_access_log_enabled = true end if kong_proxy_access_log then -- example: proxy_access_log = 'logs/some-file.log apigw_json' local _, custom_format_name = string.match(kong_proxy_access_log, "^(%S+)%s(%S+)") if custom_format_name then compile_env.custom_proxy_access_log = true end end compile_env = pl_tablex.merge(compile_env, template_env_inject or {}, true) do local worker_rlimit_nofile_auto if kong_config.nginx_main_directives then for _, directive in ipairs(kong_config.nginx_main_directives) do if directive.name == "worker_rlimit_nofile" then if directive.value == "auto" then worker_rlimit_nofile_auto = directive end break end end end local worker_connections_auto if kong_config.nginx_events_directives then for _, directive in ipairs(kong_config.nginx_events_directives) do if directive.name == "worker_connections" then if directive.value == "auto" then worker_connections_auto = directive end break end end end if worker_connections_auto or worker_rlimit_nofile_auto then local value, err = get_ulimit() if not value then return nil, err end value = math.min(value, 16384) value = math.max(value, 1024) if worker_rlimit_nofile_auto then worker_rlimit_nofile_auto.value = value end if worker_connections_auto then worker_connections_auto.value = value end end end compile_env = pl_tablex.merge(compile_env, kong_config, true) -- union compile_env.dns_resolver = table.concat(compile_env.dns_resolver or {}, " ") compile_env.lua_package_path = (compile_env.lua_package_path or "") .. ";" .. (os.getenv("LUA_PATH") or "") compile_env.lua_package_cpath = (compile_env.lua_package_cpath or "") .. ";" .. (os.getenv("LUA_CPATH") or "") local post_template, err = pl_template.substitute(conf_template, compile_env) if not post_template then return nil, "failed to compile nginx config template: " .. err end -- the second value(the count) should not be returned return (string.gsub(post_template, "(${%b{}})", function(w) local name = w:sub(4, -3) return compile_env[name:lower()] or "" end)) end local function write_env_file(path, data) os.remove(path) local flags = bit.bor(system_constants.O_CREAT(), system_constants.O_WRONLY()) local mode = ffi.new("int", bit.bor(system_constants.S_IRUSR(), system_constants.S_IWUSR(), system_constants.S_IRGRP())) local fd = ffi.C.open(path, flags, mode) if fd < 0 then local errno = ffi.errno() return nil, "unable to open env path " .. path .. " (" .. ffi.string(ffi.C.strerror(errno)) .. ")" end local ok = ffi.C.close(fd) if ok ~= 0 then local errno = ffi.errno() return nil, "failed to close fd (" .. ffi.string(ffi.C.strerror(errno)) .. ")" end local file, err = io.open(path, "w+") if not file then return nil, "unable to open env path " .. path .. " (" .. err .. ")" end local ok, err = file:write(data) file:close() if not ok then return nil, "unable to write env path " .. path .. " (" .. err .. ")" end return true end local function write_process_secrets_file(kong_conf, data) local path = kong_conf.kong_process_secrets local function write_single_secret_file(path, data) os.remove(path) local flags = bit.bor(system_constants.O_RDONLY(), system_constants.O_CREAT()) local mode = ffi.new("int", bit.bor(system_constants.S_IRUSR(), system_constants.S_IWUSR())) local fd = ffi.C.open(path, flags, mode) if fd < 0 then local errno = ffi.errno() return nil, "unable to open process secrets path " .. path .. " (" .. ffi.string(ffi.C.strerror(errno)) .. ")" end local ok = ffi.C.close(fd) if ok ~= 0 then local errno = ffi.errno() return nil, "failed to close fd (" .. ffi.string(ffi.C.strerror(errno)) .. ")" end local file, err = io.open(path, "w+b") if not file then return nil, "unable to open process secrets path " .. path .. " (" .. err .. ")" end local ok, err = file:write(data) file:close() if not ok then return nil, "unable to write process secrets path " .. path .. " (" .. err .. ")" end return true end if kong_conf.role == "control_plane" or #kong_conf.proxy_listeners > 0 or #kong_conf.admin_listeners > 0 or #kong_conf.status_listeners > 0 then local ok, err = write_single_secret_file(path .. "_http", data) if not ok then return nil, err end end if #kong_conf.stream_listeners > 0 then local ok, err = write_single_secret_file(path .. "_stream", data) if not ok then return nil, err end end return true end local function compile_kong_conf(kong_config, template_env_inject) return compile_conf(kong_config, kong_nginx_template, template_env_inject) end local function compile_kong_gui_include_conf(kong_config) -- Build connect-src in the CSP header -- Other parts are defined inside nginx_kong_gui_include.lua local csp_connect_src if kong_config.admin_gui_csp_header then -- TODO: Try bundling buttons.js with frontend assets instead of loading it from a URL csp_connect_src = { "'self'", "https://api.github.com/repos/kong/kong" } if kong_config.admin_gui_api_url then table.insert(csp_connect_src, kong_config.admin_gui_api_url) else -- If admin_gui_api_url is missing, we will add dynamic sources that echoes the requested host -- with ports defined in admin_listeners corresponding to the scheme local api_listen = admin_gui_utils.select_listener(kong_config.admin_listeners, { ssl = false }) local api_port = api_listen and api_listen.port if api_port then table.insert(csp_connect_src, "http://$host:" .. api_port) end local api_ssl_listen = admin_gui_utils.select_listener(kong_config.admin_listeners, { ssl = true }) local api_ssl_port = api_ssl_listen and api_ssl_listen.port if api_ssl_port then table.insert(csp_connect_src, "https://$host:" .. api_ssl_port) end end csp_connect_src = table.concat(csp_connect_src, " ") end return compile_conf(kong_config, kong_nginx_gui_include_template, { admin_gui_csp_connect_src = csp_connect_src, }) end local function compile_kong_stream_conf(kong_config, template_env_inject) return compile_conf(kong_config, kong_nginx_stream_template, template_env_inject) end local function compile_nginx_conf(kong_config, template) template = template or default_nginx_template return compile_conf(kong_config, template) end local function compile_wasmtime_cache_conf(kong_config) return compile_conf(kong_config, wasmtime_cache_template) end local function prepare_prefixed_interface_dir(usr_path, interface_dir, kong_config) local usr_interface_path = usr_path .. "/" .. interface_dir local interface_path = kong_config.prefix .. "/" .. interface_dir -- if the interface directory is not exist in custom prefix directory -- try symlinking to the default prefix location -- ensure user can access the interface appliation if not pl_path.exists(interface_path) and pl_path.exists(usr_interface_path) then local ln_cmd = "ln -s " .. usr_interface_path .. " " .. interface_path local ok, _, _, err_t = pl_utils.executeex(ln_cmd) if not ok then log.warn(err_t) end end end local function compile_nginx_main_inject_conf(kong_config) return compile_conf(kong_config, nginx_main_inject_template) end local function compile_nginx_http_inject_conf(kong_config) return compile_conf(kong_config, nginx_http_inject_template) end local function compile_nginx_stream_inject_conf(kong_config) return compile_conf(kong_config, nginx_stream_inject_template) end local function compile_kong_test_inject_conf(kong_config, template, template_env) return compile_conf(kong_config, template, template_env) end local function prepare_prefix(kong_config, nginx_custom_template_path, skip_write, write_process_secrets, nginx_conf_flags) log.verbose("preparing nginx prefix directory at %s", kong_config.prefix) if not exists(kong_config.prefix) then log("prefix directory %s not found, trying to create it", kong_config.prefix) local ok, err = makepath(kong_config.prefix) if not ok then return nil, err end elseif not pl_path.isdir(kong_config.prefix) then return nil, kong_config.prefix .. " is not a directory" end if not exists(kong_config.socket_path) then local ok, err = makepath(kong_config.socket_path) if not ok then return nil, err end local ok, _, _, stderr = pl_utils.executeex("chmod 755 " .. kong_config.socket_path) if not ok then return nil, "can not set correct permissions for socket path: " .. kong_config.socket_path .. " (" .. stderr .. ")" end end -- create directories in prefix for _, dir in ipairs {"logs", "pids"} do local ok, err = makepath(join(kong_config.prefix, dir)) if not ok then return nil, err end end -- create log files in case they don't already exist if not exists(kong_config.nginx_err_logs) then local ok, err = pl_file.write(kong_config.nginx_err_logs, "") if not ok then return nil, err end end if not exists(kong_config.nginx_acc_logs) then local ok, err = pl_file.write(kong_config.nginx_acc_logs, "") if not ok then return nil, err end end if not exists(kong_config.admin_acc_logs) then local ok, err = pl_file.write(kong_config.admin_acc_logs, "") if not ok then return nil, err end end -- generate default SSL certs if needed do for _, target in ipairs({ "proxy", "admin", "admin_gui", "status" }) do local ssl_enabled = kong_config[target .. "_ssl_enabled"] if not ssl_enabled and target == "proxy" then ssl_enabled = kong_config.stream_proxy_ssl_enabled end local prefix if target == "proxy" then prefix = "" else prefix = target .. "_" end local ssl_cert = kong_config[prefix .. "ssl_cert"] local ssl_cert_key = kong_config[prefix .. "ssl_cert_key"] if ssl_enabled and #ssl_cert == 0 and #ssl_cert_key == 0 then log.verbose("SSL enabled on %s, no custom certificate set: using default certificates", target) local ok, err = gen_default_ssl_cert(kong_config, target) if not ok then return nil, err end ssl_cert[1] = kong_config[prefix .. "ssl_cert_default"] ssl_cert_key[1] = kong_config[prefix .. "ssl_cert_key_default"] ssl_cert[2] = kong_config[prefix .. "ssl_cert_default_ecdsa"] ssl_cert_key[2] = kong_config[prefix .. "ssl_cert_key_default_ecdsa"] end end end -- create certs files and assign paths when they are passed as content do local function set_dhparam_path(path) if kong_config["nginx_http_ssl_dhparam"] then kong_config["nginx_http_ssl_dhparam"] = path end if kong_config["nginx_stream_ssl_dhparam"] then kong_config["nginx_stream_ssl_dhparam"] = path end for _, directive in ipairs(kong_config["nginx_http_directives"]) do if directive.name == "ssl_dhparam" and directive.value then directive.value = path end end for _, directive in ipairs(kong_config["nginx_stream_directives"]) do if directive.name == "ssl_dhparam" and directive.value then directive.value = path end end end local function is_predefined_dhgroup(group) if type(group) ~= "string" then return false end return not not openssl_pkey.paramgen({ type = "DH", group = group, }) end -- ensure the property value is a "content" (not a path), -- write the content to a file and set the path in the configuration local function write_content_set_path( contents, format, write_func, ssl_path, target, config_key ) if type(contents) == "string" then if not exists(contents) then if not exists(ssl_path) then makepath(ssl_path) end local path = join(ssl_path, target .. format) write_func(path, contents) kong_config[config_key] = path if target == "ssl-dhparam" then set_dhparam_path(path) end end elseif type(contents) == "table" then for i, content in ipairs(contents) do if not exists(content) then if not exists(ssl_path) then makepath(ssl_path) end local path = join(ssl_path, target .. "-" .. i .. format) write_func(path, content) contents[i] = path end end end end local ssl_path = join(kong_config.prefix, "ssl") for _, target in ipairs({ "proxy", "admin", "admin_gui", "status", "client", "cluster", "lua-ssl-trusted", "cluster-ca" }) do local cert_name local key_name local ssl_cert local ssl_key if target == "proxy" then cert_name = "ssl_cert" key_name = "ssl_cert_key" elseif target == "cluster" then cert_name = target .. "_cert" key_name = target .. "_cert_key" elseif target == "cluster-ca" then cert_name = "cluster_ca_cert" elseif target == "lua-ssl-trusted" then cert_name = "lua_ssl_trusted_certificate" else cert_name = target .. "_ssl_cert" key_name = target .. "_ssl_cert_key" end ssl_cert = cert_name and kong_config[cert_name] ssl_key = key_name and kong_config[key_name] if ssl_cert and #ssl_cert > 0 then write_content_set_path(ssl_cert, ".crt", write_ssl_cert, ssl_path, target, cert_name) end if ssl_key and #ssl_key > 0 then write_content_set_path(ssl_key, ".key", write_ssl_cert_key, ssl_path, target, key_name) end end local dhparam_value = kong_config["ssl_dhparam"] if dhparam_value and not is_predefined_dhgroup(dhparam_value) then write_content_set_path(dhparam_value, ".pem", write_ssl_cert, ssl_path, "ssl-dhparam", "ssl_dhparam") end end if kong_config.lua_ssl_trusted_certificate_combined then gen_trusted_certs_combined_file( kong_config.lua_ssl_trusted_certificate_combined, kong_config.lua_ssl_trusted_certificate ) end -- check ulimit local ulimit, err = get_ulimit() if not ulimit then return nil, err elseif ulimit < 4096 then log.warn([[ulimit is currently set to "%d". For better performance set it]] .. [[ to at least "4096" using "ulimit -n"]], ulimit) end if skip_write then return true end if kong_config.wasm then if kong_config.wasmtime_cache_directory then local ok, err = makepath(kong_config.wasmtime_cache_directory) if not ok then return nil, err end end if kong_config.wasmtime_cache_config_file then local wasmtime_conf, err = compile_wasmtime_cache_conf(kong_config) if not wasmtime_conf then return nil, err end pl_file.write(kong_config.wasmtime_cache_config_file, wasmtime_conf) end end -- compile Nginx configurations local nginx_template if nginx_custom_template_path then if not exists(nginx_custom_template_path) then return nil, "no such file: " .. nginx_custom_template_path end local read_err nginx_template, read_err = pl_file.read(nginx_custom_template_path) if not nginx_template then read_err = tostring(read_err or "unknown error") return nil, "failed reading custom nginx template file: " .. read_err end end if kong_config.proxy_ssl_enabled or kong_config.stream_proxy_ssl_enabled or kong_config.admin_ssl_enabled or kong_config.admin_gui_ssl_enabled or kong_config.status_ssl_enabled then gen_default_dhparams(kong_config) end local template_env = {} for flag in isplitn(nginx_conf_flags, ",") do template_env[strip(flag)] = true end local nginx_conf, err = compile_nginx_conf(kong_config, nginx_template) if not nginx_conf then return nil, err end pl_file.write(kong_config.nginx_conf, nginx_conf) -- write Kong's GUI include NGINX conf local nginx_kong_gui_include_conf, err = compile_kong_gui_include_conf(kong_config) if not nginx_kong_gui_include_conf then return nil, err end pl_file.write(kong_config.nginx_kong_gui_include_conf, nginx_kong_gui_include_conf) -- write Kong's HTTP NGINX conf local nginx_kong_conf, err = compile_kong_conf(kong_config, template_env) if not nginx_kong_conf then return nil, err end pl_file.write(kong_config.nginx_kong_conf, nginx_kong_conf) -- write Kong's stream NGINX conf local nginx_kong_stream_conf, err = compile_kong_stream_conf(kong_config, template_env) if not nginx_kong_stream_conf then return nil, err end pl_file.write(kong_config.nginx_kong_stream_conf, nginx_kong_stream_conf) -- write NGINX MAIN inject conf local nginx_main_inject_conf, err = compile_nginx_main_inject_conf(kong_config) if not nginx_main_inject_conf then return nil, err end pl_file.write(kong_config.nginx_inject_conf, nginx_main_inject_conf) -- write NGINX HTTP inject conf local nginx_http_inject_conf, err = compile_nginx_http_inject_conf(kong_config) if not nginx_http_inject_conf then return nil, err end pl_file.write(kong_config.nginx_kong_inject_conf, nginx_http_inject_conf) -- write NGINX STREAM inject conf local nginx_stream_inject_conf, err = compile_nginx_stream_inject_conf(kong_config) if not nginx_stream_inject_conf then return nil, err end pl_file.write(kong_config.nginx_kong_stream_inject_conf, nginx_stream_inject_conf) -- write Kong's test injected configuration files (*.test.conf) -- these are included in the Kong's HTTP NGINX conf by the test template local test_template_inj_path = "spec/fixtures/template_inject/" if pl_path.isdir(test_template_inj_path) then for _, file in ipairs(pl_dir.getfiles(test_template_inj_path, "*.lua")) do local t_path = pl_path.splitext(file) local t_module = string.gsub(t_path, "/", ".") local nginx_kong_test_inject_conf, err = compile_kong_test_inject_conf( kong_config, require(t_module), template_env ) if not nginx_kong_test_inject_conf then return nil, err end local t_name = pl_path.basename(t_path) local output_path = kong_config.prefix .. "/" .. t_name .. ".test.conf" pl_file.write(output_path, nginx_kong_test_inject_conf) end end -- testing written NGINX conf local ok, err = nginx_signals.check_conf(kong_config) if not ok then return nil, err end -- write kong.conf in prefix (for workers and CLI) local buf = { "# *************************", "# * DO NOT EDIT THIS FILE *", "# *************************", "# This configuration file is auto-generated. If you want to modify", "# the Kong configuration please edit/create the original `kong.conf`", "# file. Any modifications made here will be lost.", "# Start Kong with `--vv` to show where it is looking for that file.", "", } local function quote_hash(s) return s:gsub("#", "\\#") end local refs = kong_config["$refs"] local has_refs = refs and type(refs) == "table" local secrets = process_secrets.extract(kong_config) for k, v in pairs(kong_config) do -- do not output secrets in .kong_env if has_refs and refs[k] then local ref = refs[k] if type(ref) == "table" then if type(v) ~= "table" then v = { v } else v = shallow_copy(v) end for i, r in pairs(ref) do v[i] = r end elseif ref then v = ref end end if type(v) == "table" then 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 .. " = " .. quote_hash(tostring(v)) end end local env = table.concat(buf, "\n") .. "\n" local ok, err = write_env_file(kong_config.kong_env, env) if not ok then return nil, err end if kong_config.admin_gui_listeners then prepare_prefixed_interface_dir("/usr/local/kong", "gui", kong_config) end if secrets and write_process_secrets then secrets, err = process_secrets.serialize(secrets, kong_config.kong_env) if not secrets then return nil, err end ok, err = write_process_secrets_file(kong_config, secrets) if not ok then return nil, err end elseif not write_process_secrets then os.remove(kong_config.kong_process_secrets) end return true end return { get_ulimit = get_ulimit, prepare_prefix = prepare_prefix, prepare_prefixed_interface_dir = prepare_prefixed_interface_dir, compile_conf = compile_conf, compile_kong_conf = compile_kong_conf, compile_kong_gui_include_conf = compile_kong_gui_include_conf, compile_kong_stream_conf = compile_kong_stream_conf, compile_nginx_conf = compile_nginx_conf, compile_nginx_main_inject_conf = compile_nginx_main_inject_conf, compile_nginx_http_inject_conf = compile_nginx_http_inject_conf, compile_nginx_stream_inject_conf = compile_nginx_stream_inject_conf, gen_default_ssl_cert = gen_default_ssl_cert, write_env_file = write_env_file, }