getSignedUrl выдает «SigningError: Ошибка сервера метаданных»

getSignedUrl выдает «SigningError: Ошибка сервера метаданных»

Я использую 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

Связанный контент