Zadig 基于 OPA 實現 RBAC 和 ABAC 權限管理技術方案詳解
隨著 Zadig 被越來越多企業用戶和社區小伙伴采用,大家對企業級權限和安全性有更高的訴求,亟待一套權限管理方案。經過充分調研,我們最終確定了采用 OPA(開放策略代理)開源策略引擎,事實上,它已經被 Netflix,Pinterest 和 Goldman Sachs 等公司用于生產,正在成為云原生策略管理的事實標準。但 OPA 的編寫具有一定的復雜度,網上的教程和官方文檔也僅僅停留在 Demo 層面。經過 Zadig 從 v1.9.0 到 v1.10.0 的迭代,我們已完整實現了 RBAC 和 ABAC 權限管理業務和技術方案的落地,這里我們將整套方案的技術細節分享給大家。
背景介紹
OPA
開放策略代理(Open Policy Agent,發音為“ oh-pa”)是一個開放源碼的通用策略引擎,它統一了跨技術棧的策略實施。OPA 提供了一種高級聲明性語言 rego,允許您將策略指定為代碼和簡單的 API,以加載軟件中的策略決策。您可以使用 OPA 在 Microservices、 Kubernetes、 CI/CD 管道、 API 網關等中強制執行策略
圖片來源:opa 官方
權限模型
RBAC:
基于角色的訪問控制模型(RBAC: Role-based Access Control),顧名思義,給用戶定義角色,通過角色來控制權限。目前來說基于角色的訪問控制模型是應用較廣的一個,特別是 2B 方向 SAAS 領域,應用尤其常見。
如上圖示,用戶擁有角色,且可擁有多個角色,而每個角色對應不同權限。這樣的好處是:不必為每一個用戶去配置權限,擁有極大的靈活性和便利性。
ABAC:
基于屬性的訪問控制模型(ABAC: Attribute-Based Access Control),被一些人稱為是權限系統設計的未來,不同于常見的將用戶通過某種方式關聯到權限的方式,ABAC 則是通過動態計算一個或一組屬性是否滿足某種條件來進行授權判斷(可以編寫簡單的邏輯)。屬性通常來說分為四類:用戶屬性(如用戶年齡),環境屬性(如當前時間),操作屬性(如讀取)和對象屬性(如一篇文章,又稱資源屬性),所以理論上能夠實現非常靈活的權限控制,幾乎能滿足所有類型的需求。Zadig 目前主要是通過標簽模擬屬性來實現細粒度資源權限控制。
圖片來源:阿里云幫助文檔
Zadig 權限場景
- 系統級別角色-解決全系統級別的權限問題(RBAC)
管理員:擁有全系統的所有權限
普通用戶:擁有公開項目以及其所有資源的查看權限、測試管理和數據分析的查看權限
- 項目級別角色-解決項目級別的權限問題(RBAC)
project-admin:擁有該項目下的所有權限
read-only:擁有該項目下的所有資源的查看權限
read-project-only(默認):擁有該項目下工作流和集成環境list的權限(但資源會被精細化管理),服務、構建和測試資源的所有查看權限
自定義角色:自定義每個模塊權限能力
- 項目級別策略:解決項目級別資源的精細化管理(ABAC)
因此 Zadig 基于 OPA 實現 RBAC 解決了系統和項目通用的權限管理,實現 ABAC 解決了項目級別資源的精細化管理。
Zadig 權限架構設計
權限設計架構圖
Gloo 作為 Zadig 的網關,是 Zadig 所有流量的入口。通過集成 OPA 后,所有經過網關的流量都會由 OPA 來統一進行認證鑒權,而只有認證鑒權通過后才會準許訪問后端服務(aslan)。并且 OPA 決策依賴的數據會異步定時去權限管理服務(policy)和后端服務(aslan)采集決策所需要的權限和資源數據,從而實現高性能決策。
Zadig 權限數據庫模型
zadig-policy 數據庫中的相關數據模型
role:
用戶角色定義表,用來定義某項目下角色,下面的一條記錄表示在項目「zadig」下有一個「dev」角色,該角色擁有查看工作流和執行工作流的權限。
rolebinding:
用戶角色綁定表,用來將角色綁定到用戶身上,下面的一條記錄表示將「zadig」項目下的「dev」角色綁定給 uid 為「71b8aa87-a10b-11ec-af4e-fa012450189e」的用戶
policy_meta:
權限元信息表,用來將業務語意的權限轉換為對應 【endpoint+action】,在提供給 opa 的bundle 數據里角色下面的權限會被轉換成一組 url 的集合,具體轉換后的內容可以看決策數據中的 roles
policy:
用戶策略定義表,用來定義某項目下策略,下面的一條記錄表示在項目「zadig」下有一個「zadig-dev-system-zhangsan」策略
policy 和 role 表基本一致,主要區別是 policy 表多了一個 match_attributes 字段,這里表示對于項目「zadig」下打上label為【key = policy,value = zadig-dev-system-zhangsan-Workflow-zadig-workflow-dev】的workflow有擁有查看工作流和執行工作流的權限
policybinding:
用戶策略綁定表,用來將策略綁定到用戶身上,下面的一條記錄表示將「zadig」項目下的「zadig-dev-system-zhangsan」策略綁定給uid為「4fd92962-a4f6-11ec-af4e-fa012450189e」的用戶
Zadig 數據庫中的相關數據模型
label:
標簽表,標簽會同時打在權限 rule 規則和資源上,即表示權限對此標簽的資源有相關權限
labelbinding:
標簽資源關聯表,記錄標簽和資源的綁定關系
RBAC 的實現
決策數據
決策數據指的是提供給 OPA 用來執行決策的元數據集,它包括權限數據和資源數據,主要來自于權限管理服務(policy)和后端服務(aslan),在 OPA 術語中叫做 bundle,OPA 會將 bundle 緩存,提高決策效率,以下為決策數據目錄結構。
roles:
角色數據,數據來自上述 role 和 policy_meta 表,采集時會將其拼裝,因此此處的 rules 是最終拼裝的結果
bindings: role_bindings:
角色綁定數據,數據主要來自于上述 rolebinding 表
resources:
資源數據,Zadig 目前提供項目下細粒度資源的權限控制,所以需要采集工作流和環境相關資源
Workflow:工作流采集數據,原始數據存儲在后端服務(aslan)
Environment:采集數據,原始數據存儲在后端服務(aslan)
exemptions:
特殊 url 采集
Public: zadig 公開的 urls,所有用戶(包括未登錄用戶都能訪問)
Privileged: zaidg 特權 urls,只有系統 admin 用戶能訪問
Registered: zadig 所有注冊的 urls,沒有注冊的 urls 默認登錄用戶就能訪問
OPA 實現
鑒權流程:
- 校驗 url 是否無注冊,如果是無注冊,則返回通過
- 用戶是否是 admin,如果是,則返回通過
- 請求是否滿足,url 不是特權 url,并且用戶為該項目的項目管理員,如果是則返回通過
- 請求是否滿足,url 不是特權 url,并且請求匹配該用戶綁定的角色的權限,如果是則返回通過(權限不帶標簽,即 rule 中不帶有 matchAttributes
關鍵代碼(rego):
ABAC 的實現
決策數據
決策數據解釋同 RBAC 決策數據。
bindings : policy_bindings:
策略綁定數據,數據來自上述 policybinding 表。
policies:
策略數據,數據來自上述 policy 表,相比較于 roles,他的 rule 的 matchAttributes 中會帶有標簽,會對相匹配的資源進行過濾。
resources:
相比于 rbac 的 resource 采集,這里的資源 spec 中會帶上 label,用來做細粒度資源匹配。
OPA 實現
鑒權流程:
- 單個資源請求匹配,請求是否滿足 url 不是特權 url,該用戶綁定的策略權限規則匹配該請求,并且該權限的標簽匹配用戶請求資源的標簽,如果是則返回通過(權限帶標簽,即 rule 中帶 matchAttributes)
- 如果上述都不滿足,會進行多資源請求匹配,該用戶綁定的策略權限規則匹配該請求,如果是則會對匹配的資源進行過濾(權限帶標簽,即 rule 中帶matchAttributes)
- 如果所有都不滿足,則返回鑒權失敗
關鍵代碼(rego):
以上實現可以參考 Zadig 源碼位置:
pkg/microservice/policy/core/service/bundle/rego/authz.rego
展望
上面我們詳解了 Zadig 基于 OPA 的權限架構設計、數據庫模型實現以及 RBAC、ABAC 的實現,希望能給大家帶來思考和幫助。有了這樣一套權限管理方案還可以實現更多實用的功能,比如接下來的版本中,將提供根據項目細粒度權限控制來隱藏和關閉前端按鈕、系統角色權限管理和組管理能力及服務粒度的權限控制等等。
官網:https://koderover.com/
github: https://github.com/koderover/zadig