У меня есть проект NodeJS, для которого я хочу запустить несколько модульных тестов во время сборки в Google Cloud Build. Эти модульные тесты требуют отправки запроса в службу Cloud Run, которая требует аутентификации, поэтому мне нужно предоставить токен с запросом. Для аутентификации я использую библиотеку npm google-auth-library
и использую следующий код для получения токена:
const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();
const targetAudience = new URL(url);
const client = await auth.getIdTokenClient(targetAudience);
const clientHeaders = await client.getRequestHeaders();
const token = clientHeaders['Authorization'];
Когда я запускаю это локально, у меня есть учетные данные учетной записи службы JSON, и я устанавливаю местоположение этого файла JSON как GOOGLE_APPLICATION_CREDENTIALS
в среде. Но при запуске этого модульного теста в Cloud Build файл учетной записи службы не включается, поскольку он не фиксируется в репозитории git. Насколько я понимаю, это не требуется, когда он работает в Google Cloud, поскольку он должен проходить аутентификацию с помощью связанной службы. учетная запись, указанная триггером Google Cloud Build (имеющим, кстати, роль Cloud Run Invoker
).
Однако, когда я проверяю client.idTokenProvider.email
локально, я получаю адрес электронной почты учетной записи службы, но в Cloud Build значение default
.
Это мой облачный yaml:
steps:
# Install the Cloud SQL proxy
- id: proxy-install
name: node:16
entrypoint: sh
args:
- '-c'
- 'wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O /workspace/cloud_sql_proxy && chmod +x /workspace/cloud_sql_proxy'
waitFor: ['-']
# Install npm packages
- id: npm-install
name: node:16
entrypoint: npm
args: ['install', '--include=dev']
waitFor: ['proxy-install']
# Run the tests
- id: npm-test
name: node:16
entrypoint: sh
args:
- '-c'
- '(/workspace/cloud_sql_proxy -dir=/cloudsql -instances=[INSTANCE-NAME] & sleep 2) && (npm test)'
env:
- 'NODE_ENV=production'
- 'URL=[CLOUD_RUN_SERVICE_URL]'
waitFor: ['npm-install']
timeout: 600s
Итак, как мне пройти аутентификацию в службе Cloud Run при отправке запроса во время Cloud Build?
Вы должны найти ответ в моей статье. Я говорю о похожей проблеме с Cloud Functions. В любом случае, встроенная айдентика Cloud Build не очень проста и последовательна medium.com/google-cloud/…
Примечание: НЕ ИСПОЛЬЗУЙТЕ ключевой файл сервисной учетной записи (JSON), когда это возможно, это плохая практика. Моя статья также может помочь вам в этом.
@guillaume, я уже просматривал вашу статью, но не смог найти эквивалент AuthorizedSession
в модуле npm. Можно ли использовать API учетных данных служебной учетной записи с JavaScript вместо Python?
Хммм, вы можете попробовать что-то "новое" (точно не знаю, но это довольно новое в клиентской библиотеке. Убедитесь, что у вас есть последняя версия библиотеки Google OAuth2). Выполните gcloud auth application-default login --impersonate-service-account=XXXX
. Установите правильную учетную запись службы для олицетворения, убедитесь, что у вас есть (ваша учетная запись) разрешение на создание токена в учетной записи службы (создатель токена учетной записи службы роли) и используйте эти учетные данные в своем локальном коде. Java, Go и Python lib совместимы. Я не знаю, я не разработчик узлов!
Спасибо! Используя олицетворение и некоторые изменения в коде javascript, я могу пройти аутентификацию в Cloud Build. Я напишу ответ с более подробной информацией для всех, кто заинтересован.
Благодаря подсказке @guillaume blaquiere об использовании олицетворения можно пройти аутентификацию в Cloud Run из Cloud Build. В Cloud Build учетная запись службы сборки должна иметь роль: Service Account Token Creator
. Затем вы можете создать аутентифицированного клиента с помощью кода JavaScript:
const url = [CLOUD_RUN_SERVICE_URL]
const scopes = 'https://www.googleapis.com/auth/cloud-platform'
const auth = new GoogleAuth({
scopes: scopes
});
const client = auth.getClient();
let targetClient = new Impersonated({
sourceClient: client,
targetPrincipal: [YOUR-SERVICE-ACCOUNT],
lifetime: 30,
delegates: [],
targetScopes: [scopes]
});
const authClient = new IdTokenClient({
targetAudience: url,
idTokenProvider: targetClient
});
Если вы хотите запустить это локально, убедитесь, что ваша учетная запись также имеет роль Service Account Token Creator
, и сначала выполните команду:
gcloud auth application-default login --impersonate-service-account=XXXX
Отредактируйте свой вопрос и включите свой Cloud Build YAML.