Я пытаюсь вызвать службу Cloud Run с помощью Cloud Tasks, как описано в здесь.
У меня работает служба Cloud Run. Если я сделаю службу общедоступной, она будет вести себя так, как ожидалось.
Я создал облачную очередь и планирую облачную задачу с помощью локального сценария. Этот использует мою учетную запись. Скрипт выглядит так
from google.cloud import tasks_v2
client = tasks_v2.CloudTasksClient()
project = 'my-project'
queue = 'my-queue'
location = 'europe-west1'
url = 'https://url_to_my_service'
parent = client.queue_path(project, location, queue)
task = {
'http_request': {
'http_method': 'GET',
'url': url,
'oidc_token': {
'service_account_email': '[email protected]'
}
}
}
response = client.create_task(parent, task)
print('Created task {}'.format(response.name))
Я вижу, что задача появляется в очереди, но она терпит неудачу и немедленно повторяет попытку. Причина этого (путем проверки журналов) заключается в том, что служба Cloud Run возвращает ответ 401.
У моего собственного пользователя есть роли Создатель токена учетной записи службы и Пользователь учетной записи службы. В нем явно нет очереди облачных задач, но, поскольку я могу создать задачу в очереди, я полагаю, что унаследовал необходимые разрешения. Учетная запись службы [email protected] (которую я использую в задаче для получения токена OIDC) имеет, среди прочего, следующие роли:
- Cloud Tasks Enqueuer (хотя я не думаю, что он ему нужен, поскольку я создаю задачу со своей учетной записью)
- Средство выполнения задач Cloud Tasks
- Наблюдатель облачных задач
- Создатель токена учетной записи службы (я не уверен, следует ли ее добавлять в мою учетную запись - ту, которая планирует задачу, - или в учетную запись службы, которая должна выполнять вызов Cloud Run)
- Пользователь учетной записи службы (здесь же)
- Cloud Run Invoker
Итак, я проделал грязный трюк: я создал файл ключа для учетной записи службы, загрузил его локально и выдал себя локально, добавив учетную запись в мою конфигурацию gcloud с файлом ключа. Далее я бегу
curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" https://url_to_my_service
Это работает! (Кстати, он также работает, когда я снова переключаюсь на свою учетную запись)
Заключительные тесты: если я уберу oidc_token
из задачи при ее создании, я получу ответ 403 от Cloud Run! Не 401 ... Если я удалю роль Cloud Run Invoker из учетной записи службы и попробую снова локально с помощью curl, я также получу 403 вместо 401.
Если я наконец сделаю сервис Cloud Run общедоступным, все заработает.
Таким образом, похоже, что облачной задаче не удается создать токен для учетной записи службы для правильной аутентификации в службе Cloud Run.
Что мне не хватает?
Cloud Tasks Enqueuer
2.Service Account User
3.Cloud Run Invoker
(Или вызывающий объект для той службы Google, на которую вы нацеливаетесь). Адрес электронной почты учетной записи службы, добавленной в очередь, добавляется к задаче перед ее постановкой в очередь, чтобы очередь облачных задач могла использовать ее для генерации токена ... Я собираюсь посмотреть, разрешится ли эта проблема в течение 24 часов, как это сделала ваша. Это очень неприятно - person teaMonkeyFruit   schedule 04.05.2020audience
дляoidc_token
, тогда используется целевой URL-адрес из задачи, в вашем примере выше:https://url_to_my_service
. Проблема здесь в том, что если вы используете Cloud Run с пользовательскими доменами (вместо домена, сгенерированного облачным запуском), вы получите сообщение об ошибке, потому что OIDCaudience
не поддерживает пользовательские домены. Мое исправление заключалось в том, чтобы явно заполнить аудиторию URL-адресом, сгенерированным Cloud Run, и тогда это сработало. - person teaMonkeyFruit   schedule 15.05.2020