如何从GoogleCredentials获取projectId?

时间:2019-05-02 21:29:24

标签: python google-compute-engine google-cloud-dataproc

使用Python,我想获得Google Cloud上所有Dataproc集群的列表。

我将服务帐户凭据存储在JSON密钥文件中,该文件的位置由env var GOOGLE_APPLICATION_CREDENTIALS引用。这是我到目前为止的代码:

import os
import googleapiclient.discovery
from oauth2client.client import GoogleCredentials


def build_dataproc_service(credentials):
    return googleapiclient.discovery.build("dataproc", "v1", credentials=credentials)


def list_clusters():
    credentials = GoogleCredentials.get_application_default()
    dataproc = build_dataproc_service(credentials)
    clusters = dataproc.projects().regions().clusters().list(projectId="my-project", region="REGION").execute()
    return clusters


if __name__ == "__main__":
    list_clusters()

如您所见,我已经对projectId("my-project")进行了硬编码。鉴于projectId存在于JSON密钥文件中,我希望我可以通过查询credentials对象的属性来获取它,但是不存在这样的属性。 projectId 确实嵌入在credentials._service_account_email字符串属性中,但是从那里提取它很笨拙,感觉不对。

我认为必须有更好的方法。如何获取服务帐户所在项目的projectId?

请注意,最初我打算将此代码在Google Compute Engine实例上的docker容器中运行,但是将来有一天我可能想在GKE上运行。不确定是否会影响答案。

5 个答案:

答案 0 :(得分:3)

我认为客户端代码不应从GoogleCredentials中提取项目ID。请参见API doc中的此代码段。

AssetManager assets = controls.activity.getAssets();
InputStream in = assets.open("sub/file.txt");

您也许可以从from googleapiclient.discovery import build from oauth2client.client import GoogleCredentials credentials = GoogleCredentials.get_application_default() service = build('compute', 'v1', credentials=credentials) PROJECT = 'bamboo-machine-422' ZONE = 'us-central1-a' request = service.instances().list(project=PROJECT, zone=ZONE) response = request.execute() print(response) 推断出项目ID,但这并不可靠。另外,项目A中的服务帐户未绑定到该项目,它可能还具有其他项目的权限。

答案 1 :(得分:3)

对此进行正式思考的方式是,虽然projectId有时是服务帐户的属性,但projectId通常不是长期存在的凭据的属性。 。例如,考虑一下您用于gcloud CLI(如果有)与您的Google帐户/电子邮件地址相关联的离线安装的个人证书。该电子邮件身份不会驻留在任何云项目中,但可以用于派生GoogleCredential对象。

从技术上讲,如果您想“正确”地进行操作,则需要一个主服务帐户,该帐户必须拥有所有计划容纳实际使用的服务帐户的项目中的GET服务帐户描述,并且然后在服务帐户的电子邮件地址而非“凭据”对象上调用IAM API的projects.serviceAccounts.get。那里的响应可以标识服务帐户所在的项目ID。这等效于gcloud命令:

gcloud iam service-accounts describe my-service-account@projectid.iam.gserviceaccount.com

但是,正如大港所说,从长远来看,通常会事与愿违,以至于假设服务帐户仅用于其所在项目的操作,就开始烘烤。特别是,尽管service account资源本身位于项目内部,但它们通常以跨项目的方式使用。一种常见的操作模式是使用单个GCP项目来管理大量服务帐户,然后为这些帐户授予对其他GCP项目中的资源的各种细粒度访问。

答案 2 :(得分:1)

服务帐户凭据.json包含project_id,因此您可以执行以下操作:

# If this is running in a cloud function, then GCP_PROJECT should be defined
if 'GCP_PROJECT' in os.environ:
    project_id = os.environ['GCP_PROJECT']

# else if this is running locally then GOOGLE_APPLICATION_CREDENTIALS should be defined
elif 'GOOGLE_APPLICATION_CREDENTIALS' in os.environ:
    with open(os.environ['GOOGLE_APPLICATION_CREDENTIALS'], 'r') as fp:
        credentials = json.load(fp)
    project_id = credentials['project_id']
else:
    raise Exception('Failed to determine project_id')

答案 3 :(得分:0)

从UnderlyingingCredential中获取ProjectId

var credential = GoogleCredential.FromFile(googleCredentialPath);
var projectId = ((Google.Apis.Auth.OAuth2.ServiceAccountCredential)credential.UnderlyingCredential).ProjectId;

答案 4 :(得分:0)

在 C# 中

var credentials = GoogleCredential.GetApplicationDefault();
var projectId = (credentials.UnderlyingCredential as dynamic).ProjectId as string;