基础用户权限

云数据库 SelectDB 版的权限管理系统借鉴了MySQL的权限管理机制,实现了表级别细粒度的权限控制,并支持基于角色的权限访问控制和白名单机制。本文介绍云数据库 SelectDB 版包含的权限管理系统的背景和具备的权限管理能力,及一些使用时的注意事项。

名词解释

名称

属性

说明

用户标识

user_identity

在权限系统中,一个用户被识别为一个User Identity(用户标识)。用户标识由两部分组成:username和userhost。其中username为用户名,由英文大小写字母组成。userhost表示该用户链接的IP来源。user_identity有两种呈现方式:

  • user_identity以username@'userhost':表示来自userhost的username。

  • username@['domain']:其中domain为域名,可以通过DNS反向解析为一组IP地址。最终表现为一组username@'userhost'。

本文统一使用username@'userhost'来表示。

权限

privilege

权限作用的对象是节点、数据目录、数据库或表。不同的权限代表不同的操作许可。

角色

role

角色可以被视为一组访问权限的集合。新创建的用户可以被赋予某一角色,此时该用户将自动被赋予该角色所拥有的权限。后续对角色的权限变更,也会体现在所有属于该角色的用户权限上。

用户可以创建自定义命名的角色。

用户属性

user_property

用户属性直接附属于某一用户,而不是用户标识。即cmy@'192.%'和cmy@['domain']都拥有同一组用户属性,该属性属于用户cmy,而不是cmy@'192.%'或cmy@['domain']。用户属性包括但不限于:用户最大连接数和导入集群配置等等。

权限说明

权限类型

权限名称

说明

GRANT_PRIV

权限变更权限。

允许执行包括授权、撤权、添加、删除和变更用户或角色等操作。

SELECT_PRIV

对数据库、表的只读权限。

LOAD_PRIV

对数据库、表的写权限。包括Load、Insert、Delete等。

ALTER_PRIV

对数据库、表的更改权限。包括重命名数据库和表,添加、删除或变更列,添加或删除分区等操作。

CREATE_PRIV

创建数据库、表、视图的权限。

DROP_PRIV

删除数据库、表、视图的权限。

USAGE_PRIV

资源的使用权限。

权限层级

根据权限适用范围的不同,库表的权限分为以下层级:

权限级别

说明

GLOBAL LEVEL

全局权限

通过GRANT语句授予的*.*.*上的权限。被授予的权限适用于任意数据库中的任意表。

CATALOG LEVEL

数据目录级权限

通过GRANT语句授予的ctl.*.*上的权限。被授予的权限适用于指定数据目录中的任意库表。

DATABASE LEVEL

数据库级权限

通过GRANT语句授予的ctl.db.*上的权限。被授予的权限适用于指定数据库中的任意表。

TABLE LEVEL

表级权限

通过GRANT语句授予的ctl.db.tbl上的权限。被授予的权限适用于指定数据库中的指定表。

资源的权限分为以下两个层级:

权限级别

说明

GLOBAL LEVEL

全局权限

通过GRANT语句授予的*上的权限。被授予的权限适用于任意资源。

RESOURCE LEVEL

资源级权限

通过GRANT语句授予的resource_name上的权限。被授予的权限适用于指定资源。

ADMIN/GRANT权限说明

ADMIN_PRIV和GRANT_PRIV权限同时拥有授予权限的权限,较为特殊。ADMIN_PRIV和GRANT_PRIV权限相关的操作说明如下:

  • CREATE USER

    • 拥有ADMIN权限,或GLOBAL和DATABASE层级的GRANT权限的用户可以创建新用户。

  • DROP USER

    • 拥有ADMIN权限或全局层级的GRANT权限的用户可以删除用户。

  • CREATE/DROP ROLE

    • 拥有ADMIN权限或全局层级的GRANT权限的用户可以创建角色。

  • GRANT/REVOKE

    • 拥有ADMIN权限,或者GLOBAL层级GRANT权限的用户,可以授予或撤销任意用户的权限。

    • 拥有CATALOG层级GRANT权限的用户,可以授予或撤销任意用户对指定CATALOG的权限。

    • 拥有DATABASE层级GRANT权限的用户,可以授予或撤销任意用户对指定数据库的权限。

    • 拥有TABLE层级GRANT权限的用户,可以授予或撤销任意用户对指定数据库中指定表的权限。

  • SET PASSWORD

    • 拥有ADMIN权限,或者GLOBAL层级GRANT权限的用户,可以设置任意用户的密码。

    • 普通用户可以设置自己对应的UserIdentity的密码。自己对应的UserIdentity可以通过SELECT CURRENT_USER();命令查看。

    • 拥有非GLOBAL层级GRANT权限的用户,不可以设置已存在用户的密码,仅能在创建用户时指定密码。

用户属性列表

部分与用户相关的属性如下表所示:

属性名

说明

cpu_resource_limit

限制查询的CPU资源。详见会话变量cpu_resource_limit的介绍。-1 表示未设置。

default_load_cluster

默认的导入Cluster。

exec_mem_limit

限制查询的内存使用。详见会话变量exec_mem_limit的介绍。-1 表示未设置。

insert_timeout

指定用户INSERT操作的超时限制。

max_query_instances

用户同一时间点执行查询可以使用的执行单元个数。

max_user_connections

最大连接数。

query_timeout

指定用户的查询超时限制。

resource_tags

指定用户的资源标签限制。

sql_block_rules

设置SQL Block Rules。设置后,用户发送的查询如果匹配规则,则会被拒绝执行。

说明

如果某个用户属性(user property)在变量(variable)中也存在,例如query_timeout,生效的优先级次序是:session variable>user property>global variable>default value。较高优先级的变量未设置时,会自动采用下一个优先级的数值。

权限操作

操作名称

操作关键字

语法

创建用户

CREATE USER

CREATE USER [IF EXISTS] user_identity [IDENTIFIED BY 'password']
[DEFAULT ROLE 'role_name']
[password_policy]

删除用户

DROP USER

 DROP USER 'user_identity'
 
 `user_identity`:
     user@'host'
     user@['domain']

授权

GRANT

GRANT privilege_list ON priv_level TO user_identity [ROLE role_name]
 
GRANT privilege_list ON RESOURCE resource_name TO user_identity [ROLE role_name]

撤权

REVOKE

REVOKE privilege_list ON db_name[.tbl_name] FROM user_identity [ROLE role_name]
 
REVOKE privilege_list ON RESOURCE resource_name FROM user_identity [ROLE role_name]

创建角色

CREATE ROLE

 CREATE ROLE rol_name;

删除角色

DROP ROLE

 DROP ROLE rol_name;

查看当前(所有)用户权限

SHOW (ALL)GRANTS

SHOW [ALL] GRANTS [FOR user_identity];

查看已创建的角色

SHOW ROLES

SHOW ROLES

查看用户属性

SHOW PROPERTY

SHOW PROPERTY [FOR user] [LIKE key]

设置用户属性

SET PROPERTY

SET PROPERTY [FOR 'user'] 'key' = 'value' [, 'key' = 'value']

参数说明

参数

说明

[password_policy]

指定密码认证登录相关策略,具体策略如下。

  • PASSWORD_HISTORY:是否允许当前用户重置密码时使用历史密码。

    参数规则:[n|DEFAULT]默认为0表示不启用。如PASSWORD_HISTORY 10表示禁止使用过去10次设置过的密码为新密码。

  • PASSWORD_EXPIRE:设置当前用户密码的过期时间。

    参数规则:[DEFAULT|NEVER|INTERVAL n DAY/HOUR/SECOND]。默认为NEVER表示永不过期。

  • FAILED_LOGIN_ATTEMPTS:设置当前用户登录时,如果使用错误的密码登录n次后,账户将被锁定。

    参数规则:[n|DEFAULT]。默认值不限制次数。

  • PASSWORD_LOCK_TIME:设置锁定时间。

    参数规则:[n DAY/HOUR/SECOND|UNBOUNDED]。

操作示例

  • 示例1:创建用户test_user且密码为123456,允许从'172.10.XX.XX'地址登录。

    CREATE USER test_user@'172.10.XX.XX' IDENTIFIED BY '123456';
  • 示例2:删除用户test_user@'172.10.XX.XX'

    DROP USER 'test_user'@'172.10.XX.XX'
  • 示例3:授予用户test_user@'172.10.XX.XX'test_ctl.test_db.test_table的读取、修改和导入权限。

    GRANT SELECT_PRIV,ALTER_PRIV,LOAD_PRIV ON test_ctl.test_db.test_table TO 'test_user'@'172.10.XX.XX';
  • 示例4:撤销用户test_user数据库test_db的读取权限。

    REVOKE SELECT_PRIV ON test_db.* FROM 'test_user'@'172.10.XX.XX';
  • 示例5:创建角色test_role

    CREATE ROLE test_role;
  • 示例6:删除角色test_role

    DROP ROLE test_role;
  • 示例7:将数据库test_ctl.test_db的所有表的导入权限授予于角色test_role

    GRANT LOAD_PRIV ON test_ctl.test_db.* TO ROLE 'test_role';
  • 示例8:将用户test_user@'172.10.XX.XX'的角色修改为test_role

    GRANT "test_role" TO test_user@'172.10.XX.XX';
  • 示例9:查看用户test_user@'%'的权限。

    SHOW GRANTS FOR test_user@'%';
  • 示例10:查看用户test_user的属性。

    # 查看用户的全部属性
    SHOW PROPERTY FOR 'test_user';
    
    # 使用LIKE表达式查看用户的具体属性
    SHOW PROPERTY FOR 'test_user' LIKE '%max_user_connections%';
  • 示例11:设置用户test_user的属性。

    SET PROPERTY FOR 'test_user' 'max_user_connections' = '1000';

最佳实践

常见权限系统的使用场景如下:

  • 场景一

    集群的使用者分为管理员(Admin)、开发工程师(RD)和用户(Client)。其中管理员拥有整个集群的所有权限,主要负责集群的搭建、节点管理等。开发工程师负责业务建模,包括建库建表、数据的导入和修改等。用户访问不同的数据库和表来获取数据。

    在这种场景下,可以为管理员赋予ADMIN权限或GRANT权限。对RD赋予对任意或指定数据库表的 CREATE、DROP、ALTER、LOAD、SELECT权限。对Client赋予对任意或指定数据库表SELECT权限。同时,也可以通过创建不同的角色,来简化对多个用户的授权操作。

  • 场景二

    一个集群内有多个业务,每个业务可能使用一个或多个数据。每个业务需要管理自己的用户。在这种场景下,管理员用户可以为每个数据库创建一个拥有DATABASE层级GRANT权限的用户。该用户仅可以对用户进行指定的数据库的授权。

  • 场景三

    云数据库 SelectDB 版本身不支持黑名单,只有白名单功能,但可以通过某些方式来模拟黑名单。假设先创建了名为test_user1@'192.%'的用户,表示允许来自192.*的用户登录。此时如果想禁止来自192.168.XX.XX的用户登录。则可以再创建一个用户test_user2@'192.168.XX.XX'的用户,并设置一个新的密码。因为192.168.XX.XX的优先级高于192.%,所以来自192.168.XX.XX将不能再使用旧密码进行登录。

权限注意事项

  • 实例初始化时,会自动创建如下角色和用户:

    • operator角色:该角色为运维操作角色,拥有Node_priv和Admin_priv权限,即对云数据库 SelectDB 版的所有权限,允许从任意节点登录。仅实例内置的root用户(root@'%')拥有该角色。

    • admin角色:该角色为管理角色,拥有Admin_priv权限,即除节点变更以外的所有权限,允许从任意节点登录。实例初始化会自动创建一个该角色的用户admin(admin@'%'),支持创建多个该角色的用户。

  • 不支持删除或更改默认创建的角色或用户的权限。

  • 忘记admin密码如果忘记了admin密码无法登录,可以在管控平台上重置admin密码,详情请参见重置实例admin密码

  • ADMIN_PRIV权限只能在GLOBAL层级授予或撤销。

  • 拥有GLOBAL层级GRANT_PRIV等同于拥有ADMIN_PRIV,因为该层级的GRANT_PRIV有授予任意权限的权限,请谨慎使用。

  • 通过SELECT current_user();SELECT user();可以分别查看current_useruser。其中current_user表示当前用户是以哪种身份通过认证系统的,而user则是用户当前实际的user_identity。所有的权限都是赋予某一个current_user的,真实用户拥有对应的current_user的所有权限。

    举例说明:假设创建了user1@'192.%'这个用户,但是来自192.168.XX.XX的用户user1登录了系统,则此时的current_useruser1@'192.%',而useruser1@'192.168.XX.XX'

常见问题

Q:如何解决在创建用户并且进行授权时,遇到域名与IP冲突或重复IP冲突的问题?

A:执行DROP USER删除出现冲突的用户后重新创建用户,即可解决问题。

  • 域名与IP冲突:

    1. 删除该用户后,创建新用户并且授权,示例如下。

      CREATE USER test_user@['domain'];
      GRANT SELECT_PRIV ON.TO test_user@['domain'];

      例如,该domain被DNS解析为两个IP:IP1和IP2。

    2. 对用户test_user@['domain']进行一次单独授权的访问IP1授权,示例如下。

      GRANT ALTER_PRIV ON.TO test_user@'IP1';

      test_user@'IP1'的权限会被从SELECT_PRIV修改为ALTER_PRIV,且允许访问的IP变更为IP1,再次变更test_user@['domain']的权限时,test_user@'IP1'也不会跟随改变。

  • 重复IP冲突:

    删除该用户后,创建新用户,示例如下。

    CREATE USER test_user@'%' IDENTIFIED BY "12345";
    CREATE USER test_user@'192.%' IDENTIFIED BY "abcde";

    在优先级上,'192.%'优先于'%'。因此,当用户test_user从192.168.XX.XX这台机器尝试使用密码'12345'登录云数据库 SelectDB 版时会被拒绝。