可以使用 GKE Workload Identity 访问 Google 表格吗?

Posted

技术标签:

【中文标题】可以使用 GKE Workload Identity 访问 Google 表格吗?【英文标题】:Can GKE Workload Identity be used to access Google Sheets? 【发布时间】:2020-07-29 00:21:34 【问题描述】:

我目前正在使用 GKE Workload Identity 从 GKE 中访问 Google Cloud Platform 资源。这非常适用于 Google Cloud Storage 和其他平台资源。

但是,当我尝试使用 GKE Workload Identity 访问 Google 表格时,我遇到了“身份验证范围不足”的问题。

当我为服务帐户生成一个密钥文件并在我的代码中使用它时,我可以手动将范围设置为https://www.googleapis.com/auth/spreadsheets。它按预期工作,我可以访问工作表。如果我将范围更改为 https://www.googleapis.com/auth/cloud-platform,我会收到与 GKE Workload Identity 相同的错误“身份验证范围不足”。此结果表明服务帐户工作正常,因此问题似乎与分配给 GKE 工作负载标识的范围有关。

使用 GKE Workload Identity,我在 Python 中使用credentials = google.auth.default() [1] 检索凭据。 credentials 对象具有预期的服务帐户,并且范围设置为 https://www.googleapis.com/auth/cloud-platform。我现在可以访问服务帐户有权访问的存储桶和其他云资源。然而,谷歌表格似乎需要https://www.googleapis.com/auth/spreadsheets 范围,但我还没有找到任何方法来设置它。从 GKE 集群中运行的 GKE 元数据服务器检索工作负载身份(服务帐户)和范围。据我所知,GKE 工作负载标识的范围似乎被“硬编码”为https://www.googleapis.com/auth/cloud-platform。我没有找到有关这是否可以更改的信息。

(我尝试将电子表格范围添加到 GKE 节点 oauth 范围。没有效果。根据我从文档中可以理解的内容,它应该是不相关的。)

(当然我可以只使用密钥文件来完成这项工作,但 GKE 工作负载身份的全部意义在于避免安全地生成和分发密钥的所有麻烦)

[1]User Guide — google-auth 1.6.2 documentation

【问题讨论】:

我遇到了完全相同的问题。你有没有机会解决它? 我三个。请谷歌员工帮助我们 【参考方案1】:

根据google-auth 指南,您是这样设置电子表格范围的吗?

credentials, project = google.auth.default(
    scopes=['https://www.googleapis.com/auth/spreadsheets'])

我在使用默认客户端时看到了一些相同的行为,但在使用 curl 进行测试时,我使用 Workload Identity 确实取得了一些成功。

我们可以在测试 pod 上使用 curl 执行流程(例如,部署一个 ubuntu pod 并安装 curl)。您应该能够通过 curl gke-metadata-server 在 GKE pod 上验证作用域令牌是否按预期运行:

$ curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token?scopes=https%3A//www.googleapis.com/auth/spreadsheets%20

然后我们可以像这样使用在对工作表 API 的请求中返回的令牌,假设我们已经设置了 ACCESS_TOKENSPREADSHEET_ID 环境变量:

$ curl -X GET -H "Authorization: Bearer $ACCESS_TOKEN" https://sheets.googleapis.com/v4/spreadsheets/$SPREADSHEET_ID

这将返回有关您的工作表的所有信息,而不是 403 错误。

我相信这是客户端库应该在幕后做的事情,但这里可能存在一些错误。


这是一个运行在 GKE pod 上并配置了 Workload Identity 的 go 应用的工作示例(服务帐户已被授予查看工作表 ID 的访问权限)。

go.mod

module example.com/m
  
go 1.13

require (
        golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
        google.golang.org/api v0.48.0
)

main.go:

package main
  
import (
        "fmt"
        "golang.org/x/oauth2"
        "golang.org/x/oauth2/google"
        "google.golang.org/api/sheets/v4"
)

func main() 
        client, err := google.DefaultClient(oauth2.NoContext, sheets.SpreadsheetsScope)
        if err != nil 
                panic(err)
        
        srv, err := sheets.New(client)
        if err != nil 
                panic(err)
        
        resp, err := srv.Spreadsheets.Values.Get("REPLACE_WITH_YOUR_SHEET_ID", "REPLACE_WITH_YOUR_RANGE").Do()
        if err != nil 
                panic(err)
        
        fmt.Println(fmt.Sprintf("%+v", resp.Values))


FWIW 我注意到使用旧版本的 oauth2 库肯定不适用于 Workload Identity 和范围。更新以使用较新的版本解决了这个问题。

【讨论】:

我试过你的 curl 命令,但我得到了401: Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. @RutgerdeKnijf 哪个 CURL 命令返回了那个?我假设您将第一个 CURL 命令返回的 BEARER 令牌传递给第二个? 是的,你的假设是正确的。我传递了令牌,但请求(到 sheets.googleapis.com)返回了 401。 更新 google-api-client 库版本为我解决了这个问题(使用 Ruby)【参考方案2】:

是的,你可以。我无法重现您的问题,因为这(现在)可以正常工作:

import google
from googleapiclient.discovery import build

SHEET_ID = '<your_sheet_id>'
RANGE = 'Sheet1!A:Z'

credentials, project_name = google.auth.default()

service = build('sheets', 'v4', credentials=credentials).spreadsheets()

result = service.values().get(spreadsheetId=SHEET_ID, range=RANGE).execute()

print(result)  # prints out the data in the sheet

这是在运行 v1.20.10-gke.1600 的自动驾驶仪集群上测试的,WLI 设置在 default KSA 上,相应的 GSA 电子邮件在工作表上添加为 Viewer

请注意,我什至没有设置任何范围。 你会认为这是必需的:

google.auth.default(scopes=['https://www.googleapis.com/auth/spreadsheets'])`

但完全忽略:credentials.scopes = None

【讨论】:

以上是关于可以使用 GKE Workload Identity 访问 Google 表格吗?的主要内容,如果未能解决你的问题,请参考以下文章