Я использую Google Cloud Functions с триггером HTTP для создания конечной точки для вызова API. Эта конечная точка использует функцию getSignedUrl
из пакета Cloud Storage. Я хотел вернуть подписанный URL, чтобы клиент мог перейти PUT
по этому URL для загрузки файла.
Я получаю непоследовательное поведение с этим API. Иногда я получаю URL из функции. Затем я попытался обновить имя контейнера и получил эту ошибку:
{ SigningError: Failure from metadata server.
at /user_code/node_modules/@google-cloud/storage/src/file.js:1715:16
at getCredentials (/user_code/node_modules/@google-cloud/storage/node_modules/google-auto-auth/index.js:264:9)
at googleAuthClient.getCredentials (/user_code/node_modules/@google-cloud/storage/node_modules/google-auto-auth/index.js:148:11)
at process._tickDomainCallback (internal/process/next_tick.js:135:7) message: 'Failure from metadata server.' }
Если я изменю имя контейнера обратно, я все еще вижу эту ошибку. Я пробовал разные вещи, например, развертывание из терминала. Это дало мне ту же ошибку. Я также создал функцию с помощью браузера, и это начало работать. После того, как я попытался обновить имя контейнера, это перестало работать.
Погуглив, я думаю, что это проблема с разрешением или ACL, но я не уверен, как это подтвердить. В документации говорится, что функции запускаются с использованием <YOUR_PROJECT_ID>@appspot.gserviceaccount.com
учетной записи службы, что я могу подтвердить на вкладке «Общие» функции. Я вижу в IAM, что эта учетная запись службы имеет Service Account Token Creator
, что говорит:
Имитация учетных записей служб (создание токенов доступа OAuth2, подписание двоичных объектов или JWT и т. д.).
В документации getSignedUrl
говорится:
В этих средах мы вызываем API signBlob для создания подписанного URL. Этот API требует либоhttps://www.googleapis.com/auth/iamилиhttps://www.googleapis.com/auth/cloud-platformобласть действия, поэтому убедитесь, что они включены.
Мне кажется, этого должно быть достаточно, чтобы это работало. Я не знаю, как явно проверить области действия.
Единственное, что я пробовал, это запустить sign-blob
из терминала. Я запустил это:
gcloud iam service-accounts sign-blob --iam-account=<my-project-id>@appspot.gserviceaccount.com input.file output.file
и я получаю эту ошибку:
ОШИБКА: (gcloud.iam.service-accounts.sign-blob) PERMISSION_DENIED: Для выполнения этой операции в учетных записях служб projects/-/serviceAccounts/ требуется разрешение iam.serviceAccounts.signBlob[email protected].
Я не знаю, как проверить, есть ли у моей учетной записи службы это разрешение. Я пробовал искать его в IAM на веб-сайте, в gcloud
терминальной программе и в разрешениях, установленных для моих бакетов.
Вот код моей функции:
const storage = require('@google-cloud/storage')();
exports.getSignedUrl = (req, res) => {
if(req.method === 'POST') {
// Perform any authorization checks here to assert
// that the end user is authorized to upload.
const myBucket = storage.bucket('my-bucket-name');
const myFile = myBucket.file(req.body.filename);
const contentType = req.body.contentType;
// This link should only last 5 minutes
const expiresAtMs = Date.now() + 300000;
const config = {
action: 'write',
expires: expiresAtMs,
contentType: contentType
};
myFile.getSignedUrl(config, function(err, url) {
if (err) {
console.error(err);
res.status(500).end();
return;
}
res.send(url);
});
} else {
res.status(405).end();
}
}
Кто-нибудь видел это раньше или знает, почему это происходит? Или вы знаете, как я могу проверить, есть ли у моей учетной записи службы эти разрешения или области действия? Я чувствую, что это может быть ошибка в GCP, но, скорее всего, я что-то упускаю. Я застрял на этом на некоторое время, и я был бы признателен за любую помощь, которую вы можете оказать!
решение1
Я решил эту проблему, добавив роль «Cloud Functions Service Agent» к своей учетной записи службы «App Engine default service account».
Идти к:https://console.cloud.google.com/iam-admin/iam
найти «агент службы облачных функций»
управлять ролями
Я воспользовался рекомендациями по скриншотам в комментарии @rscotten:https://github.com/googleapis/nodejs-storage/issues/150
решение2
После некоторых проб и ошибок я обнаружил, что эта @google-cloud/storage
версия 1.6.0
давала мне такое поведение. Я понизил версию, 1.5.2
и она начала работать.
Я открыл по этому поводу тему на GitHub:https://github.com/googleapis/nodejs-storage/issues/150