OpenStack 学习笔记 (一)

后续的文章都贴在:臭蛋上python

这一系列笔记已经记录很长一段时间了,种种缘由没有贴出来,如今陆陆续续的贴出来。可能因为本身理解的shell

错误和疏忽,致使存在错误,欢迎你们指正,交流。json

      全部的源码分析都是基于OpenStack Folsom版本。api

      参考文档:http://hi.baidu.com/chenshake/item/184767c22c1231ba0d0a7bc7 数组

      参考文档:https://www.ibm.com/developerworks/community/blogs/e93514d3-c4f0-4aa0-8844-497f370090f5/entry/openstack_keystone_workflow_token_scoping?lang=zh 函数

      这篇博客的前半部分基本上参照ibm(连接如上)的内容。源码分析

      在理解OpenStack 受权机制以前,先明白其中的一些基本概念:post

  1. User: 所谓的User表明着一些人或者可以经过keystone获取访问的something。User经过自身的证书例如username & password 或者 api keys来访问服务。
  2. Tenant:Tenant表明nova中的一个project,就是可以聚合一些服务中的一些资源。例如,一个tenant可以有一些nova中的虚拟机,glance中的一些images,quantum中的一些networks,users默认的绑定到某个tenant中。
  3. Role:表明一组用户可以必定程度的访问资源。例如可以访问nova中的vms,glance中的images。Users可以被添加到全部的tenants中或者某个tenant。用户就获取了对相应tenant中对应角色获取的访问资源的权限。
  4. service: 某类型的服务,例如nova, quantum, glance等等都是服务
  5. endpoint: 访问服务的入口点,一个http路径。例如:catalog.RegionOne.image.internalURL = http://10.10.102.14:9292,能够经过此URL访问image服务

接下来,分析用户在访问一个服务的过程当中,keystone都作了哪些工做,整个过程描述以下:加密

1. 获取tokenurl

      首先,须要确认你将访问那个tenant,必须使用keystone来获取一个unscoped token(意味着这个token没有和特定的tenant绑定),这个unscoped token可以用来深刻查询keystone service,肯定你能访问哪些tenants。获取一个unscoped token,使用典型的REST API,在request的body中不指定tenantName。例如:

  通过成功的验证,返回的response大体以下,其中的token id就是获取到的unscoped token(访问路径:/access/token/id),token id 将被在下一次的请求中做为X-Auth-Token的值,用来标识身份。

2. 获取tenants

  接下来的一步是,使用unscoped token来获取能访问的tenants,其中租期已经由你分配的角色决定了,对于每一个tenant,都有一个肯定的角色。全部在service endpoint上执行的操做都须要一个scoped token。获取能访问的tenants,使用 GET /tenants keystone API,其中将unscoped token写入X-Auth-Token。例如:

  返回的响应以下:

  这是一个tenants数组,包含了可以访问的tenants。

3. 获取scoped tokens

  获取了可以访问的tenants以后,决定访问某个tenants,就开始须要获取一个scoped token,这个scoped token与某个特定的tenant绑定,可以提供这个tenant的metadata和在tenant中的角色。获取scoped token须要使用POST /tokens keystone API,像第一步同样,这有两种形式的API。

  1. 使用第一步中同样的request body,传递user id 和 credentials,还指定tenantName

  2. 使用包含unscoped token和tenant name的request body,这样无需再post credentials。

  在返回的response中,包含一个scoped token和相关的metadata。

  更重要的是,其中包含了一组service endpoints。这些endpoints 肯定了获取的token可以访问的服务,Keystone service manage都是基于service/endpoing catalog的.经过这些endpoings,决定访问其中的service。

  关于keystone 管理的endpoint/service catalog:

  l  Keystone管理了一些的service,这些service在keyston的service catalog中定义了,定义方式大体是,type,name,description

  l  在service catalog中,endpoint包含了region中一些基本的URL。

  l  每一个endpoint与一个service关联。

  l  Endpoint url都是base urls,做为api方位的前缀。

4. 获取scoped tokens

  如今已经获取了scoped tokens,而且知道了endpoint API的url,下一步就是调用这些service endpoint。在这一步,使用keystone来确证token的有效性。存在两种类型的token,一种基于UUID的,一种基于PKI(Public Key Infrastructure)。

   l  UUID  Keystone 将维护一个token的UUID到他们的metadata和有效性的索引,token id没有携带嵌入的metadata,则endpoint service将调用keystone的service,应用这个token id的有效性,keystone将会返回这个token所相关联的metadata,包括角色,tenancy(租期),可以用在处理api请求的内部使用,endpoint service会为每一个api request去调用keystone服务验证有效性。

  l  PKI  PKI使得endpoint service不须要每次api request都进行调用keystone验证token的有效性。PKI使用public/private certificate pair,基于X.509 技术。Keystone 拥有Public private certificate。任何人都能经过REST API获取到public certificate,private certificate只能keystone拥有。当使用PKI,第一次使用endpoint service时,endpoint service将请求keystone的public certificate,而且保存起来。使用PKI模式,keystone将会建立json格式的对象,包含token的metadata,使用private certificate来加密token,再使用MD5来为加密的token建立指纹,这样的token将做为第三步中token ID返回,这样token ID包含了metadata而不只是一个UUID字符串。Endpoint service将会确认签名,使用public certificate解密token。这样,token包含全部的metadata了,endpoint service不须要再去找keystone获取这些信息。

         可以在keystone.conf配置文件中配置token_format.

5. 验证role metadata

  Endpoint service 使用token的metadata来验证用户可以访问请求的服务。这通常都涉及到Role Base Access Control(RBAC)。基于服务的policy.json文件,使用rule engine来决定用户的token包含适当的角色访问。

6. service API request

  到此,user就可以去经过api访问有权限访问的资源。

 

   有了上面基本知识,下面结合具体的代码粗略的描述上面的流程。

   从最开始的shell命令行开始,譬如,nova list命令,但在使用命令以前,咱们须要配置一下环境变量:

  将这些参数配置正确,便可以正确的执行nova list命令了。从nova 命令启动以后,python-novaclient 的main函数首先获取一个base parser,用来解析命令行,在获取这个base parser的过程当中,就会添加参数,例如os-username等等,而且设置其默认值为,从环境变量中读取出来的值。例以下面的os-username

  接着,从命令行参数中去获取os_username,os_password,os_tenant_name,os_auth_url,endpoint_type等等和受权相关的参数,有些参数如endpoint_type为空,则获取默认的,若os_username,os_password,os_auth_url都为空,则命令报错。

      若是endpoint_type是空的,则读取默认的值publicURL,前面介绍过service endpoint type的类型,有三类,publicURL,adminURL,internalURL。若service_type为空,则读取默认的值compute或者经过命令具体执行的命令是属于什么类型的service来肯定。(在定义一个命令行将调用的函数时,能够为它添加装饰器,指定所属的service)

  譬如经过命令 nova volume-list,就会获知service_type为volume,而不是默认的compute。

      而后,从auth_url指定的服务中获取受权,程序运行到这儿以后,就到了前面介绍的第一步了,获取tokens,而且在body中指定了tenantName。

 

  在返回的body中,就已经获取了全部的service catalog,根据service_type,endpoint_type则能够生成management_url.http://10.10.102.31:8774/v2/eacac8f7935348c7a6aa3ea6fe54e18c,此url则是访问nova compute服务的base url。而后在此url基础上,加上命令的具体参数,就访问此URL的服务--nova compute。

  nova compute接受到此请求以后,会验证次请求,而后完成请求。