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(core) support static client SSL certificates #2556

Merged
merged 1 commit into from
May 25, 2017
Merged
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
17 changes: 17 additions & 0 deletions kong.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,23 @@
# the SSL key for the `proxy_listen_ssl`
# address.

#client_ssl = on # Determines if Nginx should send client-side
# SSL certificates when proxying requests.

#client_ssl_cert = # If `client_ssl` is enabled, the absolute path
# to the client SSL certificate for the
# `proxy_ssl_certificate` directive. Note that
# this value is statically defined on the node,
# and currently cannot be configured on a
# per-API basis.

#client_ssl_cert_key = # If `client_ssl` is enabled, the absolute path
# to the client SSL key for the
# `proxy_ssl_certificate_key` address. Note
# this value is statically defined on the node,
# 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
Expand Down
25 changes: 25 additions & 0 deletions kong/conf_loader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ local PREFIX_PATHS = {
ssl_cert_key_default = {"ssl", "kong-default.key"},
ssl_cert_csr_default = {"ssl", "kong-default.csr"}
;
client_ssl_cert_default = {"ssl", "kong-default.crt"},
client_ssl_cert_key_default = {"ssl", "kong-default.key"},
client_ssl_cert_csr_default = {"ssl", "kong-default.csr"}
;
admin_ssl_cert_default = {"ssl", "admin-kong-default.crt"},
admin_ssl_cert_key_default = {"ssl", "admin-kong-default.key"},
admin_ssl_cert_csr_default = {"ssl", "admin-kong-default.csr"}
Expand Down Expand Up @@ -91,6 +95,7 @@ local CONF_INFERENCES = {
dns_resolver = {typ = "array"},

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

log_level = {enum = {"debug", "info", "notice", "warn",
Expand Down Expand Up @@ -213,6 +218,21 @@ local function check_and_infer(conf)
end
end

if conf.client_ssl then
if conf.client_ssl_cert and not conf.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
errors[#errors+1] = "client_ssl_cert must be specified"
end

if conf.client_ssl_cert and not pl_path.exists(conf.client_ssl_cert) then
errors[#errors+1] = "client_ssl_cert: no such file at "..conf.client_ssl_cert
end
if conf.client_ssl_cert_key and not pl_path.exists(conf.client_ssl_cert_key) then
errors[#errors+1] = "client_ssl_cert_key: no such file at "..conf.client_ssl_cert_key
end
end

if conf.admin_ssl then
if conf.admin_ssl_cert and not conf.admin_ssl_cert_key then
errors[#errors+1] = "admin_ssl_cert_key must be specified"
Expand Down Expand Up @@ -424,6 +444,11 @@ local function load(path, custom_conf)
conf.ssl_cert_key = pl_path.abspath(conf.ssl_cert_key)
end

if conf.client_ssl_cert and conf.client_ssl_cert_key then
conf.client_ssl_cert = pl_path.abspath(conf.client_ssl_cert)
conf.client_ssl_cert_key = pl_path.abspath(conf.client_ssl_cert_key)
end

if conf.admin_ssl_cert and conf.admin_ssl_cert_key then
conf.admin_ssl_cert = pl_path.abspath(conf.admin_ssl_cert)
conf.admin_ssl_cert_key = pl_path.abspath(conf.admin_ssl_cert_key)
Expand Down
3 changes: 3 additions & 0 deletions kong/templates/kong_defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ mem_cache_size = 128m
ssl = on
ssl_cert = NONE
ssl_cert_key = NONE
client_ssl = off
client_ssl_cert = NONE
client_ssl_cert_key = NONE
admin_ssl = on
admin_ssl_cert = NONE
admin_ssl_cert_key = NONE
Expand Down
5 changes: 5 additions & 0 deletions kong/templates/nginx_kong.lua
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ server {
}
> end

> if client_ssl then
proxy_ssl_certificate ${{CLIENT_SSL_CERT}};
proxy_ssl_certificate_key ${{CLIENT_SSL_CERT_KEY}};
> end

location / {
set $upstream_host nil;
set $upstream_scheme nil;
Expand Down
56 changes: 56 additions & 0 deletions spec/01-unit/02-conf_loader_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,62 @@ describe("Configuration loader", function()
assert.True(helpers.path.isabs(conf.ssl_cert_key))
end)
end)
describe("client", function()
it("requires both proxy SSL cert and key", function()
local conf, err = conf_loader(nil, {
client_ssl = true,
client_ssl_cert = "/path/cert.pem"
})
assert.equal("client_ssl_cert_key must be specified", err)
assert.is_nil(conf)

conf, err = conf_loader(nil, {
client_ssl = true,
client_ssl_cert_key = "/path/key.pem"
})
assert.equal("client_ssl_cert must be specified", err)
assert.is_nil(conf)

conf, err = conf_loader(nil, {
client_ssl = true,
client_ssl_cert = "spec/fixtures/kong_spec.crt",
client_ssl_cert_key = "spec/fixtures/kong_spec.key"
})
assert.is_nil(err)
assert.is_table(conf)
end)
it("requires SSL cert and key to exist", function()
local conf, _, errors = conf_loader(nil, {
client_ssl = true,
client_ssl_cert = "/path/cert.pem",
client_ssl_cert_key = "/path/cert_key.pem"
})
assert.equal(2, #errors)
assert.contains("client_ssl_cert: no such file at /path/cert.pem", errors)
assert.contains("client_ssl_cert_key: no such file at /path/cert_key.pem", errors)
assert.is_nil(conf)

conf, _, errors = conf_loader(nil, {
client_ssl = true,
client_ssl_cert = "spec/fixtures/kong_spec.crt",
client_ssl_cert_key = "/path/cert_key.pem"
})
assert.equal(1, #errors)
assert.contains("client_ssl_cert_key: no such file at /path/cert_key.pem", errors)
assert.is_nil(conf)
end)
it("resolves SSL cert/key to absolute path", function()
local conf, err = conf_loader(nil, {
client_ssl = true,
client_ssl_cert = "spec/fixtures/kong_spec.crt",
client_ssl_cert_key = "spec/fixtures/kong_spec.key"
})
assert.is_nil(err)
assert.is_table(conf)
assert.True(helpers.path.isabs(conf.client_ssl_cert))
assert.True(helpers.path.isabs(conf.client_ssl_cert_key))
end)
end)
describe("admin", function()
it("requires both admin SSL cert and key", function()
local conf, err = conf_loader(nil, {
Expand Down
20 changes: 20 additions & 0 deletions spec/01-unit/03-prefix_handler_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,26 @@ describe("NGINX conf compiler", function()
assert.not_matches("ssl_protocols", kong_nginx_conf)
assert.not_matches("ssl_certificate_by_lua_block", kong_nginx_conf)
end)
describe("handles client_ssl", function()
it("on", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
client_ssl = true,
client_ssl_cert = "spec/fixtures/kong_spec.crt",
client_ssl_cert_key = "spec/fixtures/kong_spec.key",
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.matches("proxy_ssl_certificate.*spec/fixtures/kong_spec.crt", kong_nginx_conf)
assert.matches("proxy_ssl_certificate_key.*spec/fixtures/kong_spec.key", kong_nginx_conf)
end)
it("off", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
client_ssl = false,
}))
local kong_nginx_conf = prefix_handler.compile_kong_conf(conf)
assert.not_matches("proxy_ssl_certificate.*spec/fixtures/kong_spec.crt", kong_nginx_conf)
assert.not_matches("proxy_ssl_certificate_key.*spec/fixtures/kong_spec.key", kong_nginx_conf)
end)
end)
it("does not include lua_ssl_trusted_certificate/lua_ssl_verify_depth by default", function()
local conf = assert(conf_loader(helpers.test_conf_path, {
lua_ssl_verify_depth = "2"
Expand Down