API 호출에 대한 엔드포인트를 생성하기 위해 HTTP 트리거와 함께 Google Cloud Functions를 사용하고 있습니다. 이 엔드포인트는 getSignedUrl
Cloud Storage 패키지의 함수를 사용하고 있습니다. 클라이언트가 PUT
해당 URL로 파일을 업로드할 수 있도록 서명된 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: 서비스 계정 projects/-/serviceAccounts/에서 이 작업을 수행하려면 iam.serviceAccounts.signBlob 권한이 필요합니다.[이메일 보호됨].
내 서비스 계정에 이 권한이 있는지 확인하는 방법을 모르겠습니다. 웹사이트의 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 기본 서비스 계정' 서비스 계정에 'Cloud Functions 서비스 에이전트' 역할을 추가하여 문제를 해결했습니다.
이동 :https://console.cloud.google.com/iam-admin/iam
"Cloud Functions 서비스 에이전트"를 찾으세요.
역할 관리
@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