使用服务帐户验证客户端对 Golang 中 Cloud Function 的调用
Authenticate client call to Cloud Function in Golang using service account
我将自己的云函数部署到 GCP。在云功能上,我启用了使用 Google 服务帐户进行身份验证。我需要编写一个 Golang 代码来调用这个云函数。我用 Nodejs 做了同样的事情,但是不能让 Golang 工作。
这是我的 Nodejs 代码(有效):
const {GoogleAuth} = require('google-auth-library');
const targetAudience = "cloud-function-url"
async function run() {
const auth = new GoogleAuth();
const client = await auth.getIdTokenClient(targetAudience);
const res = await client.request({ url });
console.info(res.data);
}
我的 Golang 代码:
import "golang.org/x/oauth2/google"
func getToken() (err error) {
scope := "https://www.googleapis.com/auth/cloud-platform"
client, err := google.DefaultClient(context.Background(), scope)
if err != nil {
return
}
res, err := client.Get("cloud-function-url")
if err != nil {
return
}
fmt.Println(res)
return
}
我也试过自定义代码添加targetAudience
,但是也没用
baseUrl := "your-cloudfunction-baseurl"
ctx := context.Background()
targetAudience := baseUrl
credentials, err := google.FindDefaultCredentials(ctx)
if err != nil {
fmt.Printf("cannot get credentials: %v", err)
os.Exit(1)
}
tokenSrc, err := google.JWTAccessTokenSourceFromJSON(credentials.JSON, targetAudience)
if err != nil {
fmt.Printf("cannot create jwt source: %v", err)
os.Exit(1)
}
client := oauth2.NewClient(context.Background(), tokenSrc)
if err != nil {
return
}
res, err := client.Get(baseUrl + "sub-url")
if err != nil {
return
}
我已经检查并确保我的服务帐户已正确加载。在上述两种情况下,我都收到了 401 "The access token could not be verified"
我写了一个名为 token-generator 的开源应用程序。它在 Go 中,我生成签名身份令牌以便能够调用私有云 运行 和 Cloud Function。
随意使用它或复制您自己的应用程序所需的核心代码!如果您愿意,我们可以在这里讨论或在 GitHub 上提出问题。
深入 Google's Oauth Protocol and OAuth2 一段时间后,我发现 Golang 中的库没有完全遵循 google 的 OAuth2 协议。
- Google 规范中的流程:在 HTTP 客户端(使用服务帐户)中生成并签署 JWT --> 发送到 google 的服务器 --> 获取新的签名 JWT - -> 将新令牌用于其他请求
- Golang lib:生成并签署 JWT --> 将此令牌用于其他请求
令人惊讶的是,Nodejs 库可以正确处理流程,而 Golang 库却不能。我把我的调查总结成blog post。
对于那些想要简短回答的人,这是我的实现(我将一些部分移到了 public 存储库中):
import (
"context"
"fmt"
"io/ioutil"
"os"
"github.com/CodeLinkIO/go-cloudfunction-auth/cloudfunction"
"golang.org/x/oauth2/google"
)
func main() {
baseUrl := "your-cloudfunction-baseurl"
ctx := context.Background()
targetAudience := baseUrl
credentials, err := google.FindDefaultCredentials(ctx)
if err != nil {
fmt.Printf("cannot get credentials: %v", err)
os.Exit(1)
}
jwtSource, err := cloudfunction.JWTAccessTokenSourceFromJSON(credentials.JSON, targetAudience)
if err != nil {
fmt.Printf("cannot create jwt source: %v", err)
os.Exit(1)
}
client := cloudfunction.NewClient(jwtSource)
res, err := client.Get(baseUrl + "/cloudfunction-sub-page")
if err != nil {
fmt.Printf("cannot fetch result: %v", err)
os.Exit(1)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Printf("cannot read response: %v", err)
os.Exit(1)
}
println(string(body))
}
我将自己的云函数部署到 GCP。在云功能上,我启用了使用 Google 服务帐户进行身份验证。我需要编写一个 Golang 代码来调用这个云函数。我用 Nodejs 做了同样的事情,但是不能让 Golang 工作。
这是我的 Nodejs 代码(有效):
const {GoogleAuth} = require('google-auth-library');
const targetAudience = "cloud-function-url"
async function run() {
const auth = new GoogleAuth();
const client = await auth.getIdTokenClient(targetAudience);
const res = await client.request({ url });
console.info(res.data);
}
我的 Golang 代码:
import "golang.org/x/oauth2/google"
func getToken() (err error) {
scope := "https://www.googleapis.com/auth/cloud-platform"
client, err := google.DefaultClient(context.Background(), scope)
if err != nil {
return
}
res, err := client.Get("cloud-function-url")
if err != nil {
return
}
fmt.Println(res)
return
}
我也试过自定义代码添加targetAudience
,但是也没用
baseUrl := "your-cloudfunction-baseurl"
ctx := context.Background()
targetAudience := baseUrl
credentials, err := google.FindDefaultCredentials(ctx)
if err != nil {
fmt.Printf("cannot get credentials: %v", err)
os.Exit(1)
}
tokenSrc, err := google.JWTAccessTokenSourceFromJSON(credentials.JSON, targetAudience)
if err != nil {
fmt.Printf("cannot create jwt source: %v", err)
os.Exit(1)
}
client := oauth2.NewClient(context.Background(), tokenSrc)
if err != nil {
return
}
res, err := client.Get(baseUrl + "sub-url")
if err != nil {
return
}
我已经检查并确保我的服务帐户已正确加载。在上述两种情况下,我都收到了 401 "The access token could not be verified"
我写了一个名为 token-generator 的开源应用程序。它在 Go 中,我生成签名身份令牌以便能够调用私有云 运行 和 Cloud Function。
随意使用它或复制您自己的应用程序所需的核心代码!如果您愿意,我们可以在这里讨论或在 GitHub 上提出问题。
深入 Google's Oauth Protocol and OAuth2 一段时间后,我发现 Golang 中的库没有完全遵循 google 的 OAuth2 协议。
- Google 规范中的流程:在 HTTP 客户端(使用服务帐户)中生成并签署 JWT --> 发送到 google 的服务器 --> 获取新的签名 JWT - -> 将新令牌用于其他请求
- Golang lib:生成并签署 JWT --> 将此令牌用于其他请求
令人惊讶的是,Nodejs 库可以正确处理流程,而 Golang 库却不能。我把我的调查总结成blog post。
对于那些想要简短回答的人,这是我的实现(我将一些部分移到了 public 存储库中):
import (
"context"
"fmt"
"io/ioutil"
"os"
"github.com/CodeLinkIO/go-cloudfunction-auth/cloudfunction"
"golang.org/x/oauth2/google"
)
func main() {
baseUrl := "your-cloudfunction-baseurl"
ctx := context.Background()
targetAudience := baseUrl
credentials, err := google.FindDefaultCredentials(ctx)
if err != nil {
fmt.Printf("cannot get credentials: %v", err)
os.Exit(1)
}
jwtSource, err := cloudfunction.JWTAccessTokenSourceFromJSON(credentials.JSON, targetAudience)
if err != nil {
fmt.Printf("cannot create jwt source: %v", err)
os.Exit(1)
}
client := cloudfunction.NewClient(jwtSource)
res, err := client.Get(baseUrl + "/cloudfunction-sub-page")
if err != nil {
fmt.Printf("cannot fetch result: %v", err)
os.Exit(1)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Printf("cannot read response: %v", err)
os.Exit(1)
}
println(string(body))
}