Как аутентифицировать клиентское приложение Python для доступа к ограниченной функции Google Cloud? - PullRequest
0 голосов
/ 09 июля 2020

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

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

{
  "type": "service_account",
  "project_id": "XYZ",
  "private_key_id": "XYZ",
  "private_key": "XYZ",
  "client_email": "XYZ",
  "client_id": "XYZ",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "XYZ"
}

Кажется, что для аутентифицированных запросов требуется токен, включенный в заголовок request Authorization, но я не понимаю, где получить этот токен .

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

google.auth.exceptions.RefreshError: ('invalid_scope: Invalid OAuth scope or ID token audience provided.', '{"error":"invalid_scope","error_description":"Invalid OAuth scope or ID token audience provided."}')

Как мне сгенерировать этот токен для аутентификации запроса из моего Python скрипта? Или рекомендуется подход со служебной учетной записью, но что-то еще идет не так?

Ответы [ 3 ]

1 голос
/ 15 июля 2020

Мне удалось заставить это работать, хотя на момент написания в документации была ошибка, которая меня сбила с толку.

Доступ к защищенным облачным функциям возможен с помощью IDTokenCredentials класс в библиотеке google-auth:

credentials = service_account.IDTokenCredentials.from_service_account_file( 
         SERVICE_ACCOUNT_JSON_FILE, 
         target_audience="https://function/url/here",
 ) 

authed_session = AuthorizedSession(credentials)
response = authed_session.post(url)

Моя учетная запись службы настроена с ролью «Вызыватель облачных функций».

0 голосов
/ 13 июля 2020

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

  1. Предоставьте Invoker Cloud Functions.

  2. В вызывающей функции вам необходимо:

  3. Создайте подписанный Google токен идентификатора OAuth с аудиторией (aud), установленной на URL-адрес принимающей функции

  4. Включите маркер идентификатора в заголовок Authorization: Bearer ID_TOKEN в запросе на функция.

    запросы на импорт

    //# TODO<developer>: set these values
    REGION = 'us-central1'
    PROJECT_ID = 'my-project'
    RECEIVING_FUNCTION = 'my-function'
    
    //# Constants for setting up metadata server request
    //# See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature
    function_url = f'https://{REGION}-{PROJECT_ID}.cloudfunctions.net/{RECEIVING_FUNCTION}'
    metadata_server_url = \
        'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='
    token_full_url = metadata_server_url + function_url
    token_headers = {'Metadata-Flavor': 'Google'}
    
    
    def calling_function(request):
        //# Fetch the token
        token_response = requests.get(token_full_url, headers=token_headers)
        jwt = token_response.text
    
        //# Provide the token in the request to the receiving function
        function_headers = {'Authorization': f'bearer {jwt}'}
        function_response = requests.get(function_url, headers=function_headers)
    
        return function_response.text
    

Я протестировал это решение и работает должным образом.

Если вы вызываете функцию из вычислительный экземпляр, у которого нет доступа к вычисляемым метаданным (например, ваш собственный сервер), вам придется вручную сгенерировать правильный токен:

  1. Самостоятельная подпись сервисного аккаунта JWT с для утверждения target_audience задан URL-адрес получающей функции.

  2. Замените самоподписанный JWT на токен идентификатора, подписанный Google, для которого в заявке aud должен быть установлен указанный выше URL.

  3. Включите идентификатор токен в заголовке Authorization: Bearer ID_TOKEN в запросе к функции.

В документации Cloud IAP есть пример кода для демонстрации этой функциональности. Часть, которая может вас заинтересовать, должна быть это Аутентификация из учетной записи службы

0 голосов
/ 12 июля 2020

Ваша проблема почти наверняка связана с ролями, которые вы дали этой учетной записи службы. Учетные записи служб привередливы, и роли / разрешения не всегда действуют так, как вы думаете, по моему опыту. Начните с создания учетной записи службы с полными разрешениями (владельцем проекта). Используйте эту учетную запись службы в своем сценарии, а затем начните ограничивать разрешения оттуда. Похоже, вам понадобится как минимум облачная функция «админка». Если это сработает, попробуйте другой уровень ниже. Облачная функция "разработчик" et c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...