正确理解OpenStack 中角色的继承与隐含
本文目录
1. user 、project 、domain 概念
- user:实际操作资源的对象,也就是用户,相当于一个公司的员工
- project:IT 基础设施资源的集合,注意 project 代表的是一系列资源,它相当于一个公司的部门
- domain:是 project 和 user 的集合,本质上它也是代表着一系列资源的集合(从代码和数据库来看,domain 本身就只是一个特殊的 project 而已),在公有云或者私有云中常常表示一个客户。
2. user 、project 、domain 关系
user 和 project 是一对多的关系,一个用户可以拥有操作多个 project 的权限(注意:user 并不能说属于 project )
user 和 domain 是多对一的关系,一个 user 只能属于一个 domain(虽然不同 domain 下可以有同名的 user,但本质上来说是两个 user),但一个 domain 里可以有多个 user。
project 和 domain 也是 多对一的关系,一个 project 只能属于一个 domain (虽然不同 domain 下可以有同名的 project,但本质上来说是两个 project),但一个 domain 里可以有 多个 project。
3. 正确理解 Role 的用法
一个用户要想操作某个 domain 下的某个某个 project ,必须先对该用户授予访问该 project 的权限。
$ openstack role add --project <project> --user <user> <role>
在 keystone 中的角色,只有两种类型:
admin
:管理员,固定以 admin 命名_member_
:普通成员,只要不是admin的都是普通成员
目前 VMP 是每个用户创建一个 Role,实际上没有必要,因为在使用上面那条命令授权的时候,最后一个参数区分也只有两种,是 admin 和 不是 admin,如果不是 admin,而是普通成功,那么完全可以统一用 _member_
这个 role,效果一样。
4. 为什么要使用 Group ?
用户关联角色的方法有两种:
- 单个用户关联一个角色(上面已经介绍了)
- 多个用户组成一个 group 来关联角色
试想一下,如果有多个 user 想获得访问 project 的权限,那么角色授权的时候,要是还按照第一种方法去一个一个用户关联角色,就非常麻烦,并且你在使用命令 openstack role assignment list
去查看的时候,会查到非常多的规则,不容易阅读和理解。
$ openstack role add --project <project> --user <user> <role>
这时候就可以创建一个 group,然后将想访问某个 project 的 user 都加入这个 group,然后就可以在关联角色时指定 group 来授权了
$ openstack help group create <group_name>
$ openstack role add --project <project> --group <group_name> <role>
以后如果有某个新增用户想访问这个 project,也只要往 group 里加 user 就行了,同样地,要访问取消某用户对该 project 的授权,也只要从该 group 中剔除该用户即可,如此一来就实现了角色动态关联。
5. Token Scope 是什么
当你在创建 token 的时候,除了要提供用户及密码之外 ,可能还要指定 scope,详细的接口说明请访问:OpenStack API Documentation
根据 scope 的不同,token 可以分为 unscoped token,domain-scoped token 和 project-scoped token。
project-scoped token
:针对一个 project 的 tokendomain-scoped token
:针对一个 domain 的 token,它具有有限的使用场景,只用于 domain 层面的操作。与 project-scoped 相比,它只具有优先的 sevice catalogunscoped token
:当既不指定 project 也不指定 domain 为 scope ,同时 user 也没有 default project 时获得的 token,这是一种特殊的token。
如果携带了一个 domain 的 domain token,并不是说就能访问该 domain 下的所有 project 的资源,因此类似虚拟机这种是直接属于 某个 project 的,才间接属于某个 domain 的。
6. Domain:特殊的 Project
从 keystone 的数据库表来看,并没有专门的 domain 表,所有的 domain 都是和 project 放在 project 表中的,使用如下这条命令就可以查询到所有的 domain 了。
select * from project where parent_id is NULL AND is_domain=1;
Domain 实际上也是 Project,只不过他比较特殊,是最顶层的 Project
什么是最顶层?
在 project 里,有父与子的关系,通过 parent_id 这个属性来体现,从下图可以看出有很多的 project 的 父 project 都是 default,而 default 应该很熟悉了,他是默认的 domain。
在 vmp 集群里,目前有三个 domain,其中 default 是默认的 domain,另外两个是后面加上去的。
7. 帐户分级的支持
7.1 角色的继承
由于有了 Project 的父子分级的概念,再配合角色的继承功能,帐户分级就不难实现了。
Project 的父子分级上面已经介绍了,这边再介绍一下继承是如何操作的。
假设,现在有 parent-project 以它的两个子 project,分别是 sub-project-01和 sub-project-02。
并且有一个 parent-user01 拥有对 parent-project 的访问权限,而 sub-user01 可以访问 sub-project-01 ,sub-user02 可以访问 sub-project-02 。
我们的目标是:
- 拥有 parent-project 访问权限的 parent-user01,也要能访问它的两个子 project 。
- 并且后续基于 parent-project 创建的 子project,在不重新角色分配的情况下也同样能生效
方法很简单,在 parent-user01 在角色授权的时候,要执行两条命令。
- 一条不加
--inherited
,表示 parent-user01 拥有对 parent-project 的访问权限 - 一条加
--inherited
,表示 parent-user01 拥有对 parent-project 的所有子 project 的权限
当你加了第二条后,使用常规的命令查看,规则仍然只新增了一条。
但是如果加上 --effective
后,就会发现,这条命令会自动拆解成两条命令,每一条对应该 用户拥有对应的 project 的访问权限。
为什么是两条?因为我这边的 parent-project 下只建了两个 子 project。
这个 自动拆解的命令是动态生成的,不管你在什么时候,创建的子project,都会生效。
7.2 角色的隐含
要想让一个用户既拥有 admin 的权限,又拥有某个 project 的普通成员的权限,正常情况下,会创建两条规则。
但是实际不用,因为在 keystone 的角色中,还有一个隐式角色的概念。
可以让一个普通用户同时拥有另一个身份,也就是 admin 的权限。
为此,角色可以分为两种
- 显式角色:直接指明某个用户拥有访问哪个资源的权限
- 隐式角色:由配置推断出来的,该用户还拥有访问哪个资源的权限
要想开启隐式角色,需要进行一些配置,确保 /etc/keystone/keystone.conf如下配置,这个配置控制着一个角色是否应该包含没有那些直接指定的 token scope,相应于一个开关,默认就是开着的。
[token]
infer_roles = true
如果你不想某些角色被隐含,可以在配置中声明哪些角色不应该被隐含。/etc/keystone/keystone.conf
[assignment]
prohibited_implied_role = admin
CLI 命令,并不能创建隐含关系,只能使用 curl 命令。在下面这条命令中,前面是 admin 的 role,后面是 _member_
的 role,表示拥有了 admin 权限的一定拥有 普通 _member_
的权限。
curl -X PUT -H "X-Auth-Token: OS_TOKEN" -H "Content-type: application/json"OS_AUTH_URL/roles/9b821b2920544be7a4d8f71fa99fcd35/implies/9fe2ff9ee4384b1894a90878d3e92bab
隐式角色在查看的时候,同样也是需要加 --effective
参数的。