設計授權模型的最佳做法 - Amazon Verified Permissions

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

設計授權模型的最佳做法

當您準備在軟體應用程式中使用 Amazon 驗證許可服務時,第一步要立即編寫政策陳述式可能會很困難。這類似於在完全決定應用程序應該做什麼之前,通過編寫SQL聲明或API規範來開始開發應用程序的其他部分。相反地,您應該從使用者體驗開始,清楚瞭解使用者在應用程式 UI 中管理權限時應該看到的內容。然後,從這種經驗向後工作以達到實施方法。

當你做這項工作, 你會發現自己問的問題,如:

  • 我的資源是什麼? 他們彼此之間有關係嗎? 例如,檔案是否位於資料夾中?

  • 主參與者可對每個資源執行哪些動作?

  • 主體如何取得這些權限?

  • 您是否希望使用者選擇預先定義的權限 (例如「管理員」、「操作員」或「ReadOnly」),還是應該建立臨機操作政策聲明? 或者兩者都是?

  • 權限是否應該跨資源繼承,例如從父文件夾繼承權限的文件?

  • 呈現用戶體驗需要哪些類型的查詢? 例如,您是否需要列出主體可以存取的所有資源,以呈現該使用者的首頁?

  • 使用者是否會不小心將自己鎖定在自己的資源之外? 這是否需要避免?

本練習的最終結果稱為授權模型;它定義了主參與者、資源、動作,以及它們彼此之間的關聯性。產生此模型不需要 Cedar 或「已驗證權限」服務的獨特知識。取而代之的是,它首先是使用者體驗設計練習,就像其他任何其他練習一樣,並且可以顯示在成品中,例如介面模型、邏輯圖表,以及權限如何影響使用者在產品中看到的內容的整體描述中。Cedar 的設計靈活性足以滿足模型的客戶需求,而不是強迫模型不自然地彎曲以符合 Cedar 的實施。因此,對所需的用戶體驗有清晰的了解是達到最佳模型的最佳方法。

本節提供有關如何進行設計練習、需要注意的事項,以及成功使用已驗證權限的最佳作法集合的一般指引。

除了此處提供的準則外,請記得考慮 Cedar 政策語言參考指南中的最佳做法

沒有規範的「正確」模型

當你設計一個授權模型時,沒有單一的,唯一的正確答案。不同的應用程序可以有效地為類似的概念使用不同的授權模型,這是可以的。例如,考慮電腦檔案系統的表示方式。當您在類 Unix 的作業系統中建立檔案時,它不會自動繼承父資料夾的權限。相反地,在許多其他作業系統和大多數線上檔案共用服務中,檔案會繼承其父資料夾的權限。這兩個選項都是有效的,具體取決於應用程式最佳化的情況。

授權解決方案的正確性並非絕對性,但應該根據其提供客戶所需體驗的方式以及是否以預期的方式保護資源來檢視。如果您的授權模型提供了這一點,那麼它是成功的。

這就是為什麼以所需的使用者體驗開始設計是建立有效授權模型最有用的先決條件的原因。

專注於API營運以外的資源

在大多數面向消費者的應用程式中,使用權限是以應用程式支援的資源為主。例如,檔案共用應用程式可能會將權限表示為可對檔案或資料夾執行的動作。這是一個很好的,簡單的模型,抽象掉底層實現和後端API操作。

相比之下,其他類型的應用程式 (尤其是 Web 服務) 通常會設計API作業本身的權限。例如,如果 Web 服務提供了API具名createThing(),則授權模型可能會定義對應的權限,或action在 Cedar 中定義名為createThing。這在許多情況下都有效,並且易於理解權限。若要呼叫createThing作業,您需要createThing動作權限。看起來很簡單,對吧?

您會發現,[已驗證權限] 主控台中的入門程序包含直接從API. 這是一個有用的基準:您的政策存放區與其授權的原則存放區之間的直接對應。API

但是,這種API聚焦的方法可能不是最佳方法,因為僅僅APIs是客戶真正嘗試保護的代理:基礎數據和資源。如果對相同資源有多個APIs控制存取權,則系統管理員可能難以理解這些資源的路徑並相應地管理存取權。

例如,假設包含組織成員的使用者目錄。用戶可以組織成組,其中一個安全目標是禁止未經授權的方發現組成員資格。管理此使用者目錄的服務提供兩項API作業:

  • listMembersOfGroup

  • listGroupMembershipsForUser

客戶可以使用其中一項作業來探索群組成員資格。因此,權限管理員必須記住,以協調對這兩項作業的存取。如果您以後選擇添加新API操作來解決其他用例,例如,這將進一步複雜。

  • isUserInGroups(快速測試用戶是否屬於一個或多個組的新功API能)

從安全性的角度來看,這會API開啟探索群組成員資格的第三個路徑,中斷系統管理員精心設計的權限。

我們建議您忽略API語意,而是將重點放在基礎資料和資源及其關聯作業上。將此方法套用至群組成員資格範例會產生抽象權限,例如,這三個API作業中的每一個都必須參考這個權限。viewGroupMembership

API姓名 許可
listMembersOfGroup 需要群組的viewGroupMembership權限
listGroupMembershipsForUser 需要對用戶的viewGroupMembership權限
isUserInGroups 需要對用戶的viewGroupMembership權限

藉由定義這一個權限,系統管理員可以成功控制探索群組成員資格的存取權,無論現在還是永遠。作為權衡,每個API操作現在都必須記錄其可能需要的幾個權限,並且管理員在製作權限時必須查閱此文檔。必要時,這可能是一個有效的權衡,以滿足您的安全要求。

複合授權是正常的

當單一使用者活動 (例如按一下應用程式介面中的按鈕) 需要多個個別授權查詢來判斷是否允許該活動時,就會發生複合授權。例如,將檔案移至檔案系統中的新目錄可能需要三種不同的權限:從來源目錄刪除檔案的能力、將檔案新增至目標目錄的能力,以及可能觸碰檔案本身的能力 (視應用程式而定)。

如果您是設計授權模型的新手,則可能會認為每個授權決策都必須在單個授權查詢中解析。但這可能導致過於複雜的模型和令人費解的政策聲明。實際上,使用複合授權對於幫助您產生更簡單的授權模型很有用。精心設計的授權模型的一個衡量方法是,當您具有足夠分解的單個動作時,您的複合操作(例如移動文件)可以通過直觀的基元聚合來表示。

發生複合授權的另一種情況是,當多方參與授予權限的過程中。請考慮使用者可以是群組成員的組織目錄。一個簡單的方法是授予群組擁有者新增任何人的權限。但是,如果您希望用戶首先同意添加該怎麼辦? 這引入了一個握手協議,其中用戶和組都必須同意成員資格。若要完成此操作,您可以引入另一個繫結至使用者的權限,並指定使用者是否可以新增至任何群組或特定群組。當呼叫者隨後嘗試將成員新增至群組時,應用程式必須強制執行權限的兩端:呼叫者具有將成員新增至指定群組的權限,並且要新增的個別使用者具有要新增的權限。當 N-way 握手存在時,通常會觀察N複合授權查詢以強制執行協議的每個部分。

如果您發現自己遇到了涉及多個資源的設計挑戰,而且還不清楚如何建立權限模型,則可能表明您擁有複合授權案例。在這種情況下,可以通過將操作分解為多個單獨的授權檢查來找到解決方案。

多租戶考量

您可能想要開發應用程式供多個客戶 (使用您應用程式的企業或用戶) 使用,並將其與 Amazon 驗證許可整合。在開發授權模型之前,請先制定多租戶策略。您可以在一個共用原則存放區中管理客戶的政策,或為每個租用戶指派一個原則存放區

  1. 一個共用原則存放區

    所有租用戶共用單一原則存放區。應用程式會將所有授權要求傳送至共用原則存放區。

  2. 每個租用戶原則儲存

    每個租用戶都有專用的原則存放區。應用程式會根據發出要求的承租人,查詢不同的原則存放區以進行授權決定。

這兩種策略都不會創建相對較大的授權請求,這些請求可能會對您的帳單產生影響。 AWS 那麼,如何,那麼,你應該如何設計你的方法呢? 以下是可能有助於您的已驗證許可多租戶授權策略的常見條件。

租用戶原則隔離

將每個租用戶的政策與其他租戶隔離對於保護租戶數據很重要。當每個承租人都有自己的原則存放區時,他們每個人都有自己獨立的原則集。

授權流程

您可以使用每個租用戶原則存放區的要求中的原則存放區識別碼來識別發出授權要求的承租人。使用共用原則存放區時,所有要求都會使用相同的原則存放區 ID。

範本和結構描述管理

您的原則範本和原則存放區結構描述會在每個原則存放區中增加一定層級的設計和維護額外負荷。

全球政策管理

您可能想要將某些全域原則套用至每個承租人。管理全域原則的額外負荷層級會因共用和每個租用戶原則存放區模型而有所不同。

租戶下機

某些承租人會為您的結構描述和其案例特定的原則提供元素。當租用戶不再與您的組織處於使用中狀態,而您想要移除其資料時,工作量程度會隨其與其他租用戶隔離的程度而有所不同。

服務資源配額

已驗證的權限具有資源和要求率配額,可能會影響您的多租戶決策。如需配額的詳細資訊,請參閱 資源配額

比較共用原則存放區和每個租用戶原則存放

在共用和每個租用戶原則存放區模型中,每項考量都需要自己的時間和資源承諾。

考量事項 共用原則存放區中的工作量層級 每個租用戶原則存放區中的工作量
租用戶原則隔離 中等。必須在原則和授權要求中包含租用戶識別碼。 低。隔離是預設行為。其他租用戶無法存取承租人特定的原則。
授權流程 低。所有查詢都會鎖定一個原則存放區 中等。必須維護每個承租人與其原則存放區識別碼之間的對應。
範本和結構描述管理 低。必須讓一個結構描述適用於所有租用戶。 高。結構描述和範本個別可能不太複雜,但變更需要更多的協調和複雜性。
全球政策管理 低。所有政策都是全球性的,可以集中更新。 高。您必須將全域原則新增至上架中的每個原則存放區。在許多原則存放區之間複寫全域原則更新。
租戶下機 中等。必須僅識別並刪除承租人特定原則。 低。刪除策略存放區。
服務資源配額 高。租用戶共用影響政策存放區的資源配額,例如結構描述大小、每個資源的原則大小以及每個原則存放區的身分識 低。每個承租人都有專用的資源配額。

如何選擇

每個多租用戶應用程式都不同。在做出架構決策之前,請仔細比較這兩種方法及其考慮因素。

如果您的應用程式不需要承租人特定原則,而且使用單一身分識別來源,則所有租用戶的一個共用原則存放區可能是最有效的解決方案。這樣可以簡化授權流程和全域原則管理。使用一個共用原則存放區離線租用戶需要較少的工作,因為應用程式不需要刪除承租人特定原則。

但是,如果您的應用程式需要許多承租人特定原則,或使用多個身分識別來源,則每個租用戶原則存放區可能最有效。您可以使用將每個租用戶權限授與 IAM 每個原則存放區的原則來控制承租人原則的存取。離線承租人涉及刪除其原則存放區;在 shared-policy-store環境中,您必須尋找並刪除承租人特定原則。

如果可能,請填入原則範圍

政策範圍是 Cedar 政策聲明的一部分,在permitforbid關鍵字之後以及左括號之間。

說明 Cedar 政策的結構,包括範圍。

我們建議您在可能的情resource況下填入值。principal這可讓「已驗證的權限」建立原則的索引,以便更有效率地擷取,進而改善 如果您需要將相同的權限授與許多不同的主參與者或資源,建議您使用政策範本,並將其附加至每個主參與者和資源配對。

避免在when條款中建立一個包含主參與者和資源清單的大型策略。這樣做可能會導致您遇到可擴展性限制或操作挑戰。例如,若要從原則內的大型清單中新增或移除單一使用者,必須讀取整個原則、編輯清單、完整寫入新原則,以及在管理員覆寫另一個管理員的變更時處理並行錯誤。相反地,透過使用許多細微的權限,新增或移除使用者就像新增或移除套用至使用者的單一原則一樣簡單。

每個資源都存在於容器中

當您設計授權模型時,每個動作都必須與特定資源相關聯。使用諸如此類的動作viewFile,您可以將其應用到的資源非常直觀:單個文件,或者可能是文件夾中的文件集合。但是,諸如之類的操作createFile不太直觀。建模建立檔案的功能時,它會套用到哪些資源? 它不能是文件本身,因為該文件還不存在。

這是資源創建的廣義問題的一個例子。資源創建是一個引導問題。即使沒有資源存在,也必須有一種方法才能獲得創建資源的權限。解決方案是認識到每個資源都必須存在於某個容器中,並且它是容器本身充當權限的錨點。例如,如果系統中已存在資料夾,則建立檔案的能力可以建立為該資料夾的權限,因為這是具現化新資源所需權限的位置。

permit ( principal == User::"6688f676-1aa9-456a-acf4-228340b54e9d", action == Action::"createFile", resource == Folder::"c863f89b-461f-4fc2-b638-e5fa5f79a48b" );

但是,如果沒有文件夾存在呢? 也許這是一個全新的客戶帳戶,在尚未存在資源的應用程序中。在這種情況下,仍然有一個上下文可以通過詢問直觀地理解:客戶在哪裡可以創建新文件? 您不希望他們能夠在任何隨機客戶帳戶中創建文件。相反,有一個隱含的上下文:客戶自己的帳戶界限。因此,帳號本身代表用於建立資源的容器,並且可以在類似下列範例的原則中明確建模。

// Grants permission to create files within an account, // or within any sub-folder inside the account. permit ( principal == User::"6688f676-1aa9-456a-acf4-228340b54e9d", action == Action::"createFile", resource in Account::"c863f89b-461f-4fc2-b638-e5fa5f79a48b" );

但是,如果沒有帳戶怎麼辦? 您可以選擇設計客戶註冊工作流程,以便在系統中建立新帳戶。如果是這樣,您將需要一個容器來容納程序可以在其中建立帳戶的最外層邊界。這個根級容器表示系統作為一個整體,可能被命名為「系統根」。但是,決定是否需要這樣做,以及如何命名它取決於您,應用程序所有者。

對於此範例應用程式,產生的容器階層會因此顯示如下:

包含帳號的系統根目錄的檔案階層。每個帳戶都包含可以依次包含文件的文件夾。

這是一個範例階層。其他人也是有效的。要記住的是,資源創建始終發生在資源容器的上下文中。這些容器可以是隱含的,例如帳戶邊界,並且很容易忽略它們。在設計授權模型時,請務必注意這些隱含的假設,以便它們可以在授權模型中正式記錄和表示。

將主參與者與資源容器分開

當您設計資源階層時,常見的傾向之一,特別是對於面向使用者的應用程式,就是使用客戶的使用者識別做為客戶帳戶內資源的容器。

檔案階層,其中使用者身分是所有資源的容器。

我們建議您將此策略視為反模式。這是因為在更豐富的應用程序中自然傾向於將訪問權限委派給其他用戶。例如,您可以選擇引入「家庭」帳戶,讓其他使用者可以共用帳號資源。同樣地,企業客戶有時候會想要將員工的多個成員指定為帳戶部分的操作員。您可能還需要將帳戶的擁有權轉移給其他使用者,或將多個帳號的資源合併在一起。

使用使用者身分識別做為帳號的資源容器時,先前的案例會變得更加難以達成。更令人擔憂的是,如果其他人以這種方法授予對帳戶容器的訪問權限,他們可能無意中被授予修改用戶身份本身的訪問權限,例如更改 Jane 的電子郵件或登錄憑據。

因此,在可能的情況下,更具彈性的方法是將主參與者與資源容器分開,並使用諸如「管理員權限」或「擁有權」之類的概念來建立它們之間的連接模型。

使用將資源連結至關聯主參與者的資源屬性來分隔主參與者和資源。

如果您現有的應用程式無法採用此解耦模型,我們建議您在設計授權模型時盡可能地模仿它。例如,只擁有一個名Customer為的概念,該概念封裝了使用者識別、登入認證及其擁有的資源的應用程式,可以將其對應至包含一個邏輯實體 Customer Identity (包含名稱、電子郵件等) 的授權模型,以及Customer Resources或的個別邏輯實體Customer Account,做為其擁有之所有資源的父節點。兩個實體可以共用相同的Id,但具有不同的Type

使用與主參與者相關聯的更一般化的資源容器,將主參與者和資源分隔開來。

使用屬性或範本來表示關係

有兩種主要的方式來表達資源之間的關係。何時使用一個或另一個取決於關係是否已經存儲在您的應用程序數據庫中,並用於其他原因,例如合規性。如果是,請採取基於屬性的方法。如果沒有,則採取以範本為基礎的方法。

以屬性為基礎的關係

屬性可用作授權決策的輸入,以表示主參與者與一或多個資源之間的關係。

此模式適用於追蹤和管理關係的目的,而不僅僅是權限管理。例如,您必須記錄主要帳戶持有人,才能符合「了解您的客戶」規則的財務規則。權限衍生自這些關係。關係數據在授權系統之外進行管理,並在做出授權決策時作為輸入獲取。

下列範例顯示使用者Alice與其主要帳戶持有人的多個帳戶之間的關係如何呈現:

// Using a user attribute to represent the primary account holder relationship { "id": "df82e4ad-949e-44cb-8acf-2d1acda71798", "name": "alice", "email": "alice@example.com", "primaryOnAccounts": [ "Account::\"c943927f-d803-4f40-9a53-7740272cb969\"", "Account::\"b8ee140c-fa09-46c3-992e-099438930894\"" ] }

然後,在策略中使用屬性:

// Derived relationship permissions permit ( principal, action in Action::"primaryAccountHolderActions", resource )when { resource in principal.primaryOnAccounts };

相反地,相同的關係可以表示為包含一組使用者的資源上的屬性。primaryAccountHolders

如果主參與者與資源之間有多種關係類型,則應將這些關係類型建立為不同的屬性。例如,如果帳戶也可以擁有授權簽署者,而這些個人對帳戶具有不同的權限,則會將其表示為不同的屬性。

在上述情況下,也Alice可能是第三個帳戶的授權簽署人。下面的例子顯示了如何可以表示這一點:

// Using user attributes to represent the primary account holder and authorized signatory relationships { "id": "df82e4ad-949e-44cb-8acf-2d1acda71798", "name": "alice", "email": "alice@example.com", "primaryOnAccounts": [ "Account::\"c943927f-d803-4f40-9a53-7740272cb969\"", "Account::\"b8ee140c-fa09-46c3-992e-099438930894\"" ], "authorizedSignatoryOnAccounts": [ "Account::\"661817a9-d478-4096-943d-4ef1e082d19a\"" ] }

以下是對應的策略:

// Derived relationship permissions permit ( principal, action in Action::"primaryAccountHolderActions", resource )when { resource in principal.primaryOnAccounts }; permit ( principal, action in Action::"authorizedSignatoryActions", resource )when { resource in principal.authorizedSignatoryOnAccounts };

基於範本的關係

如果資源之間的關係僅是為了權限管理而存在,那麼將此關係存儲為模板鏈接的策略或模板是適當的。您也可以將這些範本視為在特定資源上指派的角色。

例如,在文件管理系統中,文件擁有者可以選擇將權限授與其他使用者Bob,以提供文件。Alice這建立了鮑勃和愛麗絲的文檔之間的貢獻者關係。這種關係的唯一目的是授予對文檔進行編輯和註釋的權限,因此這種關係可以表示為一個模板。在這些情況下,建議的方法是為每種類型的關係創建一個模板。在下列範例中,有兩種關係類型,ContributorReviewer,因此有兩個範本。

下列範本可用來為個別使用者建立範本連結的策略。

// Managed relationship permissions - Contributor template permit ( principal == ?principal, action in Action::"DocumentContributorActions", resource in ?resource ); // Managed relationship permissions - Reviewer template permit ( principal == ?principal, action in Action::"DocumentReviewerActions", resource in ?resource );

下列範本可用於為使用者群組建立範本連結的策略。與個別使用者的範本唯一不同之處在於,使用in運算子而非==.

// Managed relationship permissions - Contributor template permit ( principal in ?principal, action in Action::"DocumentContributorActions", resource in ?resource ); // Managed relationship permissions - Reviewer template permit ( principal in ?principal, action in Action::"DocumentReviewerActions", resource in ?resource );

然後,您可以使用這些範本來建立原則 (如下列原則),代表每次授與文件存取權限時的受管理關係權限。

//Managed relationship permissions permit ( principal in User::"df82e4ad-949e-44cb-8acf-2d1acda71798", action in Action::"DocumentContributorActions", resource in Document::"c943927f-d803-4f40-9a53-7740272cb969" ); permit ( principal in UserGroup::"df82e4ad-949e-44cb-8acf-2d1acda71798", action in Action::"DocumentReviewerActions", resource == Document::"661817a9-d478-4096-943d-4ef1e082d19a" ); permit ( principal in User::"df82e4ad-949e-44cb-8acf-2d1acda71798", action in Action::"DocumentContributorActions", resource in Folder::"b8ee140c-fa09-46c3-992e-099438930894" );

Amazon 驗證許可可在授權評估期間有效地處理許多個別、精細的政策,並以這種方式建立模型,表示已驗證的許可會在所有授權決策中 AWS CloudTrail維護完整的稽核日誌。

偏好模型中的精細權限,並在使用者介面中彙總權限

設計師後來經常後悔的一種策略是設計具有非常廣泛的操作的授權模型,例如ReadWrite,後來意識到更精細的操作是必要的。客戶反饋更精細的存取控制,或者鼓勵最低權限權限的合規性和安全審核員驅動,可以驅動對更精細的細微性的需求。

如果未預先定義細微的權限,則可能需要進行複雜的轉換,才能將應用程式程式碼和原則陳述式修改為使用者更精細的權限。例如,先前針對課程粒度動作授權的應用程式程式碼將需要修改,才能使用精細的動作。此外,還需要更新原則以反映移轉:

permit ( principal == User::"6688f676-1aa9-456a-acf4-228340b54e9d", // action == Action::"read", -- coarse-grained permission -- commented out action in [ // -- finer grained permissions Action::"listFolderContents", Action::"viewFile" ], resource in Account::"c863f89b-461f-4fc2-b638-e5fa5f79a48b" );

為了避免這種昂貴的遷移,最好事先定義精細的權限。不過,如果您的終端使用者隨後被迫瞭解更多細微的權限,這可能會導致取捨,特別是如果大多數客戶會對諸如和之類的課程粒度控制感到滿意。Read Write為了達到兩個方面的最佳效果,您可以將精細的權限分組到預先定義的集合中,例如,ReadWrite使用原則範本或動作群組等機制。透過使用這種方法,客戶只會看到課程粒度的權限。但在幕後,您已經通過將課程粒度權限建模為精細操作的集合,以確保應用程序面向未來。當客戶或稽核人員要求時,可能會公開精細的權限。

考慮查詢授權的其他原因

我們通常將授權檢查與用戶請求相關聯。檢查是判斷使用者是否有執行該要求的權限的方法。但是,您也可以使用授權數據來影響應用程序界面的設計。例如,您可能想要顯示一個主畫面,其中只顯示一般使用者可以存取的資源清單。檢視資源的詳細資訊時,您可能希望介面只顯示使用者可以在該資源上執行的作業。

這些情況可能會將權衡引入授權模型中。例如,嚴重依賴以歸因為基礎的存取控制 (ABAC) 原則可能會讓快速回答「誰有權存取什麼?」這個問題變得更加困難。這是因為回答該問題需要針對每個主參與者和資源檢查每個規則,以確定是否存在相符項目。因此,需要針對僅列出使用者可存取的資源進行最佳化的產品,可能會選擇使用以角色為基礎的存取控制 (RBAC) 模型。透過使用RBAC,可以更輕鬆地重複執行附加至使用者的所有原則,以判斷資源存取權。