繁体   English   中英

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

[英]Programmatically get current Service Account on GCP

当没有设置GOOGLE_APPLICATION_CREDENTIALS时,有没有办法以编程方式访问 GCP 实例上当前使用的服务帐户的 email? (即使用默认服务帐户时)

我查看了 GCP 文档,但我发现的唯一资源在未设置GOOGLE_APPLICATION_CREDENTIALS时无法与默认服务帐户一起使用。 我知道可以使用gcloud这样做(请参阅此 SO 问题文档),但是这些解决方案在ContainerOptimisedOS上运行时不适用。 我已经与 GCP 支持团队来回交流了几周,但他们最终无法帮助我,并将我重定向到 Stack Overflow 寻求帮助。

John 的解决方案适用于任何语言,无需任何外部库。 但是,当部署了元数据服务器时,它仅适用于 Google Cloud 环境。 您无法在计算机上执行此测试。

我建议只使用一段 Python 代码(使用 Google OAuth 库,但它适用于具有该库的其他语言)来询问库当前的凭证。 如果凭据是服务帐户(来自计算机上的 GOOGLE_APPLICATION_CREDENTIALS、ADC(应用程序默认凭据)或元数据服务器),则您打印了 email,否则,您会收到警告消息,因为您使用了用户帐户凭据

    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而不是整个 email 地址。


编辑 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?")
    }

只是添加到已接受的答案中。 如答案中所述,这似乎返回“默认”:

import google.auth

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

我发现要获取当前活动的 GSA 的 email 名称(通过元数据 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。 我认为可能存在竞争条件,我正在尝试在 pod 启动时第一次初始化 creds 之前读取service_account_email属性?

调用refresh()时会调用_retrieve_info() function,看起来这是获取 email 名称的 function。

如果我让我的脚本在启动时休眠几秒钟, service_account_email最终会填充 GSA 的 email 名称,或者直到您手动刷新或初始化客户端 API 或其他什么时才会发生这种情况?

如果您有兴趣获得确切的 email 而不仅仅是“默认”别名(当您使用计算引擎时),您可以使用凭证元数据获取它。 这对于确定 AI Platform 作业正在使用哪个服务帐户特别有用。

    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.")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM