[tarantool-patches] [PATCH 4/4] Add a privilege upgrade script and update tests.

Serge Petrenko sergepetrenko at tarantool.org
Tue Jul 17 18:47:47 MSK 2018


This patch adds a privilege upgrade script, which runs on upgrade to
1.10 and automatically grants CREATE,ALTER,DROP on objects and entities
to all users, who have READ and WRITE access on them.
Also all tests are rewritten to grant only necessary privileges, not
privileges to universe.

Closes #3539
---
 src/box/lua/upgrade.lua                     |  22 +++
 test/box-tap/auth.test.lua                  |   5 -
 test/box-tap/session.test.lua               |  15 +-
 test/box/access.result                      |   4 +-
 test/box/access.test.lua                    |   4 +-
 test/box/access_bin.result                  |   4 +-
 test/box/access_bin.test.lua                |   4 +-
 test/box/access_escalation.result           |  15 +-
 test/box/access_escalation.test.lua         |  10 +-
 test/box/access_misc.result                 |   4 +-
 test/box/access_misc.test.lua               |   4 +-
 test/box/call.result                        |   4 +-
 test/box/call.test.lua                      |   4 +-
 test/box/errinj.result                      |  30 +++-
 test/box/errinj.test.lua                    |  21 ++-
 test/box/net.box.result                     | 265 ++++++++++++++++++++++++++--
 test/box/net.box.test.lua                   | 121 +++++++++++--
 test/box/net_msg_max.result                 |  13 +-
 test/box/net_msg_max.test.lua               |   9 +-
 test/box/on_replace.result                  |   2 +-
 test/box/on_replace.test.lua                |   2 +-
 test/box/protocol.result                    |   9 +-
 test/box/protocol.test.lua                  |   5 +-
 test/box/push.result                        |  52 +++++-
 test/box/push.test.lua                      |  27 ++-
 test/box/schema_reload.result               |  32 +++-
 test/box/schema_reload.test.lua             |  16 +-
 test/box/sql.result                         |   9 +-
 test/box/sql.test.lua                       |   5 +-
 test/box/stat_net.result                    |   7 +-
 test/box/stat_net.test.lua                  |   5 +-
 test/engine/params.result                   |   6 -
 test/engine/params.test.lua                 |   2 -
 test/engine/replica_join.result             |   6 -
 test/engine/replica_join.test.lua           |   2 -
 test/replication/autobootstrap.result       |  23 ++-
 test/replication/autobootstrap.test.lua     |  10 +-
 test/replication/catch.result               |   6 -
 test/replication/catch.test.lua             |   2 -
 test/replication/errinj.result              |   3 -
 test/replication/errinj.test.lua            |   1 -
 test/replication/gc.result                  |   6 -
 test/replication/gc.test.lua                |   2 -
 test/replication/join_vclock.result         |   6 -
 test/replication/join_vclock.test.lua       |   2 -
 test/replication/skip_conflict_row.result   |   6 -
 test/replication/skip_conflict_row.test.lua |   2 -
 test/vinyl/replica_quota.result             |   6 -
 test/vinyl/replica_quota.test.lua           |   2 -
 test/wal_off/func_max.result                |  25 +--
 test/wal_off/func_max.test.lua              |  19 +-
 test/xlog/errinj.result                     |   9 +-
 test/xlog/errinj.test.lua                   |   4 +-
 test/xlog/misc.result                       |   9 +-
 test/xlog/misc.test.lua                     |   5 +-
 test/xlog/upgrade.result                    |   4 +-
 56 files changed, 672 insertions(+), 225 deletions(-)

diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index 0293f6ef8..e738d48e4 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -960,8 +960,30 @@ local function create_vsequence_space()
     box.space._vsequence:format(sequence_format)
 end
 
+local function upgrade_users_to_1_10_0()
+    local _priv = box.space[box.schema.PRIV_ID]
+    local _user = box.space[box.schema.USER_ID]
+
+    for _, user in _user:pairs() do
+        if user[0] ~= ADMIN and user[0] ~= SUPER then
+            for _, priv in _priv:pairs(user[0]) do
+                if bit.band(priv[5], box.priv.W) ~= 0 and
+                bit.band(priv[5], box.priv.R) ~= 0 then
+                    local new_privs = bit.bor(box.priv.A, box.priv.D)
+                    if priv[4] == 0 then
+                        new_privs = bit.bor(new_privs, box.priv.C)
+                    end
+                    _priv:update({priv[2], priv[3], priv[4]},
+                                 {{ "|", 5, new_privs}})
+                end
+            end
+        end
+    end
+end
+
 local function upgrade_to_1_10_0()
     create_vsequence_space()
+    upgrade_users_to_1_10_0()
 end
 
 
diff --git a/test/box-tap/auth.test.lua b/test/box-tap/auth.test.lua
index 272bd97dc..4e9879408 100755
--- a/test/box-tap/auth.test.lua
+++ b/test/box-tap/auth.test.lua
@@ -20,10 +20,7 @@ test:plan(42)
 local space = box.schema.space.create('tweedledum')
 local index = space:create_index('primary', { type = 'hash' })
 box.schema.user.create('test', {password='pass'})
-box.schema.user.grant('test', 'read,write,execute', 'universe')
 box.schema.user.create('test2', {password=''})
-box.schema.user.grant('test2', 'read,write,execute', 'universe')
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 -- check how authentication trigger work
 local msg, counter, succeeded
@@ -163,8 +160,6 @@ test:is(session.sync(), 0, "box.session.sync()")
 
 -- cleanup
 space:drop()
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
-box.schema.user.revoke('test', 'read,write,execute', 'universe')
 box.schema.user.drop('test', { if_exists = true})
 box.schema.user.drop("test2", { if_exists = true})
 
diff --git a/test/box-tap/session.test.lua b/test/box-tap/session.test.lua
index c3c07a67c..857bc643b 100755
--- a/test/box-tap/session.test.lua
+++ b/test/box-tap/session.test.lua
@@ -101,7 +101,8 @@ function audit_disconnect() box.space['tweedledum']:delete{session.id()} end
 test:is(type(session.on_connect(audit_connect)), "function", "type of trigger audit_connect on_connect")
 test:is(type(session.on_disconnect(audit_disconnect)), "function", "type of trigger audit_connect on_disconnect")
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read,write', 'space', 'tweedledum')
+box.schema.user.grant('guest', 'execute', 'universe')
 a = net.box.connect(HOST, PORT)
 test:ok(a:eval('return space:get{box.session.id()}[1] == session.id()'), "eval get_id")
 test:ok(a:eval('return session.sync() ~= 0'), "eval sync")
@@ -112,12 +113,12 @@ session.on_connect(nil, audit_connect)
 session.on_disconnect(nil, audit_disconnect)
 test:is(active_connections, 0, "active connections after other triggers")
 
-space:drop()
+space:drop() -- tweedledum
 
 test:is(session.uid(), 1, "uid == 1")
 test:is(session.user(), "admin", "user is admin")
 test:is(session.sync(), 0, "sync constant")
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 -- audit permission in on_connect/on_disconnect triggers
 box.schema.user.create('tester', { password = 'tester' })
@@ -199,7 +200,10 @@ function f2()
 	sync2 = box.session.sync()
 	cond:signal()
 end
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.func.create('f1')
+box.schema.func.create('f2')
+box.schema.user.grant('guest', 'execute', 'function', 'f1')
+box.schema.user.grant('guest', 'execute', 'function', 'f2')
 conn = net.box.connect(box.cfg.listen)
 test:ok(conn:ping(), 'connect to self')
 _ = fiber.create(function() conn:call('f1') end)
@@ -208,7 +212,8 @@ _ = fiber.create(function() conn:call('f2') end)
 while started ~= 2 do fiber.sleep(0.01) end
 test:isnt(sync1, sync2, 'session.sync() is request local')
 conn:close()
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'function', 'f1')
+box.schema.user.revoke('guest', 'execute', 'function', 'f2')
 
 inspector:cmd('stop server session with cleanup=1')
 session = nil
diff --git a/test/box/access.result b/test/box/access.result
index 9ea5568a5..f39678e26 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -370,7 +370,7 @@ box.schema.user.drop('uniuser')
 box.schema.user.create('grantor')
 ---
 ...
-box.schema.user.grant('grantor', 'read, write, execute', 'universe')
+box.schema.user.grant('grantor', 'read, write, execute, create, alter, drop', 'universe')
 ---
 ...
 session.su('grantor')
@@ -379,7 +379,7 @@ session.su('grantor')
 box.schema.user.create('grantee')
 ---
 ...
-box.schema.user.grant('grantee', 'read, write, execute', 'universe')
+box.schema.user.grant('grantee', 'read, write, execute, create, alter, drop', 'universe')
 ---
 - error: Grant access to universe '' is denied for user 'grantor'
 ...
diff --git a/test/box/access.test.lua b/test/box/access.test.lua
index 6ad7ee462..ee62df5fb 100644
--- a/test/box/access.test.lua
+++ b/test/box/access.test.lua
@@ -167,10 +167,10 @@ box.schema.user.drop('uniuser')
 -- only by its creator at the moment
 -- ------------------------------------------------------------
 box.schema.user.create('grantor')
-box.schema.user.grant('grantor', 'read, write, execute', 'universe')
+box.schema.user.grant('grantor', 'read, write, execute, create, alter, drop', 'universe')
 session.su('grantor')
 box.schema.user.create('grantee')
-box.schema.user.grant('grantee', 'read, write, execute', 'universe')
+box.schema.user.grant('grantee', 'read, write, execute, create, alter, drop', 'universe')
 session.su('grantee')
 -- fails - can't suicide - ask the creator to kill you
 box.schema.user.drop('grantee')
diff --git a/test/box/access_bin.result b/test/box/access_bin.result
index 7b30d11f2..df8ef8dee 100644
--- a/test/box/access_bin.result
+++ b/test/box/access_bin.result
@@ -8,7 +8,7 @@ test_run = env.new()
 -- Access control tests which require a binary protocol
 -- connection to the server
 --
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest','execute','universe')
 ---
 ...
 session = box.session
@@ -30,7 +30,7 @@ c:eval("return session.user()")
 c:close()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 ---
 ...
 -- gh-488 suid functions
diff --git a/test/box/access_bin.test.lua b/test/box/access_bin.test.lua
index 4c7a6d08f..e77d8c0a8 100644
--- a/test/box/access_bin.test.lua
+++ b/test/box/access_bin.test.lua
@@ -4,14 +4,14 @@ test_run = env.new()
 -- Access control tests which require a binary protocol
 -- connection to the server
 --
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest','execute','universe')
 session = box.session
 remote = require('net.box')
 c = remote.connect(box.cfg.listen)
 c:eval("session.su('admin')")
 c:eval("return session.user()")
 c:close()
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 -- gh-488 suid functions
 --
diff --git a/test/box/access_escalation.result b/test/box/access_escalation.result
index a83f1ee8a..3991a7fab 100644
--- a/test/box/access_escalation.result
+++ b/test/box/access_escalation.result
@@ -84,7 +84,7 @@ box.schema.user.create('underprivileged')
 box.schema.user.grant('underprivileged', 'read,write', 'space', '_func')
 ---
 ...
-box.schema.user.grant('underprivileged', 'create', 'universe')
+box.schema.user.grant('underprivileged', 'create', 'function')
 ---
 ...
 box.session.su('underprivileged')
@@ -99,7 +99,16 @@ box.session.su('admin')
 --
 -- create a deprived function
 --
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.func.create('escalation')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'setuid')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'escalation')
+---
+...
+box.schema.user.grant('guest', 'read', 'space', '_space')
 ---
 ...
 connection = net:connect(os.getenv("LISTEN"))
@@ -119,7 +128,7 @@ fiber.cancel(background)
 box.schema.user.drop('underprivileged')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.func.drop('escalation')
 ---
 ...
 connection:close()
diff --git a/test/box/access_escalation.test.lua b/test/box/access_escalation.test.lua
index 29b14c8ea..5aeed683d 100644
--- a/test/box/access_escalation.test.lua
+++ b/test/box/access_escalation.test.lua
@@ -61,7 +61,7 @@ connection:close()
 
 box.schema.user.create('underprivileged')
 box.schema.user.grant('underprivileged', 'read,write', 'space', '_func')
-box.schema.user.grant('underprivileged', 'create', 'universe')
+box.schema.user.grant('underprivileged', 'create', 'function')
 box.session.su('underprivileged')
 box.schema.func.create('setuid', {setuid=true})
 box.session.su('admin')
@@ -69,7 +69,10 @@ box.session.su('admin')
 -- create a deprived function
 --
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.func.create('escalation')
+box.schema.user.grant('guest', 'execute', 'function', 'setuid')
+box.schema.user.grant('guest', 'execute', 'function', 'escalation')
+box.schema.user.grant('guest', 'read', 'space', '_space')
 
 connection = net:connect(os.getenv("LISTEN"))
 
@@ -80,6 +83,5 @@ fiber.cancel(background)
 -- tear down
 
 box.schema.user.drop('underprivileged')
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
-
+box.schema.func.drop('escalation')
 connection:close()
diff --git a/test/box/access_misc.result b/test/box/access_misc.result
index 0f4892533..9291c413a 100644
--- a/test/box/access_misc.result
+++ b/test/box/access_misc.result
@@ -208,7 +208,7 @@ s:select()
 box.schema.user.create('uniuser')
 ---
 ...
-box.schema.user.grant('uniuser', 'read, write, execute', 'universe')
+box.schema.user.grant('uniuser', 'read, write, execute, create', 'universe')
 ---
 ...
 session.su('uniuser')
@@ -291,7 +291,7 @@ session.su('admin')
 box.schema.user.create('someuser')
 ---
 ...
-box.schema.user.grant('someuser', 'read, write, execute', 'universe')
+box.schema.user.grant('someuser', 'read, write, execute, create', 'universe')
 ---
 ...
 session.su('someuser')
diff --git a/test/box/access_misc.test.lua b/test/box/access_misc.test.lua
index 7dd796f62..b9fccb44e 100644
--- a/test/box/access_misc.test.lua
+++ b/test/box/access_misc.test.lua
@@ -86,7 +86,7 @@ s:select()
 -- and create this user session
 --
 box.schema.user.create('uniuser')
-box.schema.user.grant('uniuser', 'read, write, execute', 'universe')
+box.schema.user.grant('uniuser', 'read, write, execute, create', 'universe')
 session.su('uniuser')
 uid = session.uid()
 --
@@ -123,7 +123,7 @@ box.schema.func.create('uniuser_func')
 
 session.su('admin')
 box.schema.user.create('someuser')
-box.schema.user.grant('someuser', 'read, write, execute', 'universe')
+box.schema.user.grant('someuser', 'read, write, execute, create', 'universe')
 session.su('someuser')
 --
 -- Check drop objects of another user
diff --git a/test/box/call.result b/test/box/call.result
index 40d7ef952..349e5ce40 100644
--- a/test/box/call.result
+++ b/test/box/call.result
@@ -1,4 +1,4 @@
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'execute', 'universe')
 ---
 ...
 conn = require('net.box').connect(box.cfg.listen)
@@ -748,6 +748,6 @@ conn:close()
 require('msgpack').cfg { encode_sparse_safe = sparse_safe }
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 ---
 ...
diff --git a/test/box/call.test.lua b/test/box/call.test.lua
index 0cc3b8fe6..a74aac4d1 100644
--- a/test/box/call.test.lua
+++ b/test/box/call.test.lua
@@ -1,4 +1,4 @@
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'execute', 'universe')
 
 conn = require('net.box').connect(box.cfg.listen)
 conn:ping()
@@ -240,4 +240,4 @@ conn:call_16("return_sparse4")
 conn:close()
 require('msgpack').cfg { encode_sparse_safe = sparse_safe }
 
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
diff --git a/test/box/errinj.result b/test/box/errinj.result
index 54b6d578f..d89c82247 100644
--- a/test/box/errinj.result
+++ b/test/box/errinj.result
@@ -784,7 +784,7 @@ test_run:cmd('setopt delimiter ""');
 - true
 ...
 -- Port_dump can fail.
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read', 'space', '_space')
 ---
 ...
 cn = net_box.connect(box.cfg.listen)
@@ -816,7 +816,7 @@ errinj.set('ERRINJ_PORT_DUMP', false)
 cn:close()
 ---
 ...
-box.schema.user.revoke('guest', 'read, write, execute', 'universe')
+box.schema.user.revoke('guest', 'read', 'space', '_space')
 ---
 ...
 run()
@@ -1069,15 +1069,15 @@ s:drop()
 -- gh-3255: iproto can crash and discard responses, if a network
 -- is saturated, and DML yields too long on commit.
 --
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 s = box.schema.space.create('test')
 ---
 ...
 _ = s:create_index('pk')
 ---
 ...
+box.schema.user.grant('guest', 'read,write,alter', 'space', 'test')
+---
+...
 c = net_box.connect(box.cfg.listen)
 ---
 ...
@@ -1108,12 +1108,21 @@ s:drop()
 -- gh-3325: do not cancel already sent requests, when a schema
 -- change is detected.
 --
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
 s = box.schema.create_space('test')
 ---
 ...
 pk = s:create_index('pk')
 ---
 ...
+box.schema.user.grant('guest', 'read,write,alter', 'space', 'test')
+---
+...
+box.schema.user.grant('guest', 'write', 'space', '_index')
+---
+...
 s:replace{1, 1}
 ---
 - [1, 1]
@@ -1164,6 +1173,9 @@ cn:close()
 s:drop()
 ---
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 --
 -- If message memory pool is used up, stop the connection, until
 -- the pool has free memory.
@@ -1189,6 +1201,12 @@ function long_poll_f()
 end;
 ---
 ...
+box.schema.func.create('long_poll_f');
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'long_poll_f');
+---
+...
 test_run:cmd('setopt delimiter ""');
 ---
 - true
@@ -1250,7 +1268,7 @@ while finished ~= 2 do fiber.sleep(0.01) end
 cn:close()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute','universe')
+box.schema.user.revoke('guest', 'execute', 'function', 'long_poll_f')
 ---
 ...
 --
diff --git a/test/box/errinj.test.lua b/test/box/errinj.test.lua
index 185ae19fc..5046159b5 100644
--- a/test/box/errinj.test.lua
+++ b/test/box/errinj.test.lua
@@ -245,7 +245,7 @@ test_run:cmd('setopt delimiter ""');
 
 -- Port_dump can fail.
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read', 'space', '_space')
 
 cn = net_box.connect(box.cfg.listen)
 cn:ping()
@@ -255,7 +255,7 @@ assert(not ok)
 assert(string.match(tostring(ret), 'Failed to allocate'))
 errinj.set('ERRINJ_PORT_DUMP', false)
 cn:close()
-box.schema.user.revoke('guest', 'read, write, execute', 'universe')
+box.schema.user.revoke('guest', 'read', 'space', '_space')
 
 run()
 ch:get()
@@ -350,10 +350,9 @@ s:drop()
 -- is saturated, and DML yields too long on commit.
 --
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 s = box.schema.space.create('test')
 _ = s:create_index('pk')
-
+box.schema.user.grant('guest', 'read,write,alter', 'space', 'test')
 c = net_box.connect(box.cfg.listen)
 
 ch = fiber.channel(200)
@@ -369,8 +368,14 @@ s:drop()
 -- gh-3325: do not cancel already sent requests, when a schema
 -- change is detected.
 --
+
+box.schema.user.grant('guest', 'execute', 'universe')
+
 s = box.schema.create_space('test')
 pk = s:create_index('pk')
+
+box.schema.user.grant('guest', 'read,write,alter', 'space', 'test')
+box.schema.user.grant('guest', 'write', 'space', '_index')
 s:replace{1, 1}
 cn = net_box.connect(box.cfg.listen)
 errinj.set("ERRINJ_WAL_DELAY", true)
@@ -388,6 +393,7 @@ while ok == nil do fiber.sleep(0.01) end
 ok, err
 cn:close()
 s:drop()
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 --
 -- If message memory pool is used up, stop the connection, until
@@ -403,6 +409,10 @@ function long_poll_f()
     while not continue do fiber.sleep(0.01) end
     finished = finished + 1
 end;
+
+box.schema.func.create('long_poll_f');
+box.schema.user.grant('guest', 'execute', 'function', 'long_poll_f');
+
 test_run:cmd('setopt delimiter ""');
 cn = net_box.connect(box.cfg.listen)
 function long_poll() cn:call('long_poll_f') end
@@ -428,8 +438,7 @@ errinj.set("ERRINJ_TESTING", false)
 while finished ~= 2 do fiber.sleep(0.01) end
 cn:close()
 
-box.schema.user.revoke('guest', 'read,write,execute','universe')
-
+box.schema.user.revoke('guest', 'execute', 'function', 'long_poll_f')
 --
 -- gh-3289: drop/truncate leaves the space in inconsistent
 -- state if WAL write fails.
diff --git a/test/box/net.box.result b/test/box/net.box.result
index d521534fe..2cfddba72 100644
--- a/test/box/net.box.result
+++ b/test/box/net.box.result
@@ -203,6 +203,9 @@ remote.self:eval('!invalid expression')
 ---
 - error: '[string "return !invalid expression"]:1: unexpected symbol near ''!'''
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 --
 -- gh-822: net.box.call should roll back local transaction on error
 --
@@ -265,10 +268,10 @@ test_run:cmd("setopt delimiter ''");
 box.space.gh822:drop()
 ---
 ...
-box.schema.user.revoke('guest','execute','universe')
+box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space')
 ---
 ...
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest', 'execute', 'universe')
 ---
 ...
 cn:close()
@@ -496,6 +499,15 @@ cn.space.net_box_test_space:get(354)
 - [354, 1, 2, 4]
 ...
 -- reconnects after errors
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
+box.schema.func.create('test_foo')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'test_foo')
+---
+...
 -- -- 1. no reconnect
 x_fatal(cn)
 ---
@@ -593,6 +605,12 @@ type(fiber.create(function() fiber.sleep(.5) x_fatal(cn) end))
 function pause() fiber.sleep(10) return true end
 ---
 ...
+box.schema.func.create('pause')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'pause')
+---
+...
 cn:call('pause')
 ---
 - error: Peer closed
@@ -601,6 +619,9 @@ cn:call('test_foo', {'a', 'b', 'c'})
 ---
 - [[{'a': 1}], [{'b': 2}], 'c']
 ...
+box.schema.func.drop('pause')
+---
+...
 -- call
 remote.self:call('test_foo', {'a', 'b', 'c'})
 ---
@@ -612,6 +633,15 @@ cn:call('test_foo', {'a', 'b', 'c'})
 ---
 - [[{'a': 1}], [{'b': 2}], 'c']
 ...
+box.schema.func.drop('test_foo')
+---
+...
+box.schema.func.create('long_rep')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'long_rep')
+---
+...
 -- long replies
 function long_rep() return { 1,  string.rep('a', 5000) } end
 ---
@@ -641,6 +671,9 @@ res[2] == string.rep('a', 50000)
 ---
 - true
 ...
+box.schema.func.drop('long_rep')
+---
+...
 -- a.b.c.d
 u = '84F7BCFA-079C-46CC-98B4-F0C821BE833E'
 ---
@@ -654,6 +687,15 @@ X.X = X
 function X.fn(x,y) return y or x end
 ---
 ...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
+cn:close()
+---
+...
+cn = remote.connect(LISTEN.host, LISTEN.service)
+---
+...
 cn:call('X.fn', {u})
 ---
 - 84F7BCFA-079C-46CC-98B4-F0C821BE833E
@@ -666,6 +708,12 @@ cn:call('X.X.X.X:fn', {u})
 ---
 - 84F7BCFA-079C-46CC-98B4-F0C821BE833E
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
+cn:close()
+---
+...
 -- auth
 cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123', wait_connected = true })
 ---
@@ -685,7 +733,10 @@ cn.state
 box.schema.user.create('netbox', { password  = 'test' })
 ---
 ...
-box.schema.user.grant('netbox', 'read, write, execute', 'universe');
+box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space')
+---
+...
+box.schema.user.grant('netbox', 'execute', 'universe')
 ---
 ...
 cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = 'test' })
@@ -1089,6 +1140,15 @@ cn:close()
 cn = remote.connect(LISTEN.host, LISTEN.service)
 ---
 ...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
+cn:close()
+---
+...
+cn = remote.connect(LISTEN.host, LISTEN.service)
+---
+...
 cn:eval('return true')
 ---
 - true
@@ -1112,6 +1172,9 @@ remote.self.eval('return true')
 ---
 - error: 'Use remote:eval(...) instead of remote.eval(...):'
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 -- uri as the first argument
 uri = string.format('%s:%s@%s:%s', 'netbox', 'test', LISTEN.host, LISTEN.service)
 ---
@@ -1156,13 +1219,16 @@ cn:ping()
 cn:close()
 ---
 ...
-box.schema.user.revoke('netbox', 'read, write, execute', 'universe');
----
-...
 box.schema.user.drop('netbox')
 ---
 ...
 -- #594: bad argument #1 to 'setmetatable' (table expected, got number)
+box.schema.func.create('dostring')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'dostring')
+---
+...
 test_run:cmd("setopt delimiter ';'")
 ---
 - true
@@ -1182,6 +1248,9 @@ test_run:cmd("setopt delimiter ''");
 gh594()
 ---
 ...
+box.schema.func.drop('dostring')
+---
+...
 -- #636: Reload schema on demand
 sp = box.schema.space.create('test_old')
 ---
@@ -1193,6 +1262,9 @@ sp:insert{1, 2, 3}
 ---
 - [1, 2, 3]
 ...
+box.schema.user.grant('guest', 'read', 'space', 'test_old')
+---
+...
 con = remote.new(box.cfg.listen)
 ---
 ...
@@ -1218,6 +1290,9 @@ sp:insert{2, 3, 4}
 ---
 - [2, 3, 4]
 ...
+box.schema.user.grant('guest', 'read', 'space', 'test')
+---
+...
 con.space.test == nil
 ---
 - true
@@ -1248,6 +1323,9 @@ file_log:seek(0, 'SEEK_END') ~= 0
 ---
 - true
 ...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
 test_run:cmd("setopt delimiter ';'")
 ---
 - true
@@ -1269,6 +1347,9 @@ test_run:grep_log("default", "ER_NO_SUCH_PROC")
 ---
 - ER_NO_SUCH_PROC
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 -- gh-983 selecting a lot of data crashes the server or hangs the
 -- connection
 -- gh-983 test case: iproto connection selecting a lot of data
@@ -1284,6 +1365,9 @@ data1k = "aaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabb
 for i = 0,10000 do box.space.test:insert{i, data1k} end
 ---
 ...
+box.schema.user.grant('guest', 'read', 'space', 'test')
+---
+...
 net = require('net.box')
 ---
 ...
@@ -1309,6 +1393,9 @@ _ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned
 _ = box.space.test:insert{1, 2, "string"}
 ---
 ...
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
+---
+...
 c = net:connect(box.cfg.listen)
 ---
 ...
@@ -1365,6 +1452,9 @@ box.space.test:drop()
 function echo(...) return ... end
 ---
 ...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
 c = net.connect(box.cfg.listen)
 ---
 ...
@@ -1404,6 +1494,9 @@ c:eval('return echo(...)', 42)
 c:close()
 ---
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 --
 -- gh-2195 export pure msgpack from net.box
 --
@@ -1413,6 +1506,12 @@ space = box.schema.space.create('test')
 _ = box.space.test:create_index('primary')
 ---
 ...
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
+---
+...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
 c = net.connect(box.cfg.listen)
 ---
 ...
@@ -1648,6 +1747,9 @@ c:close()
 space:drop()
 ---
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 -- gh-1904 net.box hangs in :close() if a fiber was cancelled
 -- while blocked in :_wait_state() in :_request()
 options = {user = 'netbox', password = 'badpass', wait_connected = false, reconnect_after = 0.01}
@@ -1665,6 +1767,9 @@ fiber.sleep(0.01)
 f:cancel(); c:close()
 ---
 ...
+box.schema.user.grant('guest', 'read', 'space', '_schema')
+---
+...
 -- check for on_schema_reload callback
 test_run:cmd("setopt delimiter ';'")
 ---
@@ -1717,7 +1822,7 @@ test_run:cmd("setopt delimiter ''");
 ---
 - true
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'read', 'space', '_schema')
 ---
 ...
 -- Tarantool < 1.7.1 compatibility (gh-1533)
@@ -1806,7 +1911,7 @@ space ~= nil
 _ = box.space.test:create_index('primary')
 ---
 ...
-box.schema.user.grant('guest','read,write,execute','space', 'test')
+box.schema.user.grant('guest', 'read', 'space', 'test')
 ---
 ...
 c = net.connect(box.cfg.listen)
@@ -1885,7 +1990,7 @@ c:close()
 --
 -- gh-2642: box.session.type()
 --
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest','execute','universe')
 ---
 ...
 c = net.connect(box.cfg.listen)
@@ -1898,6 +2003,9 @@ c:call("box.session.type")
 c:close()
 ---
 ...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
 --
 -- On_connect/disconnect triggers.
 --
@@ -1977,6 +2085,9 @@ space:drop()
 space = box.schema.space.create('test')
 ---
 ...
+box.schema.user.grant('guest', 'read', 'space', 'test')
+---
+...
 c = net.connect(box.cfg.listen)
 ---
 ...
@@ -2010,16 +2121,28 @@ c.space.test.index.test_index ~= nil
 - true
 ...
 -- cleanup
-box.schema.user.revoke('guest','read,write,execute','universe')
----
-...
 space:drop()
 ---
 ...
 --
 -- gh-946: long polling CALL blocks input
 --
-box.schema.user.grant('guest', 'execute', 'universe')
+box.schema.func.create('fast_call')
+---
+...
+box.schema.func.create('long_call')
+---
+...
+box.schema.func.create('wait_signal')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'fast_call')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'long_call')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'wait_signal')
 ---
 ...
 c = net.connect(box.cfg.listen)
@@ -2136,6 +2259,15 @@ disconnected -- true
 box.session.on_disconnect(nil, on_disconnect)
 ---
 ...
+box.schema.func.drop('long_call')
+---
+...
+box.schema.func.drop('fast_call')
+---
+...
+box.schema.func.drop('wait_signal')
+---
+...
 --
 -- gh-2666: check that netbox.call is not repeated on schema
 -- change.
@@ -2155,6 +2287,12 @@ count = 0
 function create_space(name) count = count + 1 box.schema.create_space(name) return true end
 ---
 ...
+box.schema.func.create('create_space')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'create_space')
+---
+...
 c = net.connect(box.cfg.listen)
 ---
 ...
@@ -2203,6 +2341,9 @@ box.schema.user.revoke('guest', 'create', 'universe')
 c:close()
 ---
 ...
+box.schema.func.drop('create_space')
+---
+...
 --
 -- gh-3164: netbox connection is not closed and garbage collected
 -- ever, if reconnect_after is set.
@@ -2311,7 +2452,7 @@ weak.c
 -- binary or text protocol, and netbox could not be created from
 -- existing socket.
 --
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest', 'execute', 'universe')
 ---
 ...
 urilib = require('uri')
@@ -2350,6 +2491,9 @@ c:call('kek', {300})
 s = box.schema.create_space('test')
 ---
 ...
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
+---
+...
 pk = s:create_index('pk')
 ---
 ...
@@ -2404,7 +2548,7 @@ while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end
 c:close()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 ---
 ...
 c.state
@@ -2420,7 +2564,7 @@ c = nil
 space = box.schema.create_space('test')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read', 'space', 'test')
 ---
 ...
 _ = space:create_index('pk')
@@ -2444,6 +2588,15 @@ space:drop()
 space = box.schema.create_space('test')
 ---
 ...
+c:close()
+---
+...
+box.schema.user.grant('guest', 'read', 'space', 'test')
+---
+...
+c = net:connect(box.cfg.listen)
+---
+...
 box.internal.collation.create('test', 'ICU', 'ru-RU')
 ---
 ...
@@ -2482,6 +2635,12 @@ c = nil
 cond = nil
 ---
 ...
+box.schema.func.create('long_function')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'long_function')
+---
+...
 function long_function(...) cond = fiber.cond() cond:wait() return ... end
 ---
 ...
@@ -2589,6 +2748,15 @@ ret
 ---
 - [1, 2, 3]
 ...
+c:close()
+---
+...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
+c = net:connect(box.cfg.listen)
+---
+...
 future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true})
 ---
 ...
@@ -2609,6 +2777,15 @@ future:wait_result(100)
 ---
 - [1, 2, 3]
 ...
+c:close()
+---
+...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
+c = net:connect(box.cfg.listen)
+---
+...
 --
 -- Ensure the request is garbage collected both if is not used and
 -- if is.
@@ -2716,6 +2893,15 @@ ret
 --
 -- Test space methods.
 --
+c:close()
+---
+...
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
+---
+...
+c = net:connect(box.cfg.listen)
+---
+...
 future = c.space.test:select({1}, {is_async = true})
 ---
 ...
@@ -2822,6 +3008,15 @@ future:wait_result(100)
 ---
 - [5, 6]
 ...
+c:close()
+---
+...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
+c = net:connect(box.cfg.listen)
+---
+...
 future = c.space.test.index.pk:count({3}, {is_async = true})
 ---
 ...
@@ -2829,6 +3024,15 @@ future:wait_result(100)
 ---
 - 1
 ...
+c:close()
+---
+...
+box.schema.user.revoke('guest', 'execute', 'universe')
+---
+...
+c = net:connect(box.cfg.listen)
+---
+...
 future = c.space.test.index.pk:delete({3}, {is_async = true})
 ---
 ...
@@ -2997,12 +3201,30 @@ result
 ---
 - {48: [1, 2, 3]}
 ...
+box.schema.func.drop('long_function')
+---
+...
 --
 -- Test async schema version change.
 --
 function change_schema(i) local tmp = box.schema.create_space('test'..i) return 'ok' end
 ---
 ...
+box.schema.func.create('change_schema')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'change_schema')
+---
+...
+box.schema.user.grant('guest', 'write', 'space', '_schema')
+---
+...
+box.schema.user.grant('guest', 'read,write', 'space', '_space')
+---
+...
+box.schema.user.grant('guest', 'create', 'space')
+---
+...
 future1 = c:call('change_schema', {'1'}, {is_async = true})
 ---
 ...
@@ -3039,6 +3261,9 @@ box.space.test2:drop()
 box.space.test3:drop()
 ---
 ...
+box.schema.func.drop('change_schema')
+---
+...
 --
 -- gh-3400: long-poll input discard must not touch event loop of
 -- a closed connection.
@@ -3090,6 +3315,12 @@ test_run:grep_log('default', 'too big packet size in the header') ~= nil
 ---
 - true
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'write', 'space', '_schema')
+---
+...
+box.schema.user.revoke('guest', 'read,write', 'space', '_space')
+---
+...
+box.schema.user.revoke('guest', 'create', 'space')
 ---
 ...
diff --git a/test/box/net.box.test.lua b/test/box/net.box.test.lua
index 623475d41..bf575c6bc 100644
--- a/test/box/net.box.test.lua
+++ b/test/box/net.box.test.lua
@@ -31,7 +31,6 @@ log.info("ping is done")
 
 cn:ping()
 
-
 -- check permissions
 cn:call('unexists_procedure')
 function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end
@@ -73,6 +72,8 @@ remote.self:eval('error("exception")')
 remote.self:eval('box.error(0)')
 remote.self:eval('!invalid expression')
 
+box.schema.user.revoke('guest', 'execute', 'universe')
+
 --
 -- gh-822: net.box.call should roll back local transaction on error
 --
@@ -113,8 +114,9 @@ rollback_on_eval_error();
 test_run:cmd("setopt delimiter ''");
 box.space.gh822:drop()
 
-box.schema.user.revoke('guest','execute','universe')
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space')
+box.schema.user.grant('guest', 'execute', 'universe')
+
 cn:close()
 cn = remote.connect(box.cfg.listen)
 
@@ -189,6 +191,10 @@ cn.space.net_box_test_space:get(354)
 
 -- reconnects after errors
 
+box.schema.user.revoke('guest', 'execute', 'universe')
+box.schema.func.create('test_foo')
+box.schema.user.grant('guest', 'execute', 'function', 'test_foo')
+
 -- -- 1. no reconnect
 x_fatal(cn)
 cn.state
@@ -224,13 +230,19 @@ cn1:close()
 type(fiber.create(function() fiber.sleep(.5) x_fatal(cn) end))
 function pause() fiber.sleep(10) return true end
 
+box.schema.func.create('pause')
+box.schema.user.grant('guest', 'execute', 'function', 'pause')
 cn:call('pause')
 cn:call('test_foo', {'a', 'b', 'c'})
-
+box.schema.func.drop('pause')
 
 -- call
 remote.self:call('test_foo', {'a', 'b', 'c'})
 cn:call('test_foo', {'a', 'b', 'c'})
+box.schema.func.drop('test_foo')
+
+box.schema.func.create('long_rep')
+box.schema.user.grant('guest', 'execute', 'function', 'long_rep')
 
 -- long replies
 function long_rep() return { 1,  string.rep('a', 5000) } end
@@ -243,14 +255,21 @@ res = cn:call('long_rep')
 res[1] == 1
 res[2] == string.rep('a', 50000)
 
+box.schema.func.drop('long_rep')
+
 -- a.b.c.d
 u = '84F7BCFA-079C-46CC-98B4-F0C821BE833E'
 X = {}
 X.X = X
 function X.fn(x,y) return y or x end
+box.schema.user.grant('guest', 'execute', 'universe')
+cn:close()
+cn = remote.connect(LISTEN.host, LISTEN.service)
 cn:call('X.fn', {u})
 cn:call('X.X.X.X.X.X.X.fn', {u})
 cn:call('X.X.X.X:fn', {u})
+box.schema.user.revoke('guest', 'execute', 'universe')
+cn:close()
 
 -- auth
 
@@ -259,9 +278,10 @@ cn:is_connected()
 cn.error
 cn.state
 
-box.schema.user.create('netbox', { password  = 'test' })
-box.schema.user.grant('netbox', 'read, write, execute', 'universe');
 
+box.schema.user.create('netbox', { password  = 'test' })
+box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space')
+box.schema.user.grant('netbox', 'execute', 'universe')
 cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = 'test' })
 cn.state
 cn.error
@@ -404,6 +424,9 @@ cn:close()
 -- #544 usage for remote[point]method
 cn = remote.connect(LISTEN.host, LISTEN.service)
 
+box.schema.user.grant('guest', 'execute', 'universe')
+cn:close()
+cn = remote.connect(LISTEN.host, LISTEN.service)
 cn:eval('return true')
 cn.eval('return true')
 
@@ -413,7 +436,7 @@ cn:close()
 
 remote.self:eval('return true')
 remote.self.eval('return true')
-
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 -- uri as the first argument
 uri = string.format('%s:%s@%s:%s', 'netbox', 'test', LISTEN.host, LISTEN.service)
@@ -432,10 +455,11 @@ cn = remote.new(uri, { user = 'netbox', password = 'test' })
 cn:ping()
 cn:close()
 
-box.schema.user.revoke('netbox', 'read, write, execute', 'universe');
 box.schema.user.drop('netbox')
 
 -- #594: bad argument #1 to 'setmetatable' (table expected, got number)
+box.schema.func.create('dostring')
+box.schema.user.grant('guest', 'execute', 'function', 'dostring')
 test_run:cmd("setopt delimiter ';'")
 function gh594()
     local cn = remote.connect(box.cfg.listen)
@@ -445,12 +469,15 @@ function gh594()
 end;
 test_run:cmd("setopt delimiter ''");
 gh594()
+box.schema.func.drop('dostring')
+
 
 -- #636: Reload schema on demand
 sp = box.schema.space.create('test_old')
 _ = sp:create_index('primary')
 sp:insert{1, 2, 3}
 
+box.schema.user.grant('guest', 'read', 'space', 'test_old')
 con = remote.new(box.cfg.listen)
 con:ping()
 con.space.test_old:select{}
@@ -460,6 +487,8 @@ sp = box.schema.space.create('test')
 _ = sp:create_index('primary')
 sp:insert{2, 3, 4}
 
+box.schema.user.grant('guest', 'read', 'space', 'test')
+
 con.space.test == nil
 con:reload_schema()
 con.space.test:select{}
@@ -472,6 +501,7 @@ name = string.match(arg[0], "([^,]+)%.lua")
 file_log = require('fio').open(name .. '.log', {'O_RDONLY', 'O_NONBLOCK'})
 file_log:seek(0, 'SEEK_END') ~= 0
 
+box.schema.user.grant('guest', 'execute', 'universe')
 test_run:cmd("setopt delimiter ';'")
 
 _ = fiber.create(
@@ -483,6 +513,7 @@ _ = fiber.create(
 );
 test_run:cmd("setopt delimiter ''");
 test_run:grep_log("default", "ER_NO_SUCH_PROC")
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 -- gh-983 selecting a lot of data crashes the server or hangs the
 -- connection
@@ -495,6 +526,7 @@ data1k = "aaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabb
 
 for i = 0,10000 do box.space.test:insert{i, data1k} end
 
+box.schema.user.grant('guest', 'read', 'space', 'test')
 net = require('net.box')
 c = net:connect(box.cfg.listen)
 r = c.space.test:select(nil, {limit=5000})
@@ -505,6 +537,7 @@ _ = box.schema.space.create('test')
 _ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}})
 _ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}})
 _ = box.space.test:insert{1, 2, "string"}
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
 c = net:connect(box.cfg.listen)
 c.space.test:select{}
 c.space.test:upsert({1, 2, 'nothing'}, {{'+', 2, 1}}) -- common update
@@ -522,6 +555,7 @@ box.space.test:drop()
 
 -- CALL vs CALL_16 in connect options
 function echo(...) return ... end
+box.schema.user.grant('guest', 'execute', 'universe')
 c = net.connect(box.cfg.listen)
 c:call('echo', {42})
 c:eval('return echo(...)', {42})
@@ -533,6 +567,7 @@ c = net.connect(box.cfg.listen, {call_16 = true})
 c:call('echo', 42)
 c:eval('return echo(...)', 42)
 c:close()
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 --
 -- gh-2195 export pure msgpack from net.box
@@ -540,6 +575,8 @@ c:close()
 
 space = box.schema.space.create('test')
 _ = box.space.test:create_index('primary')
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
+box.schema.user.grant('guest', 'execute', 'universe')
 c = net.connect(box.cfg.listen)
 ibuf = require('buffer').ibuf()
 
@@ -626,6 +663,7 @@ ibuf.rpos == rpos, ibuf.wpos == wpos
 ibuf = nil
 c:close()
 space:drop()
+box.schema.user.revoke('guest', 'execute', 'universe')
 
 -- gh-1904 net.box hangs in :close() if a fiber was cancelled
 -- while blocked in :_wait_state() in :_request()
@@ -635,6 +673,8 @@ f = fiber.create(function() c:call("") end)
 fiber.sleep(0.01)
 f:cancel(); c:close()
 
+box.schema.user.grant('guest', 'read', 'space', '_schema')
+
 -- check for on_schema_reload callback
 test_run:cmd("setopt delimiter ';'")
 do
@@ -676,7 +716,7 @@ do
 end;
 test_run:cmd("setopt delimiter ''");
 
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'read', 'space', '_schema')
 
 -- Tarantool < 1.7.1 compatibility (gh-1533)
 c = net.new(box.cfg.listen)
@@ -722,7 +762,7 @@ test_run:cmd("clear filter")
 space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}})
 space ~= nil
 _ = box.space.test:create_index('primary')
-box.schema.user.grant('guest','read,write,execute','space', 'test')
+box.schema.user.grant('guest', 'read', 'space', 'test')
 
 c = net.connect(box.cfg.listen)
 
@@ -762,10 +802,12 @@ c:close()
 -- gh-2642: box.session.type()
 --
 
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest','execute','universe')
 c = net.connect(box.cfg.listen)
 c:call("box.session.type")
 c:close()
+box.schema.user.revoke('guest', 'execute', 'universe')
+
 
 --
 -- On_connect/disconnect triggers.
@@ -795,6 +837,7 @@ test_run:cmd('stop server connecter')
 --
 space:drop()
 space = box.schema.space.create('test')
+box.schema.user.grant('guest', 'read', 'space', 'test')
 c = net.connect(box.cfg.listen)
 cspace = c.space.test
 space.index.test_index == nil
@@ -806,15 +849,18 @@ cspace.index.test_index ~= nil
 c.space.test.index.test_index ~= nil
 
 -- cleanup
-box.schema.user.revoke('guest','read,write,execute','universe')
 
 space:drop()
 
 --
 -- gh-946: long polling CALL blocks input
 --
-box.schema.user.grant('guest', 'execute', 'universe')
-
+box.schema.func.create('fast_call')
+box.schema.func.create('long_call')
+box.schema.func.create('wait_signal')
+box.schema.user.grant('guest', 'execute', 'function', 'fast_call')
+box.schema.user.grant('guest', 'execute', 'function', 'long_call')
+box.schema.user.grant('guest', 'execute', 'function', 'wait_signal')
 c = net.connect(box.cfg.listen)
 
 N = 100
@@ -871,6 +917,9 @@ disconnected -- true
 
 box.session.on_disconnect(nil, on_disconnect)
 
+box.schema.func.drop('long_call')
+box.schema.func.drop('fast_call')
+box.schema.func.drop('wait_signal')
 --
 -- gh-2666: check that netbox.call is not repeated on schema
 -- change.
@@ -880,6 +929,8 @@ box.schema.user.grant('guest', 'write', 'space', '_schema')
 box.schema.user.grant('guest', 'create', 'universe')
 count = 0
 function create_space(name) count = count + 1 box.schema.create_space(name) return true end
+box.schema.func.create('create_space')
+box.schema.user.grant('guest', 'execute', 'function', 'create_space')
 c = net.connect(box.cfg.listen)
 c:call('create_space', {'test1'})
 count
@@ -894,6 +945,7 @@ box.schema.user.revoke('guest', 'write', 'space', '_space')
 box.schema.user.revoke('guest', 'write', 'space', '_schema')
 box.schema.user.revoke('guest', 'create', 'universe')
 c:close()
+box.schema.func.drop('create_space')
 
 --
 -- gh-3164: netbox connection is not closed and garbage collected
@@ -946,7 +998,7 @@ weak.c
 -- binary or text protocol, and netbox could not be created from
 -- existing socket.
 --
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest', 'execute', 'universe')
 urilib = require('uri')
 uri = urilib.parse(tostring(box.cfg.listen))
 s, greeting = net.establish_connection(uri.host, uri.service)
@@ -959,6 +1011,7 @@ c:eval('a = 200')
 a
 c:call('kek', {300})
 s = box.schema.create_space('test')
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
 pk = s:create_index('pk')
 c:reload_schema()
 c.space.test:replace{1}
@@ -983,7 +1036,7 @@ c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = fals
 while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end
 c:close()
 
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 c.state
 c = nil
 
@@ -991,7 +1044,7 @@ c = nil
 -- gh-3256 net.box is_nullable and collation options output
 --
 space = box.schema.create_space('test')
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read', 'space', 'test')
 _ = space:create_index('pk')
 _ = space:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}})
 c = net:connect(box.cfg.listen)
@@ -999,6 +1052,9 @@ c.space.test.index.sk.parts
 space:drop()
 
 space = box.schema.create_space('test')
+c:close()
+box.schema.user.grant('guest', 'read', 'space', 'test')
+c = net:connect(box.cfg.listen)
 box.internal.collation.create('test', 'ICU', 'ru-RU')
 _ = space:create_index('sk', { type = 'tree', parts = {{1, 'str', collation = 'test'}}, unique = true })
 c:reload_schema()
@@ -1013,6 +1069,8 @@ c = nil
 -- gh-3107: fiber-async netbox.
 --
 cond = nil
+box.schema.func.create('long_function')
+box.schema.user.grant('guest', 'execute', 'function', 'long_function')
 function long_function(...) cond = fiber.cond() cond:wait() return ... end
 function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end
 s = box.schema.create_space('test')
@@ -1050,13 +1108,19 @@ _ = fiber.create(function() ret = c:call('long_function', {1, 2, 3}, {is_async =
 finalize_long()
 while not ret do fiber.sleep(0.01) end
 ret
-
+c:close()
+box.schema.user.grant('guest', 'execute', 'universe')
+c = net:connect(box.cfg.listen)
 future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true})
 future:result()
 future:wait_result(0.01) -- Must fail on timeout.
 finalize_long()
 future:wait_result(100)
 
+c:close()
+box.schema.user.revoke('guest', 'execute', 'universe')
+c = net:connect(box.cfg.listen)
+
 --
 -- Ensure the request is garbage collected both if is not used and
 -- if is.
@@ -1095,6 +1159,9 @@ ret
 --
 -- Test space methods.
 --
+c:close()
+box.schema.user.grant('guest', 'read,write', 'space', 'test')
+c = net:connect(box.cfg.listen)
 future = c.space.test:select({1}, {is_async = true})
 ret = future:wait_result(100)
 ret
@@ -1128,8 +1195,14 @@ future = c.space.test.index.pk:min({}, {is_async = true})
 future:wait_result(100)
 future = c.space.test.index.pk:max({}, {is_async = true})
 future:wait_result(100)
+c:close()
+box.schema.user.grant('guest', 'execute', 'universe')
+c = net:connect(box.cfg.listen)
 future = c.space.test.index.pk:count({3}, {is_async = true})
 future:wait_result(100)
+c:close()
+box.schema.user.revoke('guest', 'execute', 'universe')
+c = net:connect(box.cfg.listen)
 future = c.space.test.index.pk:delete({3}, {is_async = true})
 future:wait_result(100)
 s:get{3}
@@ -1194,10 +1267,17 @@ future:wait_result(100)
 result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos)
 result
 
+box.schema.func.drop('long_function')
+
 --
 -- Test async schema version change.
 --
 function change_schema(i) local tmp = box.schema.create_space('test'..i) return 'ok' end
+box.schema.func.create('change_schema')
+box.schema.user.grant('guest', 'execute', 'function', 'change_schema')
+box.schema.user.grant('guest', 'write', 'space', '_schema')
+box.schema.user.grant('guest', 'read,write', 'space', '_space')
+box.schema.user.grant('guest', 'create', 'space')
 future1 = c:call('change_schema', {'1'}, {is_async = true})
 future2 = c:call('change_schema', {'2'}, {is_async = true})
 future3 = c:call('change_schema', {'3'}, {is_async = true})
@@ -1210,6 +1290,7 @@ s:drop()
 box.space.test1:drop()
 box.space.test2:drop()
 box.space.test3:drop()
+box.schema.func.drop('change_schema')
 
 --
 -- gh-3400: long-poll input discard must not touch event loop of
@@ -1238,4 +1319,6 @@ c._transport.perform_request(nil, nil, 'inject', nil, nil, data)
 c:close()
 test_run:grep_log('default', 'too big packet size in the header') ~= nil
 
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'write', 'space', '_schema')
+box.schema.user.revoke('guest', 'read,write', 'space', '_space')
+box.schema.user.revoke('guest', 'create', 'space')
diff --git a/test/box/net_msg_max.result b/test/box/net_msg_max.result
index ccda2014e..85872b65f 100644
--- a/test/box/net_msg_max.result
+++ b/test/box/net_msg_max.result
@@ -7,7 +7,13 @@ fiber = require('fiber')
 net_box = require('net.box')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read', 'space', '_space')
+---
+...
+box.schema.func.create('do_long_f')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'do_long_f')
 ---
 ...
 conn = net_box.connect(box.cfg.listen)
@@ -252,7 +258,10 @@ conn2:close()
 conn:close()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.func.drop('do_long_f')
+---
+...
+box.schema.user.revoke('guest', 'read', 'space', '_space')
 ---
 ...
 box.cfg{readahead = old_readahead, net_msg_max = limit}
diff --git a/test/box/net_msg_max.test.lua b/test/box/net_msg_max.test.lua
index 13f7050ed..c793b0f1c 100644
--- a/test/box/net_msg_max.test.lua
+++ b/test/box/net_msg_max.test.lua
@@ -3,7 +3,10 @@ test_run = require('test_run').new()
 fiber = require('fiber')
 net_box = require('net.box')
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.user.grant('guest', 'read', 'space', '_space')
+box.schema.func.create('do_long_f')
+box.schema.user.grant('guest', 'execute', 'function', 'do_long_f')
+
 conn = net_box.connect(box.cfg.listen)
 conn2 = net_box.connect(box.cfg.listen)
 active = 0
@@ -79,6 +82,7 @@ wait_finished(run_max)
 --
 -- Test minimal iproto msg count.
 --
+
 box.cfg{net_msg_max = 2}
 conn:ping()
 #conn.space._space:select{} > 0
@@ -136,5 +140,6 @@ wait_finished(110)
 conn2:close()
 conn:close()
 
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.func.drop('do_long_f')
+box.schema.user.revoke('guest', 'read', 'space', '_space')
 box.cfg{readahead = old_readahead, net_msg_max = limit}
diff --git a/test/box/on_replace.result b/test/box/on_replace.result
index fcdb43794..20ffe6412 100644
--- a/test/box/on_replace.result
+++ b/test/box/on_replace.result
@@ -540,7 +540,7 @@ s:select()
 ---
 - []
 ...
-s:drop()
+s:drop() -- test_on_repl_ddl
 ---
 ...
 --
diff --git a/test/box/on_replace.test.lua b/test/box/on_replace.test.lua
index 802aaaf2a..8a9fd3678 100644
--- a/test/box/on_replace.test.lua
+++ b/test/box/on_replace.test.lua
@@ -202,7 +202,7 @@ s:replace({8, 9})
 t = s:on_replace(function () s.index.pk:rename('newname') end, t)
 s:replace({9, 10})
 s:select()
-s:drop()
+s:drop() -- test_on_repl_ddl
 
 --
 -- gh-3020: sub-statement rollback
diff --git a/test/box/protocol.result b/test/box/protocol.result
index 3e43663b1..e03186cc9 100644
--- a/test/box/protocol.result
+++ b/test/box/protocol.result
@@ -1,6 +1,3 @@
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 --------------------------------------------------------------------------------
 -- Test case for #273: IPROTO_ITERATOR ignored in network protocol
 --------------------------------------------------------------------------------
@@ -10,6 +7,9 @@ space = box.schema.space.create('tweedledum')
 index = space:create_index('primary', { type = 'tree'})
 ---
 ...
+box.schema.user.grant('guest', 'read', 'space', 'tweedledum')
+---
+...
 for i=1,5 do space:insert{i} end
 ---
 ...
@@ -51,6 +51,3 @@ conn:close()
 space:drop()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/box/protocol.test.lua b/test/box/protocol.test.lua
index 5026d585e..805a43721 100644
--- a/test/box/protocol.test.lua
+++ b/test/box/protocol.test.lua
@@ -1,4 +1,3 @@
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 --------------------------------------------------------------------------------
 -- Test case for #273: IPROTO_ITERATOR ignored in network protocol
@@ -6,6 +5,9 @@ box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 space = box.schema.space.create('tweedledum')
 index = space:create_index('primary', { type = 'tree'})
+
+box.schema.user.grant('guest', 'read', 'space', 'tweedledum')
+
 for i=1,5 do space:insert{i} end
 
 LISTEN = require('uri').parse(box.cfg.listen)
@@ -18,4 +20,3 @@ conn.space[space.id]:select(3, { iterator = 'LT' })
 conn:close()
 
 space:drop()
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/box/push.result b/test/box/push.result
index 4ec7c546c..af730c1a7 100644
--- a/test/box/push.result
+++ b/test/box/push.result
@@ -42,7 +42,10 @@ test_run:cmd("setopt delimiter ''");
 netbox = require('net.box')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+box.schema.func.create('do_pushes')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'do_pushes')
 ---
 ...
 c = netbox.connect(box.cfg.listen)
@@ -78,6 +81,9 @@ finished = 0
 s = box.schema.create_space('test', {format = {{'field1', 'integer'}}})
 ---
 ...
+box.schema.user.grant('guest', 'write', 'space', 'test')
+---
+...
 pk = s:create_index('pk')
 ---
 ...
@@ -133,6 +139,12 @@ function dml_push_and_dml_f()
 end;
 ---
 ...
+box.schema.func.create('dml_push_and_dml');
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'dml_push_and_dml');
+---
+...
 -- At first check that a pushed message can be ignored in a binary
 -- protocol too.
 c:call('do_pushes', {300});
@@ -149,6 +161,8 @@ end;
 while finished ~= 400 do fiber.sleep(0.1) end;
 ---
 ...
+box.schema.func.drop('dml_push_and_dml')
+
 failed_catchers = {};
 ---
 ...
@@ -196,6 +210,12 @@ function push_null() box.session.push(box.NULL) end
 messages = {}
 ---
 ...
+box.schema.func.create('push_null')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'push_null')
+---
+...
 c:call('push_null', {}, {on_push = table.insert, on_push_ctx = messages})
 ---
 ...
@@ -203,6 +223,9 @@ messages
 ---
 - - null
 ...
+box.schema.func.drop('push_null')
+---
+...
 --
 -- Test binary pushes.
 --
@@ -272,6 +295,12 @@ t = setmetatable({100}, {__serialize = function() error('err in ser') end})
 function do_push() ok, err = box.session.push(t) end
 ---
 ...
+box.schema.func.create('do_push')
+---
+...
+box.schema.user.grant("guest", "execute", "function", "do_push")
+---
+...
 c:call('do_push', {}, {on_push = table.insert, on_push_ctx = messages})
 ---
 ...
@@ -284,6 +313,9 @@ messages
 ---
 - []
 ...
+box.schema.func.drop('do_push')
+---
+...
 --
 -- Test push from a non-call request.
 --
@@ -417,9 +449,18 @@ s:replace{1}
 ---
 - [1]
 ...
+box.schema.user.grant('guest', 'write', 'space', 'test')
+---
+...
 function do_push_and_duplicate() box.session.push(100) s:insert{1} end
 ---
 ...
+box.schema.func.create('do_push_and_duplicate')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'do_push_and_duplicate')
+---
+...
 future = c:call('do_push_and_duplicate', {}, {is_async = true})
 ---
 ...
@@ -447,12 +488,15 @@ keys
 - - 1
   - null
 ...
-s:drop()
+box.schema.func.drop('do_push_and_duplicate')
 ---
 ...
-c:close()
+box.schema.func.drop('do_pushes')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+s:drop()
+---
+...
+c:close()
 ---
 ...
diff --git a/test/box/push.test.lua b/test/box/push.test.lua
index 36dc9eeb1..0d2bec3fe 100644
--- a/test/box/push.test.lua
+++ b/test/box/push.test.lua
@@ -23,7 +23,9 @@ end;
 test_run:cmd("setopt delimiter ''");
 
 netbox = require('net.box')
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
+
+box.schema.func.create('do_pushes')
+box.schema.user.grant('guest', 'execute', 'function', 'do_pushes')
 
 c = netbox.connect(box.cfg.listen)
 c:ping()
@@ -37,6 +39,7 @@ catchers = {}
 started = 0
 finished = 0
 s = box.schema.create_space('test', {format = {{'field1', 'integer'}}})
+box.schema.user.grant('guest', 'write', 'space', 'test')
 pk = s:create_index('pk')
 c:reload_schema()
 test_run:cmd("setopt delimiter ';'")
@@ -77,6 +80,9 @@ function dml_push_and_dml_f()
     table.insert(catchers, catcher)
     finished = finished + 1
 end;
+box.schema.func.create('dml_push_and_dml');
+box.schema.user.grant('guest', 'execute', 'function', 'dml_push_and_dml');
+
 -- At first check that a pushed message can be ignored in a binary
 -- protocol too.
 c:call('do_pushes', {300});
@@ -87,6 +93,8 @@ for i = 1, 200 do
 end;
 while finished ~= 400 do fiber.sleep(0.1) end;
 
+box.schema.func.drop('dml_push_and_dml')
+
 failed_catchers = {};
 
 for _, c in pairs(catchers) do
@@ -121,9 +129,11 @@ failed_catchers
 --
 function push_null() box.session.push(box.NULL) end
 messages = {}
+box.schema.func.create('push_null')
+box.schema.user.grant('guest', 'execute', 'function', 'push_null')
 c:call('push_null', {}, {on_push = table.insert, on_push_ctx = messages})
 messages
-
+box.schema.func.drop('push_null')
 --
 -- Test binary pushes.
 --
@@ -148,10 +158,12 @@ err = nil
 messages = {}
 t = setmetatable({100}, {__serialize = function() error('err in ser') end})
 function do_push() ok, err = box.session.push(t) end
+box.schema.func.create('do_push')
+box.schema.user.grant("guest", "execute", "function", "do_push")
 c:call('do_push', {}, {on_push = table.insert, on_push_ctx = messages})
 ok, err
 messages
-
+box.schema.func.drop('do_push')
 --
 -- Test push from a non-call request.
 --
@@ -187,7 +199,6 @@ function do_pushes()
     return true
 end;
 test_run:cmd("setopt delimiter ''");
-
 -- Can not combine callback and async mode.
 ok, err = pcall(c.call, c, 'do_pushes', {}, {is_async = true, on_push = function() end})
 ok
@@ -209,7 +220,11 @@ s = box.schema.create_space('test')
 pk = s:create_index('pk')
 s:replace{1}
 
+box.schema.user.grant('guest', 'write', 'space', 'test')
+
 function do_push_and_duplicate() box.session.push(100) s:insert{1} end
+box.schema.func.create('do_push_and_duplicate')
+box.schema.user.grant('guest', 'execute', 'function', 'do_push_and_duplicate')
 future = c:call('do_push_and_duplicate', {}, {is_async = true})
 future:wait_result(1000)
 messages = {}
@@ -218,7 +233,7 @@ for i, message in future:pairs() do table.insert(messages, message) table.insert
 messages
 keys
 
+box.schema.func.drop('do_push_and_duplicate')
+box.schema.func.drop('do_pushes')
 s:drop()
 c:close()
-
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/box/schema_reload.result b/test/box/schema_reload.result
index 31f215bc3..c927e4fcf 100644
--- a/test/box/schema_reload.result
+++ b/test/box/schema_reload.result
@@ -1,6 +1,3 @@
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 net_box = require('net.box')
 ---
 ...
@@ -17,6 +14,9 @@ s = box.schema.create_space('test')
 i = s:create_index('primary')
 ---
 ...
+box.schema.user.grant('guest', 'read', 'space', 'test')
+---
+...
 cn = net_box.connect(LISTEN.host, LISTEN.service)
 ---
 ...
@@ -35,6 +35,9 @@ s2 = box.schema.create_space('test2')
 i2 = s2:create_index('primary')
 ---
 ...
+box.schema.user.grant('guest', 'read', 'space', 'test2')
+---
+...
 ----------------------------------
 -- TEST #1 simple reload
 ----------------------------------
@@ -123,6 +126,9 @@ s:drop()
 s2:drop()
 ---
 ...
+cn:close()
+---
+...
 --------------------------------------------------------------------------------
 -- gh-1808: support schema_version in CALL, EVAL and PING
 --------------------------------------------------------------------------------
@@ -177,6 +183,12 @@ bump_schema_version()
 function somefunc() return true end
 ---
 ...
+box.schema.func.create('somefunc')
+---
+...
+box.schema.user.grant('guest', 'execute', 'function', 'somefunc')
+---
+...
 cn:call('somefunc')
 ---
 - true
@@ -209,6 +221,18 @@ cn.schema_version == schema_version + 1
 ---
 - true
 ...
+box.schema.func.drop('somefunc')
+---
+...
+cn:close()
+---
+...
+box.schema.user.grant('guest', 'execute', 'universe')
+---
+...
+cn = net_box.connect(box.cfg.listen)
+---
+...
 -- eval
 schema_version = cn.schema_version
 ---
@@ -271,6 +295,6 @@ box.internal.schema_version() == schema_version + 1
 if box.space.bump_schema_version ~= nil then box.space.bump_schema_version:drop() end
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
 ---
 ...
diff --git a/test/box/schema_reload.test.lua b/test/box/schema_reload.test.lua
index 48ccb169c..cdfbfca75 100644
--- a/test/box/schema_reload.test.lua
+++ b/test/box/schema_reload.test.lua
@@ -1,4 +1,3 @@
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 net_box = require('net.box')
 fiber = require('fiber')
 LISTEN = require('uri').parse(box.cfg.listen)
@@ -6,6 +5,7 @@ LISTEN = require('uri').parse(box.cfg.listen)
 -- create first space
 s = box.schema.create_space('test')
 i = s:create_index('primary')
+box.schema.user.grant('guest', 'read', 'space', 'test')
 cn = net_box.connect(LISTEN.host, LISTEN.service)
 
 -- check that schema is correct
@@ -15,6 +15,7 @@ old_schema_version = cn.schema_version
 -- create one more space
 s2 = box.schema.create_space('test2')
 i2 = s2:create_index('primary')
+box.schema.user.grant('guest', 'read', 'space', 'test2')
 
 ----------------------------------
 -- TEST #1 simple reload
@@ -66,6 +67,7 @@ request_fiber:cancel()
 reload_fiber:cancel()
 s:drop()
 s2:drop()
+cn:close()
 
 --------------------------------------------------------------------------------
 -- gh-1808: support schema_version in CALL, EVAL and PING
@@ -95,6 +97,8 @@ cn.schema_version == schema_version + 1
 schema_version = cn.schema_version
 bump_schema_version()
 function somefunc() return true end
+box.schema.func.create('somefunc')
+box.schema.user.grant('guest', 'execute', 'function', 'somefunc')
 cn:call('somefunc')
 wait_new_schema()
 cn.schema_version == schema_version + 1
@@ -107,6 +111,12 @@ cn:call('somefunc')
 wait_new_schema()
 cn.schema_version == schema_version + 1
 
+box.schema.func.drop('somefunc')
+
+cn:close()
+box.schema.user.grant('guest', 'execute', 'universe')
+cn = net_box.connect(box.cfg.listen)
+
 -- eval
 schema_version = cn.schema_version
 bump_schema_version()
@@ -125,6 +135,7 @@ somefunc = nil
 
 cn:close()
 
+
 -- box.internal.schema_version()
 schema_version = box.internal.schema_version()
 schema_version > 0
@@ -132,5 +143,4 @@ bump_schema_version()
 box.internal.schema_version() == schema_version + 1
 
 if box.space.bump_schema_version ~= nil then box.space.bump_schema_version:drop() end
-
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'execute', 'universe')
diff --git a/test/box/sql.result b/test/box/sql.result
index 11a698850..a6c572f35 100644
--- a/test/box/sql.result
+++ b/test/box/sql.result
@@ -16,7 +16,10 @@ _ = box.schema.space.create('test1', { id = 555 })
 box.schema.user.create('test', { password = 'test' })
 ---
 ...
-box.schema.user.grant('test', 'execute,read,write', 'universe')
+box.schema.user.grant('test', 'read,write,alter', 'space', 'test1')
+---
+...
+box.schema.user.grant('test', 'read,write,alter', 'space', 'test')
 ---
 ...
 conn = net_box.connect('test:test@' .. box.cfg.listen)
@@ -228,10 +231,10 @@ net_box = require('net.box')
 box.schema.user.create('test', { password = 'test' })
 ---
 ...
-box.schema.user.grant('test', 'execute,read,write', 'universe')
+s = box.schema.space.create('tweedledum')
 ---
 ...
-s = box.schema.space.create('tweedledum')
+box.schema.user.grant('test', 'read,write,alter', 'space', 'tweedledum')
 ---
 ...
 index1 = s:create_index('primary', { type = 'tree', parts = { 1, 'string'} })
diff --git a/test/box/sql.test.lua b/test/box/sql.test.lua
index b1ba4168c..0523311ee 100644
--- a/test/box/sql.test.lua
+++ b/test/box/sql.test.lua
@@ -5,7 +5,8 @@ net_box = require('net.box')
 s = box.schema.space.create('test')
 _ = box.schema.space.create('test1', { id = 555 })
 box.schema.user.create('test', { password = 'test' })
-box.schema.user.grant('test', 'execute,read,write', 'universe')
+box.schema.user.grant('test', 'read,write,alter', 'space', 'test1')
+box.schema.user.grant('test', 'read,write,alter', 'space', 'test')
 
 conn = net_box.connect('test:test@' .. box.cfg.listen)
 space = conn.space.test
@@ -92,8 +93,8 @@ net_box = require('net.box')
 
 -- Prepare spaces
 box.schema.user.create('test', { password = 'test' })
-box.schema.user.grant('test', 'execute,read,write', 'universe')
 s = box.schema.space.create('tweedledum')
+box.schema.user.grant('test', 'read,write,alter', 'space', 'tweedledum')
 index1 = s:create_index('primary', { type = 'tree', parts = { 1, 'string'} })
 index2 = s:create_index('secondary', { type = 'tree', unique = false, parts = {2, 'string'}})
 function compare(a,b) return a[1] < b[1] end
diff --git a/test/box/stat_net.result b/test/box/stat_net.result
index fc1379920..b3e3db11f 100644
--- a/test/box/stat_net.result
+++ b/test/box/stat_net.result
@@ -19,7 +19,7 @@ box.stat.net.RECEIVED -- zero
 space = box.schema.space.create('tweedledum')
 ---
 ...
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest', 'read', 'space', 'tweedledum')
 ---
 ...
 index = space:create_index('primary', { type = 'hash' })
@@ -60,12 +60,9 @@ box.stat.net.RECEIVED.total
 ---
 - 0
 ...
-space:drop()
+space:drop() -- tweedledum
 ---
 ...
 cn:close()
 ---
 ...
-box.schema.user.revoke('guest','read,write,execute','universe')
----
-...
diff --git a/test/box/stat_net.test.lua b/test/box/stat_net.test.lua
index 9ddc55789..808bb71e7 100644
--- a/test/box/stat_net.test.lua
+++ b/test/box/stat_net.test.lua
@@ -7,7 +7,7 @@ box.stat.net.SENT -- zero
 box.stat.net.RECEIVED -- zero
 
 space = box.schema.space.create('tweedledum')
-box.schema.user.grant('guest','read,write,execute','universe')
+box.schema.user.grant('guest', 'read', 'space', 'tweedledum')
 index = space:create_index('primary', { type = 'hash' })
 remote = require 'net.box'
 
@@ -26,6 +26,5 @@ box.stat.reset()
 box.stat.net.SENT.total
 box.stat.net.RECEIVED.total
 
-space:drop()
+space:drop() -- tweedledum
 cn:close()
-box.schema.user.revoke('guest','read,write,execute','universe')
diff --git a/test/engine/params.result b/test/engine/params.result
index d5f4b3c82..debb40d40 100644
--- a/test/engine/params.result
+++ b/test/engine/params.result
@@ -8,9 +8,6 @@ inspector = test_run.new()
 engine = inspector:get_cfg('engine')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 s = box.schema.create_space('engine', {engine=engine})
 ---
 ...
@@ -30,6 +27,3 @@ box.space.engine:select{}
 box.space.engine:drop()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/engine/params.test.lua b/test/engine/params.test.lua
index 3272835a1..a7cb499fd 100644
--- a/test/engine/params.test.lua
+++ b/test/engine/params.test.lua
@@ -3,7 +3,6 @@ test_run = require('test_run')
 inspector = test_run.new()
 engine = inspector:get_cfg('engine')
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 s = box.schema.create_space('engine', {engine=engine})
 i = s:create_index('primary')
 
@@ -14,4 +13,3 @@ box.space.engine:select{}
 
 -- cleanup
 box.space.engine:drop()
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/engine/replica_join.result b/test/engine/replica_join.result
index 39d857fef..7d6f50a19 100644
--- a/test/engine/replica_join.result
+++ b/test/engine/replica_join.result
@@ -10,9 +10,6 @@ engine = test_run:get_cfg('engine')
 index = test_run:get_cfg('index')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 box.schema.user.grant('guest', 'replication')
 ---
 ...
@@ -535,6 +532,3 @@ box.snapshot()
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/engine/replica_join.test.lua b/test/engine/replica_join.test.lua
index 1792281e8..07320137b 100644
--- a/test/engine/replica_join.test.lua
+++ b/test/engine/replica_join.test.lua
@@ -2,7 +2,6 @@ env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
 index = test_run:get_cfg('index')
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 box.schema.user.grant('guest', 'replication')
 space = box.schema.space.create('test', { id = 99999, engine = engine })
 _ = space:create_index('primary', { type = index})
@@ -137,4 +136,3 @@ space:drop()
 box.snapshot()
 
 box.schema.user.revoke('guest', 'replication')
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/replication/autobootstrap.result b/test/replication/autobootstrap.result
index 04aeb4315..b660d0f2d 100644
--- a/test/replication/autobootstrap.result
+++ b/test/replication/autobootstrap.result
@@ -112,7 +112,16 @@ _ = test_run:cmd("switch autobootstrap1")
 u1 = box.schema.user.create('test_u')
 ---
 ...
-box.schema.user.grant('test_u', 'read,write,create', 'universe')
+box.schema.user.grant('test_u', 'create', 'space')
+---
+...
+box.schema.user.grant('test_u', 'read,write', 'space', '_space')
+---
+...
+box.schema.user.grant('test_u', 'write', 'space', '_schema')
+---
+...
+box.schema.user.grant('test_u', 'write', 'space', '_index')
 ---
 ...
 box.session.su('test_u')
@@ -131,6 +140,18 @@ box.space.test_u:select()
 ---
 - - [1, 2, 3, 4]
 ...
+box.schema.user.revoke('test_u', 'write', 'space', '_index')
+---
+...
+box.schema.user.revoke('test_u', 'write', 'space', '_schema')
+---
+...
+box.schema.user.revoke('test_u', 'read,write', 'space', '_space')
+---
+...
+box.schema.user.revoke('test_u', 'create', 'space')
+---
+...
 -- Synchronize
 vclock = test_run:get_vclock('autobootstrap1')
 ---
diff --git a/test/replication/autobootstrap.test.lua b/test/replication/autobootstrap.test.lua
index f1e2a9991..d952143b2 100644
--- a/test/replication/autobootstrap.test.lua
+++ b/test/replication/autobootstrap.test.lua
@@ -55,13 +55,21 @@ _ = test_run:cmd("switch default")
 
 _ = test_run:cmd("switch autobootstrap1")
 u1 = box.schema.user.create('test_u')
-box.schema.user.grant('test_u', 'read,write,create', 'universe')
+box.schema.user.grant('test_u', 'create', 'space')
+box.schema.user.grant('test_u', 'read,write', 'space', '_space')
+box.schema.user.grant('test_u', 'write', 'space', '_schema')
+box.schema.user.grant('test_u', 'write', 'space', '_index')
 box.session.su('test_u')
 _ = box.schema.space.create('test_u'):create_index('pk')
 box.session.su('admin')
 _ = box.space.test_u:replace({1, 2, 3, 4})
 box.space.test_u:select()
 
+box.schema.user.revoke('test_u', 'write', 'space', '_index')
+box.schema.user.revoke('test_u', 'write', 'space', '_schema')
+box.schema.user.revoke('test_u', 'read,write', 'space', '_space')
+box.schema.user.revoke('test_u', 'create', 'space')
+
 -- Synchronize
 vclock = test_run:get_vclock('autobootstrap1')
 _ = test_run:wait_vclock("autobootstrap2", vclock)
diff --git a/test/replication/catch.result b/test/replication/catch.result
index 91be32725..c8f8ca0a5 100644
--- a/test/replication/catch.result
+++ b/test/replication/catch.result
@@ -7,9 +7,6 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 net_box = require('net.box')
 ---
 ...
@@ -139,6 +136,3 @@ box.space.test:drop()
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/replication/catch.test.lua b/test/replication/catch.test.lua
index 2e2e97bc4..bba82e0e3 100644
--- a/test/replication/catch.test.lua
+++ b/test/replication/catch.test.lua
@@ -2,7 +2,6 @@ env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 net_box = require('net.box')
 errinj = box.error.injection
@@ -62,5 +61,4 @@ test_run:cmd("stop server replica")
 test_run:cmd("cleanup server replica")
 box.space.test:drop()
 box.schema.user.revoke('guest', 'replication')
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 
diff --git a/test/replication/errinj.result b/test/replication/errinj.result
index ca8af2988..f2fa1df57 100644
--- a/test/replication/errinj.result
+++ b/test/replication/errinj.result
@@ -7,9 +7,6 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 errinj = box.error.injection
 ---
 ...
diff --git a/test/replication/errinj.test.lua b/test/replication/errinj.test.lua
index 463d89a8f..eff9ef4b2 100644
--- a/test/replication/errinj.test.lua
+++ b/test/replication/errinj.test.lua
@@ -1,7 +1,6 @@
 env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 errinj = box.error.injection
 
diff --git a/test/replication/gc.result b/test/replication/gc.result
index e5c5cfccd..eeff6ac4b 100644
--- a/test/replication/gc.result
+++ b/test/replication/gc.result
@@ -27,9 +27,6 @@ function wait_gc(n) while #box.info.gc().checkpoints > n do fiber.sleep(0.01) en
 ---
 ...
 -- Grant permissions needed for replication.
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 box.schema.user.grant('guest', 'replication')
 ---
 ...
@@ -380,9 +377,6 @@ box.error.injection.set("ERRINJ_RELAY_REPORT_INTERVAL", 0)
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
 box.cfg{checkpoint_count = default_checkpoint_count}
 ---
 ...
diff --git a/test/replication/gc.test.lua b/test/replication/gc.test.lua
index a465140c8..4034942cf 100644
--- a/test/replication/gc.test.lua
+++ b/test/replication/gc.test.lua
@@ -13,7 +13,6 @@ box.cfg{checkpoint_count = 1}
 function wait_gc(n) while #box.info.gc().checkpoints > n do fiber.sleep(0.01) end end
 
 -- Grant permissions needed for replication.
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 box.schema.user.grant('guest', 'replication')
 
 -- By default, relay thread reports status to tx once a second.
@@ -176,6 +175,5 @@ replica_set.drop_all(test_run)
 s:drop()
 box.error.injection.set("ERRINJ_RELAY_REPORT_INTERVAL", 0)
 box.schema.user.revoke('guest', 'replication')
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 
 box.cfg{checkpoint_count = default_checkpoint_count}
diff --git a/test/replication/join_vclock.result b/test/replication/join_vclock.result
index 7c402dbf6..a9781073d 100644
--- a/test/replication/join_vclock.result
+++ b/test/replication/join_vclock.result
@@ -13,9 +13,6 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 errinj = box.error.injection
 ---
 ...
@@ -87,9 +84,6 @@ replica_set.drop_all(test_run)
 box.space.test:drop()
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
diff --git a/test/replication/join_vclock.test.lua b/test/replication/join_vclock.test.lua
index ac6eab75c..0b60dffc2 100644
--- a/test/replication/join_vclock.test.lua
+++ b/test/replication/join_vclock.test.lua
@@ -3,7 +3,6 @@ env = require('test_run')
 replica_set = require('fast_replica')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 
 errinj = box.error.injection
 errinj.set("ERRINJ_RELAY_FINAL_SLEEP", true)
@@ -33,5 +32,4 @@ test_run:cmd("switch default")
 
 replica_set.drop_all(test_run)
 box.space.test:drop()
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 box.schema.user.revoke('guest', 'replication')
diff --git a/test/replication/skip_conflict_row.result b/test/replication/skip_conflict_row.result
index bf794db5a..29963f56a 100644
--- a/test/replication/skip_conflict_row.result
+++ b/test/replication/skip_conflict_row.result
@@ -7,9 +7,6 @@ test_run = env.new()
 engine = test_run:get_cfg('engine')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 box.schema.user.grant('guest', 'replication')
 ---
 ...
@@ -100,6 +97,3 @@ box.space.test:drop()
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/replication/skip_conflict_row.test.lua b/test/replication/skip_conflict_row.test.lua
index 695cce9db..5f7d6ead3 100644
--- a/test/replication/skip_conflict_row.test.lua
+++ b/test/replication/skip_conflict_row.test.lua
@@ -2,7 +2,6 @@ env = require('test_run')
 test_run = env.new()
 engine = test_run:get_cfg('engine')
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 box.schema.user.grant('guest', 'replication')
 
 space = box.schema.space.create('test', {engine = engine});
@@ -34,4 +33,3 @@ test_run:cmd("stop server replica")
 test_run:cmd("cleanup server replica")
 box.space.test:drop()
 box.schema.user.revoke('guest', 'replication')
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/vinyl/replica_quota.result b/test/vinyl/replica_quota.result
index 460cc1e61..50e397199 100644
--- a/test/vinyl/replica_quota.result
+++ b/test/vinyl/replica_quota.result
@@ -1,9 +1,6 @@
 test_run = require('test_run').new()
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 box.schema.user.grant('guest', 'replication')
 ---
 ...
@@ -94,6 +91,3 @@ s:drop()
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/vinyl/replica_quota.test.lua b/test/vinyl/replica_quota.test.lua
index eade6f2f7..e04abbc22 100644
--- a/test/vinyl/replica_quota.test.lua
+++ b/test/vinyl/replica_quota.test.lua
@@ -1,6 +1,5 @@
 test_run = require('test_run').new()
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 box.schema.user.grant('guest', 'replication')
 
 s = box.schema.space.create('test', { engine = 'vinyl' })
@@ -49,4 +48,3 @@ _ = test_run:cmd("cleanup server replica")
 s:drop()
 
 box.schema.user.revoke('guest', 'replication')
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/wal_off/func_max.result b/test/wal_off/func_max.result
index 9211c4310..5a43821b2 100644
--- a/test/wal_off/func_max.result
+++ b/test/wal_off/func_max.result
@@ -36,36 +36,41 @@ function drop_limit_func()
 end;
 ---
 ...
-func_limit();
+test_run:cmd("setopt delimiter ''");
+---
+- true
+...
+func_limit()
 ---
 - error: 'A limit on the total number of functions has been reached: 32000'
 ...
-drop_limit_func();
+drop_limit_func()
 ---
 - error: Function 'func32000' does not exist
 ...
-box.schema.user.create('testuser');
+box.schema.user.create('testuser')
 ---
 ...
-box.schema.user.grant('testuser', 'read, write, execute,create', 'universe');
+box.schema.user.grant('testuser', 'read,write', 'space', '_func')
 ---
 ...
-session.su('testuser');
+box.schema.user.grant('testuser', 'create', 'function')
 ---
 ...
-func_limit();
+session.su('testuser')
+---
+...
+func_limit()
 ---
 - error: 'A limit on the total number of functions has been reached: 32000'
 ...
-drop_limit_func();
+drop_limit_func()
 ---
 - error: Function 'func32000' does not exist
 ...
 session.su('admin')
-box.schema.user.drop('testuser');
 ---
 ...
-test_run:cmd("setopt delimiter ''");
+box.schema.user.drop('testuser')
 ---
-- true
 ...
diff --git a/test/wal_off/func_max.test.lua b/test/wal_off/func_max.test.lua
index 00a095936..47fa6834b 100644
--- a/test/wal_off/func_max.test.lua
+++ b/test/wal_off/func_max.test.lua
@@ -21,13 +21,14 @@ function drop_limit_func()
         i = i + 1
     end
 end;
-func_limit();
-drop_limit_func();
-box.schema.user.create('testuser');
-box.schema.user.grant('testuser', 'read, write, execute,create', 'universe');
-session.su('testuser');
-func_limit();
-drop_limit_func();
-session.su('admin')
-box.schema.user.drop('testuser');
 test_run:cmd("setopt delimiter ''");
+func_limit()
+drop_limit_func()
+box.schema.user.create('testuser')
+box.schema.user.grant('testuser', 'read,write', 'space', '_func')
+box.schema.user.grant('testuser', 'create', 'function')
+session.su('testuser')
+func_limit()
+drop_limit_func()
+session.su('admin')
+box.schema.user.drop('testuser')
diff --git a/test/xlog/errinj.result b/test/xlog/errinj.result
index 262677f1d..6243ac701 100644
--- a/test/xlog/errinj.result
+++ b/test/xlog/errinj.result
@@ -50,15 +50,15 @@ test_run:cmd('restart server default with cleanup=1')
 errinj = box.error.injection
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 test = box.schema.create_space('test')
 ---
 ...
 _ = test:create_index('primary')
 ---
 ...
+box.schema.user.grant('guest', 'write', 'space', 'test')
+---
+...
 for i=1, box.cfg.rows_per_wal do test:insert{i, 'test'} end
 ---
 ...
@@ -85,6 +85,3 @@ test:drop()
 errinj = nil
 ---
 ...
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
diff --git a/test/xlog/errinj.test.lua b/test/xlog/errinj.test.lua
index 0ea15123f..7a5a29cb6 100644
--- a/test/xlog/errinj.test.lua
+++ b/test/xlog/errinj.test.lua
@@ -25,10 +25,11 @@ test_run:cmd('restart server default with cleanup=1')
 -- gh-881 iproto request with wal IO error
 errinj = box.error.injection
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
 test = box.schema.create_space('test')
 _ = test:create_index('primary')
 
+box.schema.user.grant('guest', 'write', 'space', 'test')
+
 for i=1, box.cfg.rows_per_wal do test:insert{i, 'test'} end
 c = require('net.box').connect(box.cfg.listen)
 
@@ -40,4 +41,3 @@ errinj.set('ERRINJ_WAL_WRITE', false)
 -- Cleanup
 test:drop()
 errinj = nil
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
diff --git a/test/xlog/misc.result b/test/xlog/misc.result
index fd3362c4c..5df21aede 100644
--- a/test/xlog/misc.result
+++ b/test/xlog/misc.result
@@ -11,12 +11,12 @@ xlog = require('xlog')
 netbox = require('net.box')
 ---
 ...
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
----
-...
 --
 -- Check that xlogs doesn't contain IPROTO_SYNC
 --
+box.schema.user.grant('guest', 'write', 'space', '_schema')
+---
+...
 conn = netbox.connect(box.cfg.listen)
 ---
 ...
@@ -68,9 +68,6 @@ box.space._schema:delete('test')
 --
 -- Clean up
 --
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
----
-...
 netbox = nil
 ---
 ...
diff --git a/test/xlog/misc.test.lua b/test/xlog/misc.test.lua
index 6e67b86a9..44adfd942 100644
--- a/test/xlog/misc.test.lua
+++ b/test/xlog/misc.test.lua
@@ -5,12 +5,12 @@ fio = require('fio')
 xlog = require('xlog')
 netbox = require('net.box')
 
-box.schema.user.grant('guest', 'read,write,execute', 'universe')
-
 --
 -- Check that xlogs doesn't contain IPROTO_SYNC
 --
 
+box.schema.user.grant('guest', 'write', 'space', '_schema')
+
 conn = netbox.connect(box.cfg.listen)
 -- insert some row using the binary protocol
 conn.space._schema:insert({'test'})
@@ -31,7 +31,6 @@ box.space._schema:delete('test')
 --
 -- Clean up
 --
-box.schema.user.revoke('guest', 'read,write,execute', 'universe')
 netbox = nil
 xlog = nil
 fio = nil
diff --git a/test/xlog/upgrade.result b/test/xlog/upgrade.result
index f02996bba..0bae10123 100644
--- a/test/xlog/upgrade.result
+++ b/test/xlog/upgrade.result
@@ -192,9 +192,9 @@ box.space._priv:select()
   - [1, 4, 'function', 3, 4]
   - [1, 4, 'role', 2, 4]
   - [1, 4, 'role', 5, 4]
-  - [1, 4, 'space', 513, 3]
+  - [1, 4, 'space', 513, 195]
   - [1, 4, 'universe', 0, 24]
-  - [1, 5, 'space', 512, 3]
+  - [1, 5, 'space', 512, 195]
   - [1, 31, 'universe', 0, 4294967295]
 ...
 box.space._vspace ~= nil
-- 
2.15.2 (Apple Git-101.1)





More information about the Tarantool-patches mailing list