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.全 ...
随机推荐
- mongodb状态
基本信息 spock:PRIMARY>db.serverStatus() { "host" :"h6.corp.yongche.org", //主机名 & ...
- HDU 2802 F(N)(简单题,找循环解)
题目链接 F(N) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- Webdriver+testNG+ReportNG+Maven+SVN+Jenkins自动化测试框架的pom.xml配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- iOS5新特性: Core Image 示例
iOS5给我们带来了很多很好很强大的功能和API.Core Image就是其中之一,它使我们很容易就能处理图片的各种效果,色彩啊,曝光啊,饱和度啊,变形啊神马的. 可惜苹果一直没能完善官方文档,也没有 ...
- Mysql主从备份、主主备份
简单介绍mysql双机,多机异地热备简单原理实战. 双机热备的概念简单说一下,就是要保持两个数据库的状态自动同步.对任何一个数据库的操作都自动应用到另外一个数据库,始终保持两个数据库数据一致. 这样做 ...
- XML回顾
xml加强 一.sax解析 1)原理: 读取xml的某个部分,解析一部分(读取一点,解析一点) 2)步骤: SAXParserFactory factory = SAXPa ...
- hdu4861(游戏)
数论问题:试题 题目没有看懂,但是解题方法感觉的确是非常巧妙的,应该是属于数论一方面的试题. 试题分析: 首先是DouBiNan先取,所以肯定优先选取剩余中值最大的,于是不存在说DouBiNan值小的 ...
- Html基础详解之(jquery)
jquery选择器: #id 根据给定的ID匹配一个元素,如果选择器中包含特殊字符,可以用两个斜杠转义.(注:查找 ID 为"myDiv"的元素.) <!DOCTYPE ht ...
- Ubuntu和Redhat(Debian)的差别
这两个最大的区别在包管理模式上. 都是用的Linux核心构架的. Redhat主要集中在 企业级服务器版的制作 是推动LINUX商业化最成功的公司 Redhat对应的桌面版制作 都是由Fedora社区 ...
- Android 禁止屏幕休眠和锁屏的方法
Introduction 常常我们开 发程序的时候我们不需要系统唤醒系统锁屏功能,比如我们在做xxxNowTV或XXX播放器这样的程序,用户有时候在看电视或视频的时候不希望系统的锁屏 功能启动,既不想 ...