diff --git a/src/box/alter.cc b/src/box/alter.cc index 280831565647e83092047b48893c6fff2e4fb41c..c2b1b971826b3535a98f584f7ad137c0af76e880 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -1502,7 +1502,8 @@ priv_def_check(struct priv_def *priv) role ? role->name : int2str(priv->object_id)); } - /* Only the creator of the role can grant or revoke it. + /* + * Only the creator of the role can grant or revoke it. * Everyone can grant 'PUBLIC' role. */ if (role->owner != grantor->uid && grantor->uid != ADMIN && diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index cd2303342ddb93cc573a1b60030690e45c26be45..6df1b9b413c6d78fa283f8c6edda40a81d8011fd 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -1044,7 +1044,7 @@ box.schema.user.grant = function(user_name, privilege, object_type, if uid == nil then box.error(box.error.NO_SUCH_USER, user_name) end - privilege = privilege_resolve(privilege) + privilege_hex = privilege_resolve(privilege) local oid = object_resolve(object_type, object_name) if grantor == nil then grantor = session.uid() @@ -1060,11 +1060,19 @@ box.schema.user.grant = function(user_name, privilege, object_type, else old_privilege = 0 end - privilege = bit.bor(privilege, old_privilege) + privilege_hex = bit.bor(privilege_hex, old_privilege) -- do not execute a replace if it does not change anything - -- XXX bug: new grantor replaces the old one, old grantor is lost - if privilege ~= old_privilege then - _priv:replace{grantor, uid, object_type, oid, privilege} + -- XXX bug if we decide to add a grant option: new grantor + -- replaces the old one, old grantor is lost + if privilege_hex ~= old_privilege then + _priv:replace{grantor, uid, object_type, oid, privilege_hex} + else + if object_type == 'role' then + box.error(box.error.ROLE_GRANTED, user_name, object_name) + else + box.error(box.error.PRIV_GRANTED, user_name, privilege, + object_type, object_name) + end end end @@ -1082,13 +1090,18 @@ box.schema.user.revoke = function(user_name, privilege, object_type, object_name if uid == nil then box.error(box.error.NO_SUCH_USER, name) end - privilege = privilege_resolve(privilege) local oid = object_resolve(object_type, object_name) local _priv = box.space[box.schema.PRIV_ID] local tuple = _priv:get{uid, object_type, oid} if tuple == nil then - return + if object_type == 'role' then + box.error(box.error.ROLE_NOT_GRANTED, user_name, object_name) + else + box.error(box.error.PRIV_NOT_GRANTED, user_name, privilege, + object_type, object_name) + end end + privilege = privilege_resolve(privilege) local old_privilege = tuple[5] local grantor = tuple[1] -- sic: diff --git a/src/errcode.h b/src/errcode.h index 5160e869884d29f6601813d12d1ba039f7b3fc3f..a128fe3319cd0c905a34418de487a224cfc63ae1 100644 --- a/src/errcode.h +++ b/src/errcode.h @@ -138,6 +138,10 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 86 */_(ER_TUPLE_REF_OVERFLOW, 1, "Tuple reference counter overflow") \ /* 87 */_(ER_ROLE_LOOP, 2, "Granting role '%s' to role '%s' would create a loop") \ /* 88 */_(ER_GRANT, 2, "Incorrect grant arguments: %s") \ + /* 89 */_(ER_PRIV_GRANTED, 2, "User '%s' already has %s access on %s '%s'") \ + /* 90 */_(ER_ROLE_GRANTED, 2, "User '%s' already has role '%s'") \ + /* 91 */_(ER_PRIV_NOT_GRANTED, 2, "User '%s' does not have %s access on %s '%s'") \ + /* 92 */_(ER_ROLE_NOT_GRANTED, 2, "User '%s' does not have role '%s'") \ /* * !IMPORTANT! Please follow instructions at start of the file diff --git a/test/box/access.result b/test/box/access.result index 975ddea6cc2c035cb9871db15e6664b6f844c0a8..2e5bf7f9375fd0069ca1e950c410a8968c09b78f 100644 --- a/test/box/access.result +++ b/test/box/access.result @@ -360,6 +360,7 @@ box.space._priv:select{id} ... box.schema.user.grant('user', 'read', 'universe') --- +- error: User 'user' already has read access on universe 'nil' ... box.space._priv:select{id} --- diff --git a/test/box/access_misc.result b/test/box/access_misc.result index 27e7d7afb79cdceb16323e25ce36051465f2b08f..b181cbba871c254d16255276042565abb065330f 100644 --- a/test/box/access_misc.result +++ b/test/box/access_misc.result @@ -53,6 +53,7 @@ box.schema.user.grant('testus', 'read', 'space', 'admin_space') ... box.schema.user.grant('testus', 'read', 'space', 'admin_space') --- +- error: User 'testus' already has read access on space 'admin_space' ... session.su('testus') --- @@ -84,6 +85,7 @@ box.schema.user.revoke('testus', 'read', 'space', 'admin_space') ... box.schema.user.revoke('testus', 'read', 'space', 'admin_space') --- +- error: User 'testus' does not have read access on space 'admin_space' ... session.su('testus') --- @@ -402,6 +404,7 @@ session.su('admin') ... box.schema.user.revoke('testuser', 'read, write, execute', 'universe') --- +- error: User 'testuser' does not have read, write, execute access on universe 'nil' ... -- -- Check that itertors check privileges diff --git a/test/box/box.net.box.result b/test/box/box.net.box.result index 19202db6c0334bf4db5850dc6a0902dac99aca6a..448a5644ed972235e3ca459023019b4bf34e0857 100644 --- a/test/box/box.net.box.result +++ b/test/box/box.net.box.result @@ -758,3 +758,6 @@ file_log:close() --- - true ... +box.schema.user.revoke('guest', 'read,write,execute', 'universe') +--- +... diff --git a/test/box/box.net.box.test.lua b/test/box/box.net.box.test.lua index a244dd421affa4e13e09f89a24b1be7ab91f2154..2839f9eb834b96bce96fbfa101a55f3eb3f6dfb9 100644 --- a/test/box/box.net.box.test.lua +++ b/test/box/box.net.box.test.lua @@ -311,3 +311,4 @@ end; --# setopt delimiter '' file_log:close() +box.schema.user.revoke('guest', 'read,write,execute', 'universe') diff --git a/test/box/misc.result b/test/box/misc.result index e08f06bee68af9cc5835a80a771bf2857e7ce0c6..4a6b2751e572cbe622e672e66348f3227db44573 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -207,8 +207,12 @@ t; - 'box.error.USER_EXISTS : 46' - 'box.error.WAL_IO : 40' - 'box.error.CREATE_USER : 43' + - 'box.error.DROP_PRIMARY_KEY : 17' + - 'box.error.PRIV_GRANTED : 89' - 'box.error.CREATE_SPACE : 9' + - 'box.error.PRIV_NOT_GRANTED : 91' - 'box.error.GRANT : 88' + - 'box.error.ROLE_GRANTED : 90' - 'box.error.TUPLE_REF_OVERFLOW : 86' - 'box.error.UNKNOWN_SCHEMA_OBJECT : 49' - 'box.error.PROC_LUA : 32' @@ -258,7 +262,7 @@ t; - 'box.error.ARG_TYPE : 26' - 'box.error.INDEX_FIELD_COUNT : 39' - 'box.error.READONLY : 7' - - 'box.error.DROP_PRIMARY_KEY : 17' + - 'box.error.ROLE_NOT_GRANTED : 92' - 'box.error.DROP_SPACE : 11' - 'box.error.UNKNOWN_REQUEST_TYPE : 48' - 'box.error.INVALID_XLOG_ORDER : 76' diff --git a/test/box/protocol.result b/test/box/protocol.result index 86698ffceaa0bb801cdbf272a034cf0bb31dc237..0783bf6302f9c5c307d867ef0d32d5945cc13302 100644 --- a/test/box/protocol.result +++ b/test/box/protocol.result @@ -51,3 +51,6 @@ 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 1349541bbcc147ba52d8859e77ca61cf6b14281e..307909c843927c63dc01597b265116aa94cb37f5 100644 --- a/test/box/protocol.test.lua +++ b/test/box/protocol.test.lua @@ -18,3 +18,4 @@ 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/role.result b/test/box/role.result index df3d02c808522cd7cb0848924ca2f733b9a38030..310edbaabf8443c8de2ea57e9dac782ebf26d710 100644 --- a/test/box/role.result +++ b/test/box/role.result @@ -67,9 +67,11 @@ box.schema.user.grant('tester', 'execute', 'role', 'tester') -- test granting a non-execute grant on a role - error box.schema.user.grant('tester', 'write', 'role', 'iddqd') --- +- error: User 'tester' already has role 'iddqd' ... box.schema.user.grant('tester', 'read', 'role', 'iddqd') --- +- error: User 'tester' already has role 'iddqd' ... -- test granting role to a role box.schema.user.grant('iddqd', 'execute', 'role', 'iddqd') @@ -82,9 +84,11 @@ box.schema.user.grant('iddqd', 'iddqd') ... box.schema.user.revoke('iddqd', 'iddqd') --- +- error: User 'iddqd' does not have role 'iddqd' ... box.schema.user.grant('tester', 'iddqd') --- +- error: User 'tester' already has role 'iddqd' ... box.schema.user.revoke('tester', 'iddqd') --- @@ -631,10 +635,12 @@ box.schema.user.create('john') box.session.su('john') --- ... +-- error box.schema.role.grant('grantee', 'role') --- - error: Read access denied for user 'john' to space '_user' ... +-- box.session.su('admin') --- ... @@ -655,6 +661,24 @@ box.schema.role.grant('grantee', 'read', 'space', 'test') --- - error: Read access denied for user 'john' ... +-- +-- granting 'public' is however an exception - everyone +-- can grant 'public' role, it's implicitly granted with +-- a grant option. +-- +box.schema.role.grant('grantee', 'public') +--- +- error: User 'grantee' already has role 'public' +... +-- +-- revoking role 'public' is another deal - only the +-- superuser can do that, and even that would be useless, +-- since one can still re-grant it back to oneself. +-- +box.schema.role.revoke('grantee', 'public') +--- +- error: Create or drop access denied for user 'john' +... box.session.su('admin') --- ... diff --git a/test/box/role.test.lua b/test/box/role.test.lua index 3af64a559f61cf7232a96cb4d8efa83ef3e52353..14acba2421be045be6ae51bd182a23ce93e5799c 100644 --- a/test/box/role.test.lua +++ b/test/box/role.test.lua @@ -244,13 +244,27 @@ box.schema.role.grant('grantee', 'role') box.schema.role.revoke('grantee', 'role') box.schema.user.create('john') box.session.su('john') +-- error box.schema.role.grant('grantee', 'role') +-- box.session.su('admin') _ = box.schema.space.create('test') box.schema.user.grant('john', 'read,write,execute', 'universe') box.session.su('john') box.schema.role.grant('grantee', 'role') box.schema.role.grant('grantee', 'read', 'space', 'test') +-- +-- granting 'public' is however an exception - everyone +-- can grant 'public' role, it's implicitly granted with +-- a grant option. +-- +box.schema.role.grant('grantee', 'public') +-- +-- revoking role 'public' is another deal - only the +-- superuser can do that, and even that would be useless, +-- since one can still re-grant it back to oneself. +-- +box.schema.role.revoke('grantee', 'public') box.session.su('admin') box.schema.user.drop('john') diff --git a/test/box/session.result b/test/box/session.result index a087de691b433742a6ee07ff1ef498d1a00e1957..49e15c219637e1000144c27056902024692a4954 100644 --- a/test/box/session.result +++ b/test/box/session.result @@ -224,3 +224,6 @@ fiber = nil session = nil --- ... +box.schema.user.revoke('guest', 'read,write,execute', 'universe') +--- +... diff --git a/test/box/session.test.lua b/test/box/session.test.lua index da1bc63e8d42ef24ae9200e76fc632f8edbe39e6..367755ebd15afe13b67412bc60304dbc4654ec81 100644 --- a/test/box/session.test.lua +++ b/test/box/session.test.lua @@ -88,3 +88,4 @@ session.uid() session.user() fiber = nil session = nil +box.schema.user.revoke('guest', 'read,write,execute', 'universe') diff --git a/test/replication/cluster.result b/test/replication/cluster.result index 8be88a719587137e3452a009ac329aa811736783..fc11db893f4e0c4a83194d7f10c6c14978ee663b 100644 --- a/test/replication/cluster.result +++ b/test/replication/cluster.result @@ -131,3 +131,6 @@ box.info.vclock[11] --- - 0 ... +box.schema.user.revoke('guest', 'read,write,execute', 'universe') +--- +... diff --git a/test/replication/cluster.test.py b/test/replication/cluster.test.py index aa41dc0a3010e5390e94d1723becd99020a2c54d..5beec7a8e80cfecfa15e353f476f0a93cf6eeed4 100644 --- a/test/replication/cluster.test.py +++ b/test/replication/cluster.test.py @@ -98,3 +98,4 @@ replica.admin('box.info.vclock[%d]' % replica_id3) # Cleanup sys.stdout.pop_filter() +master.admin("box.schema.user.revoke('guest', 'read,write,execute', 'universe')")