Skip to content

Commit

Permalink
feat(tcp-log) TLS handshake support for TCP logs
Browse files Browse the repository at this point in the history
  • Loading branch information
p0pr0ck5 committed Dec 14, 2017
1 parent f83f9cb commit f1b1512
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 4 deletions.
2 changes: 2 additions & 0 deletions kong-0.11.2-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ build = {

["kong.plugins.tcp-log.handler"] = "kong/plugins/tcp-log/handler.lua",
["kong.plugins.tcp-log.schema"] = "kong/plugins/tcp-log/schema.lua",
["kong.plugins.tcp-log.migrations.cassandra"] = "kong/plugins/tcp-log/migrations/cassandra.lua",
["kong.plugins.tcp-log.migrations.postgres"] = "kong/plugins/tcp-log/migrations/postgres.lua",

["kong.plugins.udp-log.handler"] = "kong/plugins/udp-log/handler.lua",
["kong.plugins.udp-log.schema"] = "kong/plugins/udp-log/schema.lua",
Expand Down
9 changes: 9 additions & 0 deletions kong/plugins/tcp-log/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ local function log(premature, conf, message)
return
end

if conf.tls then
ok, err = sock:sslhandshake(true, conf.tls_sni, false)
if not ok then
ngx.log(ngx.ERR, "[tcp-log] failed to perform TLS handshake to ",
host, ":", port, ": ", err)
return
end
end

ok, err = sock:send(cjson.encode(message) .. "\r\n")
if not ok then
ngx.log(ngx.ERR, "[tcp-log] failed to send data to " .. host .. ":" .. tostring(port) .. ": ", err)
Expand Down
22 changes: 22 additions & 0 deletions kong/plugins/tcp-log/migrations/cassandra.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
local plugin_config_iterator = require("kong.dao.migrations.helpers").plugin_config_iterator


return {
{
name = "2017-12-13-120000_tcp-log_tls",
up = function(_, _, dao)
for ok, config, update in plugin_config_iterator(dao, "tcp-log") do
if not ok then
return config
end
config.tls = false
local ok, err = update(config)
if not ok then
return err
end
end
end,
down = function(_, _, dao) end -- not implemented
},
}

22 changes: 22 additions & 0 deletions kong/plugins/tcp-log/migrations/postgres.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
local plugin_config_iterator = require("kong.dao.migrations.helpers").plugin_config_iterator


return {
{
name = "2017-12-13-120000_tcp-log_tls",
up = function(_, _, dao)
for ok, config, update in plugin_config_iterator(dao, "tcp-log") do
if not ok then
return config
end
config.tls = false
local ok, err = update(config)
if not ok then
return err
end
end
end,
down = function(_, _, dao) end -- not implemented
},
}

4 changes: 3 additions & 1 deletion kong/plugins/tcp-log/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ return {
host = { required = true, type = "string" },
port = { required = true, type = "number" },
timeout = { default = 10000, type = "number" },
keepalive = { default = 60000, type = "number" }
keepalive = { default = 60000, type = "number" },
tls = { default = false, type = "boolean" },
tls_sni = { type = "string" },
}
}
39 changes: 39 additions & 0 deletions spec/03-plugins/01-tcp-log/01-tcp-log_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ describe("Plugin: tcp-log (log)", function()
upstream_url = helpers.mock_upstream_url,
})

local api2 = assert(helpers.dao.apis:insert {
name = "api-2",
hosts = { "tcp_logging_tls.com" },
upstream_url = helpers.mock_upstream_url,
})

assert(helpers.dao.plugins:insert {
api_id = api1.id,
name = "tcp-log",
Expand All @@ -24,6 +30,16 @@ describe("Plugin: tcp-log (log)", function()
},
})

assert(helpers.dao.plugins:insert {
api_id = api2.id,
name = "tcp-log",
config = {
host = "127.0.0.1",
port = TCP_PORT,
tls = true,
},
})

assert(helpers.start_kong({
nginx_conf = "spec/fixtures/custom_nginx.template",
}))
Expand Down Expand Up @@ -81,4 +97,27 @@ describe("Plugin: tcp-log (log)", function()
assert.True(log_message.latencies.proxy < 3000)
assert.True(log_message.latencies.request >= log_message.latencies.kong + log_message.latencies.proxy)
end)

it("performs a TLS handshake on the remote TCP server", function()
local thread = helpers.tcp_server(TCP_PORT, { tls = true })

-- Making the request
local r = assert(client:send {
method = "GET",
path = "/request",
headers = {
host = "tcp_logging_tls.com",
},
})
assert.response(r).has.status(200)

-- Getting back the TCP server input
local ok, res = thread:join()
assert.True(ok)
assert.is_string(res)

-- Making sure it's alright
local log_message = cjson.decode(res)
assert.equal("127.0.0.1", log_message.client_ip)
end)
end)
22 changes: 19 additions & 3 deletions spec/helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -308,25 +308,41 @@ end
-- (single read).
-- @name tcp_server
-- @param `port` The port where the server will be listening to
-- @param `opts A table of options defining the server's behavior
-- @return `thread` A thread object
local function tcp_server(port, ...)
local function tcp_server(port, opts, ...)
local threads = require "llthreads2.ex"
opts = opts or {}
local thread = threads.new({
function(port)
function(port, opts)
local socket = require "socket"
local server = assert(socket.tcp())
server:settimeout(10)
assert(server:setoption('reuseaddr', true))
assert(server:bind("*", port))
assert(server:listen())
local client = assert(server:accept())

if opts.tls then
local ssl = require "ssl"
local params = {
mode = "server",
protocol = "any",
key = "spec/fixtures/kong_spec.key",
certificate = "spec/fixtures/kong_spec.crt",
}

client = ssl.wrap(client, params)
client:dohandshake()
end

local line = assert(client:receive())
client:send(line .. "\n")
client:close()
server:close()
return line
end
}, port)
}, port, opts)

return thread:start(...)
end
Expand Down

0 comments on commit f1b1512

Please sign in to comment.