Как аутентифицировать API Google (API Google Диска) из Google Compute Engine и локально без загрузки учетных данных сервисного аккаунта?

Aug 20 2020

Наша компания работает над обработкой данных из Google Таблиц (на Google Диске) из Google Cloud Platform, и у нас возникают некоторые проблемы с аутентификацией.

Есть два разных места, где нам нужно запускать код, который вызывает API-вызовы Google Drive: в производственной среде в Google Compute Engine и в средах разработки, то есть локально на ноутбуках наших разработчиков.

Наша компания довольно строго относится к учетным данным и не разрешает загрузку ключей JSON с учетными данными службы (это более эффективная практика и обеспечивает более высокий уровень безопасности). Похоже, что все документы от GCP говорят, что нужно просто загрузить ключ JSON для учетной записи службы и использовать его. Или документы Google API / разработчиков говорят, что нужно создать идентификатор клиента OAuth2 и загрузить его ключ, как здесь .
Часто они используют такой код:

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)

Но мы не можем (или просто не хотим) загружать JSON-ключи нашей учетной записи службы, поэтому мы застряли, если просто будем следовать документации.

Для среды Google Compute Engine мы смогли аутентифицироваться с помощью учетных данных GCP Application Default Credentials (ADC), то есть без явного указания учетных данных для использования в коде и позволяя клиентским библиотекам «просто работать» - это отлично работает, если каждый гарантирует, что виртуальная машина создается с правильными областями https://www.googleapis.com/auth/drive, а электронная почта учетной записи службы вычислений по умолчанию получает разрешение на доступ к листу - это объясняется в документации здесь . Сделать это можно так:

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

Однако как это сделать для разработки, то есть локально на ноутбуках наших разработчиков? Опять же, без загрузки каких-либо ключей JSON и желательно с максимально возможным подходом «просто работает»?

Обычно мы используем gcloud auth application-default loginдля создания учетных данных приложения по умолчанию, которые используются клиентскими библиотеками Google и которые «просто работают», например, для хранилища Google. Однако это не работает для API Google за пределами GCP, например API Google Диска, service = build('sheets', 'v4')который не работает с такой ошибкой: «Запрос имеет недостаточные области аутентификации». Затем мы испробовали всевозможные решения, например:

credentials, project_id = google.auth.default(scopes=["https://www.googleapis.com/auth/drive"])

и

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

и многое другое ... Все это дает множество ошибок / проблем, которые мы не можем решить, пытаясь выполнить аутентификацию в Google Drive API :(

Есть предположения?

Ответы

3 benjamincerigo Aug 20 2020 at 21:27

Один из способов сделать аутентификации из среды разработки простой заключается в использовании учетной записи службы олицетворения .

Вот блог об использовании имитации учетной записи службы, включая преимущества этого. @johnhanley (который написал сообщение в блоге) - отличный парень, и у него также есть много очень информативных ответов на SO!

Чтобы иметь возможность аутентифицировать локальный компьютер для API Google Диска, вам необходимо создать учетные данные приложения по умолчанию на локальном компьютере, который олицетворяет учетную запись службы и применяет области, необходимые для API, к которым вы хотите получить доступ.

Чтобы иметь возможность выдавать себя за учетную запись службы, ваш пользователь должен иметь эту роль roles/iam.serviceAccountTokenCreator. Эта роль может применяться ко всему проекту или к отдельной учетной записи службы.

Вы можете использовать gcloudдля этого:

gcloud iam service-accounts add-iam-policy-binding [COMPUTE_SERVICE_ACCOUNT_FULL_EMAIL] \
--member user:[USER_EMAIL] \
--role roles/iam.serviceAccountTokenCreator

Как только это будет сделано, создайте локальные учетные данные:

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]

Это решит возникшую у вас ошибку прицела. Три дополнительных области, добавленных за пределы Drive API, являются областями по умолчанию, которые gcloud auth application-default loginприменяются и необходимы.

Если вы примените области без олицетворения, вы получите такую ​​ошибку при попытке аутентификации:

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

После того, как вы настроили учетные данные, вы можете использовать тот же код, который запускается в Google Compute Engine на вашем локальном компьютере :)

Примечание: также можно установить олицетворение для всех команд gcloud:

gcloud config set auth/impersonate_service_account [COMPUTE_SERVICE_ACCOUNT_FULL_EMAIL]

Создание учетных данных приложения по умолчанию на вашем локальном компьютере путем олицетворения учетной записи службы - отличный способ аутентификации кода разработки. Это означает, что код будет иметь те же разрешения, что и учетная запись службы, которую он олицетворяет. Если это та же учетная запись службы, которая будет запускать код в производственной среде, вы знаете, что код в разработке работает так же, как и в производственной среде. Это также означает, что вам никогда не придется создавать или загружать ключи учетной записи службы.