存取控制對於多租戶軟體即服務 (SaaS) 應用程式至關重要。 SaaS 開發人員必須管理權限、細粒度授權和隔離。
在本文中,我們將示範如何使用 Amazon 驗證權限,透過每租用戶策略儲存方法在多租用戶文件管理 SaaS 應用程式中進行存取控制。我們也描述如何強制執行租戶邊界。
我們在多租戶SaaS應用程式中通常會看到以下存取控制需求:
- 應用程式開發人員需要定義適用於所有租戶的策略。
- 租戶用戶需要控制誰可以存取其資源。
- 租用戶管理員需要管理租用戶的所有資源。
此外,獨立軟體供應商 (ISV) 實施租戶隔離,以防止一個租戶存取另一個租戶的資源。加強租戶邊界對於 SaaS 企業來說勢在必行,也是 SaaS 供應商的基本主題之一。
Verified Permissions 是一種可擴展、細粒度的權限管理和授權服務,可協助您建置和現代化應用程序,而無需在應用程式程式碼中實現授權邏輯。
Verified Permissions 使用 Cedar 語言來定義策略。 Cedar 策略是聲明明確允許或明確禁止哪些主體對資源執行操作的聲明。策略集合定義了您的應用程式的授權規則。已驗證的權限將策略儲存在策略儲存中。策略儲存是策略和範本的容器。您可以從使用開源 Cedar 編寫和執行自訂授權策略部落格文章中了解有關 Cedar 策略的更多資訊。
在驗證權限之前,您必須在應用程式的程式碼中實作授權邏輯。現在,我們將向您展示驗證權限如何幫助消除範例應用程式中這種無差別的繁重工作。
多租戶文件管理 SaaS 應用程式
該應用程式允許添加、共享、存取和管理文件。它需要以下存取控制:
- 可以定義適用於所有租用戶的策略的應用程式開發人員。
- 可以控制誰可以存取其文件的租戶使用者。
- 租用戶管理員,可以管理租用戶的所有文件。
讓我們先描述應用程式架構,然後深入研究設計細節。
應用架構概述
驗證權限中有兩種多租用戶設計方法:單一共用策略儲存和每租用戶策略儲存。您可以在驗證權限使用者指南中了解這些方法的注意事項、權衡和指導。
對於範例文件管理 SaaS 應用程序,我們決定使用每租用戶策略儲存方法,原因如下:
- 輕鬆的租戶策略隔離
- 能夠為每個租戶自訂模板和架構
- 輕鬆租戶卸載
- 每租用戶策略儲存資源配額
我們決定接受以下權衡:
- 大力實施全域策略管理(因為應用程式用例不需要頻繁更改這些策略)
- 實現授權流程的中等努力(因為我們認為在這種情況下,上述原因比實現從租戶 ID 到策略儲存 ID 的對應更重要)
下圖 1 顯示了文件管理 SaaS 應用程式架構。為簡單起見,我們省略了前端並專注於後端。
- 租戶使用者登入身分提供者,例如 Amazon Cognito。他們獲得 JSON Web 令牌 (JWT),用於 API 請求。 JWT 包含諸如 user_id 之類的聲明,它標識租戶用戶,以及 tenant_id ,它定義用戶屬於哪個租戶。
- 租用戶用戶使用 JWT 向應用程式發出 API 請求。
- Amazon API Gateway 透過身分提供者驗證 JWT 的有效性。
- 如果 JWT 有效,API Gateway 會將請求轉送給計算提供者(在本例中為 AWS Lambda 函數),以便其執行業務邏輯。
- Lambda 函數承擔 AWS Identity and Access Management (IAM) 角色,其 IAM 策略允許存取提供租戶到政策儲存對應的 Amazon DynamoDB 表。 IAM 策略限制存取範圍,以便 Lambda 函數只能存取目前 tenant_id 的資料。
- Lambda 函數尋找目前要求的已驗證權限 policy_store_id 。為此,它從 JWT 中提取 tenant_id 。然後,該函數從租用戶到策略儲存映射表中檢索 policy_store_id 。
- Lambda 函數承擔另一個 IAM 角色,其 IAM 策略允許存取已驗證的權限策略儲存、文件元資料表和文件儲存。 IAM 策略使用 tenant_id 和 policy_store_id 來縮小存取範圍。
- Lambda 函數取得或儲存 DynamoDB 表中的文件元資料。此函數使用驗證權限授權請求的元資料。
- 使用步驟 5 和 6 中的信息,Lambda 函數呼叫驗證權限來做出授權決策或建立 Cedar 政策。
- 如果獲得授權,應用程式就可以存取或儲存文件。
應用架構深入探討
現在您已經了解了用例的架構,讓我們更詳細地回顧它們,並從使用者體驗向後追溯到應用程式架構的相關部分。該架構側重於權限管理。存取和儲存實際文件超出了範圍。
定義適用於所有租戶的策略
應用程式開發人員必須定義全域策略,其中包括所有租用戶的一組基本存取權限。我們使用 Cedar 策略來實施這些權限。
由於我們使用的是每租用戶策略儲存方法,因此租用戶入職流程應為每個新租用戶建立這些策略。目前,要更新策略,部署管道應將變更套用至所有策略儲存。
接下來的「新增文件」和「管理租用戶的所有文件」部分包括全域策略的範例。
確保租戶無法編輯其他租戶的策略
該應用程式使用 IAM 將一個租戶的資源與另一個租戶隔離。由於我們使用的是每租用戶策略儲存方法,因此我們可以使用 IAM 將一個租用戶原則儲存與另一個租用戶政策儲存隔離。
架構圖
- 租用戶用戶使用有效的 JWT 呼叫 API 端點。
- Lambda 函數使用 AWS Security Token Service (AWS STS) 代入具有 IAM 策略的 IAM 角色,該策略允許存取租用戶到策略儲存來對應 DynamoDB 表。 IAM 策略僅允許存取屬於請求租用戶的資料表和條目。當函數承擔該角色時,它使用 tenant_id 來限制對其分區鍵與 tenant_id 匹配的項目的存取範圍。有關此類策略的範例,請參閱如何使用 ABAC 和 AWS IAM 實施 SaaS 租用戶隔離部落格文章。
- Lambda 函數使用使用者的 tenant_id 來取得已驗證的權限 policy_store_id 。
- Lambda 函數使用與步驟 2 相同的機制來使用 tenant_id 和 policy_store_id 承擔不同的 IAM 角色,該角色僅允許存取租用戶策略儲存。
- Lambda 函數存取租用戶策略儲存。
新增文件
當用戶首次訪問該應用程式時,他們不擁有任何文件。若要新增文檔,前端呼叫 POST /documents 端點並在請求正文中提供 document_name 。
Cedar policy 雪松政策
我們需要一個允許每個租戶使用者新增文件的全域策略。租用戶入職流程會在租用戶的策略儲存中建立此原則。
此策略允許任何主體新增文件。由於我們使用的是每租用戶策略儲存方法,因此無需將主體範圍限定為租用戶。
架構圖
- 租用戶用戶呼叫 POST /documents 端點來新增文件。
- Lambda 函數使用使用者的 tenant_id 來取得已驗證的權限 policy_store_id 。
- Lambda 函數呼叫驗證權限策略儲存以檢查租用戶使用者是否有權新增文件。
- 授權成功後,Lambda 函數將新文件新增至文件元資料資料庫中,並將該文件上傳到文件儲存中。
資料庫結構描述如下表:
tenant_id (Partition key): String
tenant_id(分區鍵):字串 |
document_id (Sort key): String
document_id(排序鍵):字串 |
document_name: String 文件名稱:字串 | document_owner: String 文檔所有者:字串 |
<TENANT_ID> <租戶ID> | <DOCUMENT_ID> <文檔ID> | <DOCUMENT_NAME> <文檔名稱> | <USER_ID> <用戶ID> |
- tenant_id :JWT 聲明中的 tenant_id 。
- document_id :由應用程式建立的文件的隨機識別碼。
- document_name :隨 API 請求提供的文件的名稱。
- document_owner :建立文件的使用者。該值是 JWT 聲明中的 user_id 。
與租戶的其他使用者共用文檔
租戶使用者建立一個或多個文件後,他們可能希望與同一租戶的其他使用者共用這些文件。要共用文檔,前端會呼叫 POST /shares 端點並提供使用者想要共用的文檔的 document_id 和接收使用者的 user_id 。
雪松政策
我們需要一個全域文檔所有者策略,允許文檔所有者管理文檔,包括共用。租用戶入職流程會在租用戶的策略儲存中建立此原則。
當主體是文件擁有者時,此策略允許主體對可用資源(文件)執行操作。此策略允許我們接下來描述的 shareDocument 操作共用文件。
我們還需要一個允許接收使用者存取文件的共用策略。應用程式為每個成功的共享操作建立這些策略。我們建議您使用策略範本來定義共用策略。策略範本允許定義一次策略,然後將其附加到多個主體和資源。使用策略範本的策略稱為範本連結策略。策略範本的更新反映在使用該範本的主體和資源中。租用戶加入流程會在租用戶的策略儲存中建立共享策略範本。
以下是使用共享策略範本的範本連結策略的範例:
此策略包括接收使用者(主體)的 user_id 和文件(資源)的 document_id 。
- 租用戶用戶呼叫 POST /shares 端點來共用文件。
- Lambda 函數使用使用者的 tenant_id 從儲存租用戶到策略儲存對映的 DynamoDB 表中取得每個操作的已驗證權限 policy_store_id 和策略範本 ID。在這種情況下,函數需要使用 share_policy_template_id 。
- 此函數會查詢文件元資料 DynamoDB 資料表以擷取使用者想要共用的文件的 document_owner 屬性。
- Lambda 函數呼叫 Verified Permissions 來檢查使用者是否有權共用文件。請求上下文使用 JWT 聲明中的 user_id 作為主體,使用 shareDocument 作為操作,使用 document_id 作為資源。文件實體包含 document_owner 屬性,該屬性來自文檔元資料 DynamoDB 表。
- 如果使用者被授權共享資源,則函數會在租用戶的策略儲存中建立一個新的模板連結共享策略。此策略包括作為主體的接收使用者的 user_id 和作為資源的 document_id 。
存取共享文檔
共用文件後,接收使用者想要存取該文件。要存取文檔,前端會呼叫 GET /documents 端點並提供使用者想要存取的文檔的 document_id 。
雪松政策
如上一節所示,在共用過程中,應用程式會建立一個連結範本的共用策略,允許接收使用者存取文件。當使用者嘗試存取文件時,已驗證的權限會評估此策略。
架構圖
- 租用戶用戶呼叫 GET /documents 端點來存取文件。
- Lambda 函數使用使用者的 tenant_id 來取得已驗證的權限 policy_store_id 。
- Lambda 函數呼叫 Verified Permissions 來檢查使用者是否有權存取該文件。請求上下文使用 JWT 聲明中的 user_id 作為主體,使用 accessDocument 作為操作,使用 document_id 作為資源。
管理租戶的所有文件
當客戶註冊 SaaS 應用程式時,該應用程式會建立租用戶管理員使用者。租用戶管理員必須有權對租用戶的所有文件執行所有操作。
雪松政策
我們需要一項允許租用戶管理員管理所有文件的全域策略。租用戶入職流程會在租用戶的策略儲存中建立此原則。
此策略允許 <admin_group_id> 群組的每個成員對任何文件執行任何操作。
架構圖
- 租用戶管理員呼叫 POST /documents 端點來管理文件。
- Lambda 函數使用使用者的 tenant_id 來取得已驗證的權限 policy_store_id 。
- Lambda 函數呼叫 Verified Permissions 來檢查使用者是否有權管理文件。