Getting error using Google cloud client libraries for Go: unknown credential type: "impersonated_service_account"?

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

Getting error using Google cloud client libraries for Go: unknown credential type: "impersonated_service_account"?

问题

我正在使用Go语言与Google Cloud一起工作,并遵循John Hanley的这篇文章:https://www.jhanley.com/google-cloud-improving-security-with-impersonation/,并结合了这个SO答案:https://stackoverflow.com/questions/63506885/how-to-authenticate-google-apis-google-drive-api-from-google-compute-engine-an/63507265#63507265。

凭据已成功保存到"application_default_credentials.json"文件中,注意到"type": "impersonated_service_account"。

我的代码产生了一个"unknown credential type: "impersonated_service_account""错误:

package main

import (
...
    "cloud.google.com/go/storage"
	"golang.org/x/oauth2"
	"google.golang.org/api/docs/v1"
	"google.golang.org/api/drive/v3"
	"google.golang.org/api/impersonate"
	"google.golang.org/api/option"
...
)

var Config.GoogleServiceAccount string = "sa@example-2021.iam.gserviceaccount.com"

func main(){
  _ = getTokenAsImpersonator()
}

// From: https://pkg.go.dev/google.golang.org/api/impersonate#example-CredentialsTokenSource-ServiceAccount
func getTokenAsImpersonator() oauth2.TokenSource {
	ctx := context.Background()

	// Base credentials sourced from ADC or provided client options.
	ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
		TargetPrincipal: Config.GoogleServiceAccount,
		Scopes:          []string{"https://www.googleapis.com/auth/cloud-platform"},
		// Delegates: []string{"bar@project-id.iam.gserviceaccount.com"},
	})
	if err != nil {
		log.Fatal(err)
	}

	return ts
}

错误信息为'unknown credential type: "impersonated_service_account"':

google: error getting credentials using GOOGLE_APPLICATION_CREDENTIALS environment variable: unknown credential type: "impersonated_service_account"

我做错了什么还是这是一个错误?


更新

回答John在评论中的问题:

a) 环境变量GOOGLE_APPLICATION_CREDENTIALS的值是什么?

GOOGLE_APPLICATION_CREDENTIALS=/Users/x/.config/gcloud/application_default_credentials.json

b) 生成application_default_credentials.json文件时使用了什么命令?

gcloud auth application-default login --scopes=https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/accounts.reauth,openid --impersonate-service-account=[sa@example-2021.iam.gserviceaccount.com]


响应:

Credentials saved to file: [/Users/x/.config/gcloud/application_default_credentials.json]


c) 使用的操作系统和版本是什么?

MacOS 10.13.6

d) gcloud --version?

Google Cloud SDK 343.0.0
app-engine-go 
app-engine-python 1.9.91
bq 2.0.69
cloud-datastore-emulator 2.1.0
core 2021.05.27
gsutil 4.62
  1. 如果你能创建一个最小的示例...

我已经更新了上面的示例代码。

英文:

I am working with Google Cloud in Go and following this article by John Hanley:

https://www.jhanley.com/google-cloud-improving-security-with-impersonation/

and mashed it with this SO answer:

https://stackoverflow.com/questions/63506885/how-to-authenticate-google-apis-google-drive-api-from-google-compute-engine-an/63507265#63507265

The credentials are successfully saved to, "application_default_credentials.json":

Notice: "type": "impersonated_service_account"

    {
  "delegates": [],
  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/[sa@example-2021.iam.gserviceaccount.com]:generateAccessToken",
  "source_credentials": {
    "client_id": "...apps.googleusercontent.com",
    "client_secret": "...",
    "refresh_token": "...",
    "type": "authorized_user"
  },
  "type": "impersonated_service_account"
}

My code which produces an unknown credential type: "impersonated_service_account" error:

package main

import (
...
    "cloud.google.com/go/storage"
	"golang.org/x/oauth2"
	"google.golang.org/api/docs/v1"
	"google.golang.org/api/drive/v3"
	"google.golang.org/api/impersonate"
	"google.golang.org/api/option"
...
)

var Config.GoogleServiceAccount string = "sa@example-2021.iam.gserviceaccount.com"




func main(){
  _ = getTokenAsImpersonator()
}

// From: https://pkg.go.dev/google.golang.org/api/impersonate#example-CredentialsTokenSource-ServiceAccount
func getTokenAsImpersonator() oauth2.TokenSource {
	ctx := context.Background()

	// Base credentials sourced from ADC or provided client options.
	ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
		TargetPrincipal: Config.GoogleServiceAccount,
		Scopes:          []string{"https://www.googleapis.com/auth/cloud-platform"},
		// Delegates: []string{"bar@project-id.iam.gserviceaccount.com"},
	})
	if err != nil {
		log.Fatal(err)
	}

	return ts
}

The 'unknown credential type: "impersonated_service_account"' error:

google: error getting credentials using GOOGLE_APPLICATION_CREDENTIALS environment variable: unknown credential type: "impersonated_service_account"

Have I done something wrong or is this a bug?


UPDATE

Answering John's questions from the comments:

1.

a) What is the value of the environment variable GOOGLE_APPLICATION_CREDENTIALS?

GOOGLE_APPLICATION_CREDENTIALS=/Users/x/.config/gcloud/application_default_credentials.json

b) What command did you use to generate application_default_credentials.json?

gcloud auth application-default login --scopes=https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/accounts.reauth,openid --impersonate-service-account=[sa@example-2021.iam.gserviceaccount.com]


Response:

Credentials saved to file: [/Users/x/.config/gcloud/application_default_credentials.json]


c)Which OS and version?

MacOS 10.13.6

d)gcloud --version?

Google Cloud SDK 343.0.0
app-engine-go 
app-engine-python 1.9.91
bq 2.0.69
cloud-datastore-emulator 2.1.0
core 2021.05.27
gsutil 4.62
  1. If you can create a minimum example ...

I have updated the example code above.

答案1

得分: 5

在某个时候,我使用命令行界面来模拟一个账号:

gcloud config set auth/impersonate_service_account <service account>

然后,当尝试使用应用程序默认凭据命令时,它会将你的凭据与服务账号凭据包装在一起。

gcloud auth application-default login

你最终得到的文件看起来像这样:

{
  "delegates": [],
  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/example@example-project.iam.gserviceaccount.com:generateAccessToken",
  "source_credentials": {
    "client_id": "123abc.apps.googleusercontent.com",
    "client_secret": "XXXXXXXXX",
    "refresh_token": "XXXXXXXXX",
    "type": "authorized_user"
  },
  "type": "impersonated_service_account"
}

这似乎会导致与 Terraform 等第三方服务出现很多问题。

奇怪的是,Terraform 只是使用 Google SDK 进行 API 调用,所以实际上这与 Google 有关。

你需要移除模拟:

gcloud config unset auth/impersonate_service_account

然后再次运行应用程序默认凭据命令:

gcloud auth application-default login

现在,如果你检查你的文件,它应该是这样的:

{
  "client_id": "XXXXXXXXX",
  "client_secret": "XXXXXXXXX",
  "quota_project_id": "example-project",
  "refresh_token": "XXXXXXXXXX",
  "type": "authorized_user"
}

当我尝试模拟一个账号以便以服务账号而不是个人账号运行 Terraform 命令时,我遇到了同样的问题,但它不喜欢这样做。

编辑:重新阅读你的问题,听起来你和我处于同样的困境。我们想要使用服务账号而不是物理下载密钥。这甚至被 Google 提到作为最佳实践。但这样做会导致他们自己的 SDK 出现问题。

英文:

At some point I had used the CLI to impersonate an account:

gcloud config set auth/impersonate_service_account &lt;service account&gt;

Then later on when trying to use the application default credentials command it wraps your credentials with the service account credentials.

gcloud auth application-default login

What you end up with is a file that looks like this:

{
  &quot;delegates&quot;: [],
  &quot;service_account_impersonation_url&quot;: &quot;https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/example@example-project.iam.gserviceaccount.com:generateAccessToken&quot;,
  &quot;source_credentials&quot;: {
    &quot;client_id&quot;: &quot;123abc.apps.googleusercontent.com&quot;,
    &quot;client_secret&quot;: &quot;XXXXXXXXX&quot;,
    &quot;refresh_token&quot;: &quot;XXXXXXXXX&quot;,
    &quot;type&quot;: &quot;authorized_user&quot;
  },
  &quot;type&quot;: &quot;impersonated_service_account&quot;
}

This appears to cause a lot of problems with third party services such as terraform.

> What is strange is that Terraform is just making API calls to Google using Google SDKs, so really its something to do with Google.

You need to remove the impersonation:

gcloud config unset auth/impersonate_service_account

And then run the application default credential command again:

gcloud auth application-default login

Now if you check your file it should look like this:

{
  &quot;client_id&quot;: &quot;XXXXXXXXX&quot;,
  &quot;client_secret&quot;: &quot;XXXXXXXXX&quot;,
  &quot;quota_project_id&quot;: &quot;example-project&quot;,
  &quot;refresh_token&quot;: &quot;XXXXXXXXXX&quot;,
  &quot;type&quot;: &quot;authorized_user&quot;
}

I was hitting the same issue when I was trying to impersonate an account so I could run Terraform commands as a service account instead of my personal account but it doesn't like that.

EDIT: Rereading you question it sounds like you're in the same boat as me. We want to use service accounts without physically downloading the keys. This is even mentioned by Google as best practice. But doing so is causing issues with their own SDKs.

答案2

得分: 0

我在运行GCP Terraform提供程序测试时遇到了相同的问题。您可以通过设置环境变量GOOGLE_IMPERSONATE_SERVICE_ACCOUNT来指定Terraform必须模拟的服务帐号(文档)。

配置步骤:

  • export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
  • gcloud auth application-default login
英文:

I had the same issue running GCP Terraform provider tests. You can specify the Service Account Terraform have to impersonate setting the env variable GOOGLE_IMPERSONATE_SERVICE_ACCOUNT (documentation).

Configuration steps:

  • export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=SERVICE_ACCOUNT@PROJECT_ID.iam.gserviceaccount.com
  • gcloud auth application-default login

huangapple
  • 本文由 发表于 2021年6月11日 03:53:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/67927689.html
匿名

发表评论

匿名网友

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

确定