用户权限管理

管理员,用户和组

管理员可以创建其他管理员、用户和组。非管理员的用户不能创建其他用户或组。

当 DolphinDB 集群第一次启动时,会自动创建一个管理员,用户 ID 为 "admin",密码为 "123456"。"admin" 管理员具有所有的权限,并且不能被删除。其他管理员在刚创建时,是没有任何权限的,需要手动赋予他权限。

管理员可以赋予或禁止其他管理员,用户和组的权限,亦可撤销权限设置。

用户可以属于 0, 1 或多个组。把用户添加到组或把用户从组中移除会影响用户的访问权限。

访问权限

DolphinDB支持以下 9 种类型的权限:

1. TABLE_READ:读取指定数据表

2. TABLE_WRITE:写入指定数据表

3. DBOBJ_CREATE:在某个数据库中创建数据表

4. DBOBJ_DELETE:删除某个数据库中的数据表

5. VIEW_EXEC:执行某个视图

6. DB_MANAGE:创建以及删除数据库。可删除任何人所建数据库,包括具有 DB_OWNER 权限之用户所建数据库。

7. DB_OWNER:创建数据库并管理其创建的数据库,包括删除数据库、创建或删除数据表、增加或删除分区、可赋予、禁止或取消其他用户对自己创建的数据库的以下权限:TABLE_READ, TABLE_WRITE, DBOBJ_CREATE, DBOBJ_DELETE。

8. SCRIPT_EXEC:执行脚本

9. TEST_EXEC:执行测试脚本

可以使用 grantdenyrevoke 命令来赋予权限、禁止权限,以及撤销权限设置。以上的9种权限类型作为这三个命令中的 accessType 参数。在设置访问权限 1-5 时,还需要指定权限应用的具体对象。

用户的权限是由其本身的权限以及所属组的权限共同决定的:

  • 如果用户在组中被授予一种权限,并且该用户所在的其他组没有禁止这个权限,那么该用户拥有这个权限。

  • 若某用户被赋予了某权限,但在这之后,其所属的某个组被禁止了此权限,那么该用户不具备此权限。若使该用户重新具备此权限,管理员可以使用 grant 命令重新赋予该权限,或者使用 revoke 命令撤销之前的禁止权限,并且赋予该用户或该用户所属的组此权限。

当用户安排计划作业时,他不需要具备与对象相关的权限。但是,执行计划作业时,用户需要具备与对象相关的权限。

流数据表相关权限管理 (1.30.15 开始支持):

1. 管理员可以对用户赋予(grant)、禁止(deny)或撤销(revoke)共享内存表/共享流数据表/流数据引擎的读(READ)或写(WRITE)权限

2. 在订阅节点,用户使用 subscribeTable 函数订阅流数据表之前,应当确认其是否具有流表的 TABLE_READ 权限。 没有 TABLE_READ 权限的用户不能订阅该流表。

3. 在发布节点,若需要向共享流数据表写入数据,需要同时具有 TABLE_READTABLE_WRITE 的权限。

4. 流表的发布端和订阅端不在同一个节点时,权限对象必须为 "nodeAlias:tableName",比如:deny(`amy,TABLE_READ,"DFS_NODE1:st"), DFS_NODE1 为流数据表所在节点 Alias,st 为流数据表名。

5. 只有流数据表的创建者或 admin 用户可以删除表。

6. 使用 grant 赋予流数据表权限后,建议使用 revoke 进行撤销。

7. 当用户从一个流数据表中订阅数据存入数据表时,应当确保其有写入此数据表的权限。

例子

1. 以管理员身份登录系统,并创建数据库 dfs://db1 以及其内的数据表 pt1。

$ login(`admin, `123456);

$ n=1000000
$ ID=rand(10, n)
$ x=rand(100, n)
$ t1=table(ID, x)

$ db=database("dfs://db1", HASH,  [INT, 2]);
$ pt1 = db.createPartitionedTable(t1, `pt1, `ID)
$ pt1.append!(t1)

2. 创建名为 "football" 的组,该组包含3个成员,分别是 EliManning、JoeFlacco 和 DeionSanders。该组的所有成员都可以读取 dfs://db1/pt1 表中的数据。用户 DeionSanders 可以创建或删除数据库。

$ createUser(`EliManning, "AB123!@")
$ createUser(`JoeFlacco, "CD234@#")
$ createUser(`DeionSanders, "EF345#$")
$ createGroup(`football, `EliManning`JoeFlacco`DeionSanders)
$ grant(`football, TABLE_READ, "dfs://db1/pt1")
$ grant("DeionSanders", DB_MANAGE);

用户 EliManning 不可创建数据库:

$ login(`EliManning, "AB123!@");
$ db=database("dfs://db2", HASH,  [INT, 2]);

$ db = database("dfs://db2", HASH, [4,2]) => Not granted to create or delete databases.

3. 增加两个成员到 "football" 组中,并且把 JoeFlacco 从组中移除。使用 getUsersByGroupId 函数可以获取 "football" 组中的用户。

$ login(`admin, `123456);

$ createUser(`AlexSmith, "GH456$%")
$ createUser(`NickFoles, "IJ567%^")
$ addGroupMember(`AlexSmith`NickFoles, `football)
$ deleteGroupMember(`JoeFlacco, `football)
$ getUsersByGroupId(`football);

["AlexSmith","DeionSanders","EliManning","NickFoles"]

4. 创建名为 "baseball" 的组,该组包含 3 个成员,分别是 CliffLee、ShoheiOhtani 和 DeionSanders。

$ createUser(`CliffLee, "GH456$%")
$ createUser(`ShoheiOhtani, "IJ567%^")
$ createGroup(`baseball, `CliffLee`ShoheiOhtani`DeionSanders)

DeionSanders 属于两个组。使用 getGroupsByUserId 函数可以获取 DeionSanders 所在的组。

$ getGroupsByUserId(`DeionSanders);

["football","baseball"]

进行以下权限设置:

$ grant(`baseball, DBOBJ_CREATE, "dfs://db2")
$ deny(`baseball, TABLE_READ, "dfs://db1/pt1")
$ deny(`baseball, DB_MANAGE);

"football" 组可以读取 dfs://db1/pt1 表,而 "baseball" 组被禁止了该权限。因此,DeionSanders 不具有该权限。

$ login(`DeionSanders, "EF345#$");
$ t = loadTable("dfs://db1","pt1");
t = loadTable("dfs://db1", "pt1") => Not granted to read table dfs://db1/pt1

尽管 DeionSanders 之前已经被赋予了创建和删除数据库的权限,但是步骤4中的 "baseball" 组被禁止了该权限。DeionSanders 作为 "baseball" 组的一个成员,也被禁止了该权限。当 DeionSanders 不属于 "baseball" 组,或撤销禁止 "baseball" 组创建和删除数据库的权限,或授予 "baseball" 组该权限时,用户 DeionSanders 才具有创建和删除数据库的权限。

5. 定义一个计算表 dfs://db1/pt1 行数的函数,将它定义为视图,并赋予 "baseball" 组执行该视图的权限。

$ login(`admin, `123456);

$ def countPt1(){
$     return exec count(*) from loadTable("dfs://db1","pt1")
$ }

$ addFunctionView(countPt1)
$ grant("baseball", VIEW_EXEC, "countPt1");

尽管 "baseball" 组没有读取表 dfs://db1/pt1 的权限,但是该组成员可以通过视图 countPt1 来获取表中的记录条数。以 ShoheiOhtani 身份登录,执行以下脚本:

$ login(`ShoheiOhtani, "IJ567%^");
$ countPt1();
1000000

6. 定义一个函数,以计算表 dfs://db1/pt1 中 ID 为指定值的某列的最大值,将其定义为视图,并赋予 "baseball" 组执行该视图的权限。

$ login(`admin, `123456);

$ def getMax(column, idValue){
$ return exec max(column) from loadTable("dfs://db1","pt1") where id=idValue
$ }

$ addFunctionView(getMax)
$ grant("baseball", VIEW_EXEC, "getMax");

用户 CliffLee 可以登录并执行视图 getMax。

$ login(`CliffLee, "GH456$%")
$ getMax(x, 6);
99

7. 管理员赋予用户 MitchTrubisky DB_OWNER 的权限:

$ login(`admin, `123456);
$ createUser(`MitchTrubisky, "JI3564^")
$ grant(`MitchTrubisky,DB_OWNER);

MitchTrubisky 创建数据表 dfs://dbMT/dt,并赋予用户 NickFoles 读取该数据表的权限:

$ login(`MitchTrubisky, "JI3564^");
$ db = database("dfs://dbMT", VALUE, 1..10)
$ t=table(1..1000 as id, rand(100, 1000) as x)
$ dt = db.createTable(t, "dt").append!(t)
$ grant(`NickFoles, TABLE_READ, "dfs://dbMT/dt");

用户 NickFoles 登录并读取 dfs://dbMT/dt 数据进行计算:

$ login(`NickFoles, "IJ567%^")
$ select max(x)-min(x) from loadTable("dfs://dbMT", "dt");
99