Google Cloud Tasks 无法通过 Cloud Run 进行身份验证

bar*_*man 9 service-accounts google-cloud-tasks google-cloud-run

我正在尝试使用 Cloud Tasks 调用 Cloud Run 服务,如此处文档中所述。

我有一个正在运行的 Cloud Run 服务。如果我公开该服务,它就会按预期运行。

我创建了一个云队列,并使用本地脚本安排云任务。这个是用我自己的账号。脚本看起来像这样

from google.cloud import tasks_v2

client = tasks_v2.CloudTasksClient()

project = 'my-project'
queue = 'my-queue'
location = 'europe-west1'
url = 'https://url_to_my_service'

parent = client.queue_path(project, location, queue)

task = {
        'http_request': {
            'http_method': 'GET',
            'url': url,
            'oidc_token': {
               'service_account_email': 'my-service-account@my-project.iam.gserviceaccount.com'
            }
        }
}

response = client.create_task(parent, task)
print('Created task {}'.format(response.name))
Run Code Online (Sandbox Code Playgroud)

我看到该任务出现在队列中,但它失败并立即重试。其原因(通过检查日志)是 Cloud Run 服务返回 401 响应。

我自己的用户具有“服务帐户令牌创建者”和“服务帐户用户”角色。它没有明确的“云任务入队”,但由于我能够在队列中创建任务,我想我已经继承了所需的权限。服务帐户“my-service-account@my-project.iam.gserviceaccount.com”(我在任务中使用它来获取 OIDC 令牌)具有以下角色:

  • 云任务入队(尽管我认为它不需要这个,因为我正在使用自己的帐户创建任务)
  • 云任务任务运行器
  • 云任务查看器
  • 服务帐户令牌创建者(我不确定是否应将其添加到我自己的帐户(安排任务的帐户)或应添加到应执行对 Cloud Run 的调用的服务帐户)
  • 服务帐户用户(此处相同)
  • 云运行调用者

所以我做了一个肮脏的伎俩:我为服务帐户创建了一个密钥文件,将其下载到本地,并通过使用密钥文件将帐户添加到我的 gcloud 配置来模拟本地。接下来,我跑

curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://url_to_my_service
Run Code Online (Sandbox Code Playgroud)

这样可行!(顺便说一句,当我切换回自己的帐户时它也有效)

oidc_token最终测试:如果我在创建任务时从任务中删除,我会从 Cloud Run 收到 403 响应!不是 401...如果我从服务帐户中删除“Cloud Run Invoker”角色并在本地使用curl 重试,我也会得到 403 而不是 401。

如果我最终公开了 Cloud Run 服务,一切都会正常。

因此,Cloud Task 似乎无法为服务帐户生成令牌,以便在 Cloud Run 服务上正确进行身份验证。

我缺少什么?

tea*_*uit 10

我在这里遇到了同样的问题,这是我的修复:

诊断:生成OIDC token目前不支持audience参数中自定义域。我为我的云运行服务 ( https://my-service.my-domain.com )使用自定义域,而不是云运行生成的 url(在云运行服务仪表板中找到),如下所示:https://XXXXXX.run.app

屏蔽行为:在排队到 Cloud Tasks 的任务中,如果audience未显式设置 oidc_token 字段,则使用任务中的目标 urlaudience在请求中设置 OIDC 令牌。

就我而言,这意味着将要发送到目标https://my-service.my-domain.com/resource受众以生成 OIDC 令牌的任务排队到我的自定义域https://my-service.my-domain.com/resource。由于生成 OIDC 令牌时不支持自定义域,因此我收到了401 not authorized来自目标服务的响应。

我的修复方法:使用 Cloud Run 生成的 URL 显式填充受众,以便颁发有效令牌。在我的客户端中,我能够使用基本 url: 全局设置针对给定服务的所有任务的受众'audience' : 'https://XXXXXX.run.app'。这生成了一个有效的令牌。我不需要更改目标资源本身的 url。资源保持不变:'url' : 'https://my-service.my-domain.com/resource'

更多阅读: 我之前在设置服务到服务身份验证时遇到过这个问题:Google Cloud Run 身份验证服务到服务


bar*_*man 2

第二天我就无法再重现这个问题了。我可以通过删除 Cloud Run Invoker 角色来重现 403 响应,但我不再收到与昨天代码完全相同的 401 响应。我想这是谷歌方面的暂时问题?

另外,我注意到更新的政策实际到位需要一些时间(1 到 2 分钟)。