diff --git a/core/src/main/java/google/registry/batch/BatchModule.java b/core/src/main/java/google/registry/batch/BatchModule.java
index 95b64a88a..ece51133d 100644
--- a/core/src/main/java/google/registry/batch/BatchModule.java
+++ b/core/src/main/java/google/registry/batch/BatchModule.java
@@ -17,7 +17,6 @@ package google.registry.batch;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESAVE_TIMES;
import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
-import static google.registry.batch.CannedScriptExecutionAction.SCRIPT_PARAM;
import static google.registry.request.RequestParameters.extractBooleanParameter;
import static google.registry.request.RequestParameters.extractIntParameter;
import static google.registry.request.RequestParameters.extractLongParameter;
@@ -139,11 +138,4 @@ public class BatchModule {
static boolean provideIsDryRun(HttpServletRequest req) {
return extractBooleanParameter(req, PARAM_DRY_RUN);
}
-
- // TODO(b/234424397): remove method after credential changes are rolled out.
- @Provides
- @Parameter(SCRIPT_PARAM)
- static String provideScriptName(HttpServletRequest req) {
- return extractRequiredParameter(req, SCRIPT_PARAM);
- }
}
diff --git a/core/src/main/java/google/registry/batch/CannedScriptExecutionAction.java b/core/src/main/java/google/registry/batch/CannedScriptExecutionAction.java
index f62098bed..1cd41d2ec 100644
--- a/core/src/main/java/google/registry/batch/CannedScriptExecutionAction.java
+++ b/core/src/main/java/google/registry/batch/CannedScriptExecutionAction.java
@@ -16,11 +16,9 @@ package google.registry.batch;
import static google.registry.request.Action.Method.POST;
-import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
-import google.registry.batch.cannedscript.GroupsApiChecker;
+import google.registry.batch.cannedscript.CannedScripts;
import google.registry.request.Action;
-import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import javax.inject.Inject;
@@ -35,7 +33,7 @@ import javax.inject.Inject;
*
This action can be invoked using the Nomulus CLI command: {@code nomulus -e ${env} curl
* --service BACKEND -X POST -u '/_dr/task/executeCannedScript?script=${script_name}'}
*/
-// TODO(b/234424397): remove class after credential changes are rolled out.
+// TODO(b/277239043): remove class after credential changes are rolled out.
@Action(
service = Action.Service.BACKEND,
path = "/_dr/task/executeCannedScript",
@@ -45,29 +43,18 @@ import javax.inject.Inject;
public class CannedScriptExecutionAction implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- static final String SCRIPT_PARAM = "script";
-
- static final ImmutableMap SCRIPTS =
- ImmutableMap.of("runGroupsApiChecks", GroupsApiChecker::runGroupsApiChecks);
-
- private final String scriptName;
-
@Inject
- CannedScriptExecutionAction(@Parameter(SCRIPT_PARAM) String scriptName) {
- logger.atInfo().log("Received request to run script %s", scriptName);
- this.scriptName = scriptName;
+ CannedScriptExecutionAction() {
+ logger.atInfo().log("Received request to run scripts.");
}
@Override
public void run() {
- if (!SCRIPTS.containsKey(scriptName)) {
- throw new IllegalArgumentException("Script not found:" + scriptName);
- }
try {
- SCRIPTS.get(scriptName).run();
- logger.atInfo().log("Finished running %s.", scriptName);
+ CannedScripts.runAllChecks();
+ logger.atInfo().log("Finished running scripts.");
} catch (Throwable t) {
- logger.atWarning().withCause(t).log("Error executing %s", scriptName);
+ logger.atWarning().withCause(t).log("Error executing scripts.");
throw new RuntimeException("Execution failed.");
}
}
diff --git a/core/src/main/java/google/registry/batch/cannedscript/CannedScripts.java b/core/src/main/java/google/registry/batch/cannedscript/CannedScripts.java
new file mode 100644
index 000000000..f99d81e2d
--- /dev/null
+++ b/core/src/main/java/google/registry/batch/cannedscript/CannedScripts.java
@@ -0,0 +1,199 @@
+// Copyright 2023 The Nomulus Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package google.registry.batch.cannedscript;
+
+import com.google.api.gax.core.FixedCredentialsProvider;
+import com.google.api.services.bigquery.Bigquery;
+import com.google.api.services.dataflow.Dataflow;
+import com.google.api.services.dns.Dns;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import com.google.cloud.tasks.v2.CloudTasksClient;
+import com.google.cloud.tasks.v2.CloudTasksSettings;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.flogger.FluentLogger;
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import google.registry.config.CredentialModule;
+import google.registry.config.CredentialModule.ApplicationDefaultCredential;
+import google.registry.config.RegistryConfig.Config;
+import google.registry.config.RegistryConfig.ConfigModule;
+import google.registry.util.GoogleCredentialsBundle;
+import google.registry.util.UtilsModule;
+import java.io.IOException;
+import java.util.Optional;
+import javax.inject.Singleton;
+
+/** Canned actions invoked from {@link google.registry.batch.CannedScriptExecutionAction}. */
+// TODO(b/277239043): remove class after credential changes are rolled out.
+public class CannedScripts {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private static final Supplier COMPONENT_SUPPLIER =
+ Suppliers.memoize(DaggerCannedScripts_CannedScriptsComponent::create);
+
+ public static void runAllChecks() {
+ CannedScriptsComponent component = COMPONENT_SUPPLIER.get();
+ String projectId = component.projectId();
+ Bigquery bigquery = component.bigQuery();
+ try {
+ bigquery.datasets().list(projectId).execute().getDatasets().stream()
+ .findAny()
+ .ifPresent(
+ datasets ->
+ logger.atInfo().log("Found a BQ dataset [%s]", datasets.getFriendlyName()));
+ logger.atInfo().log("Finished accessing BQ.");
+ } catch (IOException ioe) {
+ logger.atSevere().withCause(ioe).log("Failed to access bigquery.");
+ }
+ try {
+ Dataflow dataflow = component.dataflow();
+ dataflow.projects().jobs().list(projectId).execute().getJobs().stream()
+ .findAny()
+ .ifPresent(job -> logger.atInfo().log("Found a job [%s]", job.getName()));
+ logger.atInfo().log("Finished accessing Dataflow.");
+ } catch (IOException ioe) {
+ logger.atSevere().withCause(ioe).log("Failed to access dataflow.");
+ }
+ try {
+ Storage gcs = component.gcs();
+ gcs.listAcls(projectId + "-beam");
+ logger.atInfo().log("Finished accessing gcs.");
+ } catch (RuntimeException e) {
+ logger.atSevere().withCause(e).log("Failed to access gcs.");
+ }
+ try {
+ Dns dns = component.dns();
+ dns.managedZones().list(projectId).execute().getManagedZones().stream()
+ .findAny()
+ .ifPresent(zone -> logger.atInfo().log("Found one zone [%s].", zone.getName()));
+ logger.atInfo().log("Finished accessing dns.");
+ } catch (IOException ioe) {
+ logger.atSevere().withCause(ioe).log("Failed to access dns.");
+ }
+ try {
+ CloudTasksClient client = component.cloudtasksClient();
+ com.google.cloud.tasks.v2.Queue queue =
+ client.getQueue(
+ String.format(
+ "projects/%s/locations/%s/queues/async-actions",
+ projectId, component.locationId()));
+ logger.atInfo().log("Got async queue state [%s]", queue.getState().name());
+ logger.atInfo().log("Finished accessing cloudtasks.");
+ } catch (RuntimeException e) {
+ logger.atSevere().withCause(e).log("Failed to access cloudtasks.");
+ }
+ }
+
+ @Singleton
+ @Component(
+ modules = {
+ ConfigModule.class,
+ CredentialModule.class,
+ CannedScriptsModule.class,
+ UtilsModule.class
+ })
+ interface CannedScriptsComponent {
+ Bigquery bigQuery();
+
+ CloudTasksClient cloudtasksClient();
+
+ Dataflow dataflow();
+
+ Dns dns();
+
+ Storage gcs();
+
+ @Config("projectId")
+ String projectId();
+
+ @Config("locationId")
+ String locationId();
+ }
+
+ @Module
+ static class CannedScriptsModule {
+ @Provides
+ static Bigquery provideBigquery(
+ @ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
+ @Config("projectId") String projectId) {
+ return new Bigquery.Builder(
+ credentialsBundle.getHttpTransport(),
+ credentialsBundle.getJsonFactory(),
+ credentialsBundle.getHttpRequestInitializer())
+ .setApplicationName(projectId)
+ .build();
+ }
+
+ @Provides
+ static Dataflow provideDataflow(
+ @ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
+ @Config("projectId") String projectId) {
+ return new Dataflow.Builder(
+ credentialsBundle.getHttpTransport(),
+ credentialsBundle.getJsonFactory(),
+ credentialsBundle.getHttpRequestInitializer())
+ .setApplicationName(String.format("%s billing", projectId))
+ .build();
+ }
+
+ @Provides
+ static Storage provideGcs(
+ @ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle) {
+ return StorageOptions.newBuilder()
+ .setCredentials(credentialsBundle.getGoogleCredentials())
+ .build()
+ .getService();
+ }
+
+ @Provides
+ static Dns provideDns(
+ @ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
+ @Config("projectId") String projectId,
+ @Config("cloudDnsRootUrl") Optional rootUrl,
+ @Config("cloudDnsServicePath") Optional servicePath) {
+ Dns.Builder builder =
+ new Dns.Builder(
+ credentialsBundle.getHttpTransport(),
+ credentialsBundle.getJsonFactory(),
+ credentialsBundle.getHttpRequestInitializer())
+ .setApplicationName(projectId);
+
+ rootUrl.ifPresent(builder::setRootUrl);
+ servicePath.ifPresent(builder::setServicePath);
+
+ return builder.build();
+ }
+
+ @Provides
+ public static CloudTasksClient provideCloudTasksClient(
+ @ApplicationDefaultCredential GoogleCredentialsBundle credentials) {
+ CloudTasksClient client;
+ try {
+ client =
+ CloudTasksClient.create(
+ CloudTasksSettings.newBuilder()
+ .setCredentialsProvider(
+ FixedCredentialsProvider.create(credentials.getGoogleCredentials()))
+ .build());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return client;
+ }
+ }
+}
diff --git a/core/src/main/java/google/registry/batch/cannedscript/GroupsApiChecker.java b/core/src/main/java/google/registry/batch/cannedscript/GroupsApiChecker.java
deleted file mode 100644
index 26937b96d..000000000
--- a/core/src/main/java/google/registry/batch/cannedscript/GroupsApiChecker.java
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2022 The Nomulus Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package google.registry.batch.cannedscript;
-
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static google.registry.util.RegistrarUtils.normalizeRegistrarId;
-
-import com.google.api.services.admin.directory.Directory;
-import com.google.api.services.groupssettings.Groupssettings;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Streams;
-import com.google.common.flogger.FluentLogger;
-import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
-import google.registry.config.CredentialModule;
-import google.registry.config.CredentialModule.AdcDelegatedCredential;
-import google.registry.config.RegistryConfig.Config;
-import google.registry.config.RegistryConfig.ConfigModule;
-import google.registry.groups.DirectoryGroupsConnection;
-import google.registry.model.registrar.Registrar;
-import google.registry.model.registrar.RegistrarPoc;
-import google.registry.util.GoogleCredentialsBundle;
-import google.registry.util.UtilsModule;
-import java.util.List;
-import java.util.Set;
-import javax.inject.Singleton;
-
-/**
- * Verifies that the credential with the {@link AdcDelegatedCredential} annotation can be used to
- * access the Google Workspace Groups API.
- */
-// TODO(b/234424397): remove class after credential changes are rolled out.
-public class GroupsApiChecker {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private static final Supplier COMPONENT_SUPPLIER =
- Suppliers.memoize(DaggerGroupsApiChecker_GroupsConnectionComponent::create);
-
- public static void runGroupsApiChecks() {
- GroupsConnectionComponent component = COMPONENT_SUPPLIER.get();
- DirectoryGroupsConnection groupsConnection = component.groupsConnection();
-
- List registrars =
- Streams.stream(Registrar.loadAllCached())
- .filter(registrar -> registrar.isLive() && registrar.getType() == Registrar.Type.REAL)
- .collect(toImmutableList());
- for (Registrar registrar : registrars) {
- for (final RegistrarPoc.Type type : RegistrarPoc.Type.values()) {
- String groupKey =
- String.format(
- "%s-%s-contacts@%s",
- normalizeRegistrarId(registrar.getRegistrarId()),
- type.getDisplayName(),
- component.gSuiteDomainName());
- try {
- Set currentMembers = groupsConnection.getMembersOfGroup(groupKey);
- logger.atInfo().log("Found %s members for %s.", currentMembers.size(), groupKey);
- } catch (Exception e) {
- Throwables.throwIfUnchecked(e);
- throw new RuntimeException(e);
- }
- }
- }
- }
-
- @Singleton
- @Component(
- modules = {
- ConfigModule.class,
- CredentialModule.class,
- GroupsApiModule.class,
- UtilsModule.class
- })
- interface GroupsConnectionComponent {
- DirectoryGroupsConnection groupsConnection();
-
- @Config("gSuiteDomainName")
- String gSuiteDomainName();
- }
-
- @Module
- static class GroupsApiModule {
- @Provides
- static Directory provideDirectory(
- @AdcDelegatedCredential GoogleCredentialsBundle credentialsBundle,
- @Config("projectId") String projectId) {
- return new Directory.Builder(
- credentialsBundle.getHttpTransport(),
- credentialsBundle.getJsonFactory(),
- credentialsBundle.getHttpRequestInitializer())
- .setApplicationName(projectId)
- .build();
- }
-
- @Provides
- static Groupssettings provideGroupsSettings(
- @AdcDelegatedCredential GoogleCredentialsBundle credentialsBundle,
- @Config("projectId") String projectId) {
- return new Groupssettings.Builder(
- credentialsBundle.getHttpTransport(),
- credentialsBundle.getJsonFactory(),
- credentialsBundle.getHttpRequestInitializer())
- .setApplicationName(projectId)
- .build();
- }
- }
-}
diff --git a/core/src/main/java/google/registry/tools/RequestFactoryModule.java b/core/src/main/java/google/registry/tools/RequestFactoryModule.java
index 906a3f93d..2c8099228 100644
--- a/core/src/main/java/google/registry/tools/RequestFactoryModule.java
+++ b/core/src/main/java/google/registry/tools/RequestFactoryModule.java
@@ -24,7 +24,7 @@ import com.google.api.client.util.GenericData;
import com.google.auth.oauth2.UserCredentials;
import dagger.Module;
import dagger.Provides;
-import google.registry.config.CredentialModule.DefaultCredential;
+import google.registry.config.CredentialModule.ApplicationDefaultCredential;
import google.registry.config.RegistryConfig;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.GoogleCredentialsBundle;
@@ -56,7 +56,7 @@ class RequestFactoryModule {
@Provides
static HttpRequestFactory provideHttpRequestFactory(
- @DefaultCredential GoogleCredentialsBundle credentialsBundle,
+ @ApplicationDefaultCredential GoogleCredentialsBundle credentialsBundle,
@Config("iapClientId") Optional iapClientId) {
if (RegistryConfig.areServersLocal()) {
return new NetHttpTransport()