keystone policy.json 的学习总结
keystone的policy.json文件位于:
/etc/keystone/policy.json
其内容如下:
1 {
2 "admin_required": "role:admin or is_admin:1",
34 "identity:get_project": "rule:admin_required",
35 "identity:list_projects": "rule:admin_required",
36 "identity:list_user_projects": "rule:admin_or_owner",
37 "identity:create_project": "rule:admin_required",
38 "identity:update_project": "rule:admin_required",
39 "identity:delete_project": "rule:admin_required",
41 "identity:get_user": "rule:admin_required",
42 "identity:list_users": "rule:admin_required",
43 "identity:create_user": "rule:admin_required",
44 "identity:update_user": "rule:admin_required",
45 "identity:delete_user": "rule:admin_required",
46 "identity:change_password": "rule:admin_or_owner",
此文件的格式为:“规则名”,再冒号空格,再“判定条件”。从规则名可以看出,规则名是代表的是某种动作,例如创建用户这个动作,对应动作名为“identity:create_user”,其判定条件是“rule:admin_required”。
判定条件“rule:admin_required”表示调用规则“admin_required”。“admin_required”在第2行,其判定条件是“role:admin or is_admin:1”,这就比较容易理解,如果当前用户是admin角色或者元数据中“is_admin”字段的值为1,就返回真。
判定条件中可以用“or”或者“and”等,甚至使用变量。
由于未找到官方对于配置policy.json的详细说明,本文的出现的规则语法,全部借鉴于网络。
从规则名可以知道,大概每个keystone的API在policy.json中都有对应的规则名。
经过验证,V2版本的API只验证规则“admin_required”的判定条件,而其它规则不生效。原因在于以下文件中:
/usr/lib/python2.7/site-packages/keystone/common/wsgi.py
185 class Application(BaseApplication):
274 def assert_admin(self, context):
299 creds['roles'] = user_token_ref.role_names
300 # Accept either is_admin or the admin role
301 self.policy_api.enforce(creds, 'admin_required', {})
assert_admin函数只调用了规则“admin_required”。
/usr/lib/python2.7/site-packages/keystone/identity/controllers.py
30 class User(controller.V2Controller):
31
32 @controller.v2_deprecated
33 def get_user(self, context, user_id):
34 self.assert_admin(context)
35 ref = self.identity_api.get_user(user_id)
36 return {'user': self.v3_to_v2_user(ref)}
每个动作的具体实现函数里,调用assert_admin函数进行判定条件的检查,所以只检查规则“admin_required”。
例如,如果想使V2的API不检查判定条件(即所有用户都能执行该动作),注释掉self.assert_admin(context)即可。
例如,如果想使V2的API换一个规则进行判定,把“admin_required”替换成别的规则。
操作系统中keystone命令默认是调用V2版本的API,故只生效规则“admin_required”。
V3版本的API支持policy.json中的所有规则。V3版本主要是多了“domain”的概念。V2中的tenant在V3中改名为project,任何一个project或者user只能归属于一个domain。
使用keystone相关命令创建的租户或用户,默认属于域“default”。
下面对policy.json的工作原理做一个总结。
其中最关键的文件是以下文件:
/usr/lib/python2.7/site-packages/keystone/openstack/common/policy.py
118 class Rules(dict):
Rules自动载入policy.json中的每条规则,返回字典对象rules。
它是动态的,对policy.json的修改是不需要重启keystone服务的(修改Python原代码需要重启keystone服务)。
/usr/lib/python2.7/site-packages/keystone/openstack/common/policy.py
174 class Enforcer(object):
262 def enforce(self, rule, target, creds, do_raise=False,
263 exc=None, *args, **kwargs):
296 try:
298 result = self.rules[rule](target, creds, self)
V3 API的每个动作执行时,都会调用enforce函数,判定是否符合policy.json中的规则,原因见下文。
rule是规则名,如“identity:create_endpoint”。
self.rules是keystone.openstack.common.policy.Rules类型,即包含policy.json每条规则的字典。
self.rules[rule]是keystone.openstack.common.policy.RuleCheck类型,即此处将调用RuleCheck函数,检查规则的判定条件。
/usr/lib/python2.7/site-packages/keystone/openstack/common/policy.py
830 class RuleCheck(Check):
831 def __call__(self, target, creds, enforcer):
834 try:
835 return enforcer.rules[self.match](target, creds, enforcer)
self.match是判定条件,即冒号右边的字符串。
enforcer.rules是keystone.openstack.common.policy.Rules类型,它根据self.match,决定调用何种Check函数,即enforcer.rules[self.match]可能是GenericCheck、RoleCheck、OrCheck、AndCheck等类型,然后调用对应函数。
OrCheck或AndCheck类型是当判定条件含有or或and才出现的类型。在OrCheck或AndCheck函数内部,把判定条件再拆解成GenericCheck或RoleCheck类型。例如,"domain_id:%(domain_id)s"或"role:service"。
/usr/lib/python2.7/site-packages/keystone/openstack/common/policy.py
867 class GenericCheck(Check):
880 try:
881 match = self.match % target
887 try:
889 leftval = ast.literal_eval(self.kind)
891 try:
892 leftval = creds[self.kind]
895 return match == six.text_type(leftval)
GenericCheck函数的逻辑比较复杂,涉及字典变量target和creds。
/usr/lib/python2.7/site-packages/keystone/common/controller.py
85 def protected(callback=None):
86 """Wraps API calls with role based access controls (RBAC).
152 self.policy_api.enforce(creds,
153 action,
154 utils.flatten_dict(policy_dict))
161 def filterprotected(*filters):
162 """Wraps filtered API calls with role based access controls (RBAC)." ""
193 self.policy_api.enforce(creds,
194 action,
195 utils.flatten_dict(target))
V3版本每个动作的具体实现函数中,都会调用protected或filterprotected函数,而这两个函数调用policy.py的enforce函数,传递了target(或policy_dict)变量。
utils.flatten_dict函数的作用是返回一个一维字典,即GenericCheck函数中的target变量是一维字典。
target是目标的意思,字典变量target中存储了操作对象的domain_id或user_id等。有以下几种方式传递方式:
1、列出domain中所有的用户,可以在URL中传递?domain_id=参数,如:
# curl http://controller:35357/v3/users?domain_id=660450adcc194c0bbf9e462bb21b0935 -H "X-Auth-Token:f469cb22b6384a5b8dd343e480fc7bba"|python -mjson.tool
2、列出用户的project信息,URL中传递了user_id,如:
# curl http://controller:35357/v3/users/735c4d1fc8eb4bf8b96ee6866b441d9d/projects -H "X-Auth-Token:f469cb22b6384a5b8dd343e480fc7bba"|python -mjson.tool
3、如创建用户、创建项目、删除用户等,传递了操作对象,如在哪个域创建用户,删除哪个用户等:
# curl -X POST http://controller:35357/v3/users -H "Content-type: application/json" -H "X-Auth-Token:22142d114ddc454a9fbf6d282793840e" -d '{"user": {"default_project_id": "c0d6c4a09b7649a19c394a6cd946f53f","domain_id": "660450adcc194c0bbf9e462bb21b0935","enabled": true,"name": "evecom001","password":"123456"}}'|python -mjson.tool
以上几种传递方式,其实就两类:一类是通过filterprotected函数传递;另一类是通过protected函数传递。总之target的内容是来自于http数据,若是使用curl命令调用API,则来自于URL或-d参数。
可以尝试在GenericCheck函数中添加打印target内容的代码,观察调用不同API时target内容的变化。以下是不同动作获得domain_id的不同方法:
list_users: domain_id=target['domain_id']
create_user: domain_id=target['user.domain_id']
delete_user: domain_id=target['target.user.domain_id']
list_projects: domain_id=target['domain_id']
create_project: domain_id=target['project.domain_id']
delete_project: domain_id=target['target.project.domain_id']
只有打印了才知道不同动作获得domain_id的方法是什么(或者去源代码找)。
知道了target的关键字,就可以编辑policy.json,判断当前执行操作的用户的domain_id,与被操作对象的domain_id是否一致:
"target_list_users": "domain_id:%(domain_id)s",
"target_create_user": "domain_id:%(user.domain_id)s",
"target_delete_user": "domain_id:%(target.user.domain_id)s",
"target_list_projects": "domain_id:%(domain_id)s",
"target_create_project": "domain_id:%(project.domain_id)s",
"target_delete_project": "domain_id:%(target.project.domain_id)s",
"identity:list_projects": "rule:target_list_projects",
"identity:create_project": "rule:target_create_project",
"identity:delete_project": "rule:target_delete_project",
"identity:list_users": "rule:target_list_users",
"identity:create_user": "rule:target_create_user",
"identity:delete_user": "rule:target_delete_user",
按照上述policy.json,当enforce函数检查规则“target_create_user”时,调用的是GenericCheck函数。
881 match = self.match % target
match变量的值为target['user.domain_id'],即被操作对象的domain_id。
892 leftval = creds[self.kind]
leftval变量的值为creds[domain_id],即执行操作者的domain_id。
895 return match == six.text_type(leftval)
最后enforce函数返回match是否与leftval相等的比较结果(True of False)。
至于字典变量creds,打印其关键字为:
'is_delegated_auth'
'access_token_id'
'user_id'
'roles'
'trustee_id'
'trustor_id'
'consumer_id'
'token'
'domain_id'
'project_id'
'trust_id'
有点特别奇怪,默认管理员账户admin的creds没有'domain_id'这个关键字。如果admin的creds有'domain_id'这个关键字,值应该为“default”。初步猜测是由于admin是用keystone命令创建造成的,因为keystone命令是调用V2 API,没有domain的概念,创建用户时,只指定了tenant,即V3中的project。换句话说,如果要判断用户的domain_id,创建这个用户的时候,要指定其domain_id。同理适用于project_id。
字典变量creds的关键字比较稳定,不像target的关键字不同的API都不一样。至于字典变量creds的内容如何产生,我未去寻找其源代码,因为想得通:多半是通过token就能知道是哪个用户,知道哪个用户,系统自然有它的信息。
除了keystone可以使用policy.json定义权限,其它openstack组件也有policy.json:
/etc/nova/policy.json
/etc/heat/policy.json
/etc/keystone/policy.json
/etc/glance/policy.json
/etc/neutron/policy.json
/etc/cinder/policy.json
/etc/ceilometer/policy.json
keystone policy.json 的学习总结的更多相关文章
- JSON 教程学习进度备忘
书签:跳过:另外跳过的内容有待跟进 __________________ 学习资源:W3School. _________________ 跳过的内容: 1. ______________ 知识点:1 ...
- Json.Net学习笔记
http://www.cnblogs.com/xiaojinhe2/archive/2011/10/28/2227789.html Newtonsoft.Json(Json.Net)学习笔记 http ...
- Newtonsoft.Json(Json.Net)学习
转自原文 Newtonsoft.Json(Json.Net)学习笔记 Newtonsoft.Json,一款.NET中开源的Json序列化和反序列化类库.软件下载地址: http://www.newto ...
- JSON的学习与使用
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
- Android之Json的学习
json数据包含json对象,json数组,对象是{ },数组是[ ], 数组里面还可以包含json对象,json对象之间是用逗号(,)隔开 形式如下: { "languages" ...
- Newtonsoft.Json(Json.Net)学习笔记
Newtonsoft.Json 在Vs2013中就有自带的: 下面是Json序列化和反序列化的简单封装: /// <summary> /// Json帮助类 /// </summar ...
- JSON入门学习
JSON是一种与开发语言无关的轻量级的数据格式(JavaScript Object Notation) 优点:易于阅读和编写,易于程序解析和生产 JSON数据格式中没有日期及时间的数据格式的.一般直接 ...
- json官方学习档案
项目经常用json开发,但说实话,对json了解的一直不深入.今天看了下json的官方资料,明了很多. json官方网址:http://www.json.org/json-zh.html JSON(J ...
- Newtonsoft.Json(Json.Net)学习笔记-高级使用(转)
1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称 7.动态决定属性是否序列化 8.枚举值的自定义格式化问题 9.自定义类型转换 10.全 ...
随机推荐
- sqlQuery.list()方法返回类型
SQLQuery sqlQuery = session.createSQLQuery(this.sql.toString()); List<Object[]> list = (List&l ...
- java中json数据生成和解析(复杂对象演示)
1.json简单介绍 1.1 json是最流行和广泛通用的数据传输格式,简称JavaScript Object Notation,最早在JavaScript中使用. 1.2 举个例子,下面是一个jso ...
- Java导出Excel表(poi)名中文乱码问题处理
<pre name="code" class="java">String _filename = ValidateTools.date2Str(da ...
- split和join函数的比较
关于split和join方法 处理对象字符串.split拆分字符串,join连接字符串 string.join(sep): 以string作为分隔符,将seq中的所有元素(字符串表示)合并成一个新的字 ...
- js 获取当前点击的标签
- 常见的http状态码
[200]请求已成功,请求所希望的响应头或数据体将随此响应返回. [301]被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一.如果可能,拥有连结编辑功能 ...
- Win7下配置Django+Apache+mod_wsgi+Sqlite
搭建环境: win7 64位 Django 1.8.5 Apache2.4.17 mod_wsgi_ap24py27.so Python2.7.9 1 安装Apache 下载Apache Haus版, ...
- 河南多校大一训练赛 D
题目链接:http://acm.hust.edu.cn/vjudge/contest/125004#problem/D 密码:acm Description If an integer is not ...
- PHP开发利器zend studio常见问题解答
1.如何将zend studio 9的默认GBK编码设置为其它编码,例如UTF-8? 选择window菜单->Preferences->General->Workspace,在界面当 ...
- IIS判断W3WP进程对应哪个网站
IIS 6 (Win2003 )中查看某个应用程序池对应那个 W3WP.exe 进程,可以使用如下命令,输出结果类似如下: C:\WINDOWS\system32>cscript iisapp. ...