HTTP-триггер функции Google - проблема аутентификации с сервера на сервер со служебной учетной записью - PullRequest
2 голосов
/ 08 мая 2020

Что я хочу сделать : вызвать функцию Google с моего сервера / компьютера и ограничить ее использование (простой) аутентификацией.

Что я использую : Node.js, google-auth-library библиотека для аутентификации.

Что я сделал / пробовал :

1) Создал проект в Google Cloud Functions

2) Создал простую гугл-функцию

 exports.helloWorld = (req, res) => {
  let message = req.query.message || req.body.message || 'Hello World!';
  res.status(200).send(message);
};

3) Установите мою пользовательскую учетную запись службы

4) Включенный API: - API облачных функций - API учетных данных службы IAM - API облачных вычислений - API Compute Engine - API учетных данных учетной записи службы IAM

5) Для моей учетной записи на сервере необходима авторизация (владелец проекта, администратор облачной функции, администратор проекта IAM ... (нужно больше?)

6) Сгенерированный ключ из моего сервисный аккаунт и сохранил его в формате json

NB: с разрешением allUser (без авторизации) я могу без проблем звонить на свою конечную точку

7) С моего проект, я попытался аутентифицировать свою функцию таким образом

const { JWT } = require('google-auth-library');
const fetch = require('node-fetch');
const keys = require('./service-account-keys.json');


async function callFunction(text) {
  const url = `https://europe-west1-myFunction.cloudfunctions.net/test`;

  const client = new JWT({
    email: keys.client_email,
    keyFile: keys,
    key: keys.private_key,
    scopes: [
      'https://www.googleapis.com/auth/cloud-platform',
      'https://www.googleapis.com/auth/iam',
    ],
  });

  const res = await client.request({ url });
  const tokenInfo = await client.getTokenInfo(client.credentials.access_token);

  try {
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        Authorization: `Bearer ${client.credentials.access_token}`,
      },
    });
    if (response.status !== 200) {
      console.log(response);
      return {};
    }
    return response.json();
  } catch (e) {
    console.error(e);
  }
} 

ℹ️, если я попытаюсь передать URL-адрес client.request () без имени функции (https://europe-west1-myFunction.cloudfunctions.net), я не получил ошибку, но при использовании токена JWT, полученного при вызове выборки, я получил ту же ошибку.

РЕЗУЛЬТАТ :

 Error: 
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>401 Unauthorized</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Unauthorized</h1>
<h2>Your client does not have permission to the requested URL <code>/test1</code>.</h2>
<h2></h2>
</body></html>

❓ Как мне вызвать функцию Google с какой-либо защитой, чтобы никто не смог ее использовать? (Мне не нужна конкретная c безопасность, просто случайные пользователи ее не используют) Заранее благодарим за любую помощь

1 Ответ

2 голосов
/ 08 мая 2020

Когда вы вызываете частную функцию (или частную облачную среду), вы должны использовать токен идентификации, подписанный Google .

В вашем коде вы используете токен доступа

      headers: {
        Authorization: `Bearer ${client.credentials.access_token}`,
      },

Токен доступа работает, когда вам нужно запросить Google Cloud API, а не ваши сервисы

И подписанный Google важен, потому что вы можете легко создать самоподписанный токен идентификации с google auth lib, но он не будет работать

У вас есть образец кода здесь , а я написал инструмент в Go, если вы хотите иметь примерьте

** РЕДАКТИРОВАТЬ **

Я работал над примером, и, даже если мне никогда не нравился Javascript, я должен признать, что завидую !! Это так просто в Node !!

Вот мой рабочий пример

const {GoogleAuth} = require('google-auth-library');

async function main() {
    // Define your URL, here with Cloud Run but the security is exactly the same with Cloud Functions (same underlying infrastructure)
    const url = "https://go111-vqg64v3fcq-uc.a.run.app"
    // Here I use the default credential, not an explicit key like you
    const auth = new GoogleAuth();
    //Example with the key file, not recommended on GCP environment.
    //const auth = new GoogleAuth({keyFilename:"/path/to/key.json"})

    //Create your client with an Identity token.
    const client = await auth.getIdTokenClient(url);
    const res = await client.request({url});
    console.log(res.data);
}

main().catch(console.error);

Примечание : Только учетная запись службы может генерировать токен идентификации с аудиторией. Если вы находитесь на локальном компьютере, не используйте свою учетную запись пользователя с режимом учетных данных по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...