jwt - 使用为其他服务返回的 JWT 时,Cloud Run 服务请求总是失败并返回 401。相同的请求适用于为最终用户返回的 JWT
问题描述
我有一个由多个Cloud Run Services组成的应用程序。每个服务只对一组特定的其他服务开放。
假设我有 2 个带有 URLhttps://api-service-123.run.app
和https://data-provider-service-123.run.app
. 第一个服务也有一个自定义 URL https://api.my.domain
。
api-service需要访问data-provider-service。因此,按照文档,我创建了两个按服务用户管理的服务帐户api-service-account@domain和data-provider-service-account@domain。我使用Cloud Run Invoker角色将api-service-account@domain添加到data-provider-service中。
现在,我无法使用从 Google 返回的 ID 令牌访问该帐户。我尝试了几种方法。首先,我使用了来自码头的稍微调整的代码
export const getToken = async (url: string, targetAUD?: string) => {
const auth = new GoogleAuth();
const request = async () => {
if (!targetAUD) {
targetAUD = new URL(url).origin;
}
console.info(`request ${url} with target audience ${targetAUD}`);
const client = await auth.getIdTokenClient(targetAUD);
const res = await client.request({url});
console.info(res.data);
return res.data;
}
try {
return await request();
} catch (err) {
console.error(err);
}
}
当上面的函数调用 asgetToken('http://data-provider-service-123.run.app');
时,请求失败并返回 401 Unauthorized。我也尝试将其称为getToken('https://data-provider-service-123.run.app');
并得到响应403 Forbidden。对于每个此类请求,以下条目将添加到data-provider-service日志中
{
httpRequest: {9}insertId: "60fcb7e0000c12346fe37579"
logName: "projects/my-project/logs/run.googleapis.com%2Frequests"
receiveTimestamp: "2021-07-25T01:01:20.806589957Z"
resource: {2}
severity: "WARNING"
textPayload: "The request was not authorized to invoke this service. Read more at
https://cloud.google.com/run/docs/securing/authenticating"
timestamp: "2021-07-25T01:01:20.800918Z"
trace: "projects/my-project/traces/25b3c13890aad01234829711d4e9f25"
}
我还尝试通过运行curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=http://data-provider-servive-123.run.app" \ -H "Metadata-Flavor: Google"
.
当我在Cloud Shell中执行此代码时,我得到如下所示的 JWT
{
"iss": "accounts.google.com",
"azp": "123456789-9r9s1c4alg36erliucho9t52n12n6abc.apps.googleusercontent.com",
"aud": "123456789-9r9s1c4alg36erliucho9t52n12n6abc.apps.googleusercontent.com",
"sub": "106907196154567890477",
"email": "my_email@gmail.com",
"email_verified": true,
"at_hash": "dQpctkQE2Sy1as1qv_w",
"iat": 1627173901,
"exp": 1627177501,
"jti": "448d660269d4c7816ae3zd45wrt89sb9f166452dce"
}
然后我使用邮递员发出一个https://data-provider-service/get-data
带有标题的请求Authorization: "Bearer <the_jwt_from_above>"
,一切正常
但是,如果我从我的 发出相同的请求api-service
,则返回的 JWT 是
{
"aud": "http://data-provider-service-123.run.app",
"azp": "111866132465987679716",
"email": "api-service-account@domain",
"email_verified": true,
"exp": 1627179383,
"iat": 1627175783,
"iss": "https://accounts.google.com",
"sub": "111866132465987679716"
}
如果我向邮递员发出相同的请求并将此 JWT 放入 Authorization 标头中,则会返回 401 Unauthorized。
这周我一直在尝试解决这个问题。我反复检查了权限,多次重新部署服务,但没有任何帮助。
解决方案
在询问计算元数据服务器时,我将目标服务的URL 中的http 更改为 http ,看起来它解决了问题。使用google-auth-library请求这样的令牌仍然失败,并出现 403 错误。
如果解决方案是可持续的,我将更新该答案。
推荐阅读
- azure-devops - Azure Devops 权限 - 一个区域可以对一个团队可见,而对另一个团队不可见
- java - 在java中删除重复项
- android - Android Studio 错误地报告缺少清单权限
- c# - 如何在后台启动计步器服务?
- javascript - react-sortable-hoc 行不使用 arraymove 排序
- python - Python中的ffmpeg管道输入和输出
- flutter - FlutterFire DocumentSnapshot.data() 正在返回对象?
- python - 在 python 中,我可以从嵌套函数返回,直接返回浏览器吗?
- python - 如何设置条件要求以及如何一次性做出选择
- java - 查找三个二维数组的值总和最高的点