

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

# 範例 2：具有 OPA 和 Rego 的多租戶存取控制和使用者定義的 RBAC
<a name="opa-rbac-examples"></a>

此範例使用 OPA 和 Rego 來示範如何使用租用戶使用者定義的自訂角色，在多租用戶應用程式的 API 上實作存取控制。它也會示範如何根據租用戶限制存取。此模型顯示 OPA 如何根據高階角色提供的資訊做出精細的許可決策。

![具有 OPA 和 Rego 的使用者定義 RBAC](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/opa-example-2.png)


租用戶的角色存放在外部資料 (RBAC 資料） 中，用於對 OPA 進行存取決策：

```
{
    "roles": {
        "tenant_a": {
            "all_access_role": ["viewData", "updateData"]
        },
        "tenant_b": {
            "update_data_role": ["updateData"],
            "view_data_role": ["viewData"]
        }
    }
}
```

這些角色由租戶使用者定義時，應存放在外部資料來源或身分提供者 (IdP) 中，當將租戶定義的角色映射至許可和租戶本身時，可做為事實來源。 

此範例使用 OPA 中的兩個政策來做出授權決策，並檢查這些政策如何強制執行租用戶隔離。這些政策使用先前定義的 RBAC 資料。

```
default allowViewData = false
allowViewData = true {
    input.method == "GET"
    input.path = ["viewData", tenant_id]
    input.tenant_id == tenant_id
    role_permissions := data.roles[input.tenant_id][input.role][_]
    contains(role_permissions, "viewData")
}
```

若要顯示此規則的運作方式，請考慮具有下列輸入的 OPA 查詢：

```
{
    "tenant_id": "tenant_a",
    "role": "all_access_role",
    "path": ["viewData", "tenant_a"],
    "method": "GET"
}
```

此 API 呼叫的授權決策會結合 *RBAC 資料*、*OPA 政策和* *OPA 查詢輸入*，如下所示：

1. 的使用者對 `Tenant A`進行 API 呼叫`/viewData/tenant_a`。

1. 資料微服務會接收呼叫並查詢`allowViewData`規則，傳遞 OPA 查詢輸入範例中顯示的輸入。

1. OPA 使用 OPA 政策中的查詢規則來評估提供的輸入。OPA 也會使用來自 RBAC 資料的資料來評估輸入。OPA 會執行下列動作：

   1. 驗證用於進行 API 呼叫的 方法為 `GET`。

   1. 驗證請求的路徑是否為 `viewData`。

   1. 檢查路徑`tenant_id`中的 是否等於與使用者`input.tenant_id`相關聯的 。這可確保保持租戶隔離。即使具有相同角色，另一個租戶也無法獲得進行此 API 呼叫的授權。

   1. 從角色的外部資料提取角色許可清單，並將其指派給變數 `role_permissions`。使用與 中的使用者相關聯的租戶定義角色來擷取此清單 `input.role.`

   1. 檢查`role_permissions`是否包含 許可 `viewData.`

1. OPA 會將下列決策傳回資料微服務：

```
{
    "allowViewData": true
}
```

此程序顯示 RBAC 和租戶意識如何有助於使用 OPA 做出授權決策。若要進一步說明這一點，請考慮`/viewData/tenant_b`使用下列查詢輸入對 進行 API 呼叫：

```
{
    "tenant_id": "tenant_b",
    "role": "view_data_role",
    "path": ["viewData", "tenant_b"],
    "method": "GET"
}
```

此規則會傳回與 OPA 查詢輸入相同的輸出，但適用於具有不同角色的不同租用戶。這是因為此呼叫適用於 ，`/tenant_b`且 RBAC 資料`view_data_role`中的 仍有與其相關聯的`viewData`許可。若要對 強制執行相同類型的存取控制`/updateData`，您可以使用類似的 OPA 規則：

```
default allowUpdateData = false
allowUpdateData = true {
    input.method == "POST"
    input.path = ["updateData", tenant_id]
    input.tenant_id == tenant_id
    role_permissions := data.roles[input.tenant_id][input.role][_]
    contains(role_permissions, "updateData")
}
```

此規則的功能與`allowViewData`規則相同，但會驗證不同的路徑和輸入方法。此規則仍會確保租戶隔離，並檢查租戶定義的角色是否授予 API 發起人許可。若要查看如何強制執行這項操作，請針對對 的 API 呼叫檢查下列查詢輸入`/updateData/tenant_b`：

```
{
    "tenant_id": "tenant_b",
    "role": "view_data_role",
    "path": ["updateData", "tenant_b"],
    "method": "POST"
}
```

當使用 `allowUpdateData`規則評估時，此查詢輸入會傳回下列授權決策：

```
{
    "allowUpdateData": false
}
```

此呼叫將不會獲得授權。雖然 API 呼叫者與正確的 相關聯，`tenant_id`並且使用核准的方法呼叫 API，但 `input.role`是租戶定義的 `view_data_role`。`view_data_role` 沒有 `updateData`許可；因此，對 的呼叫`/updateData`未經授權。對於擁有 `tenant_b`的使用者，此呼叫將會成功`update_data_role`。