後續的文章都貼在:臭蛋上python
這一系列筆記已經記錄很長一段時間了,種種緣由沒有貼出來,如今陸陸續續的貼出來。可能因爲本身理解的shell
錯誤和疏忽,致使存在錯誤,歡迎你們指正,交流。json
全部的源碼分析都是基於OpenStack Folsom版本。api
參考文檔:http://hi.baidu.com/chenshake/item/184767c22c1231ba0d0a7bc7 數組
這篇博客的前半部分基本上參照ibm(連接如上)的內容。源碼分析
在理解OpenStack 受權機制以前,先明白其中的一些基本概念:post
接下來,分析用戶在訪問一個服務的過程當中,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接受到此請求以後,會驗證次請求,而後完成請求。