Node.js: учетные данные облачного хранилища Google не загружаются в производственной среде

Для моего приложения экспресс-сервера у меня есть auth.json файл для аутентификации, который отлично работает при разработке. В моем развернутом приложении проверка подлинности не выполняется, когда я загружаю файл с сообщением об ошибке:

Ошибка: не удалось загрузить учетные данные по умолчанию. Перейдите к https://cloud.google.com/docs/authentication/getting-started для получения дополнительной информации.

Почему моя аутентификация не работает при развертывании?

В настоящее время все мои сегменты в этом проекте являются общедоступными для Интернета, а роли allUsers и электронная почта учетной записи службы имеют полные роли создателя / просмотра / администратора объекта хранилища. Файл auth.json находится на том же иерархическом уровне, что и app.js.

Вот мой код app.js со всеми библиотеками и почтовый запрос, который загружает изображение. Следует отметить, что функция uploadThumb() работает каждый раз, но именно uploadFile вызывает ошибку, показанную ниже.

const express = require("express");
const bodyParser = require("body-parser");
const _ = require("lodash")
const ejs = require("ejs");
const sharp = require('sharp');
const multer = require("multer");
const fs = require("file-system");
const imageThumbnail = require("image-thumbnail");
const {Storage} = require('@google-cloud/storage');
const storage = new Storage({keyFileName: "auth.json"});
const app = express();

//this writes the user submitted image to the local file system
var localStorage = multer.diskStorage({
  destination: function (req, file, cb) {
    const imageDirect = req.body.categories + "/" + req.body.subcat.charAt(0).toUpperCase() + req.body.subcat.slice(1).replace(/ /g, "-") + "/";
    var dir = "./" + imageDirect;
    if(!fs.existsSync(dir)) {
      fs.mkdirSync(dir);
    }
    cb(null, imageDirect)
  },
  filename: function (req, file, cb) {
    let tempImageName = file.originalname;
    req.imageName = tempImageName
    cb(null, tempImageName.replace(/ /g, "-"))
  }
});

var upload = multer({storage: localStorage});

app.post("/upload", upload.single("image"), (req, res) => {

//These define the paths and destinations dynamically
  let cat = req.body.categories;
  let subCatLiteral = req.body.subcat.split(" ");
  let subCat = ""
  for (i=0; i < subCatLiteral.length; i++) {
    var eachWord = subCatLiteral[i].charAt(0).toUpperCase() + subCatLiteral[i].slice(1);
    if (i < subCatLiteral.length-1) {
    subCat = subCat.concat(eachWord + "-");
    } else {
    subCat = subCat.concat(eachWord);
    }
  }
  let img = req.imageName.replace(/ /g, "-");
  let imgTitle = img.split(".")[0];
  let imagePath = cat + '/' + subCat + '/' + img


 //This is uploaded 1st
  async function uploadThumb() { 
    await storage.bucket(thumbs).upload(imgTitle + "-thumb.jpg", {metadata: {cacheControl: "no-cache"}, gzip: true, destination: cat + "/" + subCat + "/" + req.body.name.replace(/ /g, "-") + "-thumb.jpg"})
      uploadFile().catch(console.error);
      fs.unlinkSync(imgTitle + "-thumb.jpg")  //deletes file after upload 
  }


//This is uploaded 2nd, causing  the error
  async function uploadFile() {   
    await storage.bucket(bucketName).upload(imagePath, {metadata: {cacheControl: "no-cache"}, resumable: true, gzip: true, destination: cat + "/" + subCat + "/" + req.body.name.replace(/ /g, "-") + ".jpg"})
      //deletes file after upload
      fs.unlinkSync(`${cat}/${subCat}/${img}`)
      fs.rmdirSync(`./${cat}/${subCat}/`)
      setTimeout(() => {
        fs.rmdirSync(`./${cat}`)
      }, 500)
    await listFiles().catch(console.error);
  }


 //This function starts the chain of uploads
 sharp(imagePath) 
     .resize(null, 300).toFile(imgTitle + "-thumb.jpg", function(err) {
       if (!err) console.log("image resized");
       uploadThumb().catch(console.error);
   })

  res.redirect("/upload#upload");
});

Если кто-нибудь знает, почему это не работает в производстве или где именно в документации я могу найти решение, я был бы признателен.

Вот самая последняя ошибка, отправленная в журнал пассажира.

App 21701 output: Error: Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.
App 21701 output:     at GoogleAuth.getApplicationDefaultAsync (/home/kaylakos/nodevenv/rootdir/kayla/12/lib/node_modules/google-auth-library/build/src/auth/googleauth.js:157:19)
App 21701 output:     at processTicksAndRejections (internal/process/task_queues.js:97:5)
App 21701 output:     at async GoogleAuth.getClient (/home/kaylakos/nodevenv/rootdir/kayla/12/lib/node_modules/google-auth-library/build/src/auth/googleauth.js:490:17)
App 21701 output:     at async GoogleAuth.request (/home/kaylakos/nodevenv/rootdir/kayla/12/lib/node_modules/google-auth-library/build/src/auth/googleauth.js:543:24)
App 21701 output:     at async Upload.makeRequest (/home/kaylakos/nodevenv/rootdir/kayla/12/lib/node_modules/gcs-resumable-upload/build/src/index.js:320:21)
App 21701 output:     at async Upload.createURIAsync (/home/kaylakos/nodevenv/rootdir/kayla/12/lib/node_modules/gcs-resumable-upload/build/src/index.js:145:22)

person PsiKai    schedule 03.10.2020    source источник
comment
1) Client Secrets не имеет отношения к вашей проблеме. 2) Ваш код ищет учетную запись службы или учетные данные CLI gcloud auth на основе сообщения об ошибке.   -  person John Hanley    schedule 05.10.2020
comment
Хорошо, потому что секреты клиента - это то, что устранило проблему в разработке, но теперь, когда проблема вернулась в производство, вы говорите, что мне нужно что-то сделать с учетной записью службы? Если вы знаете, что мне делать или где мне искать, я буду очень признателен.   -  person PsiKai    schedule 05.10.2020
comment
Чтобы начать поиск, не могли бы вы предоставить дополнительные отладочные данные с номерами строк и файлами, на которые они ссылаются?   -  person MrTech    schedule 05.10.2020
comment
@MrTech Обновил вопрос внизу   -  person PsiKai    schedule 05.10.2020
comment
@MrTech - это то, о чем вы просите?   -  person PsiKai    schedule 05.10.2020
comment
Ваше приложение использует ADC (учетные данные приложения по умолчанию), что является ситуацией по умолчанию для SDK Google, если вы не укажете иное. Это означает, что вы настроили учетные данные в своей системе разработки, но не сделали этого в производственной системе. Прочтите ссылку в сообщении об ошибке.   -  person John Hanley    schedule 06.10.2020
comment
@JohnHanley Спасибо за разъяснения. Я прочитал страницу, на которую ссылается сообщение об ошибке, примерно сто раз ... как вы думаете, можете ли вы указать мне на конкретное место в документации, которое объясняет, что я делаю в моем случае? Могу ли я установить переменную env в моем коде? В SDK? В интерфейсе командной строки хостинга A2? У меня есть файл .json, который я загрузил из Google с моими учетными данными, и путь к нему правильный, согласно технической поддержке A2.   -  person PsiKai    schedule 06.10.2020
comment
Обычно при развертывании в облачной службе Google (App Engine, Compute Engine, Cloud Run и т. Д.) Вы разрешаете SDK использовать ADC. Затем вы настраиваете учетную запись службы по умолчанию с правильными ролями. Для какой службы вы развертываете? cloud.google.com/compute/docs/access/service-accounts   -  person John Hanley    schedule 06.10.2020
comment
Я разработал и развернул приложение за пределами среды Google, используя клиентскую библиотеку Google через node.js и загрузив SDK на свой локальный компьютер. Я использовал SDK для активации учетных данных учетной записи службы через файл .json, созданный Google в моей учетной записи службы. Я загрузил файлы кода на хостинг A2 с помощью CoreFTP. Учетная запись службы выполняет роль администратора для объектов хранилища для проекта, включая создание / удаление объектов, которые я установил в облачной консоли.   -  person PsiKai    schedule 06.10.2020
comment
Затем вам нужно будет указать имя файла JSON-ключа учетной записи службы при создании клиента. Используйте такой код: const storage = new Storage({keyFilename: "/fullpath/serviceaccount.json"});   -  person John Hanley    schedule 06.10.2020
comment
Я попытался выполнить этот точный код, но он по-прежнему дает мне ту же ошибку. Со службой технической поддержки A2 я подтвердил, что указал правильный путь к файлу, и они предполагают, что это проблема с учетными данными, а не с путем к файлу.   -  person PsiKai    schedule 06.10.2020
comment
Ошибка Could not load the default credentials означает, что вы неправильно указываете файл для загрузки учетных данных. Отредактируйте свой вопрос и покажите код, который вы используете, и удалите код, который вы пробовали. Затем опубликуйте ошибки, соответствующие коду. Включите строки, которые показывают библиотеки, которые вы используете.   -  person John Hanley    schedule 06.10.2020
comment
@JohnHanley Обновлено   -  person PsiKai    schedule 06.10.2020
comment
Я нашел здесь некоторую информацию (github.com/googleapis/google-auth -library-nodejs / issues / 798). Вы используете определенные API, такие как Cloud Vision? Чтобы получить больше информации, можете ли вы развернуть свои функции с включенным дополнительным ведением журнала (DEBUG_AUTH)?   -  person MrTech    schedule 12.10.2020