forked from tarantool/tarantool
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
config: grant runtime access to lua_call from config
This patch introduces the ability to grant execution privileges for Lua functions through declarative configuration, even when the database is in read-only mode or has an outdated schema version. Users can specify `lua_call: [<func_name>]`, enabling the execution of specified Lua functions (e.g., `failover:execute()` when all instance are in read-only mode). The `lua_call: [all]` option is also supported, allowing access to all global Lua functions except built-in ones, regardless of database mode or status. Privileges are still written to the database when possible for consistency and compatibility. Closes tarantool#10310 @TarantoolBot document Title: Grant runtime access to Lua functions via configuration It is now possible to grant execution privileges for Lua functions through the declarative configuration, even when the database is in read-only mode or has an outdated schema version. You can specify function permissions using the `lua_call` option in the configuration, for example: ```yaml credentials: users: alice: privileges: - permissions: [execute] lua_call: [my_func] ``` This grants the `alice` user permission to execute the `my_func` Lua function, regardless of the database's mode or status. The special option `lua_call: [all]` is also supported, granting access to all global Lua functions except built-in ones, bypassing database restrictions. Privileges will still be written to the database when possible to maintain compatibility and consistency with other privilege types.
- Loading branch information
1 parent
db27af7
commit 38c6b0d
Showing
6 changed files
with
363 additions
and
23 deletions.
There are no files selected for viewing
5 changes: 5 additions & 0 deletions
5
changelogs/unreleased/gh-10310-runtime-grant-lua-call-via-config.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## feature/config | ||
|
||
* Now users can specify the `lua_call` option to allow calling Lua functions | ||
even when the database is in read-only mode or has an outdated schema version | ||
(gh-10310). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
-- Extract and add functions from a user or a role definition to | ||
-- the `{[func_name] = true, <...>}` mapping `res`. | ||
-- | ||
-- The source is `lua_call` declarations. | ||
local function add_funcs(res, user_or_role_def) | ||
local privileges = user_or_role_def.privileges or {} | ||
|
||
for _, privilege in ipairs(privileges) do | ||
local permissions = privilege.permissions or {} | ||
local has_execute = false | ||
for _, perm in ipairs(permissions) do | ||
if perm == 'execute' then | ||
has_execute = true | ||
break | ||
end | ||
end | ||
if has_execute and privilege.lua_call ~= nil then | ||
for _, func_name in ipairs(privilege.lua_call) do | ||
res[func_name] = true | ||
end | ||
end | ||
end | ||
end | ||
|
||
-- Extract and add roles for the given user to the | ||
-- `{[role_name] = true, <...>}` mapping `res`, including | ||
-- transitively assigned (when a role is assigned to a role). | ||
local function add_roles(res, user_or_role_def, ctx) | ||
for _, role_name in ipairs(user_or_role_def.roles or {}) do | ||
-- Detect a recursion. | ||
if ctx.visited[role_name] then | ||
error(('Recursion detected: credentials.roles.%s depends on ' .. | ||
'itself'):format(role_name), 0) | ||
end | ||
|
||
-- Add the role into the result. | ||
res[role_name] = true | ||
|
||
-- Add the nested roles. | ||
-- | ||
-- Ignore unknown roles. For example, there is a | ||
-- built-in role 'super' that doesn't have to be | ||
-- configured. | ||
local role_def = ctx.roles[role_name] | ||
if role_def ~= nil then | ||
ctx.visited[role_name] = true | ||
add_roles(res, role_def, ctx) | ||
ctx.visited[role_name] = nil | ||
end | ||
end | ||
end | ||
|
||
-- Extract all the user's functions listed in the `lua_call` | ||
-- directives in the user definition or its roles assigned | ||
-- directly or transitively over the other roles. | ||
local function extract_funcs(user_name, ctx) | ||
local user_def = ctx.users[user_name] | ||
|
||
local roles = {} | ||
ctx.visited = {} | ||
add_roles(roles, user_def, ctx) | ||
ctx.visited = nil | ||
|
||
-- Collect a full set of functions for the given user. | ||
-- | ||
-- { | ||
-- [func_name] = true, | ||
-- <...>, | ||
-- } | ||
local funcs = {} | ||
add_funcs(funcs, user_def) | ||
for role_name, _ in pairs(roles) do | ||
local role_def = ctx.roles[role_name] | ||
if role_def ~= nil then | ||
add_funcs(funcs, role_def) | ||
end | ||
end | ||
|
||
return funcs | ||
end | ||
|
||
local function apply(config_module) | ||
-- Prepare a context with the configuration information to | ||
-- transform. | ||
local configdata = config_module._configdata | ||
local ctx = { | ||
roles = configdata:get('credentials.roles') or {}, | ||
users = configdata:get('credentials.users') or {}, | ||
} | ||
|
||
-- Collect a mapping from users to their granted functions. | ||
-- | ||
-- { | ||
-- [user_name] = { | ||
-- [func_name] = true, | ||
-- <...>, | ||
-- }, | ||
-- <...> | ||
-- } | ||
local res = {} | ||
for user_name, _ in pairs(ctx.users) do | ||
local funcs = extract_funcs(user_name, ctx) | ||
if next(funcs) ~= nil then | ||
res[user_name] = funcs | ||
end | ||
end | ||
|
||
-- Reset the runtime privileges and grant all the configured | ||
-- ones. | ||
box.internal.lua_call_runtime_priv_reset() | ||
for user_name, funcs in pairs(res) do | ||
for func_name, _ in pairs(funcs) do | ||
if func_name == 'all' then | ||
box.internal.lua_call_runtime_priv_grant(user_name, '') | ||
else | ||
box.internal.lua_call_runtime_priv_grant(user_name, func_name) | ||
end | ||
end | ||
end | ||
end | ||
|
||
return { | ||
name = 'runtime_priv', | ||
apply = apply, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.