自昨天以来,我一直在努力解决这个问题。寻找帮助其他遇到类似问题的人的解决方案,但没有什么对我有用。如果有人可以帮助我,我将不胜感激!
我创建了一个项目(名称:xxx),其中app引擎(id:app-xxx)监视GCS存储桶(名称:bucket-xxx)。 App引擎和存储桶位于同一个项目中。我尝试按照列出here列出的步骤:
使用p12密钥创建服务帐户(电子邮件:xxx@app-xxx.iam.gserviceaccount.com)。
列入白名单的网址(属性:https://app-xxx.appspot.com)。我看到网站管理员搜索控制台中列出的网址。当我使用网站管理员列表API时,也列出了相同的内容。
注册域名(app-xxx.appspot.com /)
配置gsutil以使用服务帐户 " gcloud auth activate-service-account xxx@app-xxx.iam.gserviceaccount.com --key-file path / to / key.p12"。已通过" gcloud auth list"验证命令,报告:
Credentialed帐户: - xxx@app-xxx.iam.gserviceaccount.com(有效)
我在开发者控制台的“权限”页面中看到了权限: app-xxx@appspot.gserviceaccount.com(App Engine服务帐户)
我也可以成功将文件从本地机器上传到GCS bucket-xxx: " gsutils cp local-file gs:// bucket-xxx /"
但是,当我设置通知时,它会报告: " ServiceException:401未经授权的WebHook回调频道:https://app-xxx.appspot.com/notification"
收到的响应标头显示以下错误: " WWW-Authenticate:Bearer realm =" https://accounts.google.com/" ;, error = invalid_token"
任何想法在这里可能是错的?谢谢!
答案 0 :(得分:4)
当您使用不是应用程序的默认服务帐户凭据(即您自己创建的服务帐户,即非自己创建的服务帐户)为App Engine应用程序指定webhook时,可能会出现问题app-xxx@appspot.gserviceaccount.com)。由于无法获得此帐户的p12密钥,因此您无法使用gsutil添加手表。
您需要做的是使用JSON API和应用程序的默认服务帐户凭据(AppAssertionCredentials)从App Engine应用程序内部添加监视。这是一个不完整的Python示例(我的默认设置,因为我不知道您的应用使用哪种语言),这说明了如何使用google-api-python-client来实现这一点:
from oauth2client.appengine import AppAssertionCredentials
from httplib2 import Http
from apiclient.discovery import build
credentials = AppAssertionCredentials('https://www.googleapis.com/auth/devstorage.read_only')
http_auth = credentials.authorize(Http())
storage = build('storage', 'v1', http=http_auth)
request = service.objects().watchAll(bucket='mybucket', body={args...})
request.execute()
请参阅watchAll的pydoc。请注意,您需要将应用程序的默认服务帐户添加到存储桶的ACL中才能使其正常工作(这几乎总是app-id@appspot.gserviceaccount.com,可在&#中查看39; Developer Console的权限部分)。
答案 1 :(得分:0)
只需扩展Sevle的答案:即使从(例如)Secret Manager 中检索默认应用程序服务帐户的凭据,然后从中创建客户端,也会发生这种情况< / em>。
在用TypeScript编写的Firebase项目中,我必须将代码从以下位置更改:
return google.auth.getClient({
credentials,
scopes: ['https://www.googleapis.com/auth/calendar'],
})
.then((client) => {
client.subject = settings.get('apiUser');
return google.calendar({
version: 'v3',
auth: client,
});
});
改为这样工作:
return new GoogleAuth({
scopes: ['https://www.googleapis.com/auth/calendar'],
clientOptions: { subject: settings.get('apiUser') },
}).getClient()
.then((client) =>
google.calendar({
version: 'v3',
auth: client,
})
);
请注意,第一个示例中的google
中的google.auth.getClient
与npm上的软件包googleapis
捆绑在一起,但是第二个示例中使用的new GoogleAuth
实际上来自{ {1}}。
我们对应用程序架构进行了少许更改,因此在不同的请求上我们不需要使用不同的服务帐户,因此现在对我们有用。