Skip to content

Commit

Permalink
feat(conf) allow *_cert and *_cert_key to be stored in environment va…
Browse files Browse the repository at this point in the history
…riables and vaults

### Summary

Allow several `kong.conf` values to be stored in vaults or environment variables:

- `ssl_cert`
- `ssl_cert_key`
- `admin_ssl_cert`
- `admin_ssl_cert_key`
- `status_ssl_cert`
- `status_ssl_cert_key`
- `cluster_cert`
- `cluster_cert_key`
- `client_ssl_cert`
- `client_ssl_cert_key`

#### Usage

The following is possible after this is commit is merged:

```bash
CERT=$(<cert.crt)                  \ # normal environment variable intialized from file
KONG_SSL_CERT="{vault://env/cert}" \ # a secret reference using env vault
KONG_SSL_CERT_KEY="$(<cert.key)"   \ # reading content of file to env var
kong start
```
  • Loading branch information
bungle committed Aug 19, 2022
1 parent 3379a89 commit 1c17b18
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 37 deletions.
63 changes: 48 additions & 15 deletions kong/cmd/utils/prefix_handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ local nginx_signals = require "kong.cmd.utils.nginx_signals"


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

Expand Down Expand Up @@ -65,16 +68,16 @@ local function gen_default_dhparams(kong_config)
end

if pem then
local ssl_path = pl_path.join(kong_config.prefix, "ssl")
if not pl_path.exists(ssl_path) then
local ok, err = pl_dir.makepath(ssl_path)
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 = pl_path.join(ssl_path, name .. ".pem")
if not pl_path.exists(param_file) then
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))
Expand All @@ -89,7 +92,7 @@ end

local function gen_default_ssl_cert(kong_config, target)
-- create SSL folder
local ok, err = pl_dir.makepath(pl_path.join(kong_config.prefix, "ssl"))
local ok, err = makepath(join(kong_config.prefix, "ssl"))
if not ok then
return nil, err
end
Expand All @@ -109,7 +112,7 @@ local function gen_default_ssl_cert(kong_config, target)
ssl_cert_key = kong_config["ssl_cert_key_default" .. suffix]
end

if not pl_path.exists(ssl_cert) and not pl_path.exists(ssl_cert_key) then
if not exists(ssl_cert) and not exists(ssl_cert_key) then
log.verbose("generating %s SSL certificate (", ssl_cert, ") and key (", ssl_cert_key, ") for ", target or "proxy", " listener")

local key
Expand Down Expand Up @@ -180,8 +183,22 @@ local function gen_default_ssl_cert(kong_config, target)
end


local function gen_trusted_certs_combined_file(combined_filepath, paths)
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 ",
combined_filepath)

Expand Down Expand Up @@ -376,9 +393,9 @@ end
local function prepare_prefix(kong_config, nginx_custom_template_path, skip_write, write_process_secrets)
log.verbose("preparing nginx prefix directory at %s", kong_config.prefix)

if not pl_path.exists(kong_config.prefix) then
if not exists(kong_config.prefix) then
log("prefix directory %s not found, trying to create it", kong_config.prefix)
local ok, err = pl_dir.makepath(kong_config.prefix)
local ok, err = makepath(kong_config.prefix)
if not ok then
return nil, err
end
Expand All @@ -388,26 +405,26 @@ local function prepare_prefix(kong_config, nginx_custom_template_path, skip_writ

-- create directories in prefix
for _, dir in ipairs {"logs", "pids"} do
local ok, err = pl_dir.makepath(pl_path.join(kong_config.prefix, dir))
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 pl_path.exists(kong_config.nginx_err_logs) then
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 pl_path.exists(kong_config.nginx_acc_logs) then
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 pl_path.exists(kong_config.admin_acc_logs) then
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
Expand Down Expand Up @@ -443,6 +460,22 @@ local function prepare_prefix(kong_config, nginx_custom_template_path, skip_writ
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"]

else
local ssl_path = join(kong_config.prefix, "ssl")
makepath(ssl_path)

for i, cert in ipairs(ssl_cert) do
local path = join(ssl_path, target .. "-" .. i .. ".crt")
write_ssl_cert(path, cert)
ssl_cert[i] = path
end

for i, cert_key in ipairs(ssl_cert_key) do
local path = join(ssl_path, target .. "-" .. i .. ".key")
write_ssl_cert_key(path, cert_key)
ssl_cert_key[i] = path
end
end
end
end
Expand All @@ -469,7 +502,7 @@ local function prepare_prefix(kong_config, nginx_custom_template_path, skip_writ
-- compile Nginx configurations
local nginx_template
if nginx_custom_template_path then
if not pl_path.exists(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
Expand Down
70 changes: 48 additions & 22 deletions kong/conf_loader/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ local require = require
local kong_default_conf = require "kong.templates.kong_defaults"
local process_secrets = require "kong.cmd.utils.process_secrets"
local openssl_pkey = require "resty.openssl.pkey"
local openssl_x509 = require "resty.openssl.x509"
local pl_stringio = require "pl.stringio"
local pl_stringx = require "pl.stringx"
local constants = require "kong.constants"
Expand Down Expand Up @@ -749,37 +750,51 @@ local function check_and_infer(conf, opts)
if ssl_cert then
for _, cert in ipairs(ssl_cert) do
if not exists(cert) then
errors[#errors + 1] = prefix .. "ssl_cert: no such file at " .. cert
local _, err = openssl_x509.new(cert)
if err then
errors[#errors + 1] = prefix .. "ssl_cert: no such file at " .. cert
end
end
end
end

if ssl_cert_key then
for _, cert_key in ipairs(ssl_cert_key) do
if not exists(cert_key) then
errors[#errors + 1] = prefix .. "ssl_cert_key: no such file at " .. cert_key
local _, err = openssl_pkey.new(cert_key)
if err then
errors[#errors + 1] = prefix .. "ssl_cert_key: no such file at " .. cert_key
end
end
end
end
end
end

if conf.client_ssl then
if conf.client_ssl_cert and not conf.client_ssl_cert_key then
local client_ssl_cert = conf.client_ssl_cert
local client_ssl_cert_key = conf.client_ssl_cert_key

if client_ssl_cert and not client_ssl_cert_key then
errors[#errors + 1] = "client_ssl_cert_key must be specified"

elseif conf.client_ssl_cert_key and not conf.client_ssl_cert then
elseif client_ssl_cert_key and not client_ssl_cert then
errors[#errors + 1] = "client_ssl_cert must be specified"
end

if conf.client_ssl_cert and not exists(conf.client_ssl_cert) then
errors[#errors + 1] = "client_ssl_cert: no such file at " ..
conf.client_ssl_cert
if client_ssl_cert and not exists(client_ssl_cert) then
local _, err = openssl_x509.new(client_ssl_cert)
if err then
errors[#errors + 1] = "client_ssl_cert: no such file at " .. client_ssl_cert
end
end

if conf.client_ssl_cert_key and not exists(conf.client_ssl_cert_key) then
errors[#errors + 1] = "client_ssl_cert_key: no such file at " ..
conf.client_ssl_cert_key
if client_ssl_cert_key and not exists(client_ssl_cert_key) then
local _, err = openssl_pkey.new(client_ssl_cert_key)
if err then
errors[#errors + 1] = "client_ssl_cert_key: no such file at " ..
client_ssl_cert_key
end
end
end

Expand Down Expand Up @@ -988,18 +1003,25 @@ local function check_and_infer(conf, opts)
end

if conf.role == "control_plane" or conf.role == "data_plane" then
if not conf.cluster_cert or not conf.cluster_cert_key then
local cluster_cert = conf.cluster_cert
local cluster_cert_key = conf.cluster_cert_key

if not cluster_cert or not cluster_cert_key then
errors[#errors + 1] = "cluster certificate and key must be provided to use Hybrid mode"

else
if not exists(conf.cluster_cert) then
errors[#errors + 1] = "cluster_cert: no such file at " ..
conf.cluster_cert
if not exists(cluster_cert) then
local _, err = openssl_x509.new(cluster_cert)
if err then
errors[#errors + 1] = "cluster_cert: no such file at " .. cluster_cert
end
end

if not exists(conf.cluster_cert_key) then
errors[#errors + 1] = "cluster_cert_key: no such file at " ..
conf.cluster_cert_key
if not exists(cluster_cert_key) then
local _, err = openssl_pkey.new(cluster_cert_key)
if err then
errors[#errors + 1] = "cluster_cert_key: no such file at " .. cluster_cert_key
end
end
end
end
Expand Down Expand Up @@ -1690,19 +1712,23 @@ local function load(path, custom_conf, opts)
if ssl_cert and ssl_cert_key then
if type(ssl_cert) == "table" then
for i, cert in ipairs(ssl_cert) do
ssl_cert[i] = abspath(cert)
if exists(ssl_cert[i]) then
ssl_cert[i] = abspath(cert)
end
end

else
elseif exists(ssl_cert) then
conf[prefix .. "_cert"] = abspath(ssl_cert)
end

if type(ssl_cert) == "table" then
if type(ssl_cert_key) == "table" then
for i, key in ipairs(ssl_cert_key) do
ssl_cert_key[i] = abspath(key)
if exists(ssl_cert_key[i]) then
ssl_cert_key[i] = abspath(key)
end
end

else
elseif exists(ssl_cert_key) then
conf[prefix .. "_cert_key"] = abspath(ssl_cert_key)
end
end
Expand Down

0 comments on commit 1c17b18

Please sign in to comment.