在架构和策略中使用身份源 - Amazon Verified Permissions

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

在架构和策略中使用身份源

您可能会发现要将身份源添加到策略存储中,并将提供商声明映射到您的策略存储架构中。您可以自动执行此过程或手动更新架构。用户指南的这一部分包含以下信息:

  • 何时可以自动填充策略存储架构的属性

  • 如何在您的已验证权限政策中使用 Amazon Cognito 和 OIDC 令牌声明

  • 如何为身份源手动构建架构

通过引导式设置API 关联的策略存储和带有身份源的策略存储不需要将身份 (ID) 令牌属性手动映射到架构。您可以为已验证权限提供用户池或 OIDC 令牌中的属性,并创建填充用户属性的架构。在 ID 令牌授权中,已验证权限将声明映射到委托人实体的属性。在以下情况下,您可能需要手动将 Amazon Cognito 令牌映射到您的架构:

  • 您根据示例创建了空白的策略存储区或策略存储区。

  • 您希望将访问令牌的使用范围扩展到基于角色的访问控制 (RBAC) 之外。

  • 您可以使用已验证的权限 REST API、 AWS 软件开发工具包或创建策略存储 AWS CDK。

要使用 Amazon Cognito 或 OIDC 身份提供商 (IdP) 作为已验证权限策略存储中的身份源,您的架构中必须包含提供商属性。如果您创建策略存储的方式是自动从 ID 令牌中的提供者信息填充架构,那么您就可以编写策略了。如果您创建的策略存储没有身份源架构,则必须向架构中添加提供者属性。您的架构必须与提供者令牌创建的实体IsAuthorizedWithToken或令BatchIsAuthorizedWith牌 API 请求相对应。然后,您可以使用提供者令牌中的属性来编写策略。

有关在已验证权限中为经过身份验证的用户使用 Amazon Cognito ID 和访问令牌的更多信息,请参阅 Amazon Co gnito 开发者指南中的使用亚马逊验证权限进行授权

关于架构映射的注意事项

不同标记类型的属性映射不同

在访问令牌授权中,已验证权限将声明映射到上下文。在 ID 令牌授权中,已验证权限将声明映射到委托人属性。对于您在已验证权限控制台中创建的策略存储,只有策略存储和示例策略存储才会使您没有身份来源,并要求您在架构中填充用户池属性以进行 ID 令牌授权。访问令牌授权基于基于角色的访问控制 (RBAC) 和群组成员资格声明,不会自动将其他声明映射到策略存储架构。

身份源属性不是必需的

在已验证权限控制台中创建身份源时,不会将任何属性标记为必填属性。这样可以防止丢失的索赔导致授权请求中的验证错误。您可以根据需要将属性设置为 required,但它们必须存在于所有授权请求中。

RBAC 不需要架构中的属性

身份源的架构取决于您在添加身份源时所建立的实体关联。身份源将一个声明映射到用户实体类型,将一个声明映射到群组实体类型。这些实体映射是身份源配置的核心。有了这些最少的信息,您就可以在基于角色的访问控制 (RBAC) 模型中编写对特定用户和用户可能属于的特定组执行授权操作的策略。向架构中添加令牌声明可扩展策略存储的授权范围。来自 ID 令牌的用户属性包含有关用户的信息,这些信息可以为基于属性的访问控制 (ABAC) 授权做出贡献。访问令牌中的上下文属性包含诸如 OAuth 2.0 范围之类的信息,这些信息可以提供来自提供商的额外访问控制信息,但需要进行额外的架构修改。

已验证权限控制台中的 “使用 API Gateway 和身份源进行设置” 和 “引导式设置” 选项为架构分配 ID 令牌声明。访问令牌声明的情况并非如此。要向架构中添加非组访问令牌声明,必须在 JSON 模式下编辑架构并添加 CommonTypes 属性。有关更多信息,请参阅 映射访问令牌

OIDC 团体声称支持多种格式

添加 OIDC 提供商时,您可以在 ID 或访问令牌中选择要映射到策略存储中用户的群组成员资格的群组名称。经过验证的权限可以识别以下格式的群组声明:

  1. 不带空格的字符串:"groups": "MyGroup"

  2. 以空格分隔的列表:. "groups": "MyGroup1 MyGroup2 MyGroup3" 每个字符串都是一个组。

  3. JSON(以逗号分隔)列表:"groups": ["MyGroup1", "MyGroup2", "MyGroup3"]

注意

Verified Permissions 将以空格分隔的群组声明中的每个字符串解释为一个单独的群组。要将带有空格字符的组名解释为单个组,请替换或删除声明中的空格。例如,将名为的群组设置为My Group的格式MyGroup

选择代币类型

您的策略存储与身份源配合的方式取决于身份源配置中的一个关键决定:是处理 ID 还是访问令牌。使用 Amazon Cognito 身份提供商,您可以在创建与 API 关联的策略存储时选择令牌类型。创建与 API 关联的策略存储时,必须选择是要为 ID 还是访问令牌设置授权。此信息会影响已验证权限应用于您的策略存储的架构属性,以及您的 API Gateway API 的 Lambda 授权方的语法。对于 OIDC 提供商,您必须在添加身份源时选择令牌类型。您可以选择 ID 或访问令牌,并且您的选择会将未选择的令牌类型排除在保单存储库中的处理范围之外。特别是如果您希望从身份令牌声明自动映射到已验证权限控制台中的属性中受益,请在创建身份源之前尽早决定要处理的令牌类型。更改令牌类型需要花费大量精力来重构您的策略和架构。以下主题介绍如何在策略存储中使用 ID 和访问令牌。

Cedar 解析器要求某些字符使用方括号

策略通常以类似的格式引用架构属性principal.username。对于令牌声明名称中可能出现的大多数非字母数字字符:,例如.、或/,Verified Permissions 无法解析像或这样的条件值。principal.cognito:groups context.ip-address您必须改为使用principal["cognito:username"]context["ip-address"]格式的方括号表示法来格式化这些条件。下划线字符_是声明名称中的有效字符,也是该要求的唯一非字母数字例外。

此类型主属性的部分示例架构如下所示:

"User": { "shape": { "type": "Record", "attributes": { "cognito:username": { "type": "String", "required": true }, "custom:employmentStoreCode": { "type": "String", "required": true, }, "email": { "type": "String", "required": false } } } }

这种类型的上下文属性的部分示例架构如下所示:

"GetOrder": { "memberOf": [], "appliesTo": { "resourceTypes": [ "Order" ], "context": { "type": "Record", "attributes": { "ip-address": { "required": false, "type": "String" } } }, "principalTypes": [ "User" ] } }

将针对此架构进行验证的属性的示例策略如下所示:

permit ( principal in MyCorp::UserGroup::"us-west-2_EXAMPLE|MyUserGroup", action, resource ) when { principal["cognito:username"] == "alice" && principal["custom:employmentStoreCode"] == "petstore-dallas" && principal has email && principal.email == "alice@example.com" && context["ip-address"] like "192.0.2.*" };

将 ID 令牌映射到架构

Verified Permissions 将身份令牌声明作为用户的属性进行处理:他们的姓名和头衔、群组成员资格、联系信息。ID 令牌在基于属性的访问控制 (ABAC) 授权模型中最有用。如果您想让经过验证的权限根据谁提出请求来分析对资源的访问权限,请为您的身份来源选择 ID 令牌。

亚马逊 Cognito ID 令牌

Amazon Cognito ID 令牌适用于大多数 OIDC 依赖方库。它们通过其他索赔扩展了OIDC的功能。您的应用程序可以通过 Amazon Cognito 用户池身份验证 API 操作或用户池托管用户界面对用户进行身份验证。有关更多信息,请参阅 Amazon Cognito 开发者指南中的使用 API 和终端节点

亚马逊 Cognito ID 代币中的有用声明
cognito:usernamepreferred_username

用户名的变体。

sub

用户的唯一用户标识符 (UUID)

custom:前缀的索赔

自定义用户池属性的前缀,例如custom:employmentStoreCode

标准索赔

标准 OIDC 声称类似email和。phone_number有关更多信息,请参阅 OpenID Connect Core 1.0 中包含勘误集 2 的标准声明

cognito:groups

用户的群组成员资格。在基于角色的访问控制 (RBAC) 的授权模型中,此声明提供了您可以在策略中评估的角色。

临时索赔

声明不是用户的财产,但在运行时由用户池生成令牌前 Lambda 触发器添加。临时索赔与标准索赔类似,但不在标准范围内,例如tenantdepartment

在引用带有:分隔符的 Amazon Cognito 属性的策略中,引用格式中的属性。principal["cognito:username"]角色声明cognito:groups是此规则的例外。已验证权限将此声明的内容映射到用户实体的父实体。

有关来自 Amazon Cognito 用户池的 ID 令牌结构的更多信息,请参阅 Amazon Cog nito 开发者指南中的使用 ID 令牌

以下示例 ID 令牌具有四种类型的属性。分别是 Amazon Cognito 特定声明 cognito:username、自定义声明 custom:employmentStoreCode、标准声明 email 和临时声明 tenant

{ "sub": "91eb4550-XXX", "cognito:groups": [ "Store-Owner-Role", "Customer" ], "email_verified": true, "clearance": "confidential", "iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_EXAMPLE", "cognito:username": "alice", "custom:employmentStoreCode": "petstore-dallas", "origin_jti": "5b9f50a3-05da-454a-8b99-b79c2349de77", "aud": "1example23456789", "event_id": "0ed5ad5c-7182-4ecf-XXX", "token_use": "id", "auth_time": 1687885407, "department": "engineering", "exp": 1687889006, "iat": 1687885407, "tenant": "x11app-tenant-1", "jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN1111111", "email": "alice@example.com" }

当您使用 Amazon Cognito 用户池创建身份源时,您需要指定授权请求中验证权限生成的委托人实体的类型。IsAuthorizedWithToken然后,作为评估该请求的一部分,您的策略会测试该主体的属性。您的架构定义身份源的委托人类型和属性,然后您可以在 Cedar 策略中引用它们。

您还可以指定要从 ID 令牌组声明中派生的群组实体的类型。在授权请求中,Verified Permissions 会将每个群组成员的声明映射到该群组实体类型。在策略中,您可以将该组实体引用为委托人。

以下示例说明了如何在 Verified Permissions 架构中反映示例身份令牌中的属性。有关编辑架构的更多信息,请参阅在 JSON 模式下编辑架构。如果您的身份来源配置指定了主体类型 User,那么,您可以添加类似于以下示例的内容,以使这些属性可用于 Cedar。

"User": { "shape": { "type": "Record", "attributes": { "cognito:username": { "type": "String", "required": false }, "custom:employmentStoreCode": { "type": "String", "required": false }, "email": { "type": "String" }, "tenant": { "type": "String", "required": true } } } }

在更新架构以反映 Amazon Cognito 属性后,您可以创建引用这些属性的策略。

permit ( principal in MyCorp::UserGroup::"us-west-2_EXAMPLE|MyUserGroup", action, resource ) when { principal["cognito:username"] == "alice" && principal["custom:employmentStoreCode"] == "petstore-dallas" && principal.tenant == "x11app-tenant-1" && principal has email && principal.email == "alice@example.com" };

OIDC 身份令牌

使用 OIDC 提供商提供的身份令牌与使用亚马逊 Cognito ID 令牌大致相同。区别在于索赔。您的 IdP 可能呈现标准的 OIDC 属性,或者具有自定义架构。在已验证权限控制台中创建新的策略存储时,可以添加带有示例 ID 令牌的 OIDC 身份源,也可以手动将令牌声明映射到用户属性。由于已验证权限不知道您的 IdP 的属性架构,因此您必须提供此信息。

有关更多信息,请参阅 创建 Verified Permissions 策略存储

以下是具有 OIDC 身份源的策略存储的示例架构。

"User": { "shape": { "type": "Record", "attributes": { "email": { "type": "String" }, "email_verified": { "type": "Boolean" }, "name": { "type": "String", "required": true }, "phone_number": { "type": "String" }, "phone_number_verified": { "type": "Boolean" } } } }

以下政策适用于您的 OIDC 提供商中群组的成员。

permit ( principal in MyCorp::UserGroup::"MyOIDCProvider|MyUserGroup", action, resource ) when { principal.email_verified == true && principal.email == "alice@example.com" && principal.phone_number_verified == true && principal.phone_number like "+1206*" };

映射访问令牌

Verified Permissions 处理访问令牌声明,而不是作为操作属性或上下文属性的群组声明。除了群组成员资格外,来自您的 IdP 的访问令牌可能还包含有关 API 访问的信息。访问令牌在使用基于角色的访问控制 (RBAC) 的授权模型中很有用。依赖组成员资格以外的访问令牌声明的授权模型需要在架构配置方面付出额外的努力。

映射 Amazon Cognito 访问令牌

Amazon Cognito 访问令牌具有可用于授权的声明:

亚马逊 Cognito 访问令牌中的有用声明
client_id

OIDC 依赖方的客户端应用程序的 ID。使用客户端 ID,已验证权限可以验证授权请求是否来自策略存储的允许客户端。在 machine-to-machine (M2M)授权中,请求系统使用客户端密钥对请求进行授权,并提供客户端 ID 和范围作为授权证据。

scope

代表令牌持有者的访问权限的 OAuth 2.0 范围

cognito:groups

用户的群组成员资格。在基于角色的访问控制 (RBAC) 的授权模型中,此声明提供了您可以在策略中评估的角色。

临时索赔

不是访问权限但是在运行时由用户池生成令牌前 Lambda 触发器添加的声明。临时索赔与标准索赔类似,但不在标准范围内,例如tenantdepartment。自定义访问令牌会增加您的 AWS 账单成本。

有关来自 Amazon Cognito 用户池的访问令牌结构的更多信息,请参阅 Amazon Cog nito 开发者指南中的使用访问令牌

Amazon Cognito 访问令牌在传递到 Verified Permissions 时,会映射到上下文对象。可以使用 context.token.attribute_name 来引用访问令牌的属性。以下示例访问令牌同时包含 client_idscope 声明。

{ "sub": "91eb4550-9091-708c-a7a6-9758ef8b6b1e", "cognito:groups": [ "Store-Owner-Role", "Customer" ], "iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_EXAMPLE", "client_id": "1example23456789", "origin_jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN1111111", "event_id": "bda909cb-3e29-4bb8-83e3-ce6808f49011", "token_use": "access", "scope": "MyAPI/mydata.write", "auth_time": 1688092966, "exp": 1688096566, "iat": 1688092966, "jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN2222222", "username": "alice" }

以下示例说明了如何在 Verified Permissions 架构中反映示例访问令牌中的属性。有关编辑架构的更多信息,请参阅在 JSON 模式下编辑架构

{ "MyApplication": { "actions": { "Read": { "appliesTo": { "context": { "type": "ReusedContext" }, "resourceTypes": [ "Application" ], "principalTypes": [ "User" ] } } }, ... ... "commonTypes": { "ReusedContext": { "attributes": { "token": { "type": "Record", "attributes": { "scope": { "type": "Set", "element": { "type": "String" } }, "client_id": { "type": "String" } } } }, "type": "Record" } } } }

在更新架构以反映 Amazon Cognito 属性后,您可以创建引用这些属性的策略。

permit(principal, action in [MyApplication::Action::"Read", MyApplication::Action::"GetStoreInventory"], resource) when { context.token.client_id == "52n97d5afhfiu1c4di1k5m8f60" && context.token.scope.contains("MyAPI/mydata.write") };

映射 OIDC 访问令牌

来自外部 OIDC 提供商的大多数访问令牌都与 Amazon Cognito 访问令牌非常一致。传递给 “已验证权限” 时,OIDC 访问令牌会映射到上下文对象。可以使用 context.token.attribute_name 来引用访问令牌的属性。以下示例 OIDC 访问令牌包括基本声明示例。

{ "sub": "91eb4550-9091-708c-a7a6-9758ef8b6b1e", "groups": [ "Store-Owner-Role", "Customer" ], "iss": "https://auth.example.com", "client_id": "1example23456789", "aud": "https://myapplication.example.com" "scope": "MyAPI-Read", "exp": 1688096566, "iat": 1688092966, "jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN2222222", "username": "alice" }

以下示例说明了如何在 Verified Permissions 架构中反映示例访问令牌中的属性。有关编辑架构的更多信息,请参阅在 JSON 模式下编辑架构

{ "MyApplication": { "actions": { "Read": { "appliesTo": { "context": { "type": "ReusedContext" }, "resourceTypes": [ "Application" ], "principalTypes": [ "User" ] } } }, ... ... "commonTypes": { "ReusedContext": { "attributes": { "token": { "type": "Record", "attributes": { "scope": { "type": "Set", "element": { "type": "String" } }, "client_id": { "type": "String" } } } }, "type": "Record" } } } }

更新架构以反映 IdP 属性后,您可以创建引用这些属性的策略。

permit( principal, action in [MyApplication::Action::"Read", MyApplication::Action::"GetStoreInventory"], resource ) when { context.token.client_id == "52n97d5afhfiu1c4di1k5m8f60" && context.token.scope.contains("MyAPI-read") };

Amazon Cognito 以冒号分隔的声明的替代符号

在启动已验证权限时,Amazon Cognito 令牌的推荐架构声称喜欢这些冒号分隔的字符串,cognito:groups并将其custom:store转换为使用该字符作为层次结构分隔.符。这种格式称为点符号。例如,在您的政策principal.cognito.groups中提及cognito:groups变为了。尽管您可以继续使用这种格式,但我们建议您使用括号表示法来构建架构和策略。在这种格式中,对的引用将cognito:groupsprincipal["cognito:groups"]为您的政策。从已验证权限控制台自动生成的用户池 ID 令牌架构使用方括号表示法。

您可以继续在手动构建的 Amazon Cognito 身份源的架构和策略中使用点符号。对于任何其他类型的 OIDC IdP,您不能在架构:或策略中使用带点符号或任何其他非字母数字字符。

点符号架构将:字符的每个实例嵌套为cognitocustom初始短语的子项,如以下示例所示:

"CognitoUser": { "shape": { "type": "Record", "attributes": { "cognito": { "type": "Record", "required": true, "attributes": { "username": { "type": "String", "required": true } } }, "custom": { "type": "Record", "required": true, "attributes": { "employmentStoreCode": { "type": "String", "required": true } } }, "email": { "type": "String" }, "tenant": { "type": "String", "required": true } } } }

使用这种格式的架构,您可以创建带有点符号的策略,如以下示例所示:

permit(principal, action, resource) when { principal.cognito.username == "alice" && principal.custom.employmentStoreCode == "petstore-dallas" && principal.tenant == "x11app-tenant-1" && principal has email && principal.email == "alice@example.com" };