Google Cloud Function访问Secrets Manager权限问题求助
问题场景
前端请求后端Cloud Function端点,由后端从Secrets Manager获取密钥,端点代码如下:
Endpoint.get("/get-key", authMiddleware, async (req: any, res: Response) => { try { const auth = new GoogleAuth({ scopes: ['https://www.googleapis.com/auth/cloud-platform'] }); const project = req.params.projectId; const secret = req.params.secret; const name = `projects/${project}/secrets/${secret}/versions/latest`; const credentials = await auth.getCredentials(); const ver = new SecretManagerServiceClient({credentials,projectId:project}); const request = { name, }; const response = await ver.accessSecretVersion(request); const payload = response.payload.data.toString(); console.log(`Payload: ${payload}`); return res.status(200).send({ payload }); } catch (error:any) { console.log("get key error: ", error); return res.status(500).send(error.message); } });
报错信息
PERMISSION_DENIED: Permission denied: Consumer 'project:undefined' has been suspended
排查与解决方案
先确认请求参数传递是否正确
错误里的project:undefined说明req.params.projectId没拿到有效值,先检查前端请求路径是否为/get-key/:projectId/:secret,确保参数位置对应;如果是通过query参数传递的,要改成req.query.projectId,别混淆了params和query参数的获取方式。简化SecretManager客户端初始化逻辑
Cloud Function运行时会自动使用服务账号的默认凭据,无需手动获取credentials再传入,直接初始化客户端并显式传入projectId即可:const ver = new SecretManagerServiceClient({ projectId: project });手动传递credentials反而可能覆盖默认服务账号权限,引发不必要的问题。
给服务账号配置正确权限
找到Cloud Function使用的服务账号(通常为你的项目ID@appspot.gserviceaccount.com),在IAM控制台为其添加roles/secretmanager.secretAccessor角色,确保该账号拥有访问Secrets Manager密钥的权限。检查GCP项目状态
报错提到的"has been suspended"可能是项目本身状态异常,去GCP控制台的项目设置页面确认,项目是否因欠费、违规等原因被暂停,这会直接导致权限验证失败。关于"latest"版本路径的说明
这个路径格式是有效的,latest是Secrets Manager官方支持的版本别名,用来指向最新创建的密钥版本,无需怀疑这部分的正确性。
内容的提问来源于stack exchange,提问作者haredev

