diff --git a/src/box/alter.cc b/src/box/alter.cc
index 6f6fcb097d7675bcd805efe1e6af6682436ccfee..48af128f1cae2b269b14c5b37138f4daa39f6fde 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -2523,8 +2523,10 @@ priv_def_check(struct priv_def *priv, enum priv_type priv_type)
 		break;
 	case SC_SPACE:
 	{
-		struct space *space = space_cache_find_xc(priv->object_id);
-		if (space->def->uid != grantor->def->uid &&
+		struct space *space = NULL;
+		if (priv->object_id != 0)
+			space = space_cache_find_xc(priv->object_id);
+		if ((space == NULL || space->def->uid != grantor->def->uid) &&
 		    grantor->def->uid != ADMIN) {
 			tnt_raise(AccessDeniedError,
 				  priv_name(priv_type),
@@ -2535,8 +2537,10 @@ priv_def_check(struct priv_def *priv, enum priv_type priv_type)
 	}
 	case SC_FUNCTION:
 	{
-		struct func *func = func_cache_find(priv->object_id);
-		if (func->def->uid != grantor->def->uid &&
+		struct func *func = NULL;
+		if (priv->object_id != 0)
+			func = func_cache_find(priv->object_id);
+		if ((func == NULL || func->def->uid != grantor->def->uid) &&
 		    grantor->def->uid != ADMIN) {
 			tnt_raise(AccessDeniedError,
 				  priv_name(priv_type),
@@ -2547,8 +2551,10 @@ priv_def_check(struct priv_def *priv, enum priv_type priv_type)
 	}
 	case SC_SEQUENCE:
 	{
-		struct sequence *seq = sequence_cache_find(priv->object_id);
-		if (seq->def->uid != grantor->def->uid &&
+		struct sequence *seq = NULL;
+		if (priv->object_id != 0)
+			seq = sequence_cache_find(priv->object_id);
+		if ((seq == NULL || seq->def->uid != grantor->def->uid) &&
 		    grantor->def->uid != ADMIN) {
 			tnt_raise(AccessDeniedError,
 				  priv_name(priv_type),
diff --git a/src/box/call.c b/src/box/call.c
index 6388e1e68fa472b8b4b4e7d7d81ec2eea7e99b9c..438be190ed336c747803e1e4431a89a70fc966a2 100644
--- a/src/box/call.c
+++ b/src/box/call.c
@@ -71,6 +71,8 @@ access_check_func(const char *name, uint32_t name_len, struct func **funcp)
 		return 0;
 	}
 	user_access_t access = PRIV_X | PRIV_U;
+	/* Check access for all functions. */
+	access &= ~entity_access_get(SC_FUNCTION)[credentials->auth_token].effective;
 	user_access_t func_access = access & ~credentials->universal_access;
 	if (func == NULL ||
 	    /* Check for missing Usage access, ignore owner rights. */
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index 55018d6b60e219574e27b5f929434d99a4154927..2b0597708dca4192bd1a0e8913f13eab8684c5d4 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -1804,6 +1804,9 @@ local function object_resolve(object_type, object_name)
         return 0
     end
     if object_type == 'space' then
+        if object_name == nil or object_name == 0 then
+            return 0
+        end
         local space = box.space[object_name]
         if  space == nil then
             box.error(box.error.NO_SUCH_SPACE, object_name)
@@ -1811,6 +1814,9 @@ local function object_resolve(object_type, object_name)
         return space.id
     end
     if object_type == 'function' then
+        if object_name == nil or object_name == 0 then
+            return 0
+        end
         local _vfunc = box.space[box.schema.VFUNC_ID]
         local func
         if type(object_name) == 'string' then
@@ -1825,6 +1831,9 @@ local function object_resolve(object_type, object_name)
         end
     end
     if object_type == 'sequence' then
+        if object_name == nil or object_name == 0 then
+            return 0
+        end
         local seq = sequence_resolve(object_name)
         if seq == nil then
             box.error(box.error.NO_SUCH_SEQUENCE, object_name)
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 8df4aa73bb41005201aafa296d71d05d8978f8e5..32d7791a66f1c15be650a2c488e63f157db6f275 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -69,6 +69,8 @@ struct rlist on_alter_sequence = RLIST_HEAD_INITIALIZER(on_alter_sequence);
  */
 struct latch schema_lock = LATCH_INITIALIZER(schema_lock);
 
+struct entity_access entity_access;
+
 bool
 space_is_system(struct space *space)
 {
@@ -528,6 +530,8 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
 		return "";
 	case SC_SPACE:
 		{
+			if (object_id == 0)
+				return "SPACE";
 			struct space *space = space_by_id(object_id);
 			if (space == NULL)
 				break;
@@ -535,6 +539,8 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
 		}
 	case SC_FUNCTION:
 		{
+			if (object_id == 0)
+				return "FUNCTION";
 			struct func *func = func_by_id(object_id);
 			if (func == NULL)
 				break;
@@ -542,6 +548,8 @@ schema_find_name(enum schema_object_type type, uint32_t object_id)
 		}
 	case SC_SEQUENCE:
 		{
+			if (object_id == 0)
+				return "SEQUENCE";
 			struct sequence *seq = sequence_by_id(object_id);
 			if (seq == NULL)
 				break;
diff --git a/src/box/schema.h b/src/box/schema.h
index 2b87f5f500d3a9a61cba8d3b345b3c023d9094cf..dd31d2d9daafb3e263f7a3b56d4eeef344622ccd 100644
--- a/src/box/schema.h
+++ b/src/box/schema.h
@@ -235,4 +235,30 @@ struct on_access_denied_ctx {
 	const char *object_name;
 };
 
+/** Global grants to classes of objects. */
+struct entity_access {
+       struct access space[BOX_USER_MAX];
+       struct access function[BOX_USER_MAX];
+       struct access sequence[BOX_USER_MAX];
+};
+
+/** A single instance of the global entities. */
+extern struct entity_access entity_access;
+
+static inline
+struct access *
+entity_access_get(enum schema_object_type type)
+{
+       switch (type) {
+       case SC_SPACE:
+               return entity_access.space;
+       case SC_FUNCTION:
+               return entity_access.function;
+       case SC_SEQUENCE:
+               return entity_access.sequence;
+       default:
+               return NULL;
+       }
+}
+
 #endif /* INCLUDES_TARANTOOL_BOX_SCHEMA_H */
diff --git a/src/box/sequence.c b/src/box/sequence.c
index 162147cdedbb8266d6c8d42a170325bd63ba9cb2..35b7605d22f1eaeec298672bd93bab5f9e25c2e7 100644
--- a/src/box/sequence.c
+++ b/src/box/sequence.c
@@ -250,6 +250,7 @@ access_check_sequence(struct sequence *seq)
 
 	user_access_t access = PRIV_U | PRIV_W;
 	user_access_t sequence_access = access & ~cr->universal_access;
+	sequence_access &= ~entity_access_get(SC_SEQUENCE)[cr->auth_token].effective;
 	if (sequence_access &&
 	    /* Check for missing Usage access, ignore owner rights. */
 	    (sequence_access & PRIV_U ||
diff --git a/src/box/space.c b/src/box/space.c
index 0510f232d263887393ed437b952ac708f76bdcb9..631877699eeef0e827220389175eaf274122e4d6 100644
--- a/src/box/space.c
+++ b/src/box/space.c
@@ -42,6 +42,7 @@
 #include "request.h"
 #include "xrow.h"
 #include "iproto_constants.h"
+#include "schema.h"
 
 int
 access_check_space(struct space *space, user_access_t access)
@@ -57,6 +58,7 @@ access_check_space(struct space *space, user_access_t access)
 	 * since ADMIN has universal access.
 	 */
 	user_access_t space_access = access & ~cr->universal_access;
+	space_access &= ~entity_access_get(SC_SPACE)[cr->auth_token].effective;
 
 	if (space_access &&
 	    /* Check for missing Usage access, ignore owner rights. */
diff --git a/src/box/sysview_index.c b/src/box/sysview_index.c
index f1dfbefe5abcd08ba4eefd9a5cfbbb9e38f3ea5e..3e56d1fa90f6f2b3f35db115cb1004709181b73e 100644
--- a/src/box/sysview_index.c
+++ b/src/box/sysview_index.c
@@ -222,6 +222,9 @@ vspace_filter(struct space *source, struct tuple *tuple)
 	 */
 	if (PRIV_WRDA & cr->universal_access)
 		return true;
+	/* Allow access for a user with space privileges. */
+	if (PRIV_WRDA & entity_access_get(SC_SPACE)[cr->auth_token].effective)
+		return true;
 	if (PRIV_R & source->access[cr->auth_token].effective)
 		return true; /* read access to _space space */
 	uint32_t space_id;
@@ -295,6 +298,10 @@ vfunc_filter(struct space *source, struct tuple *tuple)
 	 */
 	if ((PRIV_WRDA | PRIV_X) & cr->universal_access)
 		return true;
+	/* Allow access for a user with function privileges. */
+	if ((PRIV_WRDA | PRIV_X) &
+	    entity_access_get(SC_FUNCTION)[cr->auth_token].effective)
+		return true;
 	if (PRIV_R & source->access[cr->auth_token].effective)
 		return true; /* read access to _func space */
 
@@ -320,6 +327,10 @@ vsequence_filter(struct space *source, struct tuple *tuple)
 	 */
 	if ((PRIV_WRDA | PRIV_X) & cr->universal_access)
 		return true;
+	/* Allow access for a user with sequence privileges. */
+	if ((PRIV_WRDA | PRIV_X) &
+	    entity_access_get(SC_SEQUENCE)[cr->auth_token].effective)
+		return true;
 	if (PRIV_R & source->access[cr->auth_token].effective)
 		return true; /* read access to _sequence space */
 
diff --git a/src/box/user.cc b/src/box/user.cc
index 7fa66da8f1c11d8a3a9d3d40b2b5cac265d6e201..fbf06566a7df4e43346686b76d3c7a91543a7ca1 100644
--- a/src/box/user.cc
+++ b/src/box/user.cc
@@ -209,6 +209,10 @@ access_find(struct priv_def *priv)
 	}
 	case SC_SPACE:
 	{
+		if (priv->object_id == 0) {
+			access = entity_access.space;
+			break;
+		}
 		struct space *space = space_by_id(priv->object_id);
 		if (space)
 			access = space->access;
@@ -216,6 +220,10 @@ access_find(struct priv_def *priv)
 	}
 	case SC_FUNCTION:
 	{
+		if (priv->object_id == 0) {
+			access = entity_access.function;
+			break;
+		}
 		struct func *func = func_by_id(priv->object_id);
 		if (func)
 			access = func->access;
@@ -223,6 +231,10 @@ access_find(struct priv_def *priv)
 	}
 	case SC_SEQUENCE:
 	{
+		if (priv->object_id == 0) {
+			access = entity_access.sequence;
+			break;
+		}
 		struct sequence *seq = sequence_by_id(priv->object_id);
 		if (seq)
 			access = seq->access;
diff --git a/test/box/access.result b/test/box/access.result
index 72f91173b19e0c3deef99fe9efbcef160315c43a..ccd0b737ff4ceb5eabd7c06de4e1f924ffc824d3 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -1662,3 +1662,80 @@ box.schema.user.grant("guest", "read,write,execute", "role")
 ---
 - error: Unsupported role privilege 'read,write,execute'
 ...
+-- Check entities DML
+box.schema.user.create("tester", { password  = '123' })
+---
+...
+s = box.schema.space.create("test")
+---
+...
+_ = s:create_index("primary", {parts={1, "unsigned"}})
+---
+...
+seq = box.schema.sequence.create("test")
+---
+...
+box.schema.func.create("func")
+---
+...
+c = (require 'net.box').connect(LISTEN.host, LISTEN.service, {user='tester', password = '123'})
+---
+...
+box.session.su("tester", s.select, s)
+---
+- error: Read access to space 'test' is denied for user 'tester'
+...
+box.session.su("tester", seq.set, seq, 1)
+---
+- error: Write access to sequence 'test' is denied for user 'tester'
+...
+c:call("func")
+---
+- error: Execute access to function 'func' is denied for user 'tester'
+...
+box.schema.user.grant("tester", "read", "space")
+---
+...
+box.schema.user.grant("tester", "write", "sequence")
+---
+...
+box.schema.user.grant("tester", "execute", "function")
+---
+...
+box.session.su("tester", s.select, s)
+---
+- []
+...
+box.session.su("tester", seq.next, seq)
+---
+- 1
+...
+c:call("func")
+---
+...
+box.session.su("tester", s.insert, s, {1})
+---
+- error: Write access to space 'test' is denied for user 'tester'
+...
+box.schema.user.grant("tester", "write", "space")
+---
+...
+box.session.su("tester", s.insert, s, {1})
+---
+- [1]
+...
+box.schema.user.drop("tester")
+---
+...
+s:drop()
+---
+...
+seq:drop()
+---
+...
+box.schema.func.drop("func")
+---
+...
+c:close()
+---
+...
diff --git a/test/box/access.test.lua b/test/box/access.test.lua
index 62691c471844ce557d605d80da02fcba78902240..8d90b3813382bf42790054028536d989cc85fd08 100644
--- a/test/box/access.test.lua
+++ b/test/box/access.test.lua
@@ -640,3 +640,32 @@ box.schema.user.grant("guest", "alter", "function")
 box.schema.user.grant("guest", "execute", "sequence")
 box.schema.user.grant("guest", "read,execute", "sequence")
 box.schema.user.grant("guest", "read,write,execute", "role")
+
+-- Check entities DML
+box.schema.user.create("tester", { password  = '123' })
+s = box.schema.space.create("test")
+_ = s:create_index("primary", {parts={1, "unsigned"}})
+seq = box.schema.sequence.create("test")
+box.schema.func.create("func")
+c = (require 'net.box').connect(LISTEN.host, LISTEN.service, {user='tester', password = '123'})
+
+box.session.su("tester", s.select, s)
+box.session.su("tester", seq.set, seq, 1)
+c:call("func")
+box.schema.user.grant("tester", "read", "space")
+box.schema.user.grant("tester", "write", "sequence")
+box.schema.user.grant("tester", "execute", "function")
+box.session.su("tester", s.select, s)
+box.session.su("tester", seq.next, seq)
+c:call("func")
+
+box.session.su("tester", s.insert, s, {1})
+box.schema.user.grant("tester", "write", "space")
+box.session.su("tester", s.insert, s, {1})
+
+box.schema.user.drop("tester")
+s:drop()
+seq:drop()
+box.schema.func.drop("func")
+c:close()
+
diff --git a/test/box/lua/identifier.lua b/test/box/lua/identifier.lua
index c3149bce7920cb27b163c46c878fd0c6c25444eb..0cfb9e722a208ef25b806a6ba0277a77d2ea3cf5 100644
--- a/test/box/lua/identifier.lua
+++ b/test/box/lua/identifier.lua
@@ -36,7 +36,6 @@ invalid_testcases = {
 
 function run_test(create_func, cleanup_func)
     local json = require("json")
-    print("loosadlalsd")
     local bad_tests = {}
     for i, identifier in ipairs(valid_testcases) do
         local ok, res = pcall(create_func,identifier)