2
votes

Comment obtenir projectId depuis GoogleCredentials?

En utilisant Python, je souhaite obtenir une liste de tous mes clusters Dataproc sur Google Cloud.

J'ai des identifiants de compte de service stockés dans un fichier de clés JSON dont l'emplacement est référencé par env var GOOGLE_APPLICATION_CREDENTIALS. Voici le code que j'ai jusqu'à présent:

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()

Comme vous pouvez le voir, j'ai codé en dur le projectId ( "my-project" ). Étant donné que projectId existe dans le fichier de clés JSON, j'espérais pouvoir l'obtenir en interrogeant simplement une propriété de l'objet credentials , mais une telle propriété n'existe pas. Le projectId existe intégré dans la propriété de chaîne credentials._service_account_email mais son extraction à partir de là est maladroite et semble erronée.

Je suppose qu'il doit y avoir un meilleure façon. Comment puis-je obtenir le projectId du projet dans lequel réside le compte de service?

Notez qu'au départ, j'ai l'intention d'exécuter ce code dans un conteneur Docker sur une instance Google Compute Engine, mais un jour dans le futur Je souhaite peut-être utiliser GKE. Je ne sais pas si cela affecte la réponse ou non.


0 commentaires

4 Réponses :


3
votes

Je ne pense pas que le code client soit censé extraire l'ID de projet de GoogleCredentials. Consultez cet extrait de code du document API .

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)

Vous pourrez peut-être déduire l'ID du projet à partir de credentials._service_account_email , mais ce n'est pas fiable. De plus, un compte de service dans le projet A n'est pas lié au projet, il peut également disposer d'autorisations sur d'autres projets.


0 commentaires

4
votes

Une manière formelle de penser à cela est que si projectId est parfois une propriété d'un compte de service , un projectId n'est généralement pas une propriété d'un identifiant de longue durée . Par exemple, pensez à vos informations d'identification personnelles installées hors connexion que vous utilisez avec la CLI gcloud , le cas échéant, associée à votre compte Google / adresse e-mail. Cette identité de messagerie ne réside dans aucun projet cloud, et peut cependant être utilisée pour dériver un objet GoogleCredential.

Techniquement, si vous voulez le faire "correctement", vous avez besoin d'un maître compte de service qui dispose des autorisations nécessaires pour GET descriptions de compte de service dans tous les projets qui détiennent les comptes de service réels que vous prévoyez d'utiliser, puis appelez l ' projects.serviceAccounts.get sur l'adresse e-mail du compte de service, pas sur l'objet" credential ". Les réponses peuvent identifier l'ID du projet dans lequel réside le compte de service. Ceci est équivalent à la commande gcloud :

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

Cependant, comme le dit Dagang, cela va souvent se retourner contre vous à long terme pour commencer à baking dans les hypothèses que le compte de service ne sera utilisé que pour les opérations sur les projets dans lesquels il réside. En particulier, alors que les ressources du compte de service elles-mêmes vivent à l'intérieur des projets, elles sont souvent utilisées de manière interservices. Un modèle opérationnel courant consiste à utiliser un seul projet GCP pour gérer un grand nombre de comptes de service qui se voient ensuite accorder divers accès précis aux ressources d'autres projets GCP.


2 commentaires

Donc, il semble que mon meilleur pari est d'obtenir le projectId du serveur de métadonnées du moteur de calcul. Cela suppose que mon code s'exécute dans le même projet dans lequel résident les clusters Dataproc, dans mon cas, c'est une hypothèse sûre.


Cela semble être une approche raisonnable.



1
votes

Les informations d'identification du compte de service .json contiennent le project_id, vous pouvez donc faire:

# 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')


0 commentaires

0
votes

Obtenez le ProjectId à partir du UnderlyingCredential

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


0 commentaires