Skip to content

Commit f001417

Browse files
georgiy-belyaninTotktonada
authored andcommitted
config: apply lua_call privileges before bootstrap
This patch is a bugfix of the `lua_call` runtime access implemented in commit 38c6b0d ("config: grant runtime access to lua_call from config"). One of the main reason for runtime privileges is to allow granting guest user `lua_call` access before the initial bootstrap. During the implementation of the #10857 in terms of the new behavior of the supervised failover with the supervised bootstrap strategy it turned out runtime privileges haven't been added as a first-phase applier making it impossible to executing some of the lua functions before the initial bootstrap. This patch fixes it by adding a first-phase applier. For instance, you might allow guest connection to fetch information on instances before the bootstrap by configuring `credentials` section like this. ```yaml credentials: guest: privileges: - permissions: [ execute ] lua_call: [box.info] ``` NO_DOC=see tarantool/doc#4552, added a comment on it
1 parent 76c8264 commit f001417

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
## bugfix/config
2+
3+
* Now runtime `lua_call` privileges are also applied before the initial
4+
bootstrap, making it possible to permit some functions to be executed by the
5+
guest user before setting up the cluster.

src/box/lua/config/init.lua

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -297,14 +297,15 @@ function methods._store(self, iconfig, cconfig, source_info)
297297
self._configdata = configdata.new(iconfig, cconfig, self._instance_name)
298298
end
299299

300-
-- Invoke lua, compat, mkdir, console and box_cfg appliers at the
301-
-- first phase. Invoke all the other ones at the second phase.
300+
-- Invoke the appliers depending on the phase. The first phase
301+
-- might be long due to the long recovery process.
302302
function methods._apply_on_startup(self, opts)
303303
local first_phase_appliers = {
304304
lua = true,
305305
compat = true,
306306
mkdir = true,
307307
console = true,
308+
runtime_priv = true,
308309
box_cfg = true,
309310
}
310311

@@ -381,10 +382,10 @@ function methods._startup(self, instance_name, config_file)
381382

382383
-- Startup phase 1/2.
383384
--
384-
-- Start compat, mkdir, console and box_cfg appliers. The
385-
-- latter may force the read-only mode on this phase.
385+
-- Start first-phase appliers. The box_cfg applier may force
386+
-- the read-only mode on this phase.
386387
--
387-
-- This phase may take a long time.
388+
-- This phase may take a long time due to recovery.
388389
self:_store(self:_collect({sync_source = 'all'}))
389390
local needs_retry = self:_apply_on_startup({phase = 1})
390391

test/config-luatest/runtime_priv_test.lua

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local t = require('luatest')
2+
local net_box = require('net.box')
23
local cbuilder = require('luatest.cbuilder')
34
local cluster = require('test.config-luatest.cluster')
45

@@ -201,3 +202,46 @@ g.test_no_user_privileges_lua_call_ro_mode = function()
201202
end)
202203
end)
203204
end
205+
206+
g.test_direct_lua_call_before_initial_bootstrap = function()
207+
local config = cbuilder:new()
208+
:set_global_option('replication.bootstrap_strategy', 'supervised')
209+
:set_global_option('replication.failover', 'off')
210+
:set_global_option('credentials.users.guest', {
211+
privileges = {
212+
lua_call_priv({'box.info', 'box.ctl.make_bootstrap_leader'}),
213+
},
214+
})
215+
:add_instance('i-001', {database = {mode = 'rw'}})
216+
:add_instance('i-002', {database = {mode = 'ro'}})
217+
:config()
218+
219+
-- Don't wait for the startup since the cluster stays in
220+
-- the initial `box.cfg{}` and waits for the leader appoint.
221+
local cluster = cluster.new(g, config)
222+
cluster:start({wait_until_ready = false})
223+
local server = cluster['i-001']
224+
225+
-- Guest is the only user it's possible to connect as.
226+
local conn
227+
t.helpers.retrying({timeout = 60}, function()
228+
-- The schema can't be fetched before the bootstrap.
229+
conn = net_box.connect(server.net_box_uri, {fetch_schema = false})
230+
t.assert_equals(conn.state, 'active')
231+
end)
232+
233+
-- The user `guest` can't use the `loadstring()` function
234+
-- because he has no such permissions.
235+
local exp_err = access_error_msg('guest', 'loadstring')
236+
t.assert_error_msg_equals(exp_err, conn.call, conn, 'loadstring')
237+
238+
-- Verify the guest might execute the configured functions
239+
-- and may bootstrap cluster by calling the
240+
-- `box.ctl.make_bootstrap_leader()` function.
241+
t.assert_equals(conn:call('box.info').status, 'loading')
242+
243+
conn:call('box.ctl.make_bootstrap_leader')
244+
t.helpers.retrying({timeout = 10}, function()
245+
t.assert_equals(conn:call('box.info').status, 'running')
246+
end)
247+
end

0 commit comments

Comments
 (0)