Estou usando o Google Cloud Functions com um gatilho HTTP para criar um endpoint para uma chamada de API. Este endpoint usa a getSignedUrl
função do pacote Cloud Storage. Eu queria retornar um URL assinado para que o cliente pudesse PUT
acessar esse URL para fazer upload de um arquivo.
Estou tendo um comportamento inconsistente com esta API. Às vezes, recebo de volta um URL da função. Tentei atualizar o nome do bucket e recebi este erro:
{ 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.' }
Se eu alterar o nome do bucket novamente, ainda vejo esse erro. Eu tentei coisas diferentes, como implantar a partir do terminal. Isso me deu o mesmo erro. Também criei a função com o navegador e começou a funcionar. Depois de tentar atualizar o nome do bucket, ele parou de funcionar.
Pesquisando no Google, acho que se trata de um problema de permissão ou ACL, mas não sei como confirmá-lo. A documentação diz que as funções são executadas usando <YOUR_PROJECT_ID>@appspot.gserviceaccount.com
conta de serviço, o que posso confirmar na aba geral da função. Posso ver no IAM que esta conta de serviço tem o Service Account Token Creator
, que diz:
Representar contas de serviço (criar tokens de acesso OAuth2, assinar blobs ou JWTs, etc.).
A documentação para getSignedUrl
diz:
Nesses ambientes, chamamos a API signBlob para criar um URL assinado. Essa API requer ohttps://www.googleapis.com/auth/iamouhttps://www.googleapis.com/auth/cloud-platformescopo, portanto, certifique-se de que eles estejam ativados.
Eu sinto que isso deve ser suficiente para que funcione. Não sei como verificar explicitamente os escopos.
A única outra coisa que tentei foi executar sign-blob
a partir do terminal. Eu corri isso:
gcloud iam service-accounts sign-blob --iam-account=<my-project-id>@appspot.gserviceaccount.com input.file output.file
e recebo de volta este erro:
ERRO: (gcloud.iam.service-accounts.sign-blob) PERMISSION_DENIED: a permissão iam.serviceAccounts.signBlob é necessária para executar esta operação em projetos de conta de serviço/-/serviceAccounts/[e-mail protegido].
Não sei como verificar se minha conta de serviço tem essa permissão. Tentei procurá-lo no IAM no site, no gcloud
programa de terminal e nas permissões definidas em meus buckets.
Aqui está o código da minha função:
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();
}
}
Alguém já viu isso antes ou sabe por que isso está acontecendo? Ou você sabe como posso verificar se minha conta de serviço tem essas permissões ou escopos? Sinto que isso pode ser um bug no GCP, mas é provável que esteja faltando alguma coisa. Estou preso nisso há um tempo e agradeceria qualquer ajuda que você possa ter!
Responder1
Resolvi isso adicionando a função "Agente de serviço do Cloud Functions" à minha conta de serviço "Conta de serviço padrão do App Engine".
Vá para:https://console.cloud.google.com/iam-admin/iam
encontre "Agente de serviço do Cloud Functions"
gerenciar funções
Fui guiado por clipes de tela no comentário de @rscotten:https://github.com/googleapis/nodejs-storage/issues/150
Responder2
Depois de algumas tentativas e erros, descobri que aquela @google-cloud/storage
versão 1.6.0
estava me causando esse comportamento. Fiz o downgrade para 1.5.2
e começou a funcionar.
Abri um problema no GitHub para isso:https://github.com/googleapis/nodejs-storage/issues/150