全網(wǎng)最強(qiáng)的權(quán)限系統(tǒng)設(shè)計(jì)攻略:京東北極星商業(yè)系統(tǒng)權(quán)限管控實(shí)踐

一、ABAC經(jīng)典設(shè)計(jì)案例分析

我們先來說說個經(jīng)典的設(shè)計(jì)案例,這個設(shè)計(jì)案例會讓你進(jìn)一步的理解ABAC的能力

其實(shí)這個案例在最后的參考文章里,你也可以自己看,我這里是結(jié)合著我的理解在講

AWS IAM權(quán)限策略設(shè)計(jì)

我們先來看一個json

// 看不懂沒關(guān)系,先混個臉熟
{
    "Action":[
        "EditUser",
        "GetUser"
    ],
    "Resource":"user:1、2、3、4",
    "Condition":{
        "DateLessThan":{
            "acs:CurrentTime":"2021-03-22T17:00:00+08:00"
        }
    }
}
復(fù)制代碼

我們在上篇文章中說過,權(quán)限管控的本質(zhì)是為了控制一個訪問實(shí)體可以做什么 ,RBAC通過角色聚合權(quán)限,很容易地做到了這些,但是做過權(quán)限系統(tǒng)的人都知道,很多時(shí)候還有一些其他條件的影響,以及這個人可以訪問什么數(shù)據(jù)的限制,如果要做到這些,則需要在角色或者權(quán)限上面加上各種屬性,然后又去根據(jù)各種條件過濾,這樣子帶來的復(fù)雜性是呈指數(shù)上升的,并且不夠通用。我們再看看上面的json中,這個json我們可以把它視作一個訪問策略,在ABAC中叫做policy(上文中已經(jīng)說過),在這個policy中,Action元素其實(shí)就是一系列api code的聚合,Resource元素就是可以訪問的資源的集合,condition元素指的是額外的限定條件,所以這個json表示的是,和這個policy綁定的人可以在2021年的3月22日之前去對id為1,2,3,4的四個用戶執(zhí)行這個編輯和查看操作(對應(yīng)EditUser和GetUser),這樣,就做到了增加條件限制以及限定訪問的數(shù)據(jù)。

這個是AWS的IAM訪問策略的設(shè)計(jì),也只是其中一個很簡單的例子,但也是一個非常經(jīng)典的設(shè)計(jì)案例,它的設(shè)計(jì)思想是源自于XMACL,XMACL的文檔在結(jié)尾的文檔中(不推薦學(xué)ABAC的看這玩意,太復(fù)雜了)。

事實(shí)上亞馬遜的這個policy中的元素是非常多的,遠(yuǎn)遠(yuǎn)不止這么幾個,而且每個元素也是比我例子中的復(fù)雜的,比如我下面這個policy,它是表示獲取AlexaForBusiness這個資源的所有權(quán)限以及和其相關(guān)的AWS的權(quán)限:

// 看不懂也沒關(guān)系,因?yàn)橹皇菫榱俗屇忝靼姿枷?{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "a4b:*",
                "kms:DescribeKey"
            ],
            "Resource": "*"
        },
        {
            "Action": [
                "iam:CreateServiceLinkedRole"
            ],
            "Effect": "Allow",
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "iam:AWSServiceName": [
                        "*a4b.amazonaws.com"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:DeleteServiceLinkedRole",
                "iam:GetServiceLinkedRoleDeletionStatus"
            ],
            "Resource": "arn:aws-cn:iam::*:role/aws-service-role/*a4b.amazonaws.com/AWSServiceRoleForAlexaForBusiness*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:DeleteSecret",
                "secretsmanager:UpdateSecret"
            ],
            "Resource": "arn:aws-cn:secretsmanager:*:*:secret:A4B*"
        },
        {
            "Effect": "Allow",
            "Action": "secretsmanager:CreateSecret",
            "Resource": "*",
            "Condition": {
                "StringLike": {
                    "secretsmanager:Name": "A4B*"
                }
            }
        }
    ]
}
復(fù)制代碼

再次強(qiáng)調(diào),看不懂沒關(guān)系,別被這個json看暈了,這個策略為啥包含這么多東西,一般是只有設(shè)計(jì)者才知道的,而我們需要搞懂的是如何去設(shè)計(jì)。

二、京東北極星商業(yè)系統(tǒng)權(quán)限系統(tǒng)設(shè)計(jì)方案

1、ABAC設(shè)計(jì)本質(zhì)

我們從之前的文章中能夠明白,ABAC設(shè)計(jì)的目的是為了能夠滿足控制請求者在某些條件下是否對請求數(shù)據(jù)具備某個操作(API) 的能力,目前來看,ABAC還暫時(shí)沒有什么標(biāo)準(zhǔn)建模(policy不是由實(shí)體組成),一般都是policy的語法設(shè)計(jì),這個指的就是用一個json或者一個xml來描述一個policy ,這個policy會和用戶或者其他實(shí)體綁定,然后這個用戶或者是實(shí)體就具備了在某些條件下對某些數(shù)據(jù)的操作能力。

為什么ABAC沒有標(biāo)準(zhǔn)建模呢?作者的經(jīng)驗(yàn)是認(rèn)為,ABAC主要是語法設(shè)計(jì),因此會非常靈活,這種非常靈活的關(guān)系不適合用模型和模型
之間的約束關(guān)系來表示,因此目前經(jīng)典的設(shè)計(jì)都是用xml或者policy來表示一個policy。
復(fù)制代碼

2、業(yè)務(wù)背景概述及設(shè)計(jì)難點(diǎn)分析

京東北極星商業(yè)系統(tǒng)簡單說就是一系列SaaS服務(wù)的集合,這一系列SaaS服務(wù)在商業(yè)化過程需要有一個統(tǒng)一的底座,底座需要提供權(quán)限能力,即北極星商業(yè)操作系統(tǒng)需要向一系列的SaaS服務(wù)去提供權(quán)限管控的能力,同時(shí)包括控制每個用戶渲染的菜單的能力,這要求,我們的權(quán)限系統(tǒng)必須足夠通用,并且還能夠在各種各樣復(fù)雜的業(yè)務(wù)場景下進(jìn)行訪問控制(即鑒權(quán)服務(wù))

最后這句話里有個非常難的點(diǎn)就是鑒權(quán),因?yàn)槲覀冎?,不同的業(yè)務(wù),在鑒權(quán)的時(shí)候往往會受到業(yè)務(wù)特性的影響,但是我們的權(quán)限系統(tǒng)不可能把所有的這些業(yè)務(wù)特性都集成進(jìn)來,一方面這樣做權(quán)限系統(tǒng)就不是通用的了,再一方面,如果這樣做了,那么沒有個業(yè)務(wù)方接入的話,那就必須適配新的業(yè)務(wù)方的業(yè)務(wù)邏輯,然后還有就是復(fù)雜度會隨著時(shí)間而呈指數(shù)增長,接入方多的話,這樣的系統(tǒng)簡直會沒辦法維護(hù)。

這時(shí)候我們的ABAC便派上了用場。

3、ABAC的設(shè)計(jì)思路

面對這樣的場景,我們該怎么設(shè)計(jì)ABAC呢?我們來看看我們的語法設(shè)計(jì):

{
    "effect":"Allow",
    "actions":[
        "getUser",
        "updateUser",
        "get*"
    ],
    "resources":[
        "contextField:contextValue:resourceField:resourceValue"
    ],
    "condition":[
        {
            "operation-name":{
                "condition-key":[
                    "condition value"
                ]
            }
        }
    ]
}
復(fù)制代碼

其中action部分還是api,resource主要是各種業(yè)務(wù)條件以及業(yè)務(wù)數(shù)據(jù)的約束,condition部分目前主要是各種時(shí)間地理位置的約束,我們可以看出,condition部分完全可以由權(quán)限系統(tǒng)自己來閉環(huán),而resource部分是受業(yè)務(wù)影響的,所以我們重點(diǎn)看看resource部分的語法:

為了防止你懵逼,我還是解釋一下為什么condition部分權(quán)限系統(tǒng)自己就可以閉環(huán)?
這是因?yàn)槲覀儥?quán)限系統(tǒng)的設(shè)計(jì)condition部分就是一些公共的條件,比如時(shí)間,如果是要求當(dāng)前請求只能是早上八點(diǎn)到晚上的九點(diǎn)才
可以訪問,那么你完全可以獲取請求的當(dāng)前時(shí)間,然后再和policy中的condition value去做比對,以下是一個約束時(shí)間的json:
{
    "effect":"Allow",
    "actions":[
        "getOrder"
    ],
    "resources":[
        "contextField:contextValue:resourceField:resourceValue" 
    ],
    "condition":[
        {
            "DateLessThan":{
                "CurrentTime":[
                    "2021-03-30 17:00:00"            // 必須滿足時(shí)間小于2021-03-30 17:00:00
                ]
            }
        }
    ]
}
復(fù)制代碼

然后我們看看resource的語法設(shè)計(jì),這里我先拋出一個業(yè)務(wù)場景,現(xiàn)在有個客服SaaS系統(tǒng),采用的是租戶模式,每個租戶下有很多商家,每個商家又有很多客服人員,這就意味著每個租戶有個主商家,系統(tǒng)中有些事情是只有主商家才可以做的。這時(shí)候我們的json可以怎么設(shè)計(jì)呢?我們來看看如下例子:

{
    "effect":"Allow",
    "actions":[
        "getOrder"       
    ],
    "resources":[
        "isMain:1:orderId:12345"  // 并且必須是主商家,且只能訪問orderId為123456的訂單
    ],
    "condition":[
        {
            "DateLessThan":{
                "CurrentTime":[
                    "2021-03-30 17:00:00"              // 必須滿足時(shí)間小于2021-03-30 17:00:00
                ]
            }
        }
    ]
}
復(fù)制代碼

我們重點(diǎn)來看看resource中 “isMain:1:orderId:12345” 這個玩意,isMain就是一個業(yè)務(wù)字段,含義是是否為主商家,1的意思為主商家,所以這個json的意思就是用戶所在商戶必須是主商家并且訪問時(shí)間必須是早于2021-03-30 17:00:00才可以獲取id為12345的訂單(getOrder是獲取訂單),當(dāng)用戶和我們這個策略綁定之后呢,便可以這樣去對用戶鑒權(quán)了。

但是聰明的你肯定注意到了,權(quán)限系統(tǒng)怎么知道當(dāng)前訪問者所在商家是否是主商家呢?這是個超級重點(diǎn)的問題,這里有很多權(quán)限系統(tǒng)就走入一個坑,這個坑是什么呢?就是它們會去調(diào)用業(yè)務(wù)系統(tǒng)去查,這個做法是大錯特錯的,我們不能去依賴業(yè)務(wù)系統(tǒng)去做權(quán)限管控的,否則每來一個業(yè)務(wù)系統(tǒng)對接,我們還得去開發(fā),另外就是復(fù)雜度會隨著業(yè)務(wù)系統(tǒng)的變多而呈指數(shù)增長,這是無法接受的。那么我們是怎么做的呢?我們觀察到,一般這類屬性都是很重要的屬性,其實(shí)在前端頁面發(fā)起請求之前,就已經(jīng)查看過商家的信息了,這時(shí)候讓業(yè)務(wù)系統(tǒng)前端把這些在policy中的業(yè)務(wù)屬性帶在請求頭中就行,權(quán)限系統(tǒng)此時(shí)就可以根據(jù)這些數(shù)據(jù)和policy來做比對,從而完成鑒權(quán),并且,這樣子做,業(yè)務(wù)系統(tǒng)的改造量是非常小的。

你一定發(fā)現(xiàn)了一些通用的設(shè)計(jì)技巧但又不知道是啥對嗎?大方的我再次告訴你,policy就像是我們和權(quán)限系統(tǒng)做的約定,resource
部分就是告訴權(quán)限系統(tǒng)我會用這些業(yè)務(wù)字段來鑒權(quán),然后我請求的時(shí)候再把這些值帶上,權(quán)限系統(tǒng)來計(jì)算即可
復(fù)制代碼

4、RBAC 和 ABAC的優(yōu)勢及劣勢

我們在前面文章中說過,RBAC在應(yīng)對復(fù)雜場景的時(shí)候會顯得很吃力,但是它有沒有好處呢?答案是當(dāng)然有,它的好處顯而易見就是簡單且容易理解,我們很容易想象,一般不是開發(fā)者的這種用戶創(chuàng)建一個角色是多么的容易,但是你如果讓他去寫一個策略的json,那他怕是要罵娘,因?yàn)橐话闳烁径疾恢纉son是干嘛的,所以就更不可能會寫json。

ABAC的優(yōu)點(diǎn)就是RBAC的缺點(diǎn),它可以勝任在復(fù)雜場景下的鑒權(quán)工作,但是不知道讀者們注意到了上面的json中沒有菜單信息 這一點(diǎn)了沒,往具體的說就是如果你的系統(tǒng)使用的是個很純粹的ABAC權(quán)限模型,那么,你的系統(tǒng)是不具備管控用戶可以渲染的菜單的能力的,這時(shí)候肯定有人說,我可以通過一個人的所綁定的策略(ABAC中policy一般都是分配給人的)計(jì)算出他能訪問的所有API然后去渲染API所綁定的菜單呀,這個想法其實(shí)是大錯特錯的,一方面,因?yàn)閜olicy中有的條件是動態(tài)的,比如時(shí)間,如果純粹靠計(jì)算來的話,那么這一刻和下一刻看到的菜單很有可能是不一樣的(因?yàn)闀r(shí)間可能也是一種條件),另一方面就是,API和菜單往往不是一一對應(yīng)關(guān)系,也就是說,API上面可能綁定了多個菜單,這時(shí)候就會有粒度的問題。

5、RBAC 和 ABAC取舍以及結(jié)合

結(jié)合上面的業(yè)務(wù),我們來分析下我們的需求,我們需要做到的有如下的幾個點(diǎn):

  • 向各種各樣的業(yè)務(wù)去提供一個統(tǒng)一的、滿足各類業(yè)務(wù)要求的鑒權(quán)服務(wù)
  • 控制業(yè)務(wù)系統(tǒng)的菜單渲染能力
  • 不能向用戶展現(xiàn)太大的復(fù)雜度
  • 要讓原本的業(yè)務(wù)系統(tǒng)使用我們的權(quán)限系統(tǒng)之后業(yè)務(wù)改造成本足夠低
  • 不能與業(yè)務(wù)系統(tǒng)產(chǎn)生過多交互

為了同時(shí)滿足上面的要求,我們結(jié)合使用了RBAC和ABAC的能力,大致建模如下:

全網(wǎng)最強(qiáng)的權(quán)限系統(tǒng)設(shè)計(jì)攻略:京東北極星商業(yè)系統(tǒng)權(quán)限管控實(shí)踐

注意哈,這個不是數(shù)據(jù)庫建模,而是一個DDD的建模,具體的我就再不能解釋了,再解釋就涉及到商業(yè)機(jī)密了,大家可以參考這個設(shè)計(jì),也可以找我來進(jìn)一步交流。

原文鏈接:
https://juejin.cn/post/6951712306598248485
小編最后還給大家整理了一份面試寶典 有需要的私信小編【666】來領(lǐng)取!

image.png

image.png

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容