以编程方式在GCP上获取当前服务帐户



是否有一种方法可以在没有设置GOOGLE_APPLICATION_CREDENTIALS时以编程方式访问GCP实例上当前使用的服务帐户的电子邮件?(即。(当使用默认服务帐户时)

我已经查看了GCP文档,但是当没有设置GOOGLE_APPLICATION_CREDENTIALS时,我发现的唯一资源不能与默认服务帐户一起使用。我知道可以使用gcloud(参见此so问题或文档),但是这些解决方案在ContainerOptimisedOS上运行时不适用。我花了几个星期的时间来来回回与GCP支持团队联系,但他们的结论是无法帮助我,并将我转到Stack Overflow寻求帮助。

John的解决方案在没有任何外部库的任何语言上都非常有效。但是,它只能在部署了元数据服务器的Google Cloud环境中工作。您无法在您的计算机上执行此测试。

我建议在下面写一段Python代码(使用Google OAuth库,但它可以在其他有这个库的语言中工作)来询问库当前的凭据。如果凭据是一个服务帐户(来自您计算机上的GOOGLE_APPLICATION_CREDENTIALS、ADC(应用程序默认凭据)或元数据服务器),则打印电子邮件,否则,您将收到警告消息,因为您使用了您的用户帐户凭据

import google.auth
credentials, project_id = google.auth.default()
if hasattr(credentials, "service_account_email"):
print(credentials.service_account_email)
else:
print("WARNING: no service account credential. User account credential?")

请注意,如果使用默认服务帐户,此方法将打印default而不是整个电子邮件地址。


编辑1

ctx := context.Background()
credential,err := google.FindDefaultCredentials(ctx)
content := map[string]interface{}{}
json.Unmarshal(credential.JSON,&content)
if content["client_email"] != nil {
fmt.Println(content["client_email"])
} else {
fmt.Println("WARNING: no service account credential. User account credential?")
}

只是添加到接受的答案。正如答案中所述,这似乎返回"default":

import google.auth
credentials, project_id = google.auth.default()
# returns "default"
print(credentials.service_account_email) 

我发现要获得GSA当前活动的电子邮件名称(通过元数据api),我必须先手动刷新:

import google.auth
import google.auth.transport.requests
credentials, project_id = google.auth.default()
request = google.auth.transport.requests.Request()
credentials.refresh(request=request)
# returns "mygsa@myproject.iam.gserviceaccount.com"
print(credentials.service_account_email) 

我正在使用工作负载ID。我想也许有一个竞争条件,我试图读取service_account_email属性之前的信用得到初始化的第一次当pod启动。

refresh()被调用时,_retrieve_info()函数被调用,看起来这是抓取电子邮件名称的函数。

如果我让我的脚本在启动时睡眠几秒钟,我想知道service_account_email最终是否会被GSA的电子邮件名称填充。

查询GCP元数据服务器应该在任何GCP计算实例上工作,包括ContainerOptimisedOS,并且不使用gcloudSDK,如OP所要求的

的例子:

curl --header "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email"

如果你对确切的电子邮件感兴趣,而不仅仅是"默认"别名(当您使用计算引擎时),您可以使用凭据元数据获取它。这在确定AI平台作业正在使用哪个服务帐户时特别有用。

import google.auth
from google.auth.transport.requests import Request
from google.auth.compute_engine import _metadata

if hasattr(credentials, "service_account_email"):
print(credentials.service_account_email)
# edits made on top of the top answer's code
info = _metadata.get_service_account_info(Request(),
service_account=credentials.service_account_email)
print(f"Service account email: {info.email}")
print(f"Service account aliases: {info.aliases}")
print(f"Service account scopes: {info.scopes}")
else:
print("WARNING: no service account credentials available.")

进一步探索Guillaume Blaquiere发布的Python代码片段…

我相信如果我们提供个人用户帐户,代码将抛出Exception而不是去else:分支。下面是演示设置:

$ python -V
Python 3.8.10

$ pip list | grep google
google-auth    2.14.0

$ gcloud config get-value account
...
xxx@xxx.com  <==== My individual (personal) email address

$ env | grep GOOGLE_APPLICATION_CREDENTIALS
<==== Nothing, meaning this env var isn't set.

## I don't have the following file which means
## that I did NOT do `gcloud auth application-default login`
$ ls -l ~/.config/gcloud/application_default_credentials.json
ls: /Users/vyin/.config/gcloud/application_default_credentials.json: No such file or directory

$ cat test.py
import google.auth
credentials, project_id = google.auth.default()
if hasattr(credentials, "service_account_email"):
print(credentials.service_account_email)
else:
print("WARNING: no service account credential. User account credential?")

现在测试一下:

## Throws an Exception as I believe it should.
$ python test.py
Traceback (most recent call last):
File "test.py", line 3, in <module>
credentials, project_id = google.auth.default()
File "/....../.venv/lib/python3.8/site-packages/google/auth/_default.py", line 643, in default
raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)
google.auth.exceptions.DefaultCredentialsError: 
Could not automatically determine credentials. 
Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. 
For more information, please see https://cloud.google.com/docs/authentication/getting-started

## Now create an ADC:
$ gcloud auth application-default login

## The above command created this file:
$ ls -l ~/.config/gcloud/application_default_credentials.json
-rw-------  ... Apr 12 17:48 /Users/vyin/.config/gcloud/application_default_credentials.json

## The Python code now enters the `else:` branch.
$ python test.py
WARNING: no service account credential. User account credential?

结论:

  1. else:分支根本不适合user account——user account的结果是exception
  2. else:支路用于Application Default Credential(ADC)。

相关内容

  • 没有找到相关文章

最新更新