Skip to content

Commit

Permalink
feat(cli) exposing serf keys commands (#2069)
Browse files Browse the repository at this point in the history
  • Loading branch information
subnetmarco authored Feb 20, 2017
1 parent bb77fa1 commit 24d6473
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 20 deletions.
8 changes: 8 additions & 0 deletions kong.conf.default
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@
#cluster_encrypt_key = # base64-encoded 16-bytes key to encrypt
# cluster traffic with.

#cluster_keyring_file = # Specifies a file to load keyring data from.
# Kong is able to keep encryption keys in sync
# and perform key rotations. During a key
# rotation, there may be some period of time in
# which Kong is required to maintain more than
# one encryption key until all members have
# received the new key.

#cluster_ttl_on_failure = 3600 # Time to live (in seconds) of a node in the
# cluster when it stops sending healthcheck
# pings, possibly caused by a node or network
Expand Down
25 changes: 24 additions & 1 deletion kong/cmd/cluster.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
local log = require "kong.cmd.utils.log"
local Serf = require "kong.serf"
local pl_path = require "pl.path"
local pl_table = require "pl.tablex"
local DAOFactory = require "kong.dao.factory"
local conf_loader = require "kong.conf_loader"

local KEYS_COMMANDS = { "list", "install", "use", "remove" }

local function execute(args)
if args.command == "keygen" then
local conf = assert(conf_loader(args.conf))
Expand Down Expand Up @@ -37,6 +40,11 @@ local function execute(args)
log("force-leaving %s", node_name)
assert(serf:force_leave(node_name))
log("left node %s", node_name)
elseif args.command == "keys" then
assert(pl_table.find(KEYS_COMMANDS, args[1]), "invalid command")
assert(args[1] == "list" or #args == 2, "missing key")

print(assert(serf:keys("-"..args[1], args[2])))
end
end

Expand All @@ -52,6 +60,20 @@ The available commands are:
reachability -p Check if the cluster is reachable.
force-leave -p <node_name> Forcefully remove a node from the cluster (useful
if the node is in a failed state).
keys install <key> Install a new key onto Kong's internal keyring. This
will enable the key for decryption. The key will not
be used to encrypt messages until the primary key is
changed.
keys use <key> Change the primary key used for encrypting messages.
All nodes in the cluster must already have this key
installed if they are to continue communicating with
eachother.
keys remove <key> Remove a key from Kong's internal keyring. The key
being removed may not be the current primary key.
keys list List all currently known keys in the cluster. This
will ask all nodes in the cluster for a list of keys
and dump a summary containing each key and the
number of members it is installed on to the console.
Options:
-c,--conf (optional string) configuration file
Expand All @@ -65,6 +87,7 @@ return {
keygen = true,
members = true,
reachability = true,
["force-leave"] = true
["force-leave"] = true,
keys = true
}
}
1 change: 1 addition & 0 deletions kong/cmd/utils/serf_signals.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ function _M.start(kong_config, dao)
["-rpc-addr"] = kong_config.cluster_listen_rpc,
["-advertise"] = kong_config.cluster_advertise,
["-encrypt"] = kong_config.cluster_encrypt_key,
["-keyring-file"] = kong_config.cluster_keyring_file,
["-log-level"] = "err",
["-profile"] = kong_config.cluster_profile,
["-node"] = serf.node_name,
Expand Down
16 changes: 13 additions & 3 deletions kong/serf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ end

-- WARN: BAD, this is **blocking** IO. Legacy code from previous Serf
-- implementation that needs to be upgraded.
function Serf:invoke_signal(signal, args, no_rpc)
function Serf:invoke_signal(signal, args, no_rpc, full_error)
args = args or {}
if type(args) == "table" then
setmetatable(args, Serf.args_mt)
Expand All @@ -37,8 +37,10 @@ function Serf:invoke_signal(signal, args, no_rpc)
local cmd = string.format("%s %s %s %s", self.config.serf_path, signal, rpc, tostring(args))
local ok, code, stdout, stderr = pl_utils.executeex(cmd)
if not ok or code ~= 0 then
-- always print the first error line of serf
local err = stdout ~= "" and pl_stringx.splitlines(stdout)[1] or stderr
local err = stderr
if stdout ~= "" then
err = full_error and stdout or pl_stringx.splitlines(stdout)[1]
end
return nil, err
end

Expand Down Expand Up @@ -73,6 +75,14 @@ function Serf:force_leave(node_name)
return true
end

function Serf:keys(action, key)
local res, err = self:invoke_signal(string.format("keys %s %s", action, key
and key or ""), nil, false, true)
if not res then return nil, err end

return res
end

function Serf:members()
local res, err = self:invoke_signal("members", {["-format"] = "json"})
if not res then return nil, err end
Expand Down
1 change: 1 addition & 0 deletions kong/templates/kong_defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cluster_listen = 0.0.0.0:7946
cluster_listen_rpc = 127.0.0.1:7373
cluster_advertise = NONE
cluster_encrypt_key = NONE
cluster_keyring_file = NONE
cluster_profile = wan
cluster_ttl_on_failure = 3600
Expand Down
83 changes: 67 additions & 16 deletions spec/02-integration/01-cmd/07-cluster_spec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local helpers = require "spec.helpers"
local pl_file = require "pl.file"

describe("kong cluster", function()
setup(function()
Expand All @@ -7,9 +8,6 @@ describe("kong cluster", function()
teardown(function()
helpers.clean_prefix()
end)
after_each(function()
helpers.kill_all()
end)

it("cluster help", function()
local _, stderr = helpers.kong_exec "cluster --help"
Expand All @@ -25,20 +23,73 @@ describe("kong cluster", function()
assert.equal("", stderr)
assert.equal(26, #stdout) -- 24 + \r\n
end)
it("shows members", function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
local _, _, stdout = assert(helpers.kong_exec("cluster members --prefix "..helpers.test_conf.prefix))
assert.matches("alive", stdout)
end)
it("shows reachability", function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
local _, _, stdout = assert(helpers.kong_exec("cluster reachability --prefix "..helpers.test_conf.prefix))
assert.matches("Successfully contacted all live nodes", stdout)

describe("commands that require a running Serf", function()
setup(function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
end)
teardown(function()
helpers.kill_all()
end)

it("shows members", function()
local _, _, stdout = assert(helpers.kong_exec("cluster members --prefix "..helpers.test_conf.prefix))
assert.matches("alive", stdout)
end)
it("shows reachability", function()
local _, _, stdout = assert(helpers.kong_exec("cluster reachability --prefix "..helpers.test_conf.prefix))
assert.matches("Successfully contacted all live nodes", stdout)
end)
it("force-leaves a node", function()
local _, _, stdout = assert(helpers.kong_exec("cluster force-leave 127.0.0.1 --prefix "..helpers.test_conf.prefix))
assert.matches("left node 127.0.0.1", stdout, nil, true)
end)
end)
it("force-leaves a node", function()
assert(helpers.kong_exec("start --conf "..helpers.test_conf_path))
local _, _, stdout = assert(helpers.kong_exec("cluster force-leave 127.0.0.1 --prefix "..helpers.test_conf.prefix))
assert.matches("left node 127.0.0.1", stdout, nil, true)

describe("keys", function()
setup(function()
-- Creating a sample keyring file
local KEYRING_PATH = os.tmpname()
assert(pl_file.write(KEYRING_PATH, [[
[
"QHOYjmYlxSCBhdfiolhtDQ==",
"daZ2wnuw+Ql+2hCm7vQB6A==",
"keTZydopxtiTY7HVoqeWGw=="
]
]]))

assert(helpers.start_kong({
cluster_keyring_file = KEYRING_PATH
}))
end)

teardown(function()
helpers.kill_all()
end)

it("lists keys", function()
local ok = helpers.kong_exec("cluster keys list --prefix "..helpers.test_conf.prefix)
assert.True(ok)
end)
it("install key", function()
local ok = helpers.kong_exec("cluster keys install d7rHSZRrb2FPyJgdBAXMZQ== --prefix "..helpers.test_conf.prefix)
assert.True(ok)
end)
it("remove key", function()
local ok = helpers.kong_exec("cluster keys remove d7rHSZRrb2FPyJgdBAXMZQ== --prefix "..helpers.test_conf.prefix)
assert.True(ok)
end)
it("use key", function()
local ok = helpers.kong_exec("cluster keys use daZ2wnuw+Ql+2hCm7vQB6A== --prefix "..helpers.test_conf.prefix)
assert.True(ok)
end)

describe("errors", function()
it("fails to install an invalid key", function()
local ok = helpers.kong_exec("cluster keys install helloworld --prefix "..helpers.test_conf.prefix)
assert.False(ok)
end)
end)
end)

describe("errors", function()
Expand Down

0 comments on commit 24d6473

Please sign in to comment.