Хранение секретных ключей googleapi в переменных среды Firebase

Вопрос

Я хотел бы хранить секретный ключ API для googleapis в безопасном месте. Когда я сохраняю секретный ключ API из googleapis в качестве переменной среды Firebase, private_key не обрабатывается так же, как когда я require("./privatekey.json"); см. проблему ниже:

Контекст

Я скачал и расшифровал секретный ключ API от Google. В большинстве примеров показано сохранение декодированного файла JSON в пути к проекту. и используя require, чтобы вставить токен в код.

const SERVICE_ACCOUNT_KEY_FILE = require("./privatekey.json");  <----- This is Bad!!


const SERVICE_ACCOUNT_EMAIL = '[email protected]';
const jwt = new googleapis.auth.JWT(
        SERVICE_ACCOUNT_EMAIL,
        SERVICE_ACCOUNT_KEY_FILE.private_key,
        null,
        ['https://www.googleapis.com/auth/analytics.readonly']);

Я использовал переменные окружения Firebase от firebase-cli до firebase functions:config:set. После завершения и повторного развертывания я запускаю firebase functions:config:get и вижу:

 "googleapi_credentials": {
    "private_key": "-----BEGIN PRIVATE KEY-----\\nMIIE  ... q0DEg==\\n-----END PRIVATE KEY-----\\n",

Проблема

При настройке googleapis.auth.JWT() мне нужно предоставить секретный ключ API googleapis. Когда я использую require для извлечения секретного ключа API, запросы работают.

Однако если я попытаюсь получить доступ к переменной среды Firebase для предоставления секретного ключа API запросы не выполняются.

var jwt = new googleapis.auth.JWT(
        functions.config().googleapi_credentials.client_email,
        functions.config().googleapi_credentials.private_key, <----- NOPE!
        null,
        ['https://www.googleapis.com/auth/analytics.readonly']);

Отлаживать

Чтобы увидеть, в чем разница, я сравнил console.log() двух токенов в представлении журнала функций Firebase. Токен, который я сохранил в файле JSON и в переменных среды Firebase, выглядит одинаково в коде, то есть обе строки совпадают и содержат много \n (разрывов строк).

Теперь, когда я просматриваю, что возвращает console.log() в журналах функций Firebase, я вижу разные токены.

console.log("JSON Private.Key", privatekey.private_key)

представление в журналах возвращает отформатированную строку, в которой все \n заменены разрывами строк, и токен принимается.

console.log("Private.Key", functions.config().googleapi_credentials.private_key)

Журналы возвращают сообщение, в котором все \n заменяются на \\n, а токен не принимается.

Заключительное примечание

Функция googleapis.auth.JWT() может принимать объект в качестве аргументов? Нужно ли учитывать это при использовании переменных среды Firebase?


person Chadd    schedule 11.04.2018    source источник
comment
Пример, который я привел выше, не очень хорош, потому что документация googleapis показывает лучший способ обработки локальное и развернутое управление ключами Secret API для проверки подлинности между службами. Это может сделать мой вопрос недействительным, если эта проблема связана с аргументами функции googleapis.auth.JWT().   -  person Chadd    schedule 12.04.2018
comment
На GitHub есть открытый вопрос о том, как обрабатывается добавление косой черты, что может помочь ответить на некоторые из ваших вопросов; github.com/firebase/firebase-tools/issues/371   -  person sketchthat    schedule 12.04.2018
comment
Похоже на то, @sketchthat Хочешь получить ответ, а я закрою это?   -  person Chadd    schedule 12.04.2018
comment
Спасибо, Чадд. Только что написал.   -  person sketchthat    schedule 12.04.2018


Ответы (2)


В сведениях о среде Firebase есть проблема с добавлением косых черт, и они могут разорвать \n строки.

На GitHub есть открытый тикет, на который следует ссылаться; github.com/firebase/firebase-tools/issues/371

person sketchthat    schedule 12.04.2018

Вот хак, который я нашел опубликованным YunjorGlez. Это сработало для меня.

Вы можете использовать .replace(/\n/g, '\n'), чтобы удалить дополнительные \, которые добавляются к private_key.

const serviceAccount = functions.config().fireenv;

admin.initializeApp({
   credential: admin.credential.cert({
      "projectId": serviceAccount.project_id,
      "private_key": serviceAccount.private_key.replace(/\\n/g, '\n'),
      "clientEmail": serviceAccount.client_email
   }),
   databaseURL: whatever,
   ...
});
person Chadd    schedule 12.04.2018
comment
Другой вариант — кодировать base64 fireenv, а затем декодировать его при чтении. - person sketchthat; 13.04.2018