Skip to content

Commit

Permalink
Allow to set cluster cookie hash in membership (#2232)
Browse files Browse the repository at this point in the history
  • Loading branch information
yngvar-antonsson authored May 21, 2024
1 parent 6981250 commit 4bf7999
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ sandbox.lua
*.xlog
*.snap
package.json
*.log
10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Added
- GraphQL API to enable previously disabled instances:
``mutation { cluster { enable_servers(uuids: [...]) { } } }``.

- ``cartridge.cfg`` param ``set_cookie_hash_membership`` to set
cluster cookie hash as encryption key in membership instead of
plain cookie.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Changed
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -60,6 +64,12 @@ Fixed

- Leader autoreturn doesn't try to return leadership to unhealthy leader anymore.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Deprecated
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- Usage of plain cluster cookie as a membership encryption key by default.

-------------------------------------------------------------------------------
[2.10.0] - 2024-04-10
-------------------------------------------------------------------------------
Expand Down
42 changes: 41 additions & 1 deletion cartridge.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local http = require('http.server')
local fiber = require('fiber')
local socket = require('socket')
local json = require('json')
local digest = require('digest')
local tarantool_version = require('tarantool').version

local rpc = require('cartridge.rpc')
Expand Down Expand Up @@ -275,6 +276,34 @@ end
-- env `TARANTOOL_UPLOAD_PREFIX`,
-- args `--upload-prefix`)
--

-- @tparam ?boolean opts.enable_failover_suppressing
-- Enable failover suppressing. It forces eventual failover
-- to stop in case of constant switching.
-- default: `false`, overridden by
-- env `TARANTOOL_ENABLE_FAILOVER_SUPPRESSING`,
-- args `--enable-failover-suppressing`)
--
-- @tparam ?boolean opts.enable_synchro_mode
-- Allow to use sync spaces in Cartridge.
-- default: `false`, overridden by
-- env `TARANTOOL_ENABLE_SYNCHRO_MODE`,
-- args `--enable-synchro-mode`)
--
-- @tparam ?boolean opts.disable_raft_on_small_clusters
-- Disable Raft Failover on small clusters (where
-- number of instances is less than 3)
-- default: `true`, overridden by
-- env `TARANTOOL_DISABLE_RAFT_ON_SMALL_CLUSTERS`,
-- args `--disable-raft-on-small-clusters`)
--
-- @tparam ?boolean opts.set_cookie_hash_membership
-- Set cookie hash instead of full cluster cookie
-- as membership encryption key.
-- default: `false`, overridden by
-- env `TARANTOOL_SET_COOKIE_HASH_MEMBERSHIP`,
-- args `--set-cookie-hash-membership`)
--
-- @tparam ?table box_opts
-- tarantool extra box.cfg options (e.g. memtx_memory),
-- that may require additional tuning
Expand Down Expand Up @@ -310,6 +339,7 @@ local function cfg(opts, box_opts)
enable_sychro_mode = '?boolean',
enable_synchro_mode = '?boolean',
disable_raft_on_small_clusters = '?boolean',
set_cookie_hash_membership = '?boolean',

transport = '?string',
ssl_ciphers = '?string',
Expand Down Expand Up @@ -645,8 +675,18 @@ local function cfg(opts, box_opts)
if opts.alias == nil then
opts.alias = args.instance_name
end
local encryption_key = cluster_cookie.cookie()

if opts.set_cookie_hash_membership == true then
encryption_key = digest.md5_hex(encryption_key)
else
log.warn(
'Consider changing membership encryption key to cookie hash manually. ' ..
'set_cookie_hash_membership will be true by default in next releases.'
)
end

membership.set_encryption_key(cluster_cookie.cookie())
membership.set_encryption_key(encryption_key)
membership.set_payload('alias', opts.alias)

local probe_uri_opts, err = argparse.get_opts({probe_uri_timeout = 'number'})
Expand Down
1 change: 1 addition & 0 deletions cartridge/argparse.lua
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ local cluster_opts = {
enable_synchro_mode = 'boolean', -- **boolean**
disable_raft_on_small_clusters = 'boolean', -- **boolean**
enable_failover_suppressing = 'boolean', -- **boolean**
set_cookie_hash_membership = 'boolean', -- **boolean**

twophase_netbox_call_timeout = 'number', -- **number**
twophase_upload_config_timeout = 'number', -- **number**
Expand Down
24 changes: 24 additions & 0 deletions rst/cartridge_admin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1764,6 +1764,30 @@ a broken cluster). To do it, perform next actions:
local clusterwide_config = confapplier.get_active_config()
return confapplier.apply_config(clusterwide_config)
.. _cartridge-membership-change-encription-key:

-------------------------------------------------------------------------------
Changing membership encryption key
-------------------------------------------------------------------------------

Since Cartridge 2.11.0 you can use hash of cluster cookie instead
of plian cookie as encryption key in membership.

To migrate to this feature, perform next actions:

#. Set new encryption key on each instance:

.. code-block:: lua
local cluster_cookie = require('cartridge.cluster-cookie')
local digest = require('digest')
local membership = require('membership')
membership.set_encryption_key(digest.md5_hex(cluster_cookie.cookie()))
#. Set param ``set_cookie_hash_membership`` in ``cartridge.cfg`` to ``true``
in your ``init.lua`` file, or use environment variables. Don't forget to
persist this setting.

.. _cartridge-fix-config:

Expand Down
76 changes: 76 additions & 0 deletions test/integration/two_cluster_32_symbol_cookie_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
local fio = require('fio')
local digest = require('digest')
local t = require('luatest')
local g = t.group()

local helpers = require('test.helper')

g.before_all = function()
local cookie = digest.urandom(16):hex()

g.cluster1 = helpers.Cluster:new({
datadir = fio.tempdir(),
server_command = helpers.entrypoint('srv_basic'),
cookie = cookie..'a',
replicasets = {
{
alias = 'master',
uuid = helpers.uuid('a'),
roles = {},
servers = {{
http_port = 8081,
advertise_port = 13301,
instance_uuid = helpers.uuid('a', 'a', 1)
}},
}
},
env = {
TARANTOOL_SET_COOKIE_HASH_MEMBERSHIP = 'true',
}
})

g.cluster1:start()

g.cluster2 = helpers.Cluster:new({
datadir = fio.tempdir(),
server_command = helpers.entrypoint('srv_basic'),
cookie = cookie..'b',
replicasets = {
{
alias = 'master',
uuid = helpers.uuid('b'),
roles = {},
servers = {{
http_port = 8082,
advertise_port = 13302,
instance_uuid = helpers.uuid('b', 'b', 1)
}},
}
},
env = {
TARANTOOL_SET_COOKIE_HASH_MEMBERSHIP = 'true',
}
})

g.cluster2.servers[1]:start()
-- this instance is seen by the first cluster
-- because of membership encryption key
-- ignores keys with lenght > 32 symbols
-- setting TARANTOOL_SET_COOKIE_HASH_MEMBERSHIP to true
-- fixes this bug
end

g.after_all = function()
g.cluster1:stop()
fio.rmtree(g.cluster1.datadir)
g.cluster2:stop()
fio.rmtree(g.cluster2.datadir)
end

function g.test_two_clusters()
local res = g.cluster1.main_server:exec(function()
local members = require('membership').members()
return members['localhost:13302']
end)
t.assert_not(res)
end

0 comments on commit 4bf7999

Please sign in to comment.