

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

# 使用 Amazon Verified Permissions 實作 PDP
<a name="avp"></a>

Amazon Verified Permissions 是一種可擴展、精細的許可管理和授權服務，可用來實作政策決策點 (PDP)。作為政策引擎，它可以協助您的應用程式即時驗證使用者動作，並反白顯示過度特權或無效的許可。它透過外部化授權並集中管理政策，協助您的開發人員更快速地建置更安全的應用程式。透過將授權邏輯與應用程式邏輯分開，Verified Permissions 支援政策解耦。

透過使用 Verified Permissions 實作 PDP，並在應用程式中實作最低權限和持續驗證，開發人員可以使其應用程式存取符合[零信任](https://aws.amazon.com/security/zero-trust/)原則。此外，安全與稽核團隊可以更妥善地分析和稽核可存取應用程式中哪些資源的人員。Verified Permissions 使用 [Cedar](https://www.cedarpolicy.com/en)，這是一種專用且安全優先的開放原始碼政策語言，根據角色型存取控制 (RBAC) 和屬性型存取控制 (ABAC) 定義政策型存取控制，以實現更精細、內容感知的存取控制。

Verified Permissions 為 SaaS 應用程式提供一些有用的功能，例如能夠使用 Amazon Cognito、Google 和 Facebook 等多個身分提供者來啟用多租戶授權。另一個對 SaaS 應用程式特別有幫助的已驗證許可功能是支援每個租用戶的自訂角色。如果您正在設計客戶關係管理 (CRM) 系統，一個租戶可能會根據一組特定條件，依銷售機會定義存取的精細程度。另一個租用戶可能有另一個定義。Verified Permissions 中的基礎許可系統可以支援這些變化，這使得它成為 SaaS 使用案例的理想候選者。Verified Permissions 也支援撰寫適用於所有租用戶的政策，因此直接套用護欄政策以防止以 SaaS 供應商身分進行未經授權的存取。

![\[使用 Amazon Verified Permissions 實作 PDP\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp.png)


**為什麼要使用 Verified Permissions？**

搭配 [Amazon Cognito](https://aws.amazon.com/cognito/) 等身分提供者使用 Verified Permissions，為您的應用程式提供更動態、以政策為基礎的存取管理解決方案。您可以建置應用程式，協助使用者共用資訊和協作，同時維護其資料的安全性、機密性和隱私權。Verified Permissions 為您提供精細的授權系統，以根據身分和資源的角色和屬性強制執行存取權，協助降低營運成本。您可以定義政策模型、在中央位置建立和存放政策，並以毫秒為單位評估存取請求。

在 Verified Permissions 中，您可以使用稱為 Cedar 的簡單、人類可讀宣告性語言來表達許可。無論每個團隊的應用程式使用何種程式設計語言，都可以在團隊之間共用以 Cedar 撰寫的政策。

**使用 Verified Permissions 時應考量的事項**

在 Verified Permissions 中，您可以建立政策並將其自動化，做為佈建的一部分。您也可以在執行時間建立政策，做為應用程式邏輯的一部分。最佳實務是，當您建立政策作為租戶加入和佈建的一部分時，您應該使用持續整合和持續部署 (CI/CD) 管道來管理、修改和追蹤政策版本。或者，應用程式可以管理、修改和追蹤政策版本；不過，應用程式邏輯本質上不會執行此功能。若要在您的應用程式中支援這些功能，您必須明確設計您的應用程式以實作此功能。

如果需要從其他來源提供外部資料以達到授權決策，則必須擷取此資料並將其提供給 Verified Permissions，作為授權請求的一部分。此服務預設不會擷取其他內容、實體和屬性。

# Cedar 概觀
<a name="cedar"></a>

Cedar 是一種靈活、可擴展且可擴展的政策型存取控制語言，可協助開發人員將應用程式許可表達為政策。管理員和開發人員可以定義允許或禁止使用者對應用程式資源採取行動的政策。多個政策可以連接到單一資源。當您的應用程式使用者嘗試對資源執行動作時，您的應用程式會向 Cedar 政策引擎請求授權。Cedar 會評估適用的政策，並傳回 `ALLOW`或 `DENY`決策。Cedar 支援任何類型的主體和資源的授權規則，允許角色型存取控制 (RBAC) 和屬性型存取控制 (ABAC)，並支援透過自動化推理工具進行分析。

Cedar 可讓您將商業邏輯與授權邏輯分開。當您從應用程式的程式碼提出請求時，您可以呼叫 Cedar 的授權引擎來判斷請求是否獲得授權。如果授權 （決策為 `ALLOW`)，您的應用程式可以執行請求的操作。如果未授權 （決策為 `DENY`)，您的應用程式可能會傳回錯誤訊息。Cedar 的主要功能包括：
+ **表達性** – Cedar 專為支援授權使用案例而打造，並且以人類可讀性為考量進行開發。
+ **效能** – Cedar 支援索引政策以快速擷取，並提供快速且可擴展的即時評估與限制延遲。
+ **分析** – Cedar 支援分析工具，可最佳化您的政策並驗證您的安全模型。

如需詳細資訊，請參閱 [Cedar 網站](https://www.cedarpolicy.com/)。

# 範例 1：具有已驗證許可和 Cedar 的基本 ABAC
<a name="avp-basic-abac-examples"></a>

在此範例案例中，Amazon Verified Permissions 用於判斷哪些使用者可存取虛構薪資微服務中的資訊。本節包含 Cedar 程式碼片段，示範如何使用 Cedar 來呈現存取控制決策。這些範例並非旨在完整探索 Cedar 和 Verified Permissions 所提供的功能。如需 Cedar 的更完整概觀，請參閱 [Cedar 文件](https://docs.cedarpolicy.com/)。

在下圖中，我們希望強制執行與 `viewSalary``GET`方法相關聯的兩個一般業務規則：*員工可以檢視自己的薪資*，而*員工可以檢視向其報告的任何人員的薪資。*您可以使用 Verified Permissions 政策來強制執行這些業務規則。

![\[使用 Amazon Verified Permissions 和 Cedar 實作 PDP 的基本 ABAC 實作範例\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-1.png)


*員工可以檢視自己的薪資。*

在 Cedar 中，基本建構是*實體*，代表委託人、動作或資源。若要提出授權請求並使用 Verified Permissions 政策開始評估，您需要提供*委託人、**動作**、資源*和*實體清單。*
+ 主體 (`principal`) 是登入的使用者或角色。
+ 動作 (`action`) 是由請求評估的操作。
+ 資源 (`resource`) 是動作正在存取的元件。
+ 實體清單 (`entityList`) 包含評估請求所需的所有必要實體。

為了滿足業務規則 *員工可以檢視自己的薪資*，您可以提供驗證許可政策，如下所示。

```
permit (
    principal,
    action == Action::"viewSalary",
    resource
)
when {
    principal == resource.owner
};
```

此政策會評估 `Action` `ALLOW`是否為 ，`viewSalary`且請求中的資源是否具有等於主體的屬性擁有者。例如，如果 Bob 是請求薪資報告的登入使用者，也是薪資報告的擁有者，則政策會評估為 `ALLOW`。

下列授權請求會提交至驗證許可，以供範例政策評估。在此範例中，Bob 是發出`viewSalary`請求的登入使用者。因此，Bob 是實體類型 的委託人`Employee`。Bob 嘗試執行的動作是 ，而 `viewSalary` 顯示`viewSalary,`的資源`Salary-Bob`是 類型`Salary`。為了評估 Bob 是否可以檢視`Salary-Bob`資源，您需要提供將 類型`Employee`與 值 `Bob`（委託人） 連結至類型為 之資源擁有者屬性`Salary`的實體結構。您可以在 中提供此結構`entityList`，其中與 相關聯的屬性`Salary`包含擁有者，指定包含類型`Employee`和值 `entityIdentifier`的 `Bob`。Verified Permissions 會將授權請求中`principal`提供的 與與`Salary`資源相關聯的 `owner` 屬性進行比較，以做出決策。

```
{
  "policyStoreId": "PAYROLLAPP_POLICYSTOREID",
  "principal": {
    "entityType": "PayrollApp::Employee",
    "entityId": "Bob"
  },
  "action": {
    "actionType": "PayrollApp::Action",
    "actionId": "viewSalary"
  },
  "resource": {
    "entityType": "PayrollApp::Salary",
    "entityId": "Salary-Bob"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
          "entityType": "PayrollApp::Salary",
          "entityId": "Salary-Bob"
        },
        "attributes": {
          "owner": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Bob"
            }
          }
        }
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Bob"
        },
        "attributes": {}
      }
    ]
  }
}
```

Verified Permissions 的授權請求會傳回下列項目做為輸出，其中 屬性`decision`為 `ALLOW`或 `DENY`。

```
{
    "determiningPolicies": 
        [ 
            {
                "determiningPolicyId": "PAYROLLAPP_POLICYSTOREID" 
            }
        ],
    "decision": "ALLOW",
    "errors": [] 
}
```

在此情況下，由於 Bob 嘗試檢視自己的薪資，傳送至 Verified Permissions 的授權請求會評估為 `ALLOW`。不過，我們的目標是使用 Verified Permissions 來強制執行兩個業務規則。陳述下列項目的商業規則也應該是 true：

*員工可以檢視向他們報告的任何人員的薪資。*

若要滿足此業務規則，您可以提供另一個政策。下列政策會評估 動作`ALLOW`是否為 ，`viewSalary`且請求中的資源是否具有`owner.manager`等於委託人的屬性。例如，如果 Alice 是請求薪資報告的登入使用者，而 Alice 是報告擁有者的經理，則政策會評估為 `ALLOW`。

```
permit (
    principal,
    action == Action::"viewSalary",
    resource
)
when {
    principal == resource.owner.manager
};
```

下列授權請求會提交至驗證許可，以供範例政策評估。在此範例中，Alice 是發出`viewSalary`請求的登入使用者。因此，Alice 是委託人，而實體的類型為 `Employee`。Alice 嘗試執行的動作是 `viewSalary`，而`viewSalary`顯示的資源類型為 `Salary`，值為 `Salary-Bob`。為了評估 Alice 是否可以檢視`Salary-Bob`資源，您需要提供將 類型`Employee`與 `manager` 值連結至 屬性`Alice`的實體結構，該結構接著必須與 類型 `owner` 值`Salary`為 的 屬性相關聯`Salary-Bob`。您可以在 中提供此結構`entityList`，其中與 相關聯的屬性`Salary`包含擁有者，指定包含類型`Employee`和值 `entityIdentifier`的 `Bob`。Verified Permissions 會先檢查 `owner` 屬性，該屬性會評估為 類型`Employee`和值 `Bob`。然後，Verified Permissions 會評估與 相關聯的`manager`屬性，`Employee`並將其與提供的委託人進行比較，以做出授權決策。在這種情況下，決策`ALLOW`是因為 `principal `和 `resource.owner.manager` 屬性相等。

```
{
  "policyStoreId": "PAYROLLAPP_POLICYSTOREID",
  "principal": {
    "entityType": "PayrollApp::Employee",
    "entityId": "Alice"
  },
  "action": {
    "actionType": "PayrollApp::Action",
    "actionId": "viewSalary"
  },
  "resource": {
    "entityType": "PayrollApp::Salary",
    "entityId": "Salary-Bob"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Alice"
        },
        "attributes": {
          "manager": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "None"
            }
          }
        },
        "parents": []
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Salary",
          "entityId": "Salary-Bob"
        },
        "attributes": {
          "owner": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Bob"
            }
          }
        },
        "parents": []
      },
      {
        "identifier": {
          "entityType": "PayrollApp::Employee",
          "entityId": "Bob"
        },
        "attributes": {
          "manager": {
            "entityIdentifier": {
              "entityType": "PayrollApp::Employee",
              "entityId": "Alice"
            }
          }
        },
       "parents": []
      }
    ]
  }
}
```

到目前為止，在此範例中，我們提供了與 `viewSalary`方法相關聯的兩個業務規則，*員工可以檢視自己的薪資*，而*員工可以檢視向其報告之任何人的薪資*，並將 Verified Permissions 視為政策，以獨立滿足每個業務規則的條件。您也可以使用單一已驗證許可政策來滿足這兩個業務規則的條件：

*員工可以檢視自己的薪資以及向其報告的任何人的薪資。*

當您使用先前的授權請求時，下列政策會評估 動作`ALLOW`是否為 ，`viewSalary`而請求中的資源是否具有等於 `owner.manager`的 屬性`principal`，或 屬性`owner`是否等於 `principal`。

```
permit (
    principal,
    action == PayrollApp::Action::"viewSalary",
    resource
)
when {
    principal == resource.owner.manager ||
    principal == resource.owner
};
```

例如，如果 Alice 是請求薪資報告的登入使用者，而且 Alice 是擁有者的經理或報告的擁有者，則政策會評估為 `ALLOW`。

如需搭配 Cedar 政策使用邏輯運算子的詳細資訊，請參閱 [Cedar 文件](https://docs.cedarpolicy.com/policies/syntax-operators.html)。

# 範例 2：具有已驗證許可和 Cedar 的基本 RBAC
<a name="avp-basic-rbac-examples"></a>

此範例使用 Verified Permissions 和 Cedar 來示範基本 RBAC。如前所述，Cedar 的基本建構是實體。開發人員會定義自己的實體，也可以選擇性地在實體之間建立關係。下列範例包含三種類型的實體：`Users`、 `Roles`和 `Problems`。 `Students` 和 `Teachers`可視為 類型的實體，`Role,`且每個`User`實體都可以與零或任何 相關聯`Roles`。

![\[使用 Amazon Verified Permissions 和 Cedar 實作 PDP 的基本 RBAC 實作範例\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-2.png)


在 Cedar 中，這些關係是透過將 `Role` `Student` 連結至 `User``Bob`做為其父系來表示。此關聯會以邏輯方式將所有學生使用者分組在一個群組中。如需在 Cedar 中分組的詳細資訊，請參閱 [Cedar 文件](https://docs.cedarpolicy.com/overview/terminology.html#term-group)。

下列政策會針對連結至類型 `Students`之邏輯群組`submitProblem,`的所有委託人，評估 `ALLOW`動作的決策`Role`。

```
permit (
    principal in ElearningApp::Role::"Students",
    action == ElearningApp::Action::"submitProblem",
    resource
);
```

下列政策會針對連結至類型 `Teachers`之邏輯群組的所有委託人`answerProblem`，評估 `ALLOW` 動作`submitProblem`或 的決策`Role`。

```
permit (
    principal in ElearningApp::Role::"Teachers",
    action in [
        ElearningApp::Action::"submitProblem",
        ElearningApp::Action::"answerProblem"
    ],
    resource
);
```

為了使用這些政策評估請求，評估引擎需要知道授權請求中參考的委託人是否為適當群組的成員。因此，應用程式必須將相關的群組成員資格資訊傳遞給評估引擎，做為授權請求的一部分。這是透過 `entities` 屬性完成的，可讓您為 Cedar 評估引擎提供授權呼叫所涉及主體和資源的屬性和群組成員資格資料。在下列程式碼中，群組成員資格是透過`User::"Bob"`將 定義為具有名為 的父系來表示`Role::"Students"`。

```
{
  "policyStoreId": "ELEARNING_POLICYSTOREID",
  "principal": {
    "entityType": "ElearningApp::User",
    "entityId": "Bob"
  },
  "action": {
    "actionType": "ElearningApp::Action",
    "actionId": "answerProblem"
  },
  "resource": {
    "entityType": "ElearningApp::Problem",
    "entityId": "SomeProblem"
  },
  "entities": {
    "entityList": [
        {
            "identifier": {
                "entityType": "ElearningApp::User",
                "entityId": "Bob"
            },
            "attributes": {},
            "parents": [
                {
                    "entityType": "ElearningApp::Role",
                    "entityId": "Students"
                } 
            ]
        },
        {
          "identifier": {
            "entityType": "ElearningApp::Problem",
            "entityId": "SomeProblem"
          },
          "attributes": {},
          "parents": []
        }
      ]
  }
}
```

在此範例中，Bob 是發出`answerProblem`請求的登入使用者。因此，Bob 是委託人，而實體的類型為 `User`。Bob 嘗試執行的動作是 `answerProblem`。為了評估 Bob 是否可以執行`answerProblem`動作，您需要提供將實體`User`與 值連結的實體結構，`Bob`並透過將父實體列為 來指派其群組成員資格`Role::"Students"`。由於使用者群組中的實體只`Role::"Students"`允許執行動作 `submitProblem`，因此此授權請求會評估為 `DENY`。

另一方面，如果 和 `User` 的類型`Alice`是群組`Role::"Teachers"` 嘗試執行`answerProblem`動作的一部分，授權請求會評估為 `ALLOW`，因為政策規定群組中的主體`Role::"Teachers"`可以`answerProblem`對所有資源執行動作。下列程式碼顯示評估為 的這類 授權請求`ALLOW`。

```
{
  "policyStoreId": "ELEARNING_POLICYSTOREID",
  "principal": {
    "entityType": "ElearningApp::User",
    "entityId": "Alice"
  },
  "action": {
    "actionType": "ElearningApp::Action",
    "actionId": "answerProblem"
  },
  "resource": {
    "entityType": "ElearningApp::Problem",
    "entityId": "SomeProblem"
  },
  "entities": {
    "entityList": [
        {
            "identifier": {
                "entityType": "ElearningApp::User",
                "entityId": "Alice"
            },
            "attributes": {},
            "parents": [
                {
                    "entityType": "ElearningApp::Role",
                    "entityId": "Teachers"
                } 
            ]
        },
        {
            "identifier": {
                "entityType": "ElearningApp::Problem",
                "entityId": "SomeProblem"
            },
            "attributes": {},
            "parents": []
        }
      ]
  }
}
```

# 範例 3：使用 RBAC 進行多租戶存取控制
<a name="avp-mt-abac-examples"></a>

若要詳細說明先前的 RBAC 範例，您可以擴展需求以包含 SaaS 多租戶，這是 SaaS 供應商的常見需求。在多租用戶解決方案中，一律代表指定的租用戶提供資源存取。也就是說，租戶 A 的使用者無法檢視租戶 B 的資料，即使該資料在邏輯上或實際共置在系統中。下列範例說明如何使用多個 [Verified Permissions 政策存放區](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/policy-stores.html)實作租用戶隔離，以及如何使用使用者角色在租用戶內定義許可。

使用每個租用戶政策存放區設計模式是維護租用戶隔離，同時使用 Verified Permissions 實作存取控制的最佳實務。在此案例中，租戶 A 和租戶 B 使用者請求`DATAMICROSERVICE_POLICYSTORE_B`會分別針對個別的政策存放區 `DATAMICROSERVICE_POLICYSTORE_A`和 進行驗證。如需多租用戶 SaaS 應用程式之 Verified Permissions 設計考量事項的詳細資訊，請參閱 [Verified Permissions 多租用戶設計考量](avp-design-considerations.md)事項一節。

![\[具有 RBAC、Amazon Verified Permissions 和 Cedar 的多租戶存取控制範例\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-3.png)


下列政策位於`DATAMICROSERVICE_POLICYSTORE_A`政策存放區中。它會驗證委託人將是類型 `allAccessRole`群組的一部分`Role`。在這種情況下，將允許主體對與租用戶 A 相關聯的所有資源執行 `viewData`和 `updateData`動作。

```
permit (
    principal in MultitenantApp::Role::"allAccessRole",
    action in [
        MultitenantApp::Action::"viewData",
        MultitenantApp::Action::"updateData"
    ],
    resource
);
```

下列政策位於`DATAMICROSERVICE_POLICYSTORE_B`政策存放區中。第一個政策會驗證委託人是類型 `updateDataRole`群組的一部分`Role`。假設是這種情況，它會授予主體許可，以對與租用戶 B 相關聯的資源執行 `updateData`動作。

```
permit (
    principal in MultitenantApp::Role::"updateDataRole",
    action == MultitenantApp::Action::"updateData",
    resource
);
```

第二個政策強制允許屬於 類型`viewDataRole`群組的主體對與租用戶 B 相關聯的資源`Role`執行 `viewData`動作。

```
permit (
    principal in MultitenantApp::Role::"viewDataRole",
    action == MultitenantApp::Action::"viewData",
    resource
);
```

從租用戶 A 發出的授權請求需要傳送到`DATAMICROSERVICE_POLICYSTORE_A`政策存放區，並由屬於該存放區的政策進行驗證。在這種情況下，它是由此範例之前討論的第一個政策進行驗證。在此授權請求中，值`User`為 的 類型主體`Alice`正在請求 執行`viewData`動作。委託人屬於類型 `allAccessRole`的群組`Role`。Alice 正在嘗試對`SampleData`資源執行 `viewData`動作。由於 Alice 具有 `allAccessRole`角色，因此此評估會產生 `ALLOW`決策。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_A",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "viewData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

如果您改為檢視 向租戶 B 提出的請求`User Bob`，您會看到類似以下授權請求的內容。請求會傳送到`DATAMICROSERVICE_POLICYSTORE_B`政策存放區，因為它源自租用戶 B。在此請求中，委託人`Bob`想要`updateData`對資源 執行 動作`SampleData`。不過， `Bob` 不是可存取`updateData`該資源上 動作的群組的一部分。因此，請求會產生`DENY`決策。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_B",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Bob"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "updateData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Bob"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "viewDataRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

在此第三個範例中， `User Alice `會嘗試對資源 執行 `viewData`動作`SampleData`。此請求會導向至`DATAMICROSERVICE_POLICYSTORE_A`政策存放區，因為主體`Alice`屬於租用戶 A。 `Alice`是 類型 `allAccessRole` 群組的一部分`Role`，允許她對 資源執行`viewData`動作。因此，請求會產生 `ALLOW`決策。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE_A",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "viewData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
      },
      {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": []
      }
    ]
  }
}
```

# 範例 4：使用 RBAC 和 ABAC 進行多租戶存取控制
<a name="avp-mt-abac-rbac-examples"></a>

若要增強上一節中的 RBAC 範例，您可以將屬性新增至使用者，為多租戶存取控制建立 RBAC-ABAC 混合方法。此範例包含上一個範例中的相同角色，但會新增使用者屬性`account_lockout_flag`和內容參數 `uses_mfa`。此範例也會採用不同的方法來使用 RBAC 和 ABAC 實作多租用戶存取控制，並為每個租用戶使用一個共用政策存放區，而不是不同的政策存放區。

![\[具有 RBAC、ABAC、Amazon Verified Permissions 和 Cedar 的多租戶存取控制範例\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-4.png)


此範例代表多租用戶 SaaS 解決方案，您需要提供租用戶 A 和租用戶 B 的授權決策，類似於先前的範例。

若要實作使用者鎖定功能，範例會將 屬性新增至授權請求中的`account_lockout_flag``User`實體主體。此旗標會鎖定使用者對系統的存取，並將鎖定使用者`DENY`的所有權限。`account_lockout_flag` 屬性與`User`實體相關聯，並對 有效，`User`直到跨多個工作階段主動撤銷旗標。此範例使用 `when`條件來評估 `account_lockout_flag`。

此範例也會新增請求和工作階段的詳細資訊。內容資訊指定已使用多重要素驗證來驗證工作階段。為了實作此驗證，範例會使用 `when`條件來評估 `uses_mfa`旗標做為內容欄位的一部分。如需新增內容的最佳實務的詳細資訊，請參閱 [Cedar 文件](https://docs.cedarpolicy.com/auth/entities-syntax.html)。

```
permit (
    principal in MultitenantApp::Role::"allAccessRole",
    action in [
        MultitenantApp::Action::"viewData",
        MultitenantApp::Action::"updateData"
    ],
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

此政策可防止存取 資源，除非資源與請求主體的 `Tenant` 屬性位於相同的群組中。這種維護租用戶隔離的方法稱為*單一共享多租用戶政策存放區*方法。如需多租用戶 SaaS 應用程式之 Verified Permissions 設計考量事項的詳細資訊，請參閱 [Verified Permissions 多租用戶設計考量](avp-design-considerations.md)事項一節。

此政策也會確保委託人是 的成員`allAccessRole`，並將動作限制為 `viewData`和 `updateData`。此外，此政策會驗證 `account_lockout_flag`是 ，`false`且 的內容值會`uses_mfa`評估為 `true`。

同樣地，以下政策可確保委託人和資源都與相同的租用戶相關聯，以防止跨租用戶存取。此政策也會確保委託人是 的成員，`viewDataRole`並將動作限制為 `viewData`。此外，它會驗證 `account_lockout_flag`是 ，`false`且 的內容值會`uses_mfa`評估為 `true`。

```
permit (
    principal in MultitenantApp::Role::"viewDataRole",
    action == MultitenantApp::Action::"viewData",
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

第三個政策類似於前一個政策。此政策要求資源成為 群組的成員，而該群組對應於由 表示的實體`principal.Tenant`。這可確保主體和資源都與租用戶 B 相關聯，以防止跨租用戶存取。此政策可確保委託人是 的成員，`updateDataRole`並將動作限制為 `updateData`。此外，此政策會驗證 `account_lockout_flag`是 ，`false`且 的內容值會`uses_mfa`評估為 `true`。

```
permit (
    principal in MultitenantApp::Role::"updateDataRole",
    action == MultitenantApp::Action::"updateData",
    resource
)
when {
    principal.account_lockout_flag == false &&
    context.uses_mfa == true &&
    resource in principal.Tenant
};
```

本節稍早討論的三個政策會評估下列授權請求。在此授權請求中， 類型 `User`和 值為 的委託人會使用角色 `Alice`提出`updateData`請求`allAccessRole`。 `Alice`具有值為 `Tenant`的 屬性`Tenant::"TenantA"`。`Alice` 嘗試執行的動作是 ，`updateData,`其將套用到的資源`SampleData`類型為 `Data`。 `SampleData` 具有 `TenantA`做為父實體。

根據政策存放區中的第一個`<DATAMICROSERVICE_POLICYSTOREID>`政策， `Alice`可以對資源執行 `updateData`動作，假設符合政策 `when`子句中的條件。第一個條件需要 `principal.Tenant` 屬性才能評估為 `TenantA`。第二個條件需要主體的 屬性`account_lockout_flag`為 `false`。最終條件需要內容`uses_mfa`為 `true`。由於符合所有三個條件，請求會傳回 `ALLOW`決策。

```
{
  "policyStoreId": "DATAMICROSERVICE_POLICYSTORE",
  "principal": {
      "entityType": "MultitenantApp::User",
      "entityId": "Alice"
  },
  "action": {
      "actionType": "MultitenantApp::Action",
      "actionId": "updateData"
  },
  "resource": {
      "entityType": "MultitenantApp::Data",
      "entityId": "SampleData"
  },
  "context": {
    "contextMap": {
        "uses_mfa": {
            "boolean": true
        }
    }
  },
  "entities": {
    "entityList": [
      {
        "identifier": {
            "entityType": "MultitenantApp::User",
            "entityId": "Alice"
        },
        "attributes": {
            {
                "account_lockout_flag": {
                    "boolean": false
                },
                "Tenant": {
                   "entityIdentifier": {
                        "entityType":"MultitenantApp::Tenant",
                        "entityId":"TenantA"
                   }
                }
            }
        },
        "parents": [
            {
                "entityType": "MultitenantApp::Role",
                "entityId": "allAccessRole"
            }
        ]
        },
     {
        "identifier": {
            "entityType": "MultitenantApp::Data",
            "entityId": "SampleData"
        },
        "attributes": {},
        "parents": [
            {
                "entityType": "MultitenantApp::Tenant",
                "entityId": "TenantA"
            }
        ]
      }
    ]
  }
}
```

# 範例 5：使用 Verified Permissions 和 Cedar 進行 UI 篩選
<a name="avp-ui-filtering-examples"></a>

您也可以使用 Verified Permissions 根據授權的動作實作 UI 元素的 RBAC 篩選。這對於具有內容敏感 UI 元素的應用程式非常有用，這些元素可能會在多租用戶 SaaS 應用程式的情況下與特定使用者或租用戶相關聯。

在下列範例中，`Role``viewer`不允許 `Users` 的 執行更新。對於這些使用者，UI 不應轉譯任何更新按鈕。

![\[使用 Amazon Verified Permissions 和 Cedar 篩選 UI 的範例\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-example-5.png)


在此範例中，單一頁面 Web 應用程式有四個按鈕。哪些按鈕是可見`Role`的，取決於目前登入應用程式的使用者的 。當單頁 Web 應用程式轉譯 UI 時，它會查詢 Verified Permissions，以判斷使用者獲授權執行的動作，然後根據授權決策產生按鈕。

下列政策指定值`Role`為 的 類型`viewer`可以同時檢視使用者和資料。此政策`ALLOW`的授權決策需要 `viewData`或 `viewUsers`動作，也需要資源與 類型`Data`或 相關聯`Users`。`ALLOW` 決策允許 UI 轉譯兩個按鈕： `viewDataButton`和 `viewUsersButton`。

```
permit (
    principal in GuiAPP::Role::"viewer",
    action in [GuiAPP::Action::"viewData", GuiAPP::Action::"viewUsers"],
    resource 
)
when {
   resource in [GuiAPP::Type::"Data", GuiAPP::Type::"Users"]
};
```

下列政策指定值`Role`為 的 類型`viewerDataOnly`只能檢視資料。此政策`ALLOW`的授權決策需要 `viewData`動作，也需要資源與類型 建立關聯`Data`。`ALLOW` 決策允許 UI 轉譯按鈕 `viewDataButton`。

```
permit (
    principal in GuiApp::Role::"viewerDataOnly",
    action in [GuiApp::Action::"viewData"],
    resource in [GuiApp::Type::"Data"] 
);
```

下列政策指定`Role`值為 的 類型`admin`可以編輯和檢視資料和使用者。此政策`ALLOW`的授權決策需要 `updateData`、 `updateUsers``viewData,`或 的動作`viewUsers`，也需要資源與 類型`Data`或 相關聯`Users`。`ALLOW` 決策允許 UI 轉譯所有四個按鈕：`updateDataButton`、`viewDataButton`、 `updateUsersButton`和 `viewUsersButton`。

```
permit (
    principal in GuiApp::Role::"admin",
    action in [
        GuiApp::Action::"updateData",
        GuiApp::Action::"updateUsers",
        GuiApp::Action::"viewData", 
        GuiApp::Action::"viewUsers"
       ],
    resource 
)
when {
   resource in [GuiApp::Type::"Data", GuiApp::Type::"Users"]
};
```