getSignedUrl에서 "SigningError: 메타데이터 서버 오류"를 표시합니다.

getSignedUrl에서 "SigningError: 메타데이터 서버 오류"를 표시합니다.

API 호출에 대한 엔드포인트를 생성하기 위해 HTTP 트리거와 함께 Google Cloud Functions를 사용하고 있습니다. 이 엔드포인트는 getSignedUrlCloud 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

관련 정보