Firebase的getSignedUrl()出现SigningError

35

我正在尝试使用file.getSignedUrl()从Firebase存储中通过Google Cloud Functions (Node.js)获取下载URL。在Cloud Functions控制台中,我遇到了以下错误:

{ SigningError: A Forbidden error was returned while attempting to retrieve an access token for the Compute Engine built-in service account. This may be because the Compute Engine instance does not have the correct permission scopes specified. Permission iam.serviceAccounts.signBlob is required to perform this operation on service account projects/myapp-cd94d/serviceAccounts/myapp-cd94d@appspot.gserviceaccount.com.
    at SigningError (/user_code/node_modules/@google-cloud/storage/build/src/file.js:58:9)
    at authClient.sign.then.catch.err (/user_code/node_modules/@google-cloud/storage/build/src/file.js:1019:22)
    at process._tickDomainCallback (internal/process/next_tick.js:135:7) name: 'SigningError' }

我从将 Firebase Admin SDK 添加到您的服务器文档中复制了代码。 我在functions文件夹中有我的serviceAccountKey.jsonfirebase deploy没有给出错误。

Error parsing triggers: Cannot find module 'serviceAccountKey.json'

所以我必须找到正确的路径到我的serviceAccountKey.json文件。我甚至生成了一个新的私钥,但这并没有解决问题。我使用的是firebase-admin 6.1.0firebase-tools 6.1.0版本。以下是我的代码中相关的部分:

const admin = require('firebase-admin');
var serviceAccount = require("./myapp-cd94d-firebase-adminsdk-1234x-sEcReT.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://myapp-cd94d.firebaseio.com"
});

...

const config = {
  action: 'read',
    expires: '03-17-2025'
  };

file.getSignedUrl(config).then(function(data) {
    const url = data[0];
    console.log(url);
  })
  .catch(function(error) {
    console.error(error);
  })

我看到 Doug Stevenson的回答 有不同的代码,但它似乎等效于文档中的代码。

2个回答

130
答案与Cloud Identity and Access Management有关。首先,转到您的Google Cloud Platform IAM&管理员页面。您将看到各种服务帐户。寻找类似于myapp-cd99d@appspot.gserviceaccount.com的服务帐户。在Name列中应该会显示App Engine默认服务帐户。(如果错误提示所引用的是不同的服务帐户,请查找该服务帐户。)
Role列中,您可能会看到一些角色,也可能没有。如果您收到SigningError消息,则Role列缺少角色Service Account Token Creator。选中myapp-cd99d@appspot.gserviceaccount.com左侧的复选框以选择服务帐户,然后单击右侧的铅笔进行编辑。在下一个屏幕中,单击+添加另一个角色。向下滚动到Service Accounts,选择Service Account Token Creator,并保存。现在,您应该可以在Roles列中看到App Engine默认服务帐户Service Account Token Creator。现在您有权限创建已签名的令牌。

接着,重复这些步骤并添加一个角色为 Storage Object Creator。这将允许你运行getSignedURL()

你可以选择保存或分配 Service Account Admin 和 Storage Admin,它们分别包括 Service Account Token CreatorStorage Object Creator 角色,以及其他角色。

现在,如果你收到了 SingingError 消息,那可能是因为你跑调了 Bruce Springsteen 的 "Glory Days"。 :-)


17
我想知道的是为什么这件事没有得到处理/记录。 - galki
1
默认情况下,从Firebase控制台获取的服务账户ID和通过Cloud Functions自动发现的账户ID都没有这些权限。 - galki
1
@ThomasDavidKehoe,如何使用gcloud实现这个功能?我看到了这个链接https://cloud.google.com/iam/docs/granting-roles-to-service-accounts,但您能给我展示一个例子吗? - ilya
1
Thomas David Kehoe的回答让我朝着正确的方向前进,但我找不到Storage Object Creator角色?我发现了这个SO答案,最终解决了给我的Firebase管理SDK所需的权限来创建SignedURL的问题:https://dev59.com/4q_la4cB1Zd3GeqPzd7a#53422174此外,我也发现这篇中等文章非常有帮助:https://medium.com/@hiranya911/firebase-create-custom-tokens-without-service-account-credentials-d6049c2d2d85 - devinm
1
我刚好在听布鲁斯·斯普林斯汀的《辉煌岁月》,同时阅读这篇文章... - Miguel Puig
显示剩余6条评论

6

1
最终这对我起作用了。 https://console.developers.google.com/apis/api/iam.googleapis.com/overview?project=PROJECT_NUMBER。 PROJECT_NUMBER来自Firebase项目设置。这是我的项目的12位数字。 - akhil xavier
这是对我有效的链接:https://console.cloud.google.com/apis/library/iamcredentials.googleapis.com?project=PROJECT_NAME_OR_PROJECT_NUMBER - SuttonY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接