本页面介绍如何使用凭据访问边界来缩小或限制短期有效的凭据可以使用的 Identity and Access Management (IAM) 权限范围。
您可以使用凭据访问边界生成 OAuth 2.0 访问令牌,这些令牌代表服务账号,但具有的权限少于服务账号。例如,如果您的某个客户需要访问您控制的 Cloud Storage 数据,则可以执行以下操作:
- 创建一个可访问您拥有的每个 Cloud Storage 存储桶的服务账号。
- 为此服务账号生成 OAuth 2.0 访问令牌。
- 应用凭据访问边界,以仅允许访问包含您的客户数据的存储桶。
凭据访问边界的工作原理
要缩小权限范围,您需要定义凭据访问边界(用来指定短期有效的凭据可以访问的资源),以及在各资源上可用权限的上限。然后,您可以创建一个短期有效的凭据,并用其交换遵循凭据访问边界的新凭据。
如果您需要针对每个会话为主账号提供一组不同的权限,则与创建多个不同的服务账号并为每个服务账号授予一组不同的角色相比,使用凭据访问边界更高效。
凭据访问边界的示例
以下各个部分展示了常见使用场景的凭据访问边界示例。您在使用 OAuth 2.0 访问令牌换取作用域令牌时,可以使用凭据访问边界。
限制存储桶的权限
以下示例展示了一个简单的凭据访问边界。它应用于 Cloud Storage 存储桶 example-bucket
,并且将权限上限设置为 Storage Object Viewer 角色 (roles/storage.objectViewer
) 中包含的权限:
{
"accessBoundary": {
"accessBoundaryRules": [
{
"availablePermissions": [
"inRole:roles/storage.objectViewer"
],
"availableResource": "//storage.googleapis.com/projects/_/buckets/example-bucket"
}
]
}
}
限制多个存储桶的权限
以下示例展示了一个凭据访问边界,其中包含多个存储桶的规则:
- Cloud Storage 存储桶
example-bucket-1
:对于此存储桶,只有 Storage Object Viewer 角色 (roles/storage.objectViewer
) 中的权限可用。 - Cloud Storage 存储桶
example-bucket-2
:对于此存储桶,只有 Storage Object Creator 角色 (roles/storage.objectCreator
) 中的权限可用。
{
"accessBoundary": {
"accessBoundaryRules": [
{
"availablePermissions": [
"inRole:roles/storage.objectViewer"
],
"availableResource": "//storage.googleapis.com/projects/_/buckets/example-bucket-1"
},
{
"availablePermissions": [
"inRole:roles/storage.objectCreator"
],
"availableResource": "//storage.googleapis.com/projects/_/buckets/example-bucket-2"
}
]
}
}
限制特定对象的权限
您还可以使用 IAM Conditions 指定主账号可以访问哪些 Cloud Storage 对象。例如,您可以添加一个条件,该条件使权限可用于名称以 customer-a
开头的对象:
{ "accessBoundary": { "accessBoundaryRules": [ { "availablePermissions": [ "inRole:roles/storage.objectViewer" ], "availableResource": "//storage.googleapis.com/projects/_/buckets/example-bucket", "availabilityCondition": { "expression" : "resource.name.startsWith('projects/_/buckets/example-bucket/objects/customer-a')" } } ] } }
列出对象时限制权限
当您列出 Cloud Storage 存储桶中的对象时,会针对存储桶资源(而不是对象资源)调用方法。因此,如果系统为列出请求计算了条件,并且该条件引用了资源名称,则资源名称将标识存储桶,而不是该存储桶中的对象。例如,当您列出 example-bucket
中的对象时,资源名称为 projects/_/buckets/example-bucket
。
当您列出对象时,此命名惯例可能会导致意外行为。例如,假设您需要一个凭据访问边界,用于允许查看 example-bucket
中前缀为 customer-a/invoices/
的对象。您可以尝试在凭据访问边界中使用以下条件:
不完整:仅检查资源名称的条件
resource.name.startsWith('projects/_/buckets/example-bucket/objects/customer-a/invoices/')
此条件适用于读取对象,但不适用于列出对象:
- 当主账号尝试读取
example-bucket
中前缀为customer-a/invoices/
的对象时,该条件的计算结果为true
。 - 当主账号尝试列出具有该前缀的对象时,该条件的计算结果为
false
。resource.name
的值为projects/_/buckets/example-bucket
(没有以projects/_/buckets/example-bucket/objects/customer-a/invoices/
开头)。
为了防止此问题,除了使用 resource.name.startsWith()
之外,您的条件还可以检查名为 storage.googleapis.com/objectListPrefix
的 API 特性。此特性包含用于过滤对象列表的 prefix
参数的值。因此,您可以编写一个引用 prefix
参数的值的条件。
以下示例展示了如何在条件中使用 API 特性。它允许读取和列出 example-bucket
中前缀为 customer-a/invoices/
的对象:
完整:检查资源名称和前缀的条件
resource.name.startsWith('projects/_/buckets/example-bucket/objects/customer-a/invoices/') || api.getAttribute('storage.googleapis.com/objectListPrefix', '') .startsWith('customer-a/invoices/')
现在,您可以在凭据访问边界中使用此条件:
{
"accessBoundary": {
"accessBoundaryRules": [
{
"availablePermissions": [
"inRole:roles/storage.objectViewer"
],
"availableResource": "//storage.googleapis.com/projects/_/buckets/example-bucket",
"availabilityCondition": {
"expression":
"resource.name.startsWith('projects/_/buckets/example-bucket/objects/customer-a/invoices/') || api.getAttribute('storage.googleapis.com/objectListPrefix', '').startsWith('customer-a/invoices/')"
}
}
]
}
}
准备工作
在使用凭据访问边界之前,请确保满足以下要求:
您需要只针对 Cloud Storage 缩小权限范围,而不对其他 Google Cloud 服务这样做。
如果您需要缩小针对其他 Google Cloud 服务的权限范围,您可以创建多个服务账号并为每个服务账号授予一组不同的角色。
您可以使用 OAuth 2.0 访问令牌进行身份验证。 其他类型的短期有效的凭据不支持凭据访问边界功能。
此外,您还必须启用所需的 API:
-
Enable the IAM and Security Token Service APIs.
创建具有缩小的权限范围的短期有效的凭据
要创建具有缩小的权限范围的 OAuth 2.0 访问令牌,请按以下步骤操作:
- 向用户或服务账号授予相应的 IAM 角色。
- 定义一个凭据访问边界,以设置用户或服务账号可用权限的上限。
- 为用户或服务账号创建 OAuth 2.0 访问令牌。
- 用 OAuth 2.0 访问令牌交换遵循凭据访问边界的新令牌。
然后,您可以使用具有缩小的权限范围的新 OAuth 2.0 访问令牌,验证针对 Cloud Storage 的请求的身份。
授予 IAM 角色
凭据访问边界设置了可用于特定资源的权限的上限。它可以删减主账号已获取的权限,但无法添加该主账号尚未拥有的权限。
因此,您还必须在 Cloud Storage 存储桶上,或更高级别的资源(例如项目)上向主账号授予提供所需权限的角色。
例如,假设您需要创建一个具有缩小的权限范围的短期有效的凭据,以允许服务账号在存储桶中创建对象:
- 您必须至少向服务账号授予包含
storage.objects.create
权限的角色,例如 Storage Object Creator 角色 (roles/storage.objectCreator
)。凭据访问边界也必须包含此权限。 - 您还可以授予其包含更多权限的角色,例如 Storage Object Admin 角色 (
roles/storage.objectAdmin
)。服务账号只能使用同时出现在角色授权和凭据访问边界中的权限。
如需了解 Cloud Storage 的预定义角色,请参阅 Cloud Storage 角色。
凭据访问边界的组成部分
凭据访问边界是包含一系列访问边界规则的对象。每条规则都包含以下信息:
- 应用该规则的资源。
- 在该资源上可用的权限上限。
- 可选:进一步限制权限的条件。条件包括以下内容:
- 计算结果为
true
或false
的条件表达式。如果计算结果为true
,则允许访问;否则拒绝访问。 - 可选:标识条件的标题。
- 可选:包含有关条件的更多信息的说明。
- 计算结果为
如果您将凭据访问边界应用于短期有效的凭据,则该凭据只能访问凭据访问边界中的资源,不能获得在其他资源上可用的权限。
凭证访问边界最多可以包含 10 条访问边界规则。您只能为每个短期有效的凭据应用一个凭据访问边界。
以 JSON 对象的形式表示时,凭据访问边界包含以下字段:
字段 | |
---|---|
accessBoundary |
凭据访问边界的封装容器。 |
accessBoundary.accessBoundaryRules[] |
应用于短期有效的凭据的访问边界规则的列表。 |
accessBoundary.accessBoundaryRules[].availablePermissions[] |
用于定义对于资源可用的权限上限的列表。
每个值都是一个 IAM 预定义角色或自定义角色的标识符,并且带有前缀 |
accessBoundary.accessBoundaryRules[].availableResource |
应用规则的 Cloud Storage 存储桶的完整资源名称。请使用此格式: |
accessBoundary.accessBoundaryRules[].availabilityCondition |
可选。限制对特定 Cloud Storage 对象的权限可用性的条件。 如果要使权限可用于特定的对象(而不是 Cloud Storage 存储桶中的所有对象),请使用此字段。 |
accessBoundary.accessBoundaryRules[].availabilityCondition.expression |
一个条件表达式,用于指定可以使用权限的 Cloud Storage 对象。 如需了解如何在条件表达式中引用特定的对象,请参阅 |
accessBoundary.accessBoundaryRules[].availabilityCondition.title |
可选。标识条件目的的短字符串。 |
accessBoundary.accessBoundaryRules[].availabilityCondition.description |
可选。有关条件目的的详细信息。 |
如需查看 JSON 格式的示例,请参阅本页面上的凭据访问边界示例。
创建 OAuth 2.0 访问令牌
要创建具有缩小的权限范围的短期有效的凭据,您必须先创建一个常规的 OAuth 2.0 访问令牌。然后将常规凭据交换为具有缩小的权限范围的凭据。在创建访问令牌时,请使用 OAuth 2.0 范围 https://www.googleapis.com/auth/cloud-platform
。
要为服务账号创建访问令牌,您可以完成服务器到服务器的 OAuth 2.0 流程,或者可以使用 Service Account Credentials API 生成 OAuth 2.0 访问令牌。
如需为用户创建访问令牌,请参阅获取 OAuth 2.0 访问令牌。您还可以使用 OAuth 2.0 Playground,为您自己的 Google 账号创建访问令牌。
交换 OAuth 2.0 访问令牌
创建 OAuth 2.0 访问令牌后,您可以将访问令牌交换为符合凭据访问边界的缩小的权限范围的令牌。此过程通常涉及令牌代理和令牌使用方:
令牌代理负责定义凭据访问边界以及将访问令牌交换为具有缩小的权限范围的令牌。
令牌代理可以使用受支持的身份验证库自动交换访问令牌,也可以调用 Security Token Service 来手动交换令牌。
令牌使用方会从令牌代理请求具有缩小的权限范围的访问令牌,然后使用具有缩小的权限范围的访问令牌来执行其他操作。
令牌使用方可以使用受支持的身份验证库在访问令牌到期之前自动刷新访问令牌。或者,令牌使用方可以手动刷新令牌,也可以允许令牌过期,而无需刷新。
自动交换和刷新访问令牌
如果您使用以下某种语言创建令牌代理和令牌使用方,则可以使用 Google 的身份验证库自动交换和刷新令牌:
Go
对于 Go,您可以使用 golang.org/x/oauth2
软件包 v0.0.0-20210819190943-2bc19b11175f 版或更高版本自动交换和刷新令牌。
如需检查正在使用的软件包版本,请在应用目录中运行以下命令:
go list -m golang.org/x/oauth2
以下示例展示了令牌代理如何生成具有缩小的权限范围的令牌:
以下示例展示了令牌使用方如何使用刷新处理程序自动获取和刷新具有缩小的权限范围的令牌:
Java
对于 Java,您可以使用 com.google.auth:google-auth-library-oauth2-http
工件 1.1.0 版或更高版本自动交换和刷新令牌。
如需检查您正在使用的工件的版本,请在应用目录中运行以下 Maven 命令:
mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http
以下示例展示了令牌代理如何生成具有缩小的权限范围的令牌:
以下示例展示了令牌使用方如何使用刷新处理程序自动获取和刷新具有缩小的权限范围的令牌:
Node.js
对于 Node.js,您可以使用 google-auth-library
软件包 7.9.0 版或更高版本自动交换和刷新令牌。
如需检查正在使用的软件包版本,请在应用目录中运行以下命令:
npm list google-auth-library
以下示例展示了令牌代理如何生成具有缩小的权限范围的令牌:
以下示例展示了令牌使用方如何提供自动获取和刷新具有缩小的权限范围的令牌的刷新处理程序:
Python
对于 Python,您可以使用 google-auth
软件包 2.0.0 版或更高版本自动交换和刷新令牌。
如需检查正在使用的软件包版本,请在安装该软件包的环境中运行以下命令:
pip show google-auth
以下示例展示了令牌代理如何生成具有缩小的权限范围的令牌:
以下示例展示了令牌使用方如何提供自动获取和刷新具有缩小的权限范围的令牌的刷新处理程序:
手动交换和刷新访问令牌
令牌代理可以使用 Security Token Service API 将访问令牌交换为具有缩小的权限范围的访问令牌。然后,令牌代理可以向令牌使用方提供具有缩小的权限范围的令牌。
要交换访问令牌,请使用以下 HTTP 方法和网址:
POST https://sts.googleapis.com/v1/token
将请求中的 Content-Type
标头设置为 application/x-www-form-urlencoded
。在请求正文中添加以下字段:
字段 | |
---|---|
grant_type |
使用 |
options |
JSON 格式的凭据访问边界,采用百分号编码进行编码。 |
requested_token_type |
使用 |
subject_token |
您想要交换的 OAuth 2.0 访问令牌。 |
subject_token_type |
使用 |
响应是包含以下字段的 JSON 对象:
字段 | |
---|---|
access_token |
符合凭据访问边界的具有缩小的权限范围的 OAuth 2.0 访问令牌。 |
expires_in |
具有缩小的权限范围的令牌到期前的时间量(以秒为单位)。 仅当原始访问令牌代表服务账号时才会显示此字段。如果此字段不存在,则具有缩小的权限范围的令牌的到期时间与原始访问令牌的到期时间相同。 |
issued_token_type |
包含 |
token_type |
包含 |
例如,如果 JSON 格式的凭据访问边界存储在 ./access-boundary.json
文件中,您可以使用以下 curl
命令交换访问令牌。将 original-token
替换为原始访问令牌:
curl -H "Content-Type:application/x-www-form-urlencoded" \ -X POST \ https://sts.googleapis.com/v1/token \ -d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token_type=urn:ietf:params:oauth:token-type:access_token&requested_token_type=urn:ietf:params:oauth:token-type:access_token&subject_token=original-token" \ --data-urlencode "options=$(cat ./access-boundary.json)"
响应类似于以下示例:
{
"access_token": "ya29.dr.AbCDeFg-123456...",
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
"token_type": "Bearer",
"expires_in": 3600
}
当令牌使用方请求具有缩小的权限范围的令牌时,令牌代理应同时以具有缩小的权限范围的令牌和令牌到期前的秒数进行响应。如需刷新具有缩小的权限范围的令牌,使用方可以在现有令牌到期之前从代理请求具有缩小的权限范围的令牌。
后续步骤
- 了解 Cloud Storage 的访问权限控制。
- 创建短期有效的服务账号凭据。
- 使用服务器到服务器 OAuth 2.0 流程或 Service Account Credentials API 为服务账号创建 OAuth 2.0 访问令牌。
- 为用户创建 OAuth 2.0 访问令牌。
- 查看每个预定义角色中的权限。
- 了解自定义角色。