我使用 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 存取權令牌、簽署 blob 或 JWT 等)。
的文檔getSignedUrl
說:
在這些環境中,我們呼叫signBlob API 來建立簽章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:需要 iam.serviceAccounts.signBlob 權限才能對服務帳戶項目/-/serviceAccounts/ 執行此操作[電子郵件受保護]。
我不知道如何檢查我的服務帳戶是否具有此權限。我嘗試在 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
我透過將「雲端功能服務代理」角色新增至我的「App Engine 預設服務帳戶」服務帳戶來解決這個問題。
去: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