* [PATCH 1/2] box: remove compatibility mode for privileges
2018-10-30 13:31 [PATCH 0/2] Remove 1.7 privilege compatibility mode Serge Petrenko
@ 2018-10-30 13:32 ` Serge Petrenko
2018-11-01 15:32 ` [tarantool-patches] " Konstantin Osipov
2018-10-30 13:32 ` [PATCH 2/2] box: autogrant CREATE,ALTER,DROP to users with READ+WRITE Serge Petrenko
2018-10-30 17:48 ` [PATCH 0/2] Remove 1.7 privilege compatibility mode Vladimir Davydov
2 siblings, 1 reply; 7+ messages in thread
From: Serge Petrenko @ 2018-10-30 13:32 UTC (permalink / raw)
To: vdavydov.dev; +Cc: tarantool-patches, Serge Petrenko
Before version 1.7.7 there were no CREATE or ALTER privileges.
READ+WRITE permitted object creation and altering.
In 1.10 CREATE and ALTER privileges were introduced together with a
compatibility mode in access_check_ddl() which assumed user had CREATE
and ALTER if it had READ and WRITE on a respective object.
Now its time for us to remove this compatibility mode.
Part of #3539
---
src/box/alter.cc | 55 +++++++++++++++-------------------------
test/box/access.result | 40 +++++++++++++++++++++++------
test/box/access.test.lua | 18 +++++++++----
test/sql/iproto.result | 6 +++++
test/sql/iproto.test.lua | 2 ++
5 files changed, 74 insertions(+), 47 deletions(-)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index a6bb5a0f0..6d2c59bbc 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -65,23 +65,10 @@
static void
access_check_ddl(const char *name, uint32_t object_id, uint32_t owner_uid,
- enum schema_object_type type, enum priv_type priv_type,
- bool is_17_compat_mode)
+ enum schema_object_type type, enum priv_type priv_type)
{
struct credentials *cr = effective_user();
user_access_t has_access = cr->universal_access;
- /*
- * XXX: pre 1.7.7 there was no specific 'CREATE' or
- * 'ALTER' ACL, instead, read and write access on universe
- * was used to allow create/alter.
- * For backward compatibility, if a user has read and write
- * access on the universe, grant it CREATE access
- * automatically.
- * The legacy fix does not affect sequences since they
- * were added in 1.7.7 only.
- */
- if (is_17_compat_mode && has_access & PRIV_R && has_access & PRIV_W)
- has_access |= PRIV_C | PRIV_A;
user_access_t access = ((PRIV_U | (user_access_t) priv_type) &
~has_access);
@@ -1678,7 +1665,7 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
auto def_guard =
make_scoped_guard([=] { space_def_delete(def); });
access_check_ddl(def->name, def->id, def->uid, SC_SPACE,
- PRIV_C, true);
+ PRIV_C);
RLIST_HEAD(empty_list);
struct space *space = space_new_xc(def, &empty_list);
/**
@@ -1740,7 +1727,7 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
}
} else if (new_tuple == NULL) { /* DELETE */
access_check_ddl(old_space->def->name, old_space->def->id,
- old_space->def->uid, SC_SPACE, PRIV_D, true);
+ old_space->def->uid, SC_SPACE, PRIV_D);
/* Verify that the space is empty (has no indexes) */
if (old_space->index_count) {
tnt_raise(ClientError, ER_DROP_SPACE,
@@ -1818,7 +1805,7 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
auto def_guard =
make_scoped_guard([=] { space_def_delete(def); });
access_check_ddl(def->name, def->id, def->uid, SC_SPACE,
- PRIV_A, true);
+ PRIV_A);
if (def->id != space_id(old_space))
tnt_raise(ClientError, ER_ALTER_SPACE,
space_name(old_space),
@@ -1953,7 +1940,7 @@ on_replace_dd_index(struct trigger * /* trigger */, void *event)
if (old_tuple && new_tuple)
priv_type = PRIV_A;
access_check_ddl(old_space->def->name, old_space->def->id,
- old_space->def->uid, SC_SPACE, priv_type, true);
+ old_space->def->uid, SC_SPACE, priv_type);
struct index *old_index = space_index(old_space, iid);
/*
@@ -2361,7 +2348,7 @@ on_replace_dd_user(struct trigger * /* trigger */, void *event)
if (new_tuple != NULL && old_user == NULL) { /* INSERT */
struct user_def *user = user_def_new_from_tuple(new_tuple);
access_check_ddl(user->name, user->uid, user->owner, user->type,
- PRIV_C, true);
+ PRIV_C);
auto def_guard = make_scoped_guard([=] { free(user); });
(void) user_cache_replace(user);
def_guard.is_active = false;
@@ -2371,7 +2358,7 @@ on_replace_dd_user(struct trigger * /* trigger */, void *event)
} else if (new_tuple == NULL) { /* DELETE */
access_check_ddl(old_user->def->name, old_user->def->uid,
old_user->def->owner, old_user->def->type,
- PRIV_D, true);
+ PRIV_D);
/* Can't drop guest or super user */
if (uid <= (uint32_t) BOX_SYSTEM_USER_ID_MAX || uid == SUPER) {
tnt_raise(ClientError, ER_DROP_USER,
@@ -2398,7 +2385,7 @@ on_replace_dd_user(struct trigger * /* trigger */, void *event)
*/
struct user_def *user = user_def_new_from_tuple(new_tuple);
access_check_ddl(user->name, user->uid, user->uid,
- old_user->def->type, PRIV_A, true);
+ old_user->def->type, PRIV_A);
auto def_guard = make_scoped_guard([=] { free(user); });
struct trigger *on_commit =
txn_alter_trigger_new(user_cache_alter_user, NULL);
@@ -2501,7 +2488,7 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event)
if (new_tuple != NULL && old_func == NULL) { /* INSERT */
struct func_def *def = func_def_new_from_tuple(new_tuple);
access_check_ddl(def->name, def->fid, def->uid, SC_FUNCTION,
- PRIV_C, true);
+ PRIV_C);
auto def_guard = make_scoped_guard([=] { free(def); });
func_cache_replace(def);
def_guard.is_active = false;
@@ -2516,7 +2503,7 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event)
* who created it or a superuser.
*/
access_check_ddl(old_func->def->name, fid, uid, SC_FUNCTION,
- PRIV_D, true);
+ PRIV_D);
/* Can only delete func if it has no grants. */
if (schema_find_grants("function", old_func->def->fid)) {
tnt_raise(ClientError, ER_DROP_FUNCTION,
@@ -2530,7 +2517,7 @@ on_replace_dd_func(struct trigger * /* trigger */, void *event)
struct func_def *def = func_def_new_from_tuple(new_tuple);
auto def_guard = make_scoped_guard([=] { free(def); });
access_check_ddl(def->name, def->fid, def->uid, SC_FUNCTION,
- PRIV_A, true);
+ PRIV_A);
struct trigger *on_commit =
txn_alter_trigger_new(func_cache_replace_func, NULL);
txn_on_commit(txn, on_commit);
@@ -2688,7 +2675,7 @@ on_replace_dd_collation(struct trigger * /* trigger */, void *event)
assert(old_coll_id != NULL);
access_check_ddl(old_coll_id->name, old_coll_id->id,
old_coll_id->owner_id, SC_COLLATION,
- PRIV_D, false);
+ PRIV_D);
/*
* Set on_commit/on_rollback triggers after
* deletion from the cache to make trigger logic
@@ -2704,7 +2691,7 @@ on_replace_dd_collation(struct trigger * /* trigger */, void *event)
struct coll_id_def new_def;
coll_id_def_new_from_tuple(new_tuple, &new_def);
access_check_ddl(new_def.name, new_def.id, new_def.owner_id,
- SC_COLLATION, PRIV_C, false);
+ SC_COLLATION, PRIV_C);
struct coll_id *new_coll_id = coll_id_new(&new_def);
if (new_coll_id == NULL)
diag_raise();
@@ -2789,7 +2776,7 @@ priv_def_check(struct priv_def *priv, enum priv_type priv_type)
}
const char *name = schema_find_name(priv->object_type, priv->object_id);
access_check_ddl(name, priv->object_id, grantor->def->uid,
- priv->object_type, priv_type, false);
+ priv->object_type, priv_type);
switch (priv->object_type) {
case SC_UNIVERSE:
if (grantor->def->uid != ADMIN) {
@@ -3250,7 +3237,7 @@ on_replace_dd_sequence(struct trigger * /* trigger */, void *event)
ER_CREATE_SEQUENCE);
assert(sequence_by_id(new_def->id) == NULL);
access_check_ddl(new_def->name, new_def->id, new_def->uid,
- SC_SEQUENCE, PRIV_C, false);
+ SC_SEQUENCE, PRIV_C);
sequence_cache_replace(new_def);
alter->new_def = new_def;
} else if (old_tuple != NULL && new_tuple == NULL) { /* DELETE */
@@ -3259,7 +3246,7 @@ on_replace_dd_sequence(struct trigger * /* trigger */, void *event)
struct sequence *seq = sequence_by_id(id);
assert(seq != NULL);
access_check_ddl(seq->def->name, seq->def->id, seq->def->uid,
- SC_SEQUENCE, PRIV_D, false);
+ SC_SEQUENCE, PRIV_D);
if (space_has_data(BOX_SEQUENCE_DATA_ID, 0, id))
tnt_raise(ClientError, ER_DROP_SEQUENCE,
seq->def->name, "the sequence has data");
@@ -3276,7 +3263,7 @@ on_replace_dd_sequence(struct trigger * /* trigger */, void *event)
struct sequence *seq = sequence_by_id(new_def->id);
assert(seq != NULL);
access_check_ddl(seq->def->name, seq->def->id, seq->def->uid,
- SC_SEQUENCE, PRIV_A, false);
+ SC_SEQUENCE, PRIV_A);
alter->old_def = seq->def;
alter->new_def = new_def;
}
@@ -3357,20 +3344,20 @@ on_replace_dd_space_sequence(struct trigger * /* trigger */, void *event)
/* Check we have the correct access type on the sequence. * */
if (is_generated || !stmt->new_tuple) {
access_check_ddl(seq->def->name, seq->def->id, seq->def->uid,
- SC_SEQUENCE, priv_type, false);
+ SC_SEQUENCE, priv_type);
} else {
/*
* In case user wants to attach an existing sequence,
* check that it has read and write access.
*/
access_check_ddl(seq->def->name, seq->def->id, seq->def->uid,
- SC_SEQUENCE, PRIV_R, false);
+ SC_SEQUENCE, PRIV_R);
access_check_ddl(seq->def->name, seq->def->id, seq->def->uid,
- SC_SEQUENCE, PRIV_W, false);
+ SC_SEQUENCE, PRIV_W);
}
/** Check we have alter access on space. */
access_check_ddl(space->def->name, space->def->id, space->def->uid,
- SC_SPACE, PRIV_A, false);
+ SC_SPACE, PRIV_A);
struct trigger *on_commit =
txn_alter_trigger_new(on_commit_dd_space_sequence, space);
diff --git a/test/box/access.result b/test/box/access.result
index 8a022d032..9c190240f 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -104,7 +104,10 @@ test_run:cmd("setopt delimiter ''");
box.schema.user.create('rich')
---
...
-box.schema.user.grant('rich', 'read,write', 'universe')
+box.schema.user.grant('rich', 'read,write', 'space', '_func')
+---
+...
+box.schema.user.grant('rich', 'create', 'function')
---
...
session.su('rich')
@@ -130,15 +133,18 @@ box.space['_user']:delete{uid}
---
- error: 'Failed to drop user or role ''rich'': the user has objects'
...
-box.schema.user.revoke('rich', 'read,write', 'universe')
+box.schema.user.revoke('rich', 'public')
---
...
-box.schema.user.revoke('rich', 'public')
+box.schema.user.revoke('rich', 'read,write', 'space', '_func')
---
...
box.schema.user.revoke('rich', 'alter', 'user', 'rich')
---
...
+box.schema.user.revoke('rich', 'create', 'function')
+---
+...
box.schema.user.disable("rich")
---
...
@@ -345,7 +351,13 @@ session = box.session
box.schema.user.create('uniuser')
---
...
-box.schema.user.grant('uniuser', 'read, write, execute', 'universe')
+box.schema.user.grant('uniuser', 'create', 'space')
+---
+...
+box.schema.user.grant('uniuser', 'write', 'space', '_schema')
+---
+...
+box.schema.user.grant('uniuser', 'write', 'space', '_space')
---
...
session.su('uniuser')
@@ -583,7 +595,22 @@ session = nil
box.schema.user.create('twostep')
---
...
-box.schema.user.grant('twostep', 'read,write,execute', 'universe')
+box.schema.user.grant('twostep', 'create', 'space')
+---
+...
+box.schema.user.grant('twostep', 'create', 'function')
+---
+...
+box.schema.user.grant('twostep', 'write', 'space', '_schema')
+---
+...
+box.schema.user.grant('twostep', 'write', 'space', '_space')
+---
+...
+box.schema.user.grant('twostep', 'write', 'space', '_index')
+---
+...
+box.schema.user.grant('twostep', 'read,write', 'space', '_func')
---
...
box.session.su('twostep')
@@ -601,9 +628,6 @@ box.schema.func.create('test')
box.session.su('admin')
---
...
-box.schema.user.revoke('twostep', 'execute,read,write', 'universe')
----
-...
box.schema.user.create('twostep_client')
---
...
diff --git a/test/box/access.test.lua b/test/box/access.test.lua
index f7c18b106..4baeb2ef6 100644
--- a/test/box/access.test.lua
+++ b/test/box/access.test.lua
@@ -50,7 +50,8 @@ end;
usermax();
test_run:cmd("setopt delimiter ''");
box.schema.user.create('rich')
-box.schema.user.grant('rich', 'read,write', 'universe')
+box.schema.user.grant('rich', 'read,write', 'space', '_func')
+box.schema.user.grant('rich', 'create', 'function')
session.su('rich')
uid = session.uid()
box.schema.func.create('dummy')
@@ -58,9 +59,10 @@ session.su('admin')
box.space['_user']:delete{uid}
box.schema.func.drop('dummy')
box.space['_user']:delete{uid}
-box.schema.user.revoke('rich', 'read,write', 'universe')
box.schema.user.revoke('rich', 'public')
+box.schema.user.revoke('rich', 'read,write', 'space', '_func')
box.schema.user.revoke('rich', 'alter', 'user', 'rich')
+box.schema.user.revoke('rich', 'create', 'function')
box.schema.user.disable("rich")
-- test double disable is a no op
box.schema.user.disable("rich")
@@ -154,7 +156,9 @@ box.schema.user.drop('testus')
-- ------------------------------------------------------------
session = box.session
box.schema.user.create('uniuser')
-box.schema.user.grant('uniuser', 'read, write, execute', 'universe')
+box.schema.user.grant('uniuser', 'create', 'space')
+box.schema.user.grant('uniuser', 'write', 'space', '_schema')
+box.schema.user.grant('uniuser', 'write', 'space', '_space')
session.su('uniuser')
us = box.schema.space.create('uniuser_space')
session.su('admin')
@@ -241,13 +245,17 @@ session = nil
-- admin can't manage grants on not owned objects
-- -----------------------------------------------------------
box.schema.user.create('twostep')
-box.schema.user.grant('twostep', 'read,write,execute', 'universe')
+box.schema.user.grant('twostep', 'create', 'space')
+box.schema.user.grant('twostep', 'create', 'function')
+box.schema.user.grant('twostep', 'write', 'space', '_schema')
+box.schema.user.grant('twostep', 'write', 'space', '_space')
+box.schema.user.grant('twostep', 'write', 'space', '_index')
+box.schema.user.grant('twostep', 'read,write', 'space', '_func')
box.session.su('twostep')
twostep = box.schema.space.create('twostep')
index2 = twostep:create_index('primary')
box.schema.func.create('test')
box.session.su('admin')
-box.schema.user.revoke('twostep', 'execute,read,write', 'universe')
box.schema.user.create('twostep_client')
box.schema.user.grant('twostep_client', 'execute', 'function', 'test')
box.schema.user.drop('twostep')
diff --git a/test/sql/iproto.result b/test/sql/iproto.result
index af474bcf5..ee34f6fc1 100644
--- a/test/sql/iproto.result
+++ b/test/sql/iproto.result
@@ -37,6 +37,9 @@ box.sql.execute('select * from test')
box.schema.user.grant('guest','read,write,execute', 'universe')
---
...
+box.schema.user.grant('guest', 'create', 'space')
+---
+...
cn = remote.connect(box.cfg.listen)
---
...
@@ -583,6 +586,9 @@ box.sql.execute('drop table test')
box.schema.user.revoke('guest', 'read,write,execute', 'universe')
---
...
+box.schema.user.revoke('guest', 'create', 'space')
+---
+...
space = nil
---
...
diff --git a/test/sql/iproto.test.lua b/test/sql/iproto.test.lua
index 220331b40..b06559075 100644
--- a/test/sql/iproto.test.lua
+++ b/test/sql/iproto.test.lua
@@ -10,6 +10,7 @@ space:replace{4, 5, '6'}
space:replace{7, 8.5, '9'}
box.sql.execute('select * from test')
box.schema.user.grant('guest','read,write,execute', 'universe')
+box.schema.user.grant('guest', 'create', 'space')
cn = remote.connect(box.cfg.listen)
cn:ping()
@@ -202,6 +203,7 @@ cn:close()
box.sql.execute('drop table test')
box.schema.user.revoke('guest', 'read,write,execute', 'universe')
+box.schema.user.revoke('guest', 'create', 'space')
space = nil
-- Cleanup xlog
--
2.17.1 (Apple Git-112)
^ permalink raw reply [flat|nested] 7+ messages in thread