首页 > 解决方案 > 使用为其他服务返回的 JWT 时,Cloud Run 服务请求总是失败并返回 401。相同的请求适用于为最终用户返回的 JWT

问题描述

我有一个由多个Cloud Run Services组成的应用程序。每个服务只对一组特定的其他服务开放。

假设我有 2 个带有 URLhttps://api-service-123.run.apphttps://data-provider-service-123.run.app. 第一个服务也有一个自定义 URL https://api.my.domain

api-service需要访问data-provider-service。因此,按照文档,我创建了两个按服务用户管理的服务帐户api-service-account@domaindata-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。

这周我一直在尝试解决这个问题。我反复检查了权限,多次重新部署服务,但没有任何帮助。

标签: jwtgoogle-cloud-rungoogle-cloud-iam

解决方案


在询问计算元数据服务器时,我将目标服务URL 中的http 更改为 http ,看起来它解决了问题。使用google-auth-library请求这样的令牌仍然失败,并出现 403 错误

如果解决方案是可持续的,我将更新该答案。


推荐阅读