這一系列筆記已經記錄很長一段時間了,種種原因沒有貼出來,現在陸陸續續的貼出來。可能由於自己理解的
錯誤和疏忽,導致存在錯誤,歡迎大家指正,交流。
所有的源碼分析都是基於OpenStack Folsom版本。
參考文檔:http://hi.baidu.com/chenshake/item/184767c22c1231ba0d0a7bc7
這篇博客的前半部分基本上參照ibm(鏈接如上)的內容。
在理解OpenStack 授權機制之前,先明白其中的一些基本概念:
- User: 所謂的User代表着一些人或者能夠通過keystone獲取訪問的something。User通過自身的證書例如username & password 或者 api keys來訪問服務。
- Tenant:Tenant代表nova中的一個project,就是能夠聚合一些服務中的一些資源。例如,一個tenant能夠有一些nova中的虛擬機,glance中的一些images,quantum中的一些networks,users默認的綁定到某個tenant中。
- Role:代表一組用戶能夠一定程度的訪問資源。例如能夠訪問nova中的vms,glance中的images。Users能夠被添加到所有的tenants中或者某個tenant。用戶就獲取了對相應tenant中對應角色獲取的訪問資源的權限。
- service: 某類型的服務,例如nova, quantum, glance等等都是服務
- endpoint: 訪問服務的入口點,一個http路徑。例如:catalog.RegionOne.image.internalURL = http://10.10.102.14:9292,可以通過此URL訪問image服務
接下來,分析用戶在訪問一個服務的過程中,keystone都做了哪些工作,整個過程描述如下:
1. 獲取token
首先,需要確認你將訪問那個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接受到此請求之后,會驗證次請求,然后完成請求。