这是我几天来一直在努力解决的问题。
对于我的云运行应用程序,服务对服务的通信总是导致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 Run服务提供Service account key
,并使用从google.JWTAccessTokenSourceFromJSON
返回的令牌,但没有成功。
问题是,返回的JWT在从cURL使用时确实有效,但在Cloud Run上运行的服务中使用时不起作用。
Cloud Run服务帐户和外部服务帐户(用于密钥(都具有roles/run.invoker
IAM绑定。受众是云运行发布的服务URL。
我尝试过以下几种:
- 使用元数据服务进行令牌检索(Cloud Run中的401,但在cURL和Postman中使用令牌时有效(
- 使用JWTAccessTokenSourceFromJSON进行令牌检索(Cloud Run中的401,但在cURL和Postman中使用令牌时有效(
- 尝试在使用已颁发的令牌之前添加延迟(以防令牌未传播(
- 尝试在延迟后使用给定令牌手动ping云运行服务几次(使用
http.Client
(
似乎什么都不起作用。在Cloud run内部运行时,每个请求都返回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后面添加了一个额外的冒号(:(,这使得这个请求失败。真不敢相信我花了好几天时间才解决这个问题!