CockroachDB 是一个去中心化的分布式 NewSQL 数据库,可以支持海量数据存储、在线水平扩展、分布式 ACID Transaction 等。在数据库的用户和权限管理方面,支持常规的User,同时也支持 Role,当系统中存在大量用户时可以用 Role 进行便捷高效的权限管理。在用户登录校验方面,支持使用 SSL 证书和密码登录两种方式,更安全高效。
本文重点介绍了 CockroachDB 的用户权限管理及 Role 相关的概念、常用操作和实际使用中的注意事项。
用户User

CockroachDB 集群最开始默认只有一个 root
用户(User),该用户属于 admin
角色(Role),拥有最高的系统管理权限。
通常 root 用户
仅提供给数据库管理员使用,管理员可以通过 root
用户创建普通用户,对这些用户授予相应的数据库、表的权限,并提供给业务使用。
登录验证
CockroachDB 提供两种登录验证的方式(官方建议使用第一种方式):
通过 SSL 证书和 key 登录
登录时通过
--certs-dir
指定 CA 证书所在目录,如果该目录下有对应用户的客户端 CA 证书和 key 文件,则进行验证并登录;客户端 CA 证书和对应 key 文件是通过
cockroach cert
命令自动生成的,文件名为client.<username>.crt
和client.<username>.key
;CA 证书和对应 key 文件的文件名不能修改;CA 证书文件权限是644,key 文件权限是600
通过账户/密码登录
若在对应目录下没有找到该用户的客户端 CA 证书和 key文件,或证书验证失败,则会提示输入密码;若创建用户时没有指定密码,则该用户无法通过密码登录;
在v2.0版本中,仅支持在 Secure 集群中为用户创建登录密码;
无法给
root
用户设置密码,root
用户必须通过客户端 CA 证书和 key 登录
表结构
用户的信息在 System.users
表里面维护,users
表的结构如下
users 表用3个字段来记录一个账号:username、hashedPassword、isRole;
isRole 字段记录该账号是否 Role,可见 user 和 Role 都在 users 表中统一维护,且username 必须唯一
Role 是企业版的特性,下文会有详细介绍。
常用操作:
创建新用户
1、创建用户账号
<username>
是创建的用户名,用户名大小写不敏感,必须以字母或是下划线开头,包含字母、数值或下划线,长度为1到63个字符。如果想允许用户使用密码登录,需要在创建时使用
--password
指令,并创建密码。
2、创建用户的客户端 CA 证书和 key
需要注意的是,用户的客户端 CA 证书和 key 文件要和集群的 CA 证书放在同一个目录,因为登录时只会在--certs-dir
指定的目录下查找,若找不到则校验失败,转为密码登录。
更多关于创建证书的内容,可以查阅 《Create Security Certificates》(http://t.cn/Rk62hhH)
3、给用户授权
创建新用户后,需要给该用户授予相应数据库、表的具体权限。
用户授权的用法和 MySQL 非常类似,更多具体的权限,可以查阅 《GRANT》 (http://t.cn/Rk62xai)
使用中有两点要注意:
若不对用户授予某 database 的权限,它将无法看到该 database,尽管用户可能有该 database 的 table 的权限。
用户对 table 的操作,需要为用户授予对应 table 的权限,而不能直接在 database 上授权。
查看用户信息
修改用户密码
注意,密码部分<password>
如果不加引号,则会忽略大小写;如果要保留大小写,则需要给密码加上引号。
删除用户
删除用户并不会删掉该账号对应的权限。为了避免后续创建同名账号后,使用到旧账号的权限,建议在删除用户前把该账号的权限一并删掉。
删除权限使用REVOKE
命令,更多用法查阅:《REVOKE》(
http://t.cn/Rk62YLC
)
角色Role(企业版)

Role
可以看作是包含一组成员的实体,它的成员可以是 user
或者 Role。我们可以将数据库、表的权限分配给一个 Role,然后加入一些成员,这些成员将会继承该 Role 的权限,后续如果需要调整这些成员的权限,则只需要调整对应的 Role 权限即可。
在用户较多的大型数据库集群中,可以使用 Role
来进行更便捷高效的用户权限管理。目前 Role 相关功能仅在企业版提供,若需要体验该功能,可以在 CockroachDB 官网申请 license,可免费试用30天;也可以期待9月底百度云CockroachDB邀测,届时参加邀测也可体验。
下表是 Role
的一些基本概念:
Term | Descripition |
---|---|
root | 默认存在于 admin 角色里的一个用户, root 用户一定属于 admin 角色,且无法被移除。 |
Role admin | Role中的某个具有管理员权限的成员,该成员可以编辑对应Role的成员。可以使用WITH ADMIN OPTION 来创建一个Role admin。 |
Role | 角色,成员可以包括用户或者角色。 |
Inherit | 为其成员授予Role具体权限的行为,可以理解为成员继承了Role的权限 |
Indirect member | 间接成为 Role 成员的 user 或 Role。例如A是C的成员,C是B的成员,或者A经过多重关联后隶属于B。 |
Direct member | 作为 Role 的直接成员的 user 或 Role,例如A是B的成员。 |
Superuser Admin | admin 角色的一个成员,只有超级用户可以创建 Role 或者删除 Role。 admin 是默认的,且不允许删除。 |
集群最开始默认只有一个 admin
角色,该角色拥有一个成员 root
;admin
角色无法被删除,root
用户也无法从 admin
角色中移除。
admin
角色拥有集群管理员的权限,可以通过"SHOW GRANTS FOR admin;"
查看该角色具体的权限;将普通用户加入 admin
角色后,普通用户也将拥有集群管理员的权限,例如创建/删除 Role、创建用户等。
Role有一些特性:
Role 无法登录,它没有密码,也无法创建客户端证书
Roles 和 users 在同一个 namespace,如果存在一个用户
marc
,则无法创建名为marc
的角色Role 不能相互属于对方的成员,例如A是B的成员,B是A的成员
Role 的所有权限都会被它的成员所继承
只有
admin
角色可以创建和删除角色;Role admins
可以修改 Role 的成员只要一个 Role 还有权限,它就无法被删除
角色的成员数量没有限制(除了
admin
角色)
想要修改 Role 的成员,需要满足以下其中一点:
cockroach 管理员(
admin
角色)Role admin(使用
WITH ADMIN OPTION
指令添加到角色的成员)
常用操作:
创建 Role
如果
<Rolename>
已经存在,则创建失败;只有管理员有权限创建 Role,普通用户无权限创建 Role;
由于 Role 功能是企业版本特性,因此会检查是否有合法的
license
修改 Role 成员
将 user 加入到 Role,或者从 Role 中移除,操作过程和普通授权类似,使用GRANT
和REVOKE
命令,如下所示:
将
username
添加为Rolename
的成员;若加上WITH ADMIN OPTION
,则该用户将成为 Role admin,拥有修改角色成员的权限;WITH ADMIN OPTION
权限也可以继承,例如A ∈ B ∈ C,且B是C的admin,于是A也有C的admin权限
查看 Role 信息
Role 和成员的关系通过System.role_members
表维护,表结构如下:
通过三个字段维护 Role 及其成员信息:Role、member、isAdmin;
可以通过 “select * from System.role_members;” 查看所有Role及其成员;
删除
当删除角色的时候,该角色相关的成员归属关系也将会被删除。
迁移及向后兼容
从旧版本迁移到v2.0时将执行以下任务:
在 System.user 表里添加 isRole 列
在 System.users 表里添加 admin 角色
创建 System.Role_members 表格
创建 root 用户
将 root 用户添加到 admin 角色,并设置 isAdmin = true
赋予 admin 角色和 root 用户相同的权限
注意:
特意保留
root
的权限,是为了适配版本降级如果用户名
admin
存在,则log.Fatal
迁移过程,并要求用户降级/删除用户/再试一次。
Role成员扩展
展开角色的成员是执行权限检查所必需的。 由于此操作比较频繁,CockroachDB 在每个节点缓存一份相关数据,并通过增加 Role_members
表描述符版本来触发刷新。
权限检查过程如下:
如果用户的扩展角色未缓存,则使用 Role_members 表来扩展角色
在表描述符的 ModificationTime 中执行 Role_members 表的读取
读取 Role_members 的操作是在表描述符的 ModificationTime 中执行
这部分cache持有 Role_members 表的租约
当 Role_members 表描述符版本更改(表示 Role 成员权限变更)时,刷新表中的角色
这可以确保我们可以合理保持角色成员身份信息的最新状态,只有在发生更改时才会强制刷新。
Role 缓存可以是一个简单的LRU缓存,最大为几MB,这是可配置的。 由于缓存条目可能较小,我们可以让这些缓存不活跃一段时间后过期,而不是不断刷新它们。
可以预先计算 Role 成员扩展,使权限检查执行效率更高。
权限检查
权限检查目前主要涉及以下三个函数,它们均在p.session.User
上执行:
这些函数检查指定用户的多项内容,包括:
在描述符中具有所需的权限
是否
root
或者node
用户对描述符是否有“any”特权
对于 Roles 来说,将对包含以下内容的 names 集合进行权限检查:
username
user 所属的扩展角色列表
权限检查会检查集合中的任何name是否具有所需的权限。
对于 root 用户的权限检查是以硬编码方式检查扩展列表是否包含 admin 角色。
admin
角色是与当前 root
用户对应的特殊角色。 我们目前检查if user == security.RootUser
。它是在群集创建时(或迁移)创建的,并将root
作为成员进行初始化;它的成员不能为空,也不能被删除。
结语

CockroachDB 的权限管理和许多常见的数据库系统比较相似,针对普通用户授予特定的数据库、表的权限,在理解和使用上没有太大的成本。
v2.0 在用户和权限的基础上,增加了Role 的高级功能来对用户较复杂数据库权限进行便捷高效的管理,该功能目前为企业版功能。
对于绝大多数业务场景来说,使用普通的用户功能即可满足要求。
关于我们:我们是百度DBA团队,团队有两位CockroachDB PMC Member及一位Contributor, 目前正积极推动NewSQL在百度内部以及外部的发展。除了NewSQL, 我们在MySQL, PostgreSQL, GreenPlum有多年的内核开发经验及实践经验,对数据库和大数据领域有疑问或者需求欢迎联系我们,同时欢迎有志青年加入我们!
关注我们