在Cloud Run中使用默认凭据进行域范围委派

huangapple go评论79阅读模式
英文:

Domain wide delegation with default credentials in Cloud Run

问题

在golang中,我想使用Cloud Run提供的默认服务帐号凭据来创建委派凭据(域范围委派),具体来说是以用户身份调用Drive API。当凭据从JSON文件获取时,我已经成功实现了这一点,但是当凭据由Cloud Run提供时却没有成功。我在Python中遇到了同样的问题,并按照这个示例解决了它,但是我不确定如何在go中实现。

以下是一个示例代码(gin处理程序),当从JSON文件加载时可以工作(具有域范围委派的服务帐号密钥),但是当从Cloud Run派生凭据时无法工作:

email := "user@mydomain.com"
params := google.CredentialsParams{
    Scopes:  []string{"https://www.googleapis.com/auth/drive.readonly"},
    Subject: email}
creds, credErr := google.FindDefaultCredentialsWithParams(c, params)
if credErr != nil {
    msg := fmt.Sprintf("Unable to create credentials as %v: %v", email, credErr)
    fmt.Println(msg)
    c.String(http.StatusInternalServerError, msg)
    return
}

// CREATE DRIVE SERVICE
client := oauth2.NewClient(c, creds.TokenSource)
driveService, driveErr := drive.NewService(c, option.WithHTTPClient(client))
if driveErr != nil {
    msg := fmt.Sprintf("Unable to retrieve Drive client: %v", driveErr)
    fmt.Println(msg)
    c.String(http.StatusInternalServerError, msg)
    return
}

// List Files
r, listErr := driveService.Files.List().PageSize(10).Do()
if listErr != nil {
    log.Fatal(listErr)
}
fmt.Printf("Received %v files\n", len(r.Files))
for _, i := range r.Files {
    fmt.Println(i.Name)
}
c.String(http.StatusOK, "Ok")
return

当我从JSON文件运行时,它会列出来自user@mydomain.com的十个文件名。当我在Cloud Run中运行时(不在容器中包含JSON文件),它找不到任何文件,我认为这是因为凭据不是用户凭据,而是没有访问任何文件权限的服务帐号凭据。

英文:

In golang I'd like to use default service account credentials provided by Cloud Run to create delegated credentials (domain-wide delegation), specifically to invoke the Drive API as the user. I've got this working when the credentials are obtained from a json file, but not when provided by Cloud Run. I had the same problem in Python and followed this example to solve it, but am not sure how to do this in go.

Code example (gin handler) that works when loading from JSON file (service account key with domain-wide delegation) but not when deriving credentials from Cloud Run:

email := "user@mydomain.com"
params := google.CredentialsParams{
	Scopes:  []string{"https://www.googleapis.com/auth/drive.readonly"},
	Subject: email}
creds, credErr := google.FindDefaultCredentialsWithParams(c, params)
if credErr != nil {
	msg := fmt.Sprintf("Unable to create credentials as %v: %v", email, credErr)
	fmt.Println(msg)
	c.String(http.StatusInternalServerError, msg)
	return
}

// CREATE DRIVE SERVICE
client := oauth2.NewClient(c, creds.TokenSource)
driveService, driveErr := drive.NewService(c, option.WithHTTPClient(client))
if driveErr != nil {
	msg := fmt.Sprintf("Unable to retrieve Drive client: %v", driveErr)
	fmt.Println(msg)
	c.String(http.StatusInternalServerError, msg)
	return
}

// List Files
r, listErr := driveService.Files.List().PageSize(10).Do()
if listErr != nil {
	log.Fatal(listErr)
}
fmt.Printf("Received %v files\n", len(r.Files))
for _, i := range r.Files {
	fmt.Println(i.Name)
}
c.String(http.StatusOK, "Ok")
return

When I run this from JSON file, it lists the ten file names from user@mydomain.com. When I run this in Cloud Run (without including the JSON file in the container), it doesn't find any files, and I believe this is because the credentials are not user credentials, but rather service account credentials without access to any files.

答案1

得分: 2

要在没有服务帐号密钥的情况下使用域范围委派,您需要执行以下步骤:

  1. 创建一个JWT断言,用于模拟用户身份。具体步骤可以参考此链接
  2. 调用配置了域范围委派的服务帐号上的projects.serviceAccounts.signJwt接口,对断言进行签名。更多信息可以参考此链接
  3. 使用签名后的断言来交换访问令牌。

有关更多详细信息,您可以参考这篇博文这个问题

英文:

To use domain-wide delegation without a service account key you have to:

  1. Create a JWT assertion for impersonating a user
  2. Call projects.serviceAccounts.signJwt on a service account that's configured for domain-wide delegation to sign the assertion
  3. Exchange the signed assertion against an access token

This blog post and this question have more details.

huangapple
  • 本文由 发表于 2022年10月10日 22:25:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/74016443.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定