如何授予对Cloud Function的访问权限,以便它可以访问G-suite用户的G-mail帐户

时间:2020-09-18 15:10:06

标签: google-cloud-platform google-cloud-functions gmail-api service-accounts

我要做什么。

我正在尝试使Cloud Function能够访问G-suite用户的G-mail帐户,以便我可以在其上调用Gmail API监视功能。

问题

无法使用具有Cloud Function中委派权限的服务帐户在G-suite用户帐户上调用功能。重新收到400错误,提示错误请求,前提条件失败。

我尝试过的事情。

我已经按照此documentation然后在G-suite中在GCP中创建了服务帐户,为服务帐户指定了https://mail.google.com/的范围

我已经测试了如何成功访问在我的计算机上直接在下面运行代码的G-suite用户gmail帐户。我会注意到GoogleCredential已过时,因此我不在Cloud Function中使用它。

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());
        }
    }
}

我正在努力让Cloud Function做到这一点。从我的理解来看,因为我已经使用域范围内的授权权限设置了服务帐户,并称为ServiceAccountCredentials.GetApplicationDefault(),所以我不需要像在本地测试中那样在代码中引用凭据文件,尽管这样做可能是错的,link据我所知。

当我运行此代码时,当它尝试运行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"
} ]

很难理解服务帐户,云功能和Gmail API协同工作的方式,因此,如果有人可以帮助我,那就太好了。

谢谢。

编辑1-G-suite控制台,显示授予服务帐户的访问权限。 enter image description here

0 个答案:

没有答案
相关问题