Облачные задачи Google не могут пройти аутентификацию в Cloud Run - PullRequest
2 голосов
/ 09 апреля 2020

Я пытаюсь вызвать службу Cloud Run с использованием облачных задач, как описано в документации здесь .

У меня работает служба 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': 'my-service-account@my-project.iam.gserviceaccount.com'
            }
        }
}

response = client.create_task(parent, task)
print('Created task {}'.format(response.name))

Я вижу, что задача появляется в очереди, но она не выполняется и сразу же повторяется. Причина этого (путем проверки журналов) заключается в том, что служба Cloud Run возвращает ответ 401.

Мой собственный пользователь имеет роли «Создатель токена учетной записи службы» и «Пользователь учетной записи службы». У него нет явного «Cloud Tasks Enqueuer», но, поскольку я могу создать задачу в очереди, я предполагаю, что унаследовал необходимые разрешения. Учетная запись службы "my-service-account@my-project.iam.gserviceaccount.com" (которую я использую в задаче для получения токена OID C), помимо прочего, выполняет следующие роли:

  • Enqueuer Cloud Tasks (хотя я не Не думаю, что это нужно, так как я создаю задачу со своей учетной записью)
  • Cloud Tasks Runner Task *
  • Cloud Tasks Viewer
  • Service Token Creator (я) я не уверен, следует ли добавить это в мою учетную запись - ту, которая планирует задачу - или в учетную запись службы, которая должна выполнять вызов в 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.

Чего мне не хватает?

Ответы [ 2 ]

1 голос
/ 10 апреля 2020

На следующий день я больше не могу воспроизвести эту проблему. Я могу воспроизвести 403 ответа, удалив роль Cloud Run Invoker, но я больше не получаю 401 ответов с точно таким же кодом, как вчера. Я полагаю, что это была временная проблема со стороны Google?

Кроме того, я заметил, что требуется некоторое время, чтобы обновленные политики вступили в силу (от 1 до 2 минут).

1 голос
/ 10 апреля 2020

1.Я создал частное облако Запустите службу , используя этот код:

import os

from flask import Flask
from flask import request


app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def hello_world():
    target = os.environ.get('TARGET', 'World')
    print(target)
    return str(request.data)

if __name__ == "__main__":
    app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))

2. Я создал учетную запись службы с --role=roles/run.invoker, которую я буду ассоциировать с задачей облака

 gcloud iam service-accounts create SERVICE-ACCOUNT_NAME \
 --display-name "DISPLAYED-SERVICE-ACCOUNT_NAME"  
 gcloud iam service-accounts list

 gcloud run services add-iam-policy-binding SERVICE \
 --member=serviceAccount:SERVICE-ACCOUNT_NAME@PROJECT-ID.iam.gserviceaccount.com \ 
 --role=roles/run.invoker 

3. Я создал очередь

gcloud tasks queues create my-queue

4. Я создаю test.py

from google.cloud import tasks_v2
from google.protobuf import timestamp_pb2
import datetime

# Create a client.
client = tasks_v2.CloudTasksClient()

# TODO(developer): Uncomment these lines and replace with your values.
project = 'your-project'
queue = 'your-queue'
location = 'europe-west2' # app engine locations
url = 'https://helloworld/index'
payload = 'Hello from the Cloud Task'

# Construct the fully qualified queue name.
parent = client.queue_path(project, location, queue)

# Construct the request body.
task = {
        'http_request': {  # Specify the type of request.
            'http_method': 'POST',
            'url': url,  # The full url path that the task will be sent to.
            'oidc_token': {
                'service_account_email': "your-service-account"
            },
             'headers' : {
             'Content-Type': 'application/json',
           }
        }
}

# Convert "seconds from now" into an rfc3339 datetime string.
d = datetime.datetime.utcnow() + datetime.timedelta(seconds=60)

# Create Timestamp protobuf.
timestamp = timestamp_pb2.Timestamp()
timestamp.FromDatetime(d)

# Add the timestamp to the tasks.
task['schedule_time'] = timestamp
task['name'] = 'projects/your-project/locations/app-engine-loacation/queues/your-queue/tasks/your-task'


converted_payload = payload.encode()

# Add the payload to the request.
task['http_request']['body'] = converted_payload


# Use the client to build and send the task.
response = client.create_task(parent, task)

print('Created task {}'.format(response.name))
#return response

5. Я запускаю код в Google Cloud Оболочка с моей учетной записью, которая имеет роль владельца.

6.Полученный ответ имеет вид:

Created task projects/your-project/locations/app-engine-loacation/queues/your-queue/tasks/your-task

7.Проверьте журналы, успех

enter image description here

...