云 运行:服务到服务 401,而 curl 工作
Cloud Run: Service-to-Service 401 while curl works
这是我几天来一直在努力解决的问题。
我的云 运行 应用程序的服务到服务通信总是导致 401。
对于服务中的令牌检索,我一直在使用以下代码片段:
tokenURL := fmt.Sprintf("/instance/service-accounts/default/identity?audience=%s", c.serviceURL)
var err error
token, err = metadata.Get(tokenURL)
if err != nil {
return nil, fmt.Errorf("metadata.Get: failed to query id_token: %+v", err)
}
我也曾尝试向我的 Cloud 运行 服务提供 Service account key
,但使用从 google.JWTAccessTokenSourceFromJSON
返回的令牌无济于事。
问题是返回的 JWT 在从 cURL 使用时确实有效,但在云 运行 上的 运行 服务中使用时无效。
云 运行 服务帐户和外部服务帐户(用于密钥)都具有 roles/run.invoker
IAM 绑定。而观众是云运行发布的服务URL.
我尝试了以下方法:
- 使用元数据服务进行令牌检索(Cloud 运行 中的 401,但在 cURL 和 Postman 中使用令牌时有效)
- 使用 JWTAccessTokenSourceFromJSON 进行令牌检索(Cloud 运行 中的 401,但在 cURL 和 Postman 中使用令牌时有效)
- 尝试在使用颁发的令牌之前添加延迟(以防令牌未传播)
- 尝试在延迟后使用给定的令牌手动 ping Cloud 运行 服务几次(使用
http.Client
)
似乎没有任何效果。 Cloud 运行 中 运行 时的每个请求都返回 401,并且日志显示 The request was not authorized to invoke this service. Read more at https://cloud.google.com/run/docs/securing/authenticating
。使用 cURL 或 Postman 时,我可以访问该服务。
我试过这些方法来调用服务:
tokenURL := fmt.Sprintf("/instance/service-accounts/default/identity?audience=%s", c.serviceURL)
var err error
token, err := metadata.Get(tokenURL)
if err != nil {
return nil, fmt.Errorf("metadata.Get: failed to query id_token: %+v", err)
}
// First one (ping)
req, _ := http.NewRequest("GET", "{{serviceURL}}", nil)
req.Header.Set("Authorization", "Bearer: "+token)
l, _ := cr.Do(req)
m, _ := ioutil.ReadAll(l.Body)
logrus.Println(l.Header)
logrus.Println(string(m))
// RoundTripper
r.Header.Set("Authorization", "Bearer: "+token)
return c.r.RoundTrip(r)
感谢您的回答。
谢谢!
在发布代码示例时,我刚刚意识到我在 Bearer 之后添加了一个额外的冒号 (:),这使得此请求失败。不敢相信我花了几天时间来解决这个问题!
这是我几天来一直在努力解决的问题。
我的云 运行 应用程序的服务到服务通信总是导致 401。
对于服务中的令牌检索,我一直在使用以下代码片段:
tokenURL := fmt.Sprintf("/instance/service-accounts/default/identity?audience=%s", c.serviceURL)
var err error
token, err = metadata.Get(tokenURL)
if err != nil {
return nil, fmt.Errorf("metadata.Get: failed to query id_token: %+v", err)
}
我也曾尝试向我的 Cloud 运行 服务提供 Service account key
,但使用从 google.JWTAccessTokenSourceFromJSON
返回的令牌无济于事。
问题是返回的 JWT 在从 cURL 使用时确实有效,但在云 运行 上的 运行 服务中使用时无效。
云 运行 服务帐户和外部服务帐户(用于密钥)都具有 roles/run.invoker
IAM 绑定。而观众是云运行发布的服务URL.
我尝试了以下方法:
- 使用元数据服务进行令牌检索(Cloud 运行 中的 401,但在 cURL 和 Postman 中使用令牌时有效)
- 使用 JWTAccessTokenSourceFromJSON 进行令牌检索(Cloud 运行 中的 401,但在 cURL 和 Postman 中使用令牌时有效)
- 尝试在使用颁发的令牌之前添加延迟(以防令牌未传播)
- 尝试在延迟后使用给定的令牌手动 ping Cloud 运行 服务几次(使用
http.Client
)
似乎没有任何效果。 Cloud 运行 中 运行 时的每个请求都返回 401,并且日志显示 The request was not authorized to invoke this service. Read more at https://cloud.google.com/run/docs/securing/authenticating
。使用 cURL 或 Postman 时,我可以访问该服务。
我试过这些方法来调用服务:
tokenURL := fmt.Sprintf("/instance/service-accounts/default/identity?audience=%s", c.serviceURL)
var err error
token, err := metadata.Get(tokenURL)
if err != nil {
return nil, fmt.Errorf("metadata.Get: failed to query id_token: %+v", err)
}
// First one (ping)
req, _ := http.NewRequest("GET", "{{serviceURL}}", nil)
req.Header.Set("Authorization", "Bearer: "+token)
l, _ := cr.Do(req)
m, _ := ioutil.ReadAll(l.Body)
logrus.Println(l.Header)
logrus.Println(string(m))
// RoundTripper
r.Header.Set("Authorization", "Bearer: "+token)
return c.r.RoundTrip(r)
感谢您的回答。
谢谢!
在发布代码示例时,我刚刚意识到我在 Bearer 之后添加了一个额外的冒号 (:),这使得此请求失败。不敢相信我花了几天时间来解决这个问题!