Come autenticare le API di Google (API di Google Drive) da Google Compute Engine e localmente senza scaricare le credenziali dell'account di servizio?
La nostra azienda sta lavorando al trattamento dei dati da Fogli Google (all'interno di Google Drive) da Google Cloud Platform e stiamo riscontrando alcuni problemi con l'autenticazione.
Esistono due posizioni diverse in cui è necessario eseguire codice che effettui chiamate API a Google Drive: all'interno della produzione in Google Compute Engine e all'interno degli ambienti di sviluppo, ad esempio localmente sui laptop dei nostri sviluppatori.
La nostra azienda è piuttosto severa in merito alle credenziali e non consente il download delle chiavi JSON delle credenziali dell'account di servizio (questa è una pratica migliore e fornisce una maggiore sicurezza). Apparentemente tutti i documenti di GCP dicono di scaricare semplicemente la chiave JSON per un account di servizio e usarla. Oppure i documenti di Google API / sviluppatori dicono di creare un ID client OAuth2 e scaricarne la chiave come qui .
Spesso usano codice come questo:
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
Ma non possiamo (o semplicemente non vogliamo) scaricare le nostre chiavi JSON dell'account di servizio, quindi siamo bloccati se seguiamo solo i documenti.
Per l'ambiente Google Compute Engine siamo stati in grado di eseguire l'autenticazione utilizzando le credenziali predefinite dell'applicazione GCP (ADC), ovvero non specificando esplicitamente le credenziali da utilizzare nel codice e lasciando che le librerie client "funzionino" - questo funziona alla grande fintanto che ci si assicura che la VM viene creata con gli ambiti corretti https://www.googleapis.com/auth/drive
e all'email dell'account di servizio di calcolo predefinito viene concessa l'autorizzazione per il foglio a cui è necessario accedere: questo è spiegato nella documentazione qui . Puoi farlo in questo modo;
from googleapiclient.discovery import build
service = build('sheets', 'v4')
SPREADSHEET_ID="<sheet_id>"
RANGE_NAME="A1:A2"
s = service.spreadsheets().values().get(
spreadsheetId=SPREADSHEET_ID,
range=RANGE_NAME, majorDimension="COLUMNS"
).execute()
Tuttavia, come lo facciamo per lo sviluppo, cioè localmente sui laptop dei nostri sviluppatori? Ancora una volta, senza scaricare alcuna chiave JSON e preferibilmente con l'approccio più "funzionante" possibile?
Di solito usiamo gcloud auth application-default login
per creare credenziali di applicazione predefinite che le librerie client di Google utilizzano che "funzionano e basta", come per lo spazio di archiviazione di Google. Tuttavia, questo non funziona per le API di Google al di fuori di GCP, come l'API di Google Drive service = build('sheets', 'v4')
che non riesce con questo errore: "La richiesta aveva ambiti di autenticazione insufficienti". Quindi abbiamo provato tutti i tipi di soluzioni come:
credentials, project_id = google.auth.default(scopes=["https://www.googleapis.com/auth/drive"])
e
credentials, project_id = google.auth.default()
credentials = google_auth_oauthlib.get_user_credentials(
["https://www.googleapis.com/auth/drive"], credentials._client_id, credentials._client_secret)
)
e altro ... Il che fornisce una miriade di errori / problemi che non possiamo superare quando si tenta di eseguire l'autenticazione all'API di Google Drive :(
qualche idea?
Risposte
Un metodo per semplificare l'autenticazione dagli ambienti di sviluppo consiste nell'utilizzare la rappresentazione dell'account di servizio .
Ecco un blog sull'utilizzo della rappresentazione dell'account di servizio, inclusi i vantaggi di questa operazione. @johnhanley (che ha scritto il post sul blog) è un ragazzo fantastico e ha molte risposte molto istruttive anche su SO!
Per poter fare in modo che il tuo computer locale si autentichi per l'API di Google Drive, dovrai creare credenziali di applicazione predefinite sul tuo computer locale che impersona un account di servizio e applica gli ambiti necessari per le API a cui desideri accedere.
Per poter impersonare un account di servizio, il tuo utente deve avere il ruolo roles/iam.serviceAccountTokenCreator
. Questo ruolo può essere applicato a un intero progetto oa un singolo account di servizio.
Puoi usare gcloudper fare questo:
gcloud iam service-accounts add-iam-policy-binding [COMPUTE_SERVICE_ACCOUNT_FULL_EMAIL] \
--member user:[USER_EMAIL] \
--role roles/iam.serviceAccountTokenCreator
Fatto ciò, crea le credenziali locali:
gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/accounts.reauth \
--impersonate-service-account=[COMPUTE_SERVICE_ACCOUNT_FULL_EMAIL]
Questo risolverà l'errore degli ambiti che hai ricevuto. I tre ambiti aggiuntivi aggiunti oltre l'ambito dell'API di Drive sono gli ambiti predefiniti che si gcloud auth application-default login
applicano e sono necessari.
Se applichi gli ambiti senza impersonificazione, riceverai un errore come questo durante il tentativo di autenticazione:
HttpError: <HttpError 403 when requesting https://sheets.googleapis.com/v4/spreadsheets?fields=spreadsheetId&alt=json returned "Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the sheets.googleapis.com. We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting. For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.">
Dopo aver impostato le credenziali puoi utilizzare lo stesso codice eseguito su Google Compute Engine sulla tua macchina locale :)
Nota: è anche possibile impostare la rappresentazione per tutti i comandi di gcloud:
gcloud config set auth/impersonate_service_account [COMPUTE_SERVICE_ACCOUNT_FULL_EMAIL]
La creazione di credenziali dell'applicazione predefinite sulla macchina locale impersonando un account di servizio è un modo semplice per autenticare il codice di sviluppo. Significa che il codice avrà esattamente le stesse autorizzazioni dell'account di servizio che sta impersonando. Se questo è lo stesso account di servizio che eseguirà il codice in produzione, saprai che il codice in fase di sviluppo viene eseguito come in produzione. Significa anche che non devi mai creare o scaricare chiavi dell'account di servizio.