From 5c1d9bd5c33f1a990ecfcfa60d2402a9bd54b2d7 Mon Sep 17 00:00:00 2001 From: weiminyu Date: Mon, 10 Sep 2018 13:16:44 -0700 Subject: [PATCH] Refactor DelegatedCredential provisioning for GSuite domains Updated the registar contact group management, which is the only use case for this credential. Also updated GSuite domain delegated admin access config in admin dashboard for both sandbox (used by alpha and sandbox) and prod. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=212320157 --- .../registry/config/CredentialModule.java | 23 +++++++++++++ .../registry/config/files/default-config.yaml | 5 +-- .../registry/groups/DirectoryModule.java | 15 ++------- .../registry/groups/GroupssettingsModule.java | 11 ++----- java/google/registry/request/Modules.java | 33 ------------------- 5 files changed, 30 insertions(+), 57 deletions(-) diff --git a/java/google/registry/config/CredentialModule.java b/java/google/registry/config/CredentialModule.java index 4061fd1b6..b6ba7fa52 100644 --- a/java/google/registry/config/CredentialModule.java +++ b/java/google/registry/config/CredentialModule.java @@ -79,6 +79,29 @@ public abstract class CredentialModule { return credential; } + /** + * Provides a {@link GoogleCredential} with delegated admin access for a G Suite domain. + * + *

The G Suite domain must grant delegated admin access to the registry service account with + * all scopes in {@code requiredScopes}, including ones not related to G Suite. + */ + @DelegatedCredential + @Provides + @Singleton + public static GoogleCredential provideDelegatedCredential( + @Config("credentialOauthScopes") ImmutableList requiredScopes, + @JsonCredential GoogleCredential googleCredential, + @Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress) { + return new GoogleCredential.Builder() + .setTransport(Utils.getDefaultTransport()) + .setJsonFactory(Utils.getDefaultJsonFactory()) + .setServiceAccountId(googleCredential.getServiceAccountId()) + .setServiceAccountPrivateKey(googleCredential.getServiceAccountPrivateKey()) + .setServiceAccountScopes(requiredScopes) + .setServiceAccountUser(gSuiteAdminAccountEmailAddress) + .build(); + } + /** Dagger qualifier for the Application Default Credential. */ @Qualifier public @interface DefaultCredential {} diff --git a/java/google/registry/config/files/default-config.yaml b/java/google/registry/config/files/default-config.yaml index 3ba24741e..2ff11252b 100644 --- a/java/google/registry/config/files/default-config.yaml +++ b/java/google/registry/config/files/default-config.yaml @@ -185,10 +185,7 @@ credentialOAuth: - https://www.googleapis.com/auth/drive # View and manage groups on your domain in Directory API. - https://www.googleapis.com/auth/admin.directory.group - # Inherited from current code. - # TODO(weiminyu): verify if the scope above is sufficient by itself. - - https://www.googleapis.com/auth/admin.directory.group.member - # View and manage the settings of a Google Apps Group. + # View and manage group settings in Group Settings API. - https://www.googleapis.com/auth/apps.groups.settings icannReporting: diff --git a/java/google/registry/groups/DirectoryModule.java b/java/google/registry/groups/DirectoryModule.java index 700efc48e..e5fe05f6c 100644 --- a/java/google/registry/groups/DirectoryModule.java +++ b/java/google/registry/groups/DirectoryModule.java @@ -16,12 +16,10 @@ package google.registry.groups; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.services.admin.directory.Directory; -import com.google.api.services.admin.directory.DirectoryScopes; -import com.google.common.collect.ImmutableSet; import dagger.Module; import dagger.Provides; +import google.registry.config.CredentialModule.DelegatedCredential; import google.registry.config.RegistryConfig.Config; -import javax.inject.Named; /** Dagger module for the Google {@link Directory} service. */ @Module @@ -29,15 +27,8 @@ public final class DirectoryModule { @Provides static Directory provideDirectory( - @Named("delegatedAdmin") GoogleCredential credential, - @Config("projectId") String projectId) { - return new Directory.Builder( - credential.getTransport(), - credential.getJsonFactory(), - credential.createScoped( - ImmutableSet.of( - DirectoryScopes.ADMIN_DIRECTORY_GROUP_MEMBER, - DirectoryScopes.ADMIN_DIRECTORY_GROUP))) + @DelegatedCredential GoogleCredential credential, @Config("projectId") String projectId) { + return new Directory.Builder(credential.getTransport(), credential.getJsonFactory(), credential) .setApplicationName(projectId) .build(); } diff --git a/java/google/registry/groups/GroupssettingsModule.java b/java/google/registry/groups/GroupssettingsModule.java index 7fe3ac481..23621e58c 100644 --- a/java/google/registry/groups/GroupssettingsModule.java +++ b/java/google/registry/groups/GroupssettingsModule.java @@ -16,12 +16,10 @@ package google.registry.groups; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.services.groupssettings.Groupssettings; -import com.google.api.services.groupssettings.GroupssettingsScopes; -import com.google.common.collect.ImmutableSet; import dagger.Module; import dagger.Provides; +import google.registry.config.CredentialModule.DelegatedCredential; import google.registry.config.RegistryConfig.Config; -import javax.inject.Named; /** Dagger module for the Google {@link Groupssettings} service. */ @Module @@ -29,12 +27,9 @@ public final class GroupssettingsModule { @Provides static Groupssettings provideDirectory( - @Named("delegatedAdmin") GoogleCredential credential, - @Config("projectId") String projectId) { + @DelegatedCredential GoogleCredential credential, @Config("projectId") String projectId) { return new Groupssettings.Builder( - credential.getTransport(), - credential.getJsonFactory(), - credential.createScoped(ImmutableSet.of(GroupssettingsScopes.APPS_GROUPS_SETTINGS))) + credential.getTransport(), credential.getJsonFactory(), credential) .setApplicationName(projectId) .build(); } diff --git a/java/google/registry/request/Modules.java b/java/google/registry/request/Modules.java index a0fe007c9..5b9cdf0ff 100644 --- a/java/google/registry/request/Modules.java +++ b/java/google/registry/request/Modules.java @@ -31,17 +31,14 @@ import com.google.appengine.api.urlfetch.URLFetchService; import com.google.appengine.api.urlfetch.URLFetchServiceFactory; import com.google.appengine.api.users.UserService; import com.google.appengine.api.users.UserServiceFactory; -import com.google.common.collect.ImmutableSet; import dagger.Binds; import dagger.Module; import dagger.Provides; -import google.registry.config.RegistryConfig.Config; import google.registry.keyring.api.KeyModule.Key; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.Set; import java.util.function.Function; -import javax.inject.Named; import javax.inject.Provider; import javax.inject.Singleton; @@ -206,35 +203,5 @@ public final class Modules { final Provider googleCredentialProvider) { return scopes -> googleCredentialProvider.get().createScoped(scopes); } - - /** - * Provides a GoogleCredential that will connect to GAE using delegated admin access. This is - * needed for API calls requiring domain admin access to the relevant GAFYD using delegated - * scopes, e.g. the Directory API and the Groupssettings API. - * - *

Note that you must call {@link GoogleCredential#createScoped} on the credential provided - * by this method first before using it, as this does not and cannot set the scopes, and a - * credential without scopes doesn't actually provide access to do anything. - */ - @Provides - @Singleton - @Named("delegatedAdmin") - static GoogleCredential provideDelegatedAdminGoogleCredential( - GoogleCredential googleCredential, - HttpTransport httpTransport, - @Config("gSuiteAdminAccountEmailAddress") String gSuiteAdminAccountEmailAddress) { - return new GoogleCredential.Builder() - .setTransport(httpTransport) - .setJsonFactory(googleCredential.getJsonFactory()) - .setServiceAccountId(googleCredential.getServiceAccountId()) - .setServiceAccountPrivateKey(googleCredential.getServiceAccountPrivateKey()) - // Set the scopes to empty because the default value is null, which throws an NPE in the - // GoogleCredential constructor. We don't yet know the actual scopes to use here, and it - // is thus the responsibility of every user of a delegated admin credential to call - // createScoped() on it first to get the version with the correct scopes set. - .setServiceAccountScopes(ImmutableSet.of()) - .setServiceAccountUser(gSuiteAdminAccountEmailAddress) - .build(); - } } }