google-cloud-platform - 如何授予对云功能的访问权限,以便它可以访问 G-suite 用户的 G-mail 帐户
问题描述
我正在尝试做的事情。
我试图让云函数能够访问 G-suite 用户的 G-mail 帐户,以便我可以在它们上调用 Gmail API 监视函数。
问题
无法使用具有云函数中委派权限的服务帐户调用 G 套件用户帐户上的函数。得到一个 400 错误,说 Bad Request,Failed Precondition。
我试过的。
我按照此文档在 GCP 中创建了一个服务帐户,然后在 G-suite 中创建了一个服务帐户,为服务帐户提供了https://mail.google.com/的范围
我已经测试了访问 G-suite 用户的 gmail 帐户,该帐户直接在我的计算机上运行下面的代码。我会注意到 GoogleCredential 已被弃用,所以我没有在我的云函数中使用它。
public class WatchTest {
@Test
public void callWatchOnGSuiteUsers() throws IOException {
String SERVICE_ACCOUNT_FILE_PATH = "/path/file.json";
FileInputStream credentialsFile = new FileInputStream(SERVICE_ACCOUNT_FILE_PATH);
GoogleCredential init = GoogleCredential.fromStream(credentialsFile);
HttpTransport httpTransport = init.getTransport();
JsonFactory jsonFactory = init.getJsonFactory();
GoogleCredential credentials = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(init.getServiceAccountId())
.setServiceAccountPrivateKey(init.getServiceAccountPrivateKey())
.setServiceAccountScopes(Collections.singleton(GmailScopes.MAIL_GOOGLE_COM))
.setServiceAccountUser("user@example.com")
.build();
Gmail gmail = new Gmail.Builder(httpTransport, jsonFactory, credentials).setApplicationName("gmail").build();
List<String> watchTopics = new ArrayList<>();
watchTopics.add("INBOX");
WatchRequest watchRequest = new WatchRequest();
watchRequest.setLabelIds(watchTopics);
watchRequest.setTopicName("projects/{project-id}}/topics/{topic-name}}");
gmail.users().watch("user@example.com", watchRequest).execute();
}
我的云功能
部署使用:
gcloud functions deploy my-cloud-function
--entry-point WatchTrigger
--service-account deletgated-authority-test@<project-id>.iam.gserviceaccount.com
--runtime java11
--region <example-region>
--trigger-resource <bucket>
--trigger-event google.storage.object.finalize
云功能代码:
public class WatchTrigger implements BackgroundFunction<GcsEvent> {
@Override
public void accept(GcsEvent payload, Context context) throws Exception {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
List<String> scopes = new ArrayList<>();
scopes.add(GmailScopes.MAIL_GOOGLE_COM);
GoogleCredentials credentials = ServiceAccountCredentials.getApplicationDefault()
.createScoped(scopes)
.createDelegated("user@example.com")
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
Gmail gmail = new Gmail.Builder(httpTransport, jsonFactory, requestInitializer)
.setApplicationName("GMAIL")
.build();
ListLabelsResponse listResponse = gmail.users().labels().list("user@example.com").execute();
List<Label> labels = listResponse.getLabels();
if (labels.isEmpty()) {
System.out.println("No labels found.");
} else {
System.out.println("Labels:");
for (Label label : labels) {
System.out.printf("- %s\n", label.getName());
}
}
}
我正在努力让云功能做同样的事情。根据我的理解,因为我已经使用域范围的授权设置了服务帐户并调用了 ServiceAccountCredentials.GetApplicationDefault() 我不应该像在本地测试中那样在代码中引用凭据文件,尽管这可能错了,链接到我对此的理解。
当我运行此代码时,它尝试运行 gmail.getLabels 函数时返回 400 错误。所以我不太确定问题出在那个电话还是凭证上。但是从我在其他类似的 Stack Overflow 帖子上看到的情况来看,其他人正在返回相同的错误,他们正在讨论凭据是问题所在。
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
GET https://www.googleapis.com/gmail/v1/users/user@example.com/labels
{
"code" : 400,
"error" : [ {
"domain" : "global",
"message" : Precondition check failed.".
"reason" : "failedPrecondition"
} ]
很难理解服务帐户、Cloud Functions 和 Gmail API 协同工作的方式,所以如果有人能在这方面帮助我,那就太好了。
谢谢。
解决方案
推荐阅读
- r - 用数据框中的另一列标记 x 轴
- swift - 是否可以使用 CoreML 模型检测对象并找到该对象的测量值?
- c++ - ZMQ - 丢包
- android - 如何在每次点击时将 Android 按钮中编辑文本的最大长度字符限制增加 10 个?
- vue.js - 以编程方式设置输入值不会刷新组件 DOM
- r - openxlsx 使用与我的普通 Excel 应用程序不同的表格样式
- android - setDefaultNightMode() 仅在 PreferenceFragment 中的第二次调用后有效
- sql-server - SQL Server 中的按位运算
- c# - JSON 值无法转换为 System.Int32
- javascript - 检测圆重叠