閱讀295 返回首頁    go 阿裏雲 go 技術社區[雲棲]


MongoDB權限驗證流程

上篇文章說到,MongoDB的網絡通訊協議流程。拿到請求對象後,會調用assemblyResonse函數處理。這部分的代碼實在沒什麼章法可言,if-else遍地,實在不怎麼優雅。可以感受到隨著需求的增長,很多代碼都是硬套上去的。本篇介紹的是基本的處理請求,基本請求所指的是command命令以外的處理行為。

assembleResponse

首先,獲取到線程綁定(ThreadLocal)Client對象,並對權限模塊初始化,更新Auth Cache中過期或者失效的權限信息。然後,根據配置記錄diaglog;接著統計操作計數器。接著,調用receivedXXXX函數,執行相關請求,其間會對權限進行判斷。最後,根據slowlog配置,記錄Profiling數據。

Query為例:

try {
    ...
    Status status = client->getAuthorizationSession()->checkAuthForQuery(ns, q.query);
    audit::logQueryAuthzCheck(client, ns, q.query, status.code());
    uassertStatusOK(status);
    ...
catch (AssertionException& e) {
    ...
    ok = false;
}

checkAuthForQuery之後會調用isAuthorizedForActionsOnNamespace做具體的驗證功能:

if (!isAuthorizedForActionsOnNamespace(ns, ActionType::find)) {
    return Status(ErrorCodes::Unauthorized,
        str::stream() << "not authorized for query on " << ns.ns());
}

isAuthorizedForActionsOnNamespace函數用來驗證資源和動作的權限合法性,不同的操作都對應自己的一套動作,相關的對應關係總結如下:

OP_CODE VALUE receivedXXXX checkAuthForXXXX ActionType
OP_UPDATE 2001 receivedUpdate checkAuthForUpdate update
OP_INSERT 2002 receivedInsert checkAuthForInsert createIndex/insert
OP_QUERY 2004 receivedQuery checkAuthForQuery find
OP_GET_MORE 2005 receivedGetMore checkAuthForGetMore listCollections/listIndexes/find
OP_DELETE 2006 receivedDelete checkAuthForDelete remove
OP_KILL_CURSORS 2007 receivedKillCursors checkAuthForKillCursors killCursors

PS:

  1. 2003操作代碼已經廢棄,目前是保留字段
  2. command請求也是通過OP_QUERY發送過來的,對於command請求,代碼上分之處理,個人不是很喜歡這個混用OP_CODE的風格,也許是偉大的**曆史原因**造成的
  3. inprog killop unlock 不走以上流程,通過Query包封裝傳遞過來後,調用了相應的處理函數處理
  4. command的權限驗證額外說明
  5. 所有的ActionType定義在db/auth/action_types.txt中,非常多

isAuthorizedForActionsOnNamespace

主要對Action和Resource封裝,然後調用_isAuthorizedForPrivilege完成功能。

簡單介紹下Privilege,Action就是對數據的操作,比如Query,Insert都可以歸納為Action;Resource就是數據集合,可以是Collection,也可以是DB,那Privilege就是Action*Privilege的組合,一個Privilege可以含有多個Action,但在Privilege維度上,Action都隻能與一個(或者表達式)Resource組合。Privilege的集合可以組合成Role概念,方便用戶配置。

這個函數的處理算法是,遍曆授權過的所有用戶,和待驗證的Resource比較,如果找到,則對比Action,所有的Action都找到的話,則通過驗證。

for (UserSet::iterator it = _authenticatedUsers.begin();
        it != _authenticatedUsers.end(); ++it) {
    User* user = *it;
    for (int i = 0; i getActionsForResource(resourceSearchList[i]);
        unmetRequirements.removeAllActionsFromSet(userActions);
        if (unmetRequirements.empty())
            return true;
    }
}

最後更新:2017-04-01 13:37:08

  上一篇:go PostgreSQL pg_clog fsync 頻率分析
  下一篇:go C++項目管理