Cloud Tasks не может аутентифицировать вызовы Cloud Run Jobs

Я ломал голову, пытаясь понять, что не так с этой установкой. Мне удалось добиться успеха, но думаю, что я просто упускаю эту последнюю часть.

У меня есть следующая установка:

  1. Облачное выполнение задания А («задачи постановки в очередь»)
  2. Облачное выполнение задания B («элемент процесса»)
  3. очередь облачных задач («элементы процесса»)

Моя цель — запланировать запуск задания «задачи в очереди» раз в две недели. Это задание выполняет некоторые действия (не важные), а затем ставит некоторые задачи в очередь «элементов процесса».

Кажется, это работает нормально

Каждая задача должна вызывать задание «элемент процесса» с некоторыми переопределениями. Очередь должна управлять ограничением скорости выполнения каждой задачи.

Кажется, в этом проблема.

Настройка IAM:

  • учетная запись службы облачных задач
    • Роль: Cloud Run Invoker с переопределениями
      • run.jobs.run
      • run.jobs.runWithOverrides
      • run.routes.invoke
  • Учетная запись службы выполнения заданий в облаке (учетная запись службы вычислений по умолчанию)
    • Очередь облачных задач
    • Создатель токена сервисного аккаунта
    • Пользователь сервисного аккаунта

Я создал специальную роль с разрешением run.jobs.runWithOverrides, чтобы можно было передавать дополнительные переопределения заданию «элемент процесса» через аргументы в каждой задаче.

Отрывок из того, как я создаю/ставлю задачи в очередь (обратите внимание, все находится в регионе us-west1):

// NOTE: This code is inside the "enqueue-tasks" job

import { CloudTasksClient } from "@google-cloud/tasks"

const client = new CloudTasksClient()

const project = "my-project-id"
const location = "us-west1"
const queueName = "process-items"
const taskId = "task-123" // example for item #123
const url = "https://run.googleapis.com/v2/projects/my-project-id/locations/us-west1/jobs/process-item:run"

await client.createTask({
    parent: client.queuePath(project, location, queueName),
    task: {
        name: client.taskPath(project, location, queueName, taskId),
        httpRequest: {
            httpMethod: "POST",
            url: url,
            oidcToken: {
                serviceAccountEmail: "[email protected]",
                audience: url,
            },
            headers: {
                "Content-Type": "application/json",
            },
            body: Buffer.from(JSON.stringify({ overrides: { containerOverrides: [{args: "--item-id=123"}]}})).toString("base64"),
        },
    },
})

Теперь, хоть я и новичок в GCP, я считаю, что все делаю правильно! Однако по какой-то причине, когда облачные задачи выполняются, они всегда терпят неудачу со статусом «НЕСАНКЦИОНИРОВАНО», и при просмотре панели мониторинга моих заданий облачного запуска я не вижу для них никакого вызова.

Чтобы проверить и убедиться в правильности SA моей облачной задачи, я создал токен доступа в качестве SA из CLI gcloud со следующим:

gcloud auth print-access-token --impersonate-service-account=cloud-task-service-account@my-project.iam.gserviceaccount.com

Затем использовал Bruno (приложение, похожее на почтальона/бессонницу), чтобы попытаться сделать вызов вручную в качестве облачной задачи SA.

> POST https://run.googleapis.com/v2/projects/my-project-id/locations/us-west1/jobs/process-item:run
> authorization: Bearer ya29.c.c0AY...XYZ
> content-type: application/json
> data {"overrides":{"containerOverrides":[{"args":["--item-id=123"]}]}}

Это прекрасно удается! Это заставляет меня думать, что что-то не так с тем, как я ставлю задачи в очередь. Документы невероятно запутаны, и даже копаясь в видеороликах на YouTube, я не могу найти в Интернете никаких ресурсов, таких как Cloud Run Job -> Cloud Tasks -> Cloud Run Job. Буду рад добавить более подробную информацию, если это необходимо, но очень любопытно, если я здесь что-то упускаю :/

Изучив эту похожую проблему , мне интересно, связана ли проблема с аудиторией OIDC. Я просмотрел документацию по конечной точке для запуска задания облачного запуска через REST и нашел это, но, возможно, есть еще одна недокументированная конечная точка, которую я предполагаю использовать с OIDC?

Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
0
0
153
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Безопасность Google Cloud не так сложна, но полна ловушек! И вы почувствовали себя в одном из них. Позволь мне объяснить.

Вы должны использовать OIDC (токен идентификации) при вызове ВАШЕГО API (развернутого в Cloud Run, App Engine (с IAP) или облачных функциях). Вы должны использовать OAuth (токен доступа) при вызове API Google.

Вы можете заметить, что используете print-access-token с командой gcloud, а не print-identity-token, и это сработало!


Поэтому используйте oauthToken (и без аудитории) вместо oidcToken в определении задачи.

Вау, это была проблема. Корю себя, что как-то это пропустил. Думаю, я слишком внимательно следил за примерами/видео. В любом случае, большое спасибо за помощь!

Jordankid93 21.05.2024 19:42

Другие вопросы по теме