Я ищу лучший способ аутентификации Google Cloud Function с помощью сервисного аккаунта. Прямо сейчас я сохраняю файл учетных данных json на серверной части. Это код моего приложения https://github.com/ChristianOConnor/spheron-react-api-stack. Это приложение может быть развернуто на любой хостинговой платформе, но на данный момент приложение создано для развертывания на протоколе Web3 под названием Spheron. TLDR, Spheron запускает внутренний экспресс-сервер на удобной для web3 платформе обслуживания/хостинга контента под названием Akash. Это означает, что тот, кто размещает мой внутренний экспресс-сервер, имеет доступ к учетным данным моей учетной записи службы GCP. Вы можете увидеть весь код по ссылке, которую я предоставил, но для простоты доступа это файл server.js, который будет на Akash.
сервер.js
var express = require("express");
var app = express();
require("dotenv").config();
const GoogleAuth = require("google-auth-library").GoogleAuth;
const cors = require("cors");
app.use(
cors({ origin: process.env.ORIGIN, credentials: process.env.CREDENTIALS })
);
app.get("/hello", async function (req, res) {
const keyInJsn = JSON.parse(process.env.CREDENTIALS_STR);
const auth = new GoogleAuth({
credentials: keyInJsn,
});
const url = process.env.RUN_APP_URL;
//Create your client with an Identity token.
const client = await auth.getIdTokenClient(url);
const result = await client.request({ url });
const resData = result.data;
res.send(resData);
});
var server = app.listen(8081, function () {
var host = server.address().address;
var port = server.address().port;
console.info("Example app listening at http://localhost:", port);
});
process.env.CREDENTIALS_STR
— учетные данные служебной учетной записи, настроенные в следующем формате:
CREDENTIALS_STR = {"type": "service_account","project_id": "<PROJECT ID>","private_key_id": "<PRIVATE KEY ID>","private_key": "-----BEGIN PRIVATE KEY-----\<PRIVATE KEY>\n-----END PRIVATE KEY-----\n","client_email": "<SERVICE ACCOUNT NAME>@<PROJECT NAME>.iam.gserviceaccount.com","client_id": "<CLIENT ID>","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": "https://www.googleapis.com/robot/v1/metadata/x509/<SERVICE ACCOUNT NAME>.iam.gserviceaccount.com"}
Поставщик Akash может видеть эту строку. Есть ли лучший способ выполнить аутентификацию для учетной записи службы GCP, которая не предоставляет учетные данные поставщику хостинга/сервера?
Также не отвлекайтесь на вещи web3. Это приложение по сути работает так же, как традиционное приложение web2 с серверной частью и клиентом. Если это поможет вам подумать об этом иначе, представьте, что я развертываю Netlify со статическим клиентом и функцией Netlify.
У вас есть идентичность с вашим сервисом web3? Что-то основанное на OAuth2?
@ al-dann Разве секретному менеджеру не требуется служебная учетная запись для аутентификации? И даже если я отключу аутентификацию, я думаю, что сервер все равно получит простую текстовую версию секретного ключа. Если бы я настроил функцию для прямого обращения к менеджеру секретов, мне все равно пришлось бы вызывать функцию без аутентификации. Это похоже на странную Уловку-22, лол.
@guillaumeblaquiere Идентификация для службы web3? Звучит многообещающе, знаете ли вы соответствующий пример?
@guillaumeblaquiere о, я нашел эту статью, которую вы написали medium.com/google-cloud/…. Это способ сделать это? Должен ли я создать конечную точку облачного запуска для запуска функции?
Теперь вы можете использовать API Gateway, управляемую службу Google Cloud на основе ESPv2 (и моя статья все еще действительна, но с API-интерфейсами API Gateway).
Наверняка какая-то учетная запись службы используется для запуска облачной функции (для выполнения кода облачной функции). И этой служебной учетной записи могут быть предоставлены все необходимые разрешения (включая доступ к соответствующим секретам SM) с использованием возможностей ordinray IAM. Кроме того, эта учетная запись службы не имеет ничего общего с личностью и учетными данными вызывающей стороны этой облачной функции. То, что получит «последний сервис» — полностью дизайнерское решение, реализованное внутри кода облачной функции. Но если для дальнейшего обслуживания требуются какие-то секреты, SM может быть хорошим кандидатом для их хранения.
@al-dann, это пример того, о чем вы говорите, и будет ли это работать для того, что я делаю cloud.google.com/nodejs/docs/reference/iam-credentials/latest? Кроме того, если это сработает, куда мне поместить токен? Как заголовок Bearer: token
в запросе на получение URL-адреса триггера функции?
@guillaumeblaquiere, вы говорите, что я должен заменить «идентификатор конечной точки» на «Шлюз API?»
Я имею в виду, что весь продукт ESPv2 теперь управляется API Gateway. Вам больше не нужно развертывать его в Cloud Run, он управляем. Вам нужно только настроить его.
@guillaumeblaquiere — это лучшее руководство по его использованию cloud.google.com/endpoints/docs/openapi/set-up-cloud-run-espv2. Или есть лучшее руководство, с которым вы знакомы?
Предпочитаю это: medium.com/google-cloud/…
@guillaumeblaquiere В этом руководстве также используется «Шлюз API», устарел ли он в пользу «ESPv2?»
Наоборот, предпочитайте управляемое решение, чем ESPv2.
Хорошо, спасибо, я буду продолжать пытаться заставить это работать
Компромисс, к которому я пришел, заключался в создании шлюза API для функции. Это позволяет вызывать функцию без каких-либо учетных данных и по-прежнему запускать ее из учетной записи службы. Однако это создает отдельную квази-уязвимость, поскольку любой, у кого есть ссылка на шлюз API, также может вызвать функцию без аутентификации.
Во-первых, я включил API управления службами, API шлюза API и API управления службами. Затем я создал API-шлюз с моей учетной записью службы, которая запускает мою указанную облачную функцию. Я загрузил такой файл для спецификации API:
swagger: '2.0'
info:
title: api-gateway-cloud-function
description: API Gateway Calling Cloud Function
version: 1.0.0
schemes:
- https
produces:
- application/json
paths:
/whateveryouwanttocallthispath:
get:
summary: My Cloud Function
operationId: whatever
x-google-backend:
address: <CLOUD_RUN_URL>
responses:
'200':
description: OK
Вы можете проверить это, запустив функцию с помощью команды curl в терминале bash curl {gatewayId}-{hash}.{region_code}.gateway.dev/v1/whateveryouwanttocallthispath
. Он работает без файла учетных данных json.
Проблема в том, что вы могли бы добиться аналогичного результата, просто позволив функции вызываться без проверки подлинности... Я знаю, если этот метод имеет много преимуществ.
Я никогда не работал с java или js и никогда не работал в вашем контексте, но, исходя из общих соображений дизайна, вы думали об использовании Secret Manager cloud.google.com/secret-manager для хранения учетных данных? Облачная функция (код) может получать учетные данные, например, во время выполнения, поэтому нет необходимости хранить их ни в конфигурации, ни в переменных среды.