getSignedUrl 给出“签名错误:元数据服务器失败”

jsa*_*buo 4 google-cloud-storage google-cloud-platform

我正在使用带有 HTTP 触发器的 Google Cloud Functions 来为 API 调用创建端点。此端点正在使用getSignedUrlCloud 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.' }
Run Code Online (Sandbox Code Playgroud)

如果我改回存储桶名称,我仍然会看到此错误。我尝试了不同的方法,例如从终端部署。那给了我同样的错误。我还使用浏览器创建了该功能,并开始工作。在我尝试更新存储桶名称后,它停止工作。

通过谷歌搜索,我认为这是权限或 ACL 问题,但我不确定如何确认。文档说函数使用<YOUR_PROJECT_ID>@appspot.gserviceaccount.com服务帐户运行,我可以在函数的常规选项卡中确认。我可以在 IAM 中看到此服务帐户具有Service Account Token Creator,它说:

模拟服务帐户(创建 OAuth2 访问令牌、签署 blob 或 JWT 等)。

的文档getSignedUrl说:

在这些环境中,我们调用 signBlob API 来创建签名 URL。该 API 需要https://www.googleapis.com/auth/iamhttps://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
Run Code Online (Sandbox Code Playgroud)

我回来了这个错误:

错误:(gcloud.iam.service-accounts.sign-blob) PERMISSION_DENIED:需要权限 iam.serviceAccounts.signBlob 才能对服务帐户项目/-/serviceAccounts/my-project-id@appspot.gserviceaccount.com 执行此操作。

我不知道如何检查我的服务帐户是否具有此权限。我已经尝试在网站上的 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有人以前见过这个,或者知道为什么会这样?或者您知道如何检查我的服务帐户是否具有这些权限或范围?我觉得这可能是 GCP 中的一个错误,但很可能我遗漏了一些东西。我已经被困在这个问题上一段时间了,如果您能提供任何帮助,我将不胜感激!

Mat*_*man 12

我通过将“云函数服务代理”角色添加到我的“App Engine 默认服务帐户”服务帐户来解决它。

转到:https : //console.cloud.google.com/iam-admin/iam

找到“云功能服务代理”
管理角色

我在@rscotten 评论中得到了屏幕剪辑的指导:https : //github.com/googleapis/nodejs-storage/issues/150