Skip to content

Commit

Permalink
Merge pull request #456 from Mashape/fix/ssl
Browse files Browse the repository at this point in the history
Closes #453 and #235
  • Loading branch information
subnetmarco committed Aug 10, 2015
2 parents 06ef332 + 2bdc780 commit 15e6029
Show file tree
Hide file tree
Showing 15 changed files with 96 additions and 84 deletions.
3 changes: 0 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ test-integration:
test-plugins:
@busted -v spec/plugins

test-all:
@busted -v spec/

coverage:
@rm -f luacov.*
@busted --coverage spec/
Expand Down
1 change: 1 addition & 0 deletions kong-0.4.1-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ build = {

["kong.cli.utils"] = "kong/cli/utils/utils.lua",
["kong.cli.utils.dnsmasq"] = "kong/cli/utils/dnsmasq.lua",
["kong.cli.utils.ssl"] = "kong/cli/utils/ssl.lua",
["kong.cli.utils.signal"] = "kong/cli/utils/signal.lua",
["kong.cli.utils.input"] = "kong/cli/utils/input.lua",
["kong.cli.db"] = "kong/cli/db.lua",
Expand Down
7 changes: 5 additions & 2 deletions kong/cli/utils/signal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

local IO = require "kong.tools.io"
local cutils = require "kong.cli.utils"
local ssl = require "kong.cli.utils.ssl"
local constants = require "kong.constants"
local syslog = require "kong.tools.syslog"
local socket = require "socket"
Expand Down Expand Up @@ -101,7 +102,7 @@ local function prepare_nginx_working_dir(args_config)
cutils.logger:warn("Setting \"memory_cache_size\" to default 128MB")
end

local ssl_cert_path, ssl_key_path = cutils.get_ssl_cert_and_key(kong_config)
local ssl_cert_path, ssl_key_path = ssl.get_ssl_cert_and_key(kong_config)
local trusted_ssl_cert_path = kong_config.databases_available[kong_config.database].properties.ssl_certificate -- DAO ssl cert

-- Extract nginx config from kong config, replace any needed value
Expand Down Expand Up @@ -222,6 +223,7 @@ function _M.prepare_kong(args_config, signal)

cutils.logger:info("Connecting to the database...")
prepare_database(args_config)
ssl.prepare_ssl()
prepare_nginx_working_dir(args_config, signal)
end

Expand Down Expand Up @@ -316,7 +318,8 @@ function _M.is_running(args_config)

if IO.file_exists(kong_config.pid_file) then
local pid = IO.read_file(kong_config.pid_file)
if os.execute("kill -0 "..pid) == 0 then
local _, code = IO.os_execute("kill -0 "..pid)
if code == 0 then
return true
else
cutils.logger:warn("It seems like Kong crashed the last time it was started!")
Expand Down
55 changes: 55 additions & 0 deletions kong/cli/utils/ssl.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
local cutils = require "kong.cli.utils"
local utils = require "kong.tools.utils"
local IO = require "kong.tools.io"

local _M = {}

function _M.get_ssl_cert_and_key(kong_config)
local ssl_cert_path, ssl_key_path

if (kong_config.ssl_cert_path and not kong_config.ssl_key_path) or
(kong_config.ssl_key_path and not kong_config.ssl_cert_path) then
cutils.logger:error_exit("Both \"ssl_cert_path\" and \"ssl_key_path\" need to be specified in the configuration, or none of them")
elseif kong_config.ssl_cert_path and kong_config.ssl_key_path then
ssl_cert_path = kong_config.ssl_cert_path
ssl_key_path = kong_config.ssl_key_path
else
ssl_cert_path = IO.path:join(cutils.get_luarocks_install_dir(), "ssl", "kong-default.crt")
ssl_key_path = IO.path:join(cutils.get_luarocks_install_dir(), "ssl", "kong-default.key")
end

-- Check that the file exists
if ssl_cert_path and not IO.file_exists(ssl_cert_path) then
cutils.logger:error_exit("Can't find default Kong SSL certificate at: "..ssl_cert_path)
end
if ssl_key_path and not IO.file_exists(ssl_key_path) then
cutils.logger:error_exit("Can't find default Kong SSL key at: "..ssl_key_path)
end

return ssl_cert_path, ssl_key_path
end

function _M.prepare_ssl()
local ssl_cert_path = IO.path:join(cutils.get_luarocks_install_dir(), "ssl", "kong-default.crt")
local ssl_key_path = IO.path:join(cutils.get_luarocks_install_dir(), "ssl", "kong-default.key")

if not (IO.file_exists(ssl_cert_path) and IO.file_exists(ssl_key_path)) then
-- Autogenerating the certificates for the first time
cutils.logger:info("Auto-generating the default SSL certificate and key...")

local file_name = os.tmpname()
local passphrase = utils.random_string()

IO.os_execute([[
cd /tmp && \
openssl genrsa -des3 -out ]]..file_name..[[.key -passout pass:]]..passphrase..[[ 1024 && \
openssl req -new -key ]]..file_name..[[.key -out ]]..file_name..[[.csr -subj "/C=US/ST=California/L=San Francisco/O=Kong/OU=IT Department/CN=localhost" -passin pass:]]..passphrase..[[ && \
cp ]]..file_name..[[.key ]]..file_name..[[.key.org && \
openssl rsa -in ]]..file_name..[[.key.org -out ]]..file_name..[[.key -passin pass:]]..passphrase..[[ && \
openssl x509 -req -in ]]..file_name..[[.csr -signkey ]]..file_name..[[.key -out ]]..file_name..[[.crt && \
sudo mv ]]..file_name..[[.crt ]]..ssl_cert_path..[[ && \
sudo mv ]]..file_name..[[.key ]]..ssl_key_path)
end
end

return _M
26 changes: 0 additions & 26 deletions kong/cli/utils/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -119,31 +119,6 @@ local function get_kong_config_path(args_config)
return config_path
end

local function get_ssl_cert_and_key(kong_config)
local ssl_cert_path, ssl_key_path

if (kong_config.ssl_cert_path and not kong_config.ssl_key_path) or
(kong_config.ssl_key_path and not kong_config.ssl_cert_path) then
logger:error_exit("Both \"ssl_cert_path\" and \"ssl_key_path\" need to be specified in the configuration, or none of them")
elseif kong_config.ssl_cert_path and kong_config.ssl_key_path then
ssl_cert_path = kong_config.ssl_cert_path
ssl_key_path = kong_config.ssl_key_path
else
ssl_cert_path = IO.path:join(get_luarocks_install_dir(), "ssl", "kong-default.crt")
ssl_key_path = IO.path:join(get_luarocks_install_dir(), "ssl", "kong-default.key")
end

-- Check that the file exists
if ssl_cert_path and not IO.file_exists(ssl_cert_path) then
logger:error_exit("Can't find default Kong SSL certificate at: "..ssl_cert_path)
end
if ssl_key_path and not IO.file_exists(ssl_key_path) then
logger:error_exit("Can't find default Kong SSL key at: "..ssl_key_path)
end

return ssl_cert_path, ssl_key_path
end

-- Checks if a port is open on localhost
-- @param `port` The port to check
-- @return `open` True if open, false otherwise
Expand All @@ -157,7 +132,6 @@ return {
logger = logger,
get_kong_infos = get_kong_infos,
get_kong_config_path = get_kong_config_path,
get_ssl_cert_and_key = get_ssl_cert_and_key,
get_luarocks_install_dir = get_luarocks_install_dir,
is_port_open = is_port_open
}
12 changes: 10 additions & 2 deletions kong/tools/http_client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ local ltn12 = require "ltn12"

local _M = {}

local function get_response(resp)
if #resp == 0 then
return nil
else
return table.concat(resp, "")
end
end

local function http_call(options)
-- Set Host header accordingly
local parsed_url = url.parse(options.url)
Expand All @@ -28,10 +36,10 @@ local function http_call(options)
options.options = "all"

local _, code, headers = https.request(options)
return resp[1], code, headers
return get_response(resp), code, headers
else
local _, code, headers = http.request(options)
return resp[1], code, headers
return get_response(resp), code, headers
end
end

Expand Down
8 changes: 5 additions & 3 deletions kong/tools/io.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ end

function _M.os_execute(command)
local n = os.tmpname() -- get a temporary file name to store output
local exit_code = os.execute("/bin/bash -c '"..command.." > "..n.." 2>&1'")
local f = os.tmpname() -- get a temporary file name to store script
_M.write_to_file(f, command)
local exit_code = os.execute("/bin/bash "..f.." > "..n.." 2>&1")
local result = _M.read_file(n)
os.remove(n)

return string.gsub(result, "[%\r%\n]", ""), exit_code / 256
os.remove(f)
return string.gsub(string.gsub(result, "^"..f..":[%s%w]+:%s*", ""), "[%\r%\n]", ""), exit_code / 256
end

function _M.cmd_exists(cmd)
Expand Down
5 changes: 0 additions & 5 deletions spec/integration/cli/restart_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local IO = require "kong.tools.io"
local spec_helper = require "spec.spec_helpers"

describe("CLI", function()
Expand Down Expand Up @@ -26,11 +25,7 @@ describe("CLI", function()
end)

it("should restart kong when it's crashed", function()
local kong_pid = IO.read_file(spec_helper.get_env().configuration.pid_file)
os.execute("pkill -9 nginx")
while os.execute("kill -0 "..kong_pid.." ") == 0 do
-- Wait till it's really over
end

local res, code = spec_helper.restart_kong()
assert.are.same(0, code)
Expand Down
2 changes: 1 addition & 1 deletion spec/integration/proxy/api_resolver_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe("Resolver", function()

assert.same(6, utils.table_size(cert))
assert.same("Kong", cert.organizationName)
assert.same("IT", cert.organizationalUnitName)
assert.same("IT Department", cert.organizationalUnitName)
assert.same("US", cert.countryName)
assert.same("California", cert.stateOrProvinceName)
assert.same("San Francisco", cert.localityName)
Expand Down
4 changes: 2 additions & 2 deletions spec/integration/proxy/dns_resolver_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe("DNS", function()
describe("DNS", function()

it("should work when calling local IP", function()
local thread = spec_helper.start_tcp_server(TCP_PORT) -- Starting the mock TCP server
local thread = spec_helper.start_http_server(TCP_PORT) -- Starting the mock TCP server

local _, status = http_client.get(spec_helper.STUB_GET_URL, nil, { host = "dns1.com" })
assert.are.equal(200, status)
Expand All @@ -33,7 +33,7 @@ describe("DNS", function()
end)

it("should work when calling local hostname", function()
local thread = spec_helper.start_tcp_server(TCP_PORT) -- Starting the mock TCP server
local thread = spec_helper.start_http_server(TCP_PORT) -- Starting the mock TCP server

local _, status = http_client.get(spec_helper.STUB_GET_URL, nil, { host = "dns2.com" })
assert.are.equal(200, status)
Expand Down
22 changes: 13 additions & 9 deletions spec/plugins/ssl/access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ local IO = require "kong.tools.io"
local http_client = require "kong.tools.http_client"
local cjson = require "cjson"
local ssl_fixtures = require "spec.plugins.ssl.fixtures"
local cutils = require "kong.cli.utils"

local STUB_GET_SSL_URL = spec_helper.STUB_GET_SSL_URL
local STUB_GET_URL = spec_helper.STUB_GET_URL
Expand All @@ -21,7 +22,7 @@ describe("SSL Plugin", function()
{ name = "API TESTS 13 (ssl)", public_dns = "ssl3.com", target_url = "http://mockbin.com" }
},
plugin_configuration = {
{ name = "ssl", value = { cert = ssl_fixtures.cert, key = ssl_fixtures.key }, __api = 1 },
{ name = "ssl", value = { cert = ssl_fixtures.cert, key = ssl_fixtures.key }, __api = 1 },
{ name = "ssl", value = { cert = ssl_fixtures.cert, key = ssl_fixtures.key, only_https = true }, __api = 2 }
}
}
Expand All @@ -32,7 +33,7 @@ describe("SSL Plugin", function()
teardown(function()
spec_helper.stop_kong()
end)

describe("SSL Util", function()

it("should not convert an invalid cert to DER", function()
Expand All @@ -52,14 +53,14 @@ describe("SSL Plugin", function()
end)

end)

describe("SSL Resolution", function()

it("should return default CERTIFICATE when requesting other APIs", function()
local parsed_url = url.parse(STUB_GET_SSL_URL)
local res = IO.os_execute("(echo \"GET /\"; sleep 2) | openssl s_client -connect "..parsed_url.host..":"..tostring(parsed_url.port).." -servername test4.com")

assert.truthy(res:match("US/ST=California/L=San Francisco/O=Kong/OU=IT/CN=localhost"))
assert.truthy(res:match("US/ST=California/L=San Francisco/O=Kong/OU=IT Department/CN=localhost"))
end)

it("should work when requesting a specific API", function()
Expand All @@ -70,7 +71,7 @@ describe("SSL Plugin", function()
end)

end)

describe("only_https", function()

it("should block request without https", function()
Expand All @@ -91,9 +92,12 @@ describe("SSL Plugin", function()
describe("should work with curl", function()
local response = http_client.get(API_URL.."/apis/", {public_dns="ssl3.com"})
local api_id = cjson.decode(response).data[1].id
local current_path = IO.os_execute("pwd")
local res = IO.os_execute("curl -s -o /dev/null -w \"%{http_code}\" "..API_URL.."/apis/"..api_id.."/plugins/ --form \"name=ssl\" --form \"value.cert=@"..current_path.."/ssl/kong-default.crt\" --form \"value.key=@"..current_path.."/ssl/kong-default.key\"")
assert.are.equal("201", res)
end)

local ssl_cert_path = IO.path:join(cutils.get_luarocks_install_dir(), "ssl", "kong-default.crt")
local ssl_key_path = IO.path:join(cutils.get_luarocks_install_dir(), "ssl", "kong-default.key")

local res = IO.os_execute("curl -s -o /dev/null -w \"%{http_code}\" "..API_URL.."/apis/"..api_id.."/plugins/ --form \"name=ssl\" --form \"value.cert=@"..ssl_cert_path.."\" --form \"value.key=@"..ssl_key_path.."\"")
assert.are.equal(201, tonumber(res))
end)

end)
2 changes: 1 addition & 1 deletion spec/unit/tools/io_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ describe("IO", function()

local res, code = IO.os_execute("LC_ALL=\"C\";asdasda \"Hello\"")
assert.are.same(127, code)
assert.are.same("/bin/bash: asdasda: command not found", res)
assert.are.same("asdasda: command not found", res)
end)

end)
3 changes: 3 additions & 0 deletions ssl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SSL

This is the directory where Kong will place the auto-generated default SSL certificate and key.
15 changes: 0 additions & 15 deletions ssl/kong-default.crt

This file was deleted.

15 changes: 0 additions & 15 deletions ssl/kong-default.key

This file was deleted.

0 comments on commit 15e6029

Please sign in to comment.