

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon 已验证权限多租户设计注意事项
<a name="avp-design-considerations"></a>

在多租户 SaaS 解决方案中使用 Amazon 验证权限来实施授权时，需要考虑多种设计选项。在探索这些选项之前，让我们澄清一下多租户 SaaS 环境中*隔离*和*授权*之间的区别。[隔离](https://docs.aws.amazon.com/whitepapers/latest/saas-architecture-fundamentals/tenant-isolation.html)租户可以防止入站和出站数据泄露给错误的租户。授权可确保用户拥有访问租户的权限。

在已验证的权限中，策略存储在策略存储中。如Verified Permissions [文档](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/design-multi-tenancy-considerations.html)中所述，您可以通过为每个租户使用单独的策略存储来隔离租户的策略，也可以通过为所有租户使用单个策略存储来允许租户共享策略。本节讨论了这两种隔离策略的优缺点，并描述了如何使用分层部署模型来部署它们。有关其他背景信息，请参阅 “已验证权限” 文档。

尽管本节中讨论的标准侧重于已验证的权限，但一般概念植根于[隔离思维方式](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/isolation-mindset.html)及其提供的指导。SaaS 应用程序必须始终将[租户隔离](https://docs.aws.amazon.com/whitepapers/latest/saas-architecture-fundamentals/tenant-isolation.html)视为其设计的一部分，这种一般的隔离原则延伸到在 SaaS 应用程序中包括经过验证的权限。本节还引用了核心的SaaS隔离模型，例如[孤立的SaaS模型和池](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/silo-isolation.html)[化的SaaS](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/pool-isolation.html) 模型。有关更多信息，请参阅 Well-Architecte AWS d 框架 SaaS 镜头中的[核心隔离概念](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/core-isolation-concepts.html)。

设计多租户 SaaS 解决方案时的关键考虑因素是租户隔离和租户入职。租户隔离会影响安全、隐私、弹性和性能。租户入职会影响您的运营流程，因为它与运营开销和可观察性有关。经历SaaS旅程或实施多租户解决方案的组织必须始终优先考虑SaaS应用程序如何处理租赁。尽管 SaaS 解决方案可能倾向于特定的隔离模型，但不一定要求整个 SaaS 解决方案保持一致。例如，您为应用程序的前端组件选择的隔离模型可能与您为微服务或授权服务选择的隔离模型不同。

**Topics**
+ [租户入职和用户租户注册](avp-design-onboarding-registration.md)
+ [每租户策略存储](avp-design-per-tenant-store.md)
+ [一个共享的多租户策略存储](avp-design-shared-store.md)
+ [分层部署模型](avp-design-tiered.md)

# 租户入职和用户租户注册
<a name="avp-design-onboarding-registration"></a>

SaaS 应用程序遵守 [SaaS 身份](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/saas-identity.html)的概念，并遵循将[用户身份绑定到租户身份](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/general-design-principles.html)的一般最佳实践。绑定涉及将租户标识符存储为身份提供者中用户的声明或属性。这就将向租户映射身份的责任从每个应用程序转移到用户注册流程。然后，每位经过身份验证的用户都将拥有正确的租户身份，作为 JSON Web 令牌 (JWT) 的一部分。

同样，为授权请求选择正确的策略存储不应由应用程序逻辑决定。要确定特定授权请求应使用哪个策略存储，请维护用户到策略存储或租户与策略存储的映射。这些映射通常保存在您的应用程序引用的数据存储中，例如 Amazon DynamoDB 或亚马逊关系数据库服务 (Amazon RDS)。您也可以通过身份提供商 (IdP) 中的数据来提供或补充这些映射。然后，租户、用户和策略存储之间的关系通常通过包含授权请求所需的所有关系的 JWT 提供给用户。

此示例显示了属于租户`TenantA`并使用带有策略存储 ID 的策略存储进行授权的用户 `Alice` JWT `ps-43214321` 的显示方式。

```
{
   "sub":"1234567890",
   "name":"Alice",
   "tenant":"TenantA",
   "policyStoreId":"ps-43214321"
}
```

# 每租户策略存储
<a name="avp-design-per-tenant-store"></a>

Amazon Verified Permissions 中的每租户策略存储设计模型将 SaaS 应用程序中的每个租户与其自己的策略存储区相关联。此模型类似于 SaaS [孤岛隔离](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/silo-isolation.html)模型。两种模式都要求创建租户特定的基础设施，并且具有相似的优缺点。这种方法的主要好处是基础设施强制的租户隔离，支持每个租户的独特授权模式，消除了[邻居的噪音](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/noisy-neighbor.html)担忧，以及缩小了策略更新或部署失败的影响范围。这种方法的缺点包括更复杂的租户入职流程、部署和运营。如果解决方案对每个租户都有唯一的策略，则推荐使用按租户策略存储的方法。

如果您的 SaaS 应用程序需要，按租户策略存储模型可以提供一种高度孤立的租户隔离方法。您也可以将此模型与[池隔离](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/pool-isolation.html)配合使用，但是您的 Verified Permissions 实现不会共享更广泛的池隔离模型的标准优势，例如简化的管理和操作。

在每租户策略存储中，租户隔离是通过在用户注册过程中将租户的策略存储标识符映射到用户的 SaaS 身份来实现的，如前所述。这种方法将租户的策略存储与用户主体紧密地联系在一起，并提供了一种在整个 SaaS 解决方案中共享映射的一致方式。您可以将 SaaS 应用程序作为 IdP 的一部分或外部数据源（例如 DynamoDB）进行维护，从而将其提供到 SaaS 应用程序的映射。这还可以确保委托人是租户的一部分，并且使用租户的策略存储。

此示例说明了如何将包含用户`policyStoreId`和`tenant`的 JWT 从 API 端点传递到授权方中的策略评估点， AWS Lambda 授权方将请求路由到正确的策略存储。

![\[Amazon 已验证权限中的按租户策略存储模型\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-per-tenant.png)


以下示例策略说明了每租户策略商店的设计范例。`Alice`属于的用户还`TenantA.`会 policyStoreId`store-a`映射到的租户身份，`Alice,`并强制使用正确的策略存储。这样可以确保使用`TenantA`的策略。

**注意**  
每租户策略存储模型隔离了租户的策略。授权会强制执行允许用户对其数据执行的操作。任何使用此模型的假设应用程序所涉及的资源都应使用其他隔离机制进行隔离，如Well-Architected Fr [amework，SaaS Lens AWS 文档](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/core-isolation-concepts.html)中所定义。

在此策略中，`Alice`有权查看所有资源的数据。

```
permit (
    principal == MultiTenantApp::User::"Alice",
    action == MultiTenantApp::Action::"viewData",
    resource
);
```

要提出授权请求并使用已验证权限策略开始评估，您需要提供与映射到租户的唯一 ID 相对应的策略存储 ID `store-a`。

```
{
   "policyStoreId":"store-a",
   "principal":{
      "entityType":"MultiTenantApp::User",
      "entityId":"Alice"
   },
   "action":{
      "actionType":"MultiTenantApp::Action",
      "actionId":"viewData"
   },
   "resource":{
      "entityType":"MultiTenantApp::Data",
      "entityId":"my_example_data"
   },
   "entities":{
      "entityList":[
         [
            {
               "identifier":{
                  "entityType":"MultiTenantApp::User",
                  "entityId":"Alice"
               },
               "attributes":{},
               "parents":[]
            },
            {
               "identifier":{
                  "entityType":"MultiTenantApp::Data",
                  "entityId":"my_example_data"
               },
               "attributes":{},
               "parents":[]
            }
         ]
      ]
   }
}
```

该用户`Bob`属于租户 B， policyStoreId`store-b`并且还映射到的租户身份`Bob`，这会强制使用正确的策略存储。这样可以确保使用租户 B 的策略。

在此策略中，`Bob`有权自定义所有资源的数据。在此示例中，`customizeData`可能是仅针对租户 B 的操作，因此该策略对租户 B 来说是唯一的。每租户策略存储模型本质上支持基于每个租户的自定义策略。

```
permit (
    principal == MultiTenantApp::User::"Bob",
    action == MultiTenantApp::Action::"customizeData",
    resource
);
```

要提出授权请求并使用已验证权限策略开始评估，您需要提供与映射到租户的唯一 ID 相对应的策略存储 ID `store-b`。

```
{
   "policyStoreId":"store-b",
   "principal":{
      "entityType":"MultiTenantApp::User",
      "entityId":"Bob"
   },
   "action":{
      "actionType":"MultiTenantApp::Action",
      "actionId":"customizeData"
   },
   "resource":{
      "entityType":"MultiTenantApp::Data",
      "entityId":"my_example_data"
   },
   "entities":{
      "entityList":[
         [
            {
               "identifier":{
                  "entityType":"MultiTenantApp::User",
                  "entityId":"Bob"
               },
               "attributes":{},
               "parents":[]
            },
            {
               "identifier":{
                  "entityType":"MultiTenantApp::Data",
                  "entityId":"my_example_data"
               },
               "attributes":{},
               "parents":[]
            }
         ]
      ]
   }
}
```

使用已验证的权限，可以将 IdP 与策略存储集成，但不是必需的。这种集成允许策略将身份存储中的委托人明确引用为策略的主体。[有关如何作为已验证权限的 IdP 与 Amazon Cognito 集成的更多信息，请参阅已验证权限文档和 [Amazon](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/identity-providers.html) Cognito 文档。](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-authorization-with-avp.html)

将策略存储与 IdP 集成时，每个策略存储只能使用一个[身份源](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/identity-providers.html)。例如，如果您选择将已验证权限与 Amazon Cognito 集成，则必须镜像用于隔离已验证权限策略存储和 Amazon Cognito 用户池的租户策略。策略存储库和用户池也必须位于同一位置 AWS 账户。

![\[在按租户设计模型中将经过验证的权限与 Amazon Cognito 集成\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/cognito-per-tenant.png)


在操作层面上，每租户策略存储具有审计优势，因为您可以轻松地为每个租户AWS CloudTrail 单独查询[已记录的活动](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/monitoring-overview.html)。但是，我们仍然建议您将每个租户维度上的其他自定义指标记录到 Amazon CloudWatch。

按租户策略存储方法还需要密切关注两个[已验证的权限配额](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/quotas.html)，以确保它们不会干扰 SaaS 解决方案的运行。这些配额是每个账户*每个区域的策略存储量和每个账户*每个*区域的每秒IsAuthorized 请求数*。您可以申请提高两个配额。

有关如何实现按租户策略存储模型的更详细示例，请参阅 AWS 博客文章 [SaaS 访问控制使用每租户策略存储的 Amazon Verified Permis](https://aws.amazon.com/blogs/security/saas-access-control-using-amazon-verified-permissions-with-a-per-tenant-policy-store/) sions。

# 一个共享的多租户策略存储
<a name="avp-design-shared-store"></a>

一个共享的多租户策略存储设计模型在 Amazon 中为所有租户使用 SaaS 解决方案中所有租户的单个多租户策略存储经过验证的权限。这种方法的主要好处是简化了管理和操作，特别是因为在租户入职期间，您不必创建额外的策略存储库。这种方法的缺点包括策略更新或部署中的任何失败或错误所造成的影响范围扩大，以及更容易受到[噪音邻居](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/noisy-neighbor.html)效应的影响。此外，如果您的解决方案要求每个租户都有独特的策略，我们不建议使用这种方法。在这种情况下，请改用每租户策略存储模型，以保证使用正确租户的策略。

一个共享的多租户策略存储方法类似于 SaaS [池化隔离模型](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/pool-isolation.html)。如果您的 SaaS 应用程序需要，它可以提供一种共享的租户隔离方法。如果您的 SaaS 解决方案对其微服务应用[孤立隔离](https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/silo-isolation.html)，则也可以使用此模型。选择模型时，应独立评估租户数据隔离要求和 SaaS 应用程序所需的已验证权限策略结构。

如前所述，为了在整个 SaaS 解决方案中采用一致的方式共享租户标识符，最好在用户注册期间将标识符映射到用户的 SaaS 身份。您可以将 SaaS 应用程序作为 IdP 的一部分或外部数据源（例如 DynamoDB）进行维护，从而将其提供给 SaaS 应用程序。我们还建议您将共享策略存储 ID 映射到用户。尽管 ID 不用作租户隔离的一部分，但这是一种很好的做法，因为它有助于将来的更改。

以下示例显示了 API 端点如何为属于不同租户但与策略存储 ID 共享策略存储以`store-multi-tenant`进行授权的用户`Alice`和`Bob`发送 JWT。由于所有租户共享一个策略存储，因此您无需在令牌或数据库中维护策略存储 ID。由于所有租户共享一个策略存储 ID，因此您可以将该 ID 作为环境变量提供，您的应用程序可以使用该变量来调用策略存储。

![\[已验证权限共享设计模型\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-shared.png)


以下示例策略说明了一个共享的多租户策略设计范例。在此策略中`MultiTenantApp::User`，`MultiTenantApp::Role``Admin`拥有父项的委托人有权查看所有资源的数据。

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

由于使用的是单个策略存储，因此已验证权限策略存储必须确保与委托人关联的租赁属性与与资源关联的租赁属性相匹配。这可以通过在策略存储中加入以下策略来实现，以确保所有在资源和委托人上没有匹配租赁属性的授权请求都被拒绝。

```
forbid(
    principal, 
    action, 
    resource
)
unless {
    resource.Tenant == principal.Tenant
};
```

对于使用一个共享的多租户策略存储模型的授权请求，策略存储 ID 是共享策略存储的标识符。在以下请求中 `User``Alice`，允许访问是因为她有 of`Admin`，并且与资源和委托人关联的`Tenant`属性都是`TenantA`。`Role`

```
{
   "policyStoreId":"store-multi-tenant",
   "principal":{
      "entityType":"MultiTenantApp::User",
      "entityId":"Alice"
   },
   "action":{
      "actionType":"MultiTenantApp::Action",
      "actionId":"viewData"
   },
   "resource":{
      "entityType":"MultiTenantApp::Data",
      "entityId":"my_example_data"
   },
   "entities":{
      "entityList":[
         {
            "identifier":{
               "entityType":"MultiTenantApp::User",
               "entityId":"Alice"
            },
            "attributes": {
                {
                    "Tenant": {
                        "entityIdentifier": {
                            "entityType":"MultitenantApp::Tenant",
                            "entityId":"TenantA"
                        }
                    }
                }
            },
            "parents":[
               {
                  "entityType":"MultiTenantApp::Role",
                  "entityId":"Admin"
               }
            ]
         },
         {
            "identifier":{
               "entityType":"MultiTenantApp::Data",
               "entityId":"my_example_data"
            },
            "attributes": {
                {
                    "Tenant": {
                        "entityIdentifier": {
                            "entityType":"MultitenantApp::Tenant",
                            "entityId":"TenantA"
                        }
                    }
                }
            },
            "parents":[]
         }
      ]
   }
}
```

使用已验证的权限，可以将 IdP 与策略存储集成，但不是必需的。这种集成允许策略将身份存储中的委托人明确引用为策略的主体。[有关如何作为已验证权限的 IdP 与 Amazon Cognito 集成的更多信息，请参阅已验证权限文档和 [Amazon](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/identity-providers.html) Cognito 文档。](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-authorization-with-avp.html)

将策略存储与 IdP 集成时，每个策略存储只能使用一个[身份源](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/identity-providers.html)。例如，如果您选择将已验证权限与 Amazon Cognito 集成，则必须镜像用于隔离已验证权限策略存储和 Amazon Cognito 用户池的租户策略。策略存储库和用户池也必须位于同一位置 AWS 账户。

![\[在共享设计模型中将经过验证的权限与 Amazon Cognito 集成\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/cognito-shared.png)


从运营和审计的角度来看，一个共享的多租户策略存储模式有一个缺点，因为[记录的活动 AWS CloudTrail](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/monitoring-overview.html)需要更多的复杂查询才能筛选出租户上的单个活动，因为每个记录的 CloudTrail 呼叫都使用相同的策略存储。在这种情况下，将每个租户维度上的其他自定义指标记录 CloudWatch 到 Amazon 会很有帮助，这样可以确保适当的可观察性和审计能力水平。

单一共享的多租户策略存储方法还需要密切关注[已验证的权限配额](https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/quotas.html)，以确保它们不会干扰 SaaS 解决方案的运行。特别是，我们建议您监控每个*区域每个账户的每秒IsAuthorized 请求*量配额，以确保不超过其限制。您可以申请增加此配额。

# 分层部署模型
<a name="avp-design-tiered"></a>

通过创建分层部署模型，您可以将高优先级 “企业级” 租户与可能更多的 “标准层” 客户隔离开来。在此模型中，您可以针对每个层级单独推出部署到策略存储库中的策略的任何更改，这样可以将每个层级的客户与其级别之外所做的更改隔离开来。在分层部署模型中，策略存储通常是作为每个层级的初始基础架构配置的一部分创建的，而不是在租户加入时进行部署。

如果您的解决方案主要使用池化隔离模型，则可能需要额外的隔离或自定义。例如，您可以创建一个 “高级层”，其中每个租户都将获得自己的租户层基础架构，通过部署只有一个租户的池化实例来创建孤立的模型。这可以采取完全分离的 “高级租户A” 和 “高级租户B” 基础架构的形式，包括保单存储。这种方法为最高级别的客户提供了孤立的隔离模型。

在分层部署模型中，每个策略存储都应遵循相同的隔离模型，尽管它是分开部署的。由于正在使用多个策略存储，因此您需要在整个 SaaS 解决方案中强制采用一致的方式共享与租户关联的策略存储标识符。与每租户策略存储模型一样，最好在用户注册期间将租户标识符映射到用户的 SaaS 身份。

下图显示了三个层：`Standard Tier``Enterprise Tier`、和`Premium Tier 1`。每个层都单独部署在自己的基础架构中，并在该层内使用一个共享策略存储。标准和企业层包含多个租户。 `TenantA``TenantB`并且在企业层中`Standard Tier`，`TenantC``TenantD`并且在企业层中。

`Premium Tier 1`仅包含`TenantP`，因此您可以像解决方案具有完全孤立的隔离模型一样为高级租户提供服务，并提供自定义策略等功能。为新的高级级别客户提供入职将导致`Premium Tier 2`基础设施的创建。

**注意**  
高级层中的应用程序、部署和租户注册与标准层和企业层相同。唯一的区别是，高级层级入职工作流程始于配置新的层级基础架构。



![\[已验证权限分层部署模型\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/saas-multitenant-api-access-authorization/images/avp-tiered-deployment.png)
