ABAC - 基于属性的访问控制 - 复杂场景下访问控制解决之道
引言
引言
在一個典型的軟件開發場景中,你作為一名開發人員加入到某個項目后,假設是“超人組”,你往往需要訪問這個項目的代碼庫然后才能開始工作。當你的 Team Lead 將你加入 Git Organization 后,你自然可以訪問到“超人組”的代碼倉庫,然后就可以愉快的進行開發工作了。但是,當你的任務完成后,可能你需要參與另一個項目,你自然就沒有權利去訪問“超人組”的代碼庫,所以你的 TL 會將你移出。這是一個典型的訪問控制場景,我們所控制的對象是工程師,資源則是代碼倉庫。
對于軟件工程師來說,類似的場景十分常見,可以說任何一個系統都存在訪問控制機制,從操作系統到復雜的云上應用,我們也發明了很多名詞、技術來實現類似的功能,但是核心都是為了控制人或者其他對象,能否訪問資源。
Access Control Mechanism (ACM): The logical component that serves to receive the access request from the subject, to decide, and to enforce the access decision.
RBAC 的缺憾
對于訪問控制模型,大家最熟悉、或者實現最多的就是 RBAC Role Based Access Control,我們通過賦予不同 role 的不同權限來進行訪問控制。對于一個主體(往往是組織內的人員或者某個客戶端),他可以擁有多個 role 以應對多種不同的操作權限。RBAC 的流行很重要很大程度上是貼近現實生活,方便大家理解與使用,例如老王是銷售經理,同時也是技術委員會的成員,我們很自然就給他兩個 role:Sales Manager 與 Technology Group Member,而這兩個 role 對應的權限也很清晰明確,Sales Manager 可以查看所有的銷售數據,并進行修改等,而 Technology Group Member 只能查看技術上的文獻,不論是在系統設計還是在運營時,這些名詞都與我們的 title 相對應,對于管理人員來說,只是修改不同的 role 對應的權限而已。 當老王專心去做技術研究之后,我們就移除他的 Sales Manager Role,這樣他就無法訪問銷售上的數據了。
RBAC 在很多時候是管用的,比如我們的系統是面向銷售公司或者學校這種組織架構很嚴整的地方,但是在復雜場景下,RBAC 漸漸就不夠用了,它會產生很多虛無的 role 而且在管理和控制上更難:在某個醫療機構中,我們想要控制一個科室內,護士只能訪問自己所負責的病人資料時,我們就無法直接使用 nurse 這個 role,我們需要更細粒度的 role 去劃分病人老張還是老王,這就會產生和現實不對應的 role,例如:老張的護士,老王的護士。在醫院這種病人流動性很大的場景下,頻繁的創建和銷毀 role 是很容易出問題,我們的確要求很頻繁,但是與現實不 match 的虛無的 role 很難管理。
另一種情況是,如果管理者考慮醫療數據的安全性與隱私性,不希望護士在離開醫院后能夠訪問到病人資料,我們會更加難辦,常見的策略要么是在底層網絡層進行處理,直接禁止在院外的一切訪問,但是很多企業的需求往往是,使用 VPN 我依舊可以訪問內部的資源,但是我還是希望基于所在地進行精確的控制,比如看郵件是可以的,但是看財務數據是不行的。在 RBAC 下,我們也可以通過虛擬的 role 來控制,比如下班后給與其 Out of Office 的 role,然后給與這個 role 最小的權限,這自然又需要虛擬的 role 與大量的動態控制。
一般來說,在 RBAC 中濫用 role 所帶來的問題被稱為 “role explosion”,跟“曹操”與“曹操小時候”這個笑話很類似,但的確我們的訪問控制系統中存在很多這樣的 role。
ABAC
介紹
所以,直覺上來說我們需要更多的“東西”來進行更精細的訪問控制,用來匹配我們復雜的業務場景,同時,我們也希望這個新的模型易于理解和實現,也利于控制與運維,這就是 ABAC —— 基于屬性的訪問控制 (Attribute Based Access Control) —— 想要解決的問題。簡單來說,對于 ABAC 我們判斷一個用戶是否能訪問某項資源,是對其很多不同屬性的計算而得到的。
傳統的 RBAC 與 ACL 等訪問控制機制中,可以認為是 ABAC 的子集,對于 RBAC,只是我們的訪問機制的實現只是基于屬性 role 而已,ACL 則是基于屬性是 identity 的 AC。
術語
要理解 ABAC 首先需要從一些領域內的術語說起,按照我個人的習慣,對于專業性的術語一向是不翻譯的,因為的確是受夠了每次討論授權、認證、驗權、驗證等區別,雖然技術討論時彼此都理解要說的是什么,但是在場景中這是需要獨一無二的、易于理解的名字的(此處插入 DDD 的通用語言),此外還有一個好處就是好寫代碼,正確的名字可以幫助你的代碼易于理解和維護。
Attribute:屬性,用于表示 subject、object 或者 environment conditions 的特點,attribute 使用 key-value 的形式來存儲這些信息,比如我在公司的 role 是 developer,role 是 key,developer 是 value,而我的小組昵稱袋熊,key 是 team,value 是 wombat。
Subject:常常指代使用系統的人或者其他使用者(non-person entity,NPE),比如說客戶端程序,訪問 API 的 client 或者移動設備等等。當然一個 subject 可以有多個的 attributes,就像用戶屬性這些我們曾經用過的名詞一樣。
Object:指代我們這個 ACM 需要管理的資源,比如文件,比如某項記錄,比如某臺機器或者某個網站,任何你需要進行訪問控制的資源都可以稱為 object,同樣 object 也可以有多項屬性,比如袋熊組的桌子,或者洛克組的線上實例,我們也常常使用 resource 來描述這些資源,但是在 ABAC 的環境下,我們稱為 object。
Operation:有了 object 有了 subject,自然就有了 subject 需要做的事情,比如查看某條記錄,登錄某臺服務器,使用某個 SaaS 服務進行報銷或者查看候選人的作業。往往包括我們常說的讀、寫、修改、拷貝等等,一般 operation 是會表達在 request 中的,比如 HTTP method。
Policy:通過 subject、object 的 attribute 與 environment conditions 一起來判斷 subject 的請求是否能夠允許的關系表示,比如說:policy 可以用人類語言這樣表達,只有袋熊組的人才能訪問這幾臺服務器,或者只有在辦公室才能訪問這些資源,但對于機器來說,無非就是一個判斷語句罷了。當然了,policy 可以是一堆這樣 boolean 邏輯判斷的組合,比如只有公司的正式員工、并且在公司的六樓區域的網絡中,才能訪問某個服務。你可以使用 Specification Pattern 來實現 policy,其實沒那么復雜。
Environment Conditions:表示目前進行的訪問請求發生時,的操作或情境的上下文。Environment conditions 常常用來描述環境特征,是獨立于 subject 與 object 的,常用來描述系統的情況:比如時間,當前的安全等級,生產環境還是測試環境等等。
基本場景與概念
一個典型的 ABAC 場景描述如下圖,當 subject 需要去讀取某一條記錄時,我們的訪問控制機制在請求發起后遍開始運作,該機制需要計算,來自 policy 中記錄的規則,subject 的 attribute,object 的 attribute 以及 environment conditions,而最后會產生一個是否允許讀取的結果。
在 NIST 的描述中,我們對 ACM 內部進行進一步的抽象,可以得出這兩個核心模塊:Policy Decision Point (PDP) 與 Policy Enforcement Point (PEP),如下圖:
所以,實現 ABAC 的核心機制是在請求發起后,subject attributes、object attributes 與 environment conditions 作為輸入,PEP 獲取規則,PDP 進行計算,最后確定是否有權進行請求。ABAC 的邏輯并不復雜,根據之前我們所畫的基本場景與機制的圖中,你可以很輕松的開始進行架構設計,往往最開始你需要定義出 subject、object 以及其相關的 attribute,同時你也需要思考,當去進行 object 訪問時,你該如何表達 request 以及 operation。
RESTful 是我們常用的設計風格,RESTful 的流行是與 HTTP 協議密不可分的,其中我們很看重 HTTP 協議中的 methods,并且賦予了這些 methods 易于理解的語義,我們會很自然的認為 GET 是獲取資源,而 POST 是創建新的資源,PUT 則是修改,使用這些 methods 是與控制資源聯系在一起。但是,在 HTTP 協議中,并沒有規定 GET 是否可以進行資源上的修改和更新,因為這只是個傳輸協議罷了,是我們在這個協議之上發明了新的東西,所以也沒有“官方的、標準的” RESTful。之所以在這里提到 RESTful 與 HTTP 的關系,是想讓大家理解在進行 ABAC 系統設計時,operation 是可以有很多種表達的,而重要的是定義這些 operation 與 request 的關系,你可以使用 SOAP 或者其他協議,或者在 RESTful 之上自己發明一些字段,或者加入進 HTTP header,但是一定需要有清楚的 operation 描述。
為什么 ABAC 能解決復雜場景下的問題
在學習 ABAC 的過程中我發現,ABAC 和很多創新一樣,并不是因為科技的突破性進展,而只是在 RBAC 的思維上前進了一點,理解 ABAC 的術語時,你能很快的聯想到已有的技術實踐,比如 AWS IAM。而且,這些術語也如同我們做面向對象編程時,是很好的描述現實的。
Attribute 易于管理
我們可以很容易的為不同的用戶設計 attribute,往往在很多企業的實現中存在一個 consumer profile 或者 user details 的服務,這些服務中很多字段比如職位、職級、辦公室、項目等就是天然的 attribute,對于需要管理的 object,如果是一臺虛擬機,那么 IP 地址、歸屬組織、cost code 等都可以是 attribute,而且因為 attribute 是 K-V 式的,往往一張一對多的表就可以控制好 subject、object 與 attribute 的對應。
細粒度授權支持
ABAC 能做到細粒度的授權管理,我們知道,在 policy 中,我們的準許訪問的判斷是可以寫的很靈活的,我們甚至可以判斷請求中的某個屬性是否滿足于一個正則表達式,或者字符串相等(這個很常見,特別是在使用 AWS IAM 做最小權限原則時),我們也可以使用邏輯與、邏輯或的關系自由組合很多不同的訪問規則。你可以使用之前提到的 Specification Pattern 很輕松的實現靈活的 policy,解析 JSON 或者 XML 去動態的創建規則,而這些含有規則的 JSON 或 XML,則是可以被編程實現的(可編程的 policy 是動態的授權驗權的前提)。你的 policy 甚至可以做到,只有姓張的工程師在某個項目時才能訪問某個資源,在 RBAC 的時代,這是很難的。
訪問控制管理成本很低
ABAC 對系統管理員是友好的,在 RBAC 的時代,如果我需要實現細粒度的資源管理或者經常 subject 與 object 的對應關系經常變動,那么管理員難以操作的,也很容易出現問題,其中常常被采用的解決方案就是創建那些本不應該存在的 role。但是在 ABAC 時代,管理員的管理對象會縮減到 policy,也就是只處理訪問控制。我們再回到醫療機構的那個例子中,如果某個護士負責照顧老張,系統管理員只需要新建一個 policy 并寫上允許訪問即可,當老張出院后,只需要刪除或者失效這個 policy 就可以了。在 RBAC 的環境中,你可能需要為某個虛擬的 role 動態的添加 permission,而 permission 如果到了針對單個病人的情況下,是絕對多如牛毛的,特別是有兩個叫做老張的病人時。
往往,我們會使用 JSON 或者 XML 定義這個 policy,那么,這一切都可以完全自動化,而不需要使用管理員點擊。再現實一些的話,我們可以完全實現一個審批的流程,如果你使用過 Google Drive,你會對這個請求訪問的過程絕不陌生。
動態的總體控制
Environment conditions 也能夠提供統一的系統級別的控制,比如威脅等級或者按照區域劃分安全級別,不同的區域使用 ABAC 時,可能環境上會有變化。例如我們常用紅區來表示最高安全級別,那么我們默認就需要 deny 所有請求,并且會觸發警報等等,但是在綠區這種辦公區域,可能默認所有的請求都是被允許的等等。Environment conditions 可以提供“拉閘”這樣的功能,而且它也是可以動態調整的。
ABAC 在落地上的一些經驗和故事
AWS IAM
如果誰能作為 ABAC 比較好的實現榜樣的話,我第一個想起的就是 AWS IAM 的實現。如果當你的企業正在使用公有云時,對公有云的資源進行控制是非常難以管理的,你當然可以為每個小組安排好虛擬機或者 RDS 之類的,但是這太靜態了,而且也不足以細粒度。比如,當我們想實現最小權限原則時就很難辦到(例如你的數據庫只想被你確定的幾臺實例所訪問到),往往這種需求會實現為,在某個網段內,大家都可以訪問到某個數據庫或者中間件,那自然是不夠理想的。
公有云的資源是租用的,你可以按照自己的需求動態的擴容或者降低你的資源,那么這種場景下,資源是動態的,而且變化很大(可能會根據流量動態的啟動實例或者關閉),那在這種情況下如何做到訪問控制與最小權限原則,那你就不能再基于 users 與 roles 進行操作,這時候你就需要 ABAC。好消息是,AWS 作為云計算的領導者,很早就實現了類似的功能,而使用 IAM 則是 operations 的必修課。
請參考這個視頻,來自 AWS Senior Manager,個人認為是講的最好的 IAM 與 ABAC 介紹。
一些實踐經驗
最開始實踐 ABAC 是因為我們在進行一個內部云的資源控制項目,在設計時我們參考了 AWS 的玩法,并進行了類似的設計。實際上 ABAC 是與你要管理的資源無關的,更像是一種模式,在云資源控制中大多數 subject 不是用戶或者真正的人,而是客戶端、實例機器等。實現一個類似 policy 的策略管理并不是很難,主要的工作在管理端的開發以及為客戶端提供 SDK 上了,此外還有集成策略。我們也考慮過 XACML & NGAC (Next Generation Access Control) 去描述 policy 或者直接使用,但 XACML 過于復雜以及并不成熟,最后還是采取了自研的策略。故事這里是很多的,但是篇幅有限不予展開。
總結
ABAC 在概念上的設計的確是有先進性的,對于有 RBAC 知識的人,ABAC 不難理解,也就是“基于用戶屬性進行訪問權限判斷”,但是當我去閱讀 NIST 的文章或者參考 XACML 實現時,卻擔心 ABAC 的復雜實現,畢竟 NIST 給與的企業級實現考慮的長度占文章的一半。對于 ABAC 的概念,這并不是復雜度的來源,而是授權這件事本身的復雜性,對于系統的設計者與管理者來說,一旦需要關注細粒度的授權管理,那么復雜是無法避免的。
微服務的流行與 ABAC 的配合值得寫另一篇文章,特別是分布式身份驗證之后,怎么做到分布式的授權與驗權,怎么實現 PEP、PDP 等 ABAC 提倡的模塊設計,這些東西可否做成應用程序透明的方式,可否與 security sidecar 集成等等,這些都是可以進一步完善的。
業務人員希望有一種業務語言能夠描述授權策略,但是 gap 在于技術人員無法理解與實現,對于 ABAC 這種授權模式中,我們需要的是一位能夠同時說業務與技術兩種語言的人,將真正的業務需要轉為技術語言,從而指導落地。
參考文獻
- NIST (美國國家標準技術研究所) 的 ABAC 的定義與實現考慮,最重要的資料
- AWS IAM ABAC 介紹
- Specification Pattern
- ABAC 與 XACML 復雜性討論
- Yet Another Authorization Language
- XACML
- Next Generation Access Controls NGAC
總結
以上是生活随笔為你收集整理的ABAC - 基于属性的访问控制 - 复杂场景下访问控制解决之道的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于AI恶意软件分类技术(5)
- 下一篇: Qt跨平台原理