是否有一种方法可以在没有设置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,并且不使用gcloud
SDK,如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?
结论:
else:
分支根本不适合user account
——user account
的结果是exception
。else:
支路用于Application Default Credential
(ADC)。