首页 > 代码库 > 初识keystone
初识keystone
前言
OpenStack概念不多讲了,因为讲不明白。只了解过keystone,其他服务是干什么的,怎么用的,目前还没有驱动力去了解,所以就自觉闭嘴了,只贴一张比较有意思的图。
Openstack社区非常活跃,开发者很多,代码和文档更新也很频繁,最近几天看文档的过程中就发现过文档内容调整的情况,虽然官网上的文档非常多,但是感觉有点分散,加上V2和V3 版本并存,有些概念和设计在不断演进,新学者刚开始不太容易理出头绪,下面对这段时间学习keystone的一些心得做个总结。
“keystone"的中文意思是拱心石,就是石拱门上面最中间那块石头,将两边的石头塞住不会掉下来,如图:
Keystone是Openstack家庭的一个成员,在2012年的Essex版本成为核心服务,它将内部的Identity, Catalog, Token和Policy服务统一对外提供给Openstack的其他服务。两个最主要的功能一是用户身份认证以及允许用户做什么,另一个功能是为服务编目,有哪些服务可用以及它们的访问点是什么。
基本概念
Keystone的核心概念主要包括:user, project(tenant), domain,token, role, service, endpoint等,V3版本将V2 版本的tenant改名为project,同时增加了domain概念。
下面是我总结的领域模型:
- user代表一个用户,有相关联的用户名和密码以及其他诸如email等数据
- project包含了一些基础设施资源,记得有人举例说project(以前的tenant)就好比一个宾馆,里面有各种设施
- domain是V3新增加的概念,类似于命名空间,在不同的domain之间,用户名、project、group名字可以相同。但是domain和role的名字必须全局唯一
- role就是角色,比如admin,member等,名字可以随便起,叫”女王陛下“完全没问题,但是各个服务有权利自己解释角色的定义,后面会进一步说明这一点
- group似乎也是V3新增的概念,可以将用户分组,直接给group赋予权限,有GBP(Group based policy)。group在Keystone中不是必须的
- token就是令牌,用户认证通过后被分配给一个令牌,以后拿着这个令牌可以在规定的范围内活动,也就是说令牌不仅有身份信息,比如用户角色,还有作用范围,通常是project和domain;另外token还有有效期,过期失效;如果中间表现不好,还可能被提前吊销(revoke)
进一步说明一下上面几个概念的关系: role是相对的,一个用户在不同project里面可以有不同的role,在给user或者group授予role时必须指定domain或者project; domain是目前最大的概念,可以包含project,user等,在两个domain里面可以建立两套名称完全相同,但是功能各不相同的系统。
catalog就是目录或者注册表,它可以提供service的索引服务,告诉用户有哪些service以及如何找到这些服务(endpoint)。在云中,不同服务可能分布在各个角落,或者一个服务可能根据地域(region)不同提供就近的服务接入点。Keystone支持两种方式来注册catalog,一种是模板文件,另一种是SQL存储方式,前者参考Keystone源码目录中的etc/default_catalog.templates,后者需要在keystong启动后通过API来注册。
还有一个关键概念没讲到,就是policy,理解它花了我好几袋烟的功夫。下面的表述未必完全正确,但目前还讲得通。
Policy提供了RBAC(Role based access control)功能,policy是由每个服务自己来管理的,由一组rule组成, 每个service定义自己的rule。 用户访问服务提供的API时,要告诉service你是一个什么角色,但是service自己来解读role的含义。比如说英女王到了一个英联邦国家,人家一看元首来了,赶紧给你吃香的喝辣的,好酒好肉伺候着,基本上你想干啥就干啥,但是,如果女王到了一个阿拉伯国家,人家可能最多跟你客气一下,能干什么还要听人家的,甚至搞不好门都不让进,压根不欢迎你。
Keystone做的很灵活的一点就是所有后端的provider都是可配置的,用户也可以自定义provider。对于Policy,各个service默认采用oslo-incubator policy engine,它通过读取policy.json文件来解析action和role之间的对应关系,决定用户是否有权限进行相应操作。oslo-incubator的实现在openstack/common/policy.py中。
V3版本中,keystone提供了操作policy的API,数据保存在DB中,可能为今后集中控制权限做准备。但是目前,这个特性并没有真正使用。
Keystone中间件-auth_token
这个东东没有仔细研究过,这里一带而过了。
Keystone既然为各个service提供了认证服务,那各个服务怎么用呢?一种高大上的方式就是用auth_token,放到pipeline中,各个服务自己负责auth_token安装和配置。其实就是http拦截器,拦截每一个http请求,检查头部token信息,提取用户、角色等信息,如果验证通过,放行,否则拒绝请求。
认证流程
贴上随处可见的流程图,说实话,有一步没看懂,麻烦明白人给讲一下
就是第4步,endpoint到keystone的过程中,里面说有“Does it allow that service usage"的过程,这个Keystone是如何判断的?其他不多说了,很好理解。
UUID&PKI
Keystone的token有两种格式:UUID和PKI。UUID是一个定长的随机字符串,PKI全称是public key Infrastructure,这个概念应该属于加密的范畴,并不是Keystone的独创的,详情请度娘或谷歌。
两种格式各有优劣,最大的不同是UUID必须每次都经过Keystone才能认证,而PKI是自包含的,service可以自己根据标准算法来检查签名,这样的好处就是提高了验证效率,Keystone不会成为整个Openstack的瓶颈。但是PKI token也带来了一个问题,因为PKI token包含了很多元数据以及catalog等信息,会很大,不仅带来了网络开销,而且可能超出一些服务器的限制,引发异常。下面就讲一下如何验证PKI签名以及解决token过大的几种方法。
插一句,昨晚写到这里的时候已经夜里12点了,突然无法保存文章,再一刷新,CSDN直接返回500,内部升级... 还好丢掉的不多,否则白码了这么多字,岂不哭死。
PKI离线验证
在测试环境中,通过keystone-manage pki_setup生成私钥及自签署证书,关于公钥、私钥、证书等概念请参考我转发的上一篇文章《CentOS6.5下openssl加密解密及CA自签颁发证书详解》,这里不再解释了。
Keystone的PKI token实际上是将包含元数据,比如用户、角色、catalog等信息的json数据用自己的私钥和CA证书来签名,用到的命令是:
openssl cms -sign -signer /etc/keystone/ssl/certs/signing_cert.pem -inkey /etc/keystone/ssl/private/signing_key.pem -outform PEM -nosmimecap -nodetach -nocerts -noattr < metadata.json如果不用重定向,可以用-in和-out参数生成cms格式的文件。上面命令生成的密文就是token。
验证token合法性就是拿Keystone的证书以及CA的签字证书来检查,命令是:
openssl cms -verify -certfile /etc/keystone/ssl/certs/signing_cert.pem -CAfile /etc/keystone/ssl/certs/ca.pem -inform PEM -nosmimecap -nodetach -nocerts -noattr < cms_token如果命令返回成功就能看到原始的metadata了。
但是,从Keystone API得到的token并不符合CMS标准,不能直接调用上面的命令,需要做一下转换,参考Keystone的源码:
https://github.com/openstack/python-keystoneclient/blob/master/keystoneclient/common/cms.py
def token_to_cms(signed_text): copy_of_text = signed_text.replace('-', '/') lines = ['-----BEGIN CMS-----'] lines += textwrap.wrap(copy_of_text, 64) lines.append('-----END CMS-----\n') return '\n'.join(lines)也就是要将原始的token做一些字符替换,加上头尾两端CMS注释,然后将token字符串按每行64个字符折叠起来。这样再调用上面的验证命令就OK了。
Token太大
这个问题在Keystone社区也有很多讨论,给出了各种方案,这里总结一下我看到的几种,供大家参考
- 改用UUID Token,废话了~
- 用PKI Token的MD5值替代原始Token放到HTTP请求header的X-Auth-Token属性中。我验证过,工作没有问题,但是就丢失了原来包含的元数据。
- 关掉catalog,给元数据减肥,验证时用这个URL:v3/auth/tokens?nocatalog
- 使用zlib压缩token,在keystone.conf中配置Token的provider为:provider=keystone.token.providers.pkiz.Provider
Keystone在Ubuntu上的安装配置
据说Ubuntu是对Openstack支持比较好的Linux发行版本,但是直接使用apt-get install安装的Keystone版本比较老,跟Ubuntu的repository有关,我后来是直接从源码安装的。
环境Ubuntu 14.04 LTS,步骤如下:
git clone http://github.com/openstack/keystone.git python setup.py install
有些python的依赖需要提前安装,比如python-dev, python-setuptools, python-pip
安装配置mysql,Keystone默认使用sqllite,我改用mysql,更熟悉些
sudo apt-get install python-mysqldb mysql-server
配置mysql权限
mysql> CREATE DATABASE keystone; mysql> GRANT ALL ON keystone.* TO 'keystone'@'%' IDENTIFIED BY [YOUR_KEYSTONE_PASSWORD]; flush privileges;将Keystone源码目录etc目录下的配置文件拷贝到/etc/keystone目录下,修改一下配置文件后缀
修改主配置keystone.conf,主要改了几个地方,数据库连接、token provider、[signing]段除第一项外全部打开
初始化数据库,执行:keystone-manage db_sync,可能又有python依赖,安装之
初始化SSL,先创建keystone用户,然后执行pki_setup
sudo groupadd keystone sudo useradd -g keystone keystone sudo chown -R keystone:keystone /etc/keystone sudo keystone-manage pki_setup --keystone-user keystone --keystone-group keystone最后启动keystone
Keystone-all [--debug]
使用命令行
Keystone有两个客户端,一个是python-keystoneclient,一个是openstack client。前者目前不支持V3的API,官方推荐用openstack client。
安装方式:
wget http://tarballs.openstack.org/python-openstackclient/python-openstackclient-0.4.0.tar.gz sudo python setup.py install执行openstack客户端命令时需要带一些参数,也可以设为环境变量
export OS_IDENTITY_API_VERSION=3 export OS_AUTH_URL=http://localhost:5000/v3 export OS_TOKEN=netscreen export OS_URL=http://localhost:35357/v3然后就可以执行类似于:openstack user list 这样的命令了,返回结果如图
使用Curl
这里只举个例子,更多参考:http://docs.openstack.org/developer/keystone/api_curl_examples.html#
curl -i -H "Content-Type: application/json" -d ' { "auth": { "identity": { "methods": ["password"], "password": { "user": { "name": "admin", "domain": { "id": "default" }, "password": "secrete" } } }, "scope": { "project": { "name": "demo", "domain": { "id": "default" } } } } }' http://localhost:5000/v3/auth/tokens ; echo返回如图
结束语
花了两个多星期,把Keystone翻了一遍,只为技术选型。但是如果不是基于openstack,只用keystone来做一个集群应用的RBAC是否有意义,答案恐怕偏向于否定。“云”对我而言还飘在高高的天上,遥不可及,以后如果有需要会进一步研究下去。
如果上面有理解错误或者选型建议,请不吝赐教,谢谢。
初识keystone