如何从 GoogleCredentials 获取 projectId?
How do I get projectId from GoogleCredentials?
使用 Python 我想获取 Google 云上所有 Dataproc 集群的列表。
我将服务帐户凭据存储在 JSON 密钥文件中,其位置由环境变量 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 上。不确定这是否会影响答案。
我认为客户端代码不应该从 GoogleCredentials 中提取项目 ID。请参阅 API doc 中的此代码片段。
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)
您或许可以从 credentials._service_account_email
推断出项目 ID,但这并不可靠。此外,项目 A 中的服务帐户未绑定到该项目,它可能还具有对其他项目的权限。
一种正式的思考方式是,虽然 projectId 有时是 服务帐户 的 属性,但 projectId 通常不是 属性长期存在的 凭据 。例如,想想您在 gcloud
CLI 中使用的离线安装的个人凭证(如果有)与您的 Google account/email 地址相关联。该电子邮件身份不在 任何 云项目中,但可用于派生 GoogleCredential 对象。
从技术上讲,如果您想这样做 "properly" 您需要一个主服务帐户,该帐户有权 GET
拥有您计划的实际服务帐户的所有项目中的服务帐户描述使用,然后在服务帐户电子邮件地址上调用 IAM API 的 projects.serviceAccounts.get,而不是在 "credential" 对象上。那里的响应可以识别服务帐户所在的项目 ID。这相当于 gcloud
命令:
gcloud iam service-accounts describe my-service-account@projectid.iam.gserviceaccount.com
然而,正如 Dagang 所说,在长期 运行 开始烘烤时,通常会适得其反,假设服务帐户将仅用于其所在项目的操作。特别是,虽然 service account
资源本身存在于项目中,但它们通常以跨项目的方式使用。一种常见的操作模式是使用单个 GCP 项目来管理大量服务帐户,然后授予这些帐户对其他 GCP 项目中资源的各种细粒度访问权限。
服务帐户凭据 .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')
从 UnderlyingCredential 获取 ProjectId
var credential = GoogleCredential.FromFile(googleCredentialPath);
var projectId = ((Google.Apis.Auth.OAuth2.ServiceAccountCredential)credential.UnderlyingCredential).ProjectId;
在 C# 中
var credentials = GoogleCredential.GetApplicationDefault();
var projectId = (credentials.UnderlyingCredential as dynamic).ProjectId as string;
使用 Python 我想获取 Google 云上所有 Dataproc 集群的列表。
我将服务帐户凭据存储在 JSON 密钥文件中,其位置由环境变量 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 上。不确定这是否会影响答案。
我认为客户端代码不应该从 GoogleCredentials 中提取项目 ID。请参阅 API doc 中的此代码片段。
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)
您或许可以从 credentials._service_account_email
推断出项目 ID,但这并不可靠。此外,项目 A 中的服务帐户未绑定到该项目,它可能还具有对其他项目的权限。
一种正式的思考方式是,虽然 projectId 有时是 服务帐户 的 属性,但 projectId 通常不是 属性长期存在的 凭据 。例如,想想您在 gcloud
CLI 中使用的离线安装的个人凭证(如果有)与您的 Google account/email 地址相关联。该电子邮件身份不在 任何 云项目中,但可用于派生 GoogleCredential 对象。
从技术上讲,如果您想这样做 "properly" 您需要一个主服务帐户,该帐户有权 GET
拥有您计划的实际服务帐户的所有项目中的服务帐户描述使用,然后在服务帐户电子邮件地址上调用 IAM API 的 projects.serviceAccounts.get,而不是在 "credential" 对象上。那里的响应可以识别服务帐户所在的项目 ID。这相当于 gcloud
命令:
gcloud iam service-accounts describe my-service-account@projectid.iam.gserviceaccount.com
然而,正如 Dagang 所说,在长期 运行 开始烘烤时,通常会适得其反,假设服务帐户将仅用于其所在项目的操作。特别是,虽然 service account
资源本身存在于项目中,但它们通常以跨项目的方式使用。一种常见的操作模式是使用单个 GCP 项目来管理大量服务帐户,然后授予这些帐户对其他 GCP 项目中资源的各种细粒度访问权限。
服务帐户凭据 .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')
从 UnderlyingCredential 获取 ProjectId
var credential = GoogleCredential.FromFile(googleCredentialPath);
var projectId = ((Google.Apis.Auth.OAuth2.ServiceAccountCredential)credential.UnderlyingCredential).ProjectId;
在 C# 中
var credentials = GoogleCredential.GetApplicationDefault();
var projectId = (credentials.UnderlyingCredential as dynamic).ProjectId as string;