From e80f2934387794e0421674a70daaa61619d7a55a Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Fri, 22 Jan 2021 14:31:13 -0500 Subject: [PATCH] Require an override flag to allow updating pending delete domains (#939) * Require an override flag to allow updating pending delete domains Needing to update pending delete domains is an uncommon situation, yet currently we are allowing superusers to do so without any extra validation (which has led to errors). This adds a new override flag to gate the update of pending delete domains; without it, the update will fail. --- .../registry/tools/UpdateDomainCommand.java | 12 ++++ .../tools/UpdateDomainCommandTest.java | 59 ++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/google/registry/tools/UpdateDomainCommand.java b/core/src/main/java/google/registry/tools/UpdateDomainCommand.java index a0e99f703..8a84d7078 100644 --- a/core/src/main/java/google/registry/tools/UpdateDomainCommand.java +++ b/core/src/main/java/google/registry/tools/UpdateDomainCommand.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.domain.rgp.GracePeriodStatus.AUTO_RENEW; +import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE; import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.util.PreconditionsUtils.checkArgumentPresent; @@ -139,6 +140,11 @@ final class UpdateDomainCommand extends CreateOrUpdateDomainCommand { + " deleted at the end of its current registration period.") Boolean autorenews; + @Parameter( + names = {"--force_in_pending_delete"}, + description = "Force a superuser update even on domains that are in pending delete") + boolean forceInPendingDelete; + @Override protected void initMutatingEppToolCommand() { if (!nameservers.isEmpty()) { @@ -186,6 +192,12 @@ final class UpdateDomainCommand extends CreateOrUpdateDomainCommand { "The domain '%s' has status SERVER_UPDATE_PROHIBITED. Verify that you are allowed " + "to make updates, and if so, use the domain_unlock command to enable updates.", domain); + checkArgument( + !domainBase.getStatusValues().contains(PENDING_DELETE) || forceInPendingDelete, + "The domain '%s' has status PENDING_DELETE. Verify that you really are intending to " + + "update a domain in pending delete (this is uncommon), and if so, pass the " + + "--force_in_pending_delete parameter to allow this update.", + domain); // Use TreeSets so that the results are always in the same order (this makes testing easier). Set addAdminsThisDomain = new TreeSet<>(addAdmins); diff --git a/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java b/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java index 8c15348ba..b4ca09ff2 100644 --- a/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdateDomainCommandTest.java @@ -16,6 +16,7 @@ package google.registry.tools; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.domain.rgp.GracePeriodStatus.AUTO_RENEW; +import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE; import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE; import static google.registry.testing.DatabaseHelper.createTld; @@ -334,6 +335,39 @@ class UpdateDomainCommandTest extends EppToolCommandTestCase adminResourceKey1 = adminContact1.createVKey(); + VKey adminResourceKey2 = adminContact2.createVKey(); + VKey techResourceKey1 = techContact1.createVKey(); + VKey techResourceKey2 = techContact2.createVKey(); + + persistResource( + newDomainBase("example.tld") + .asBuilder() + .setContacts( + ImmutableSet.of( + DesignatedContact.create(DesignatedContact.Type.ADMIN, adminResourceKey1), + DesignatedContact.create(DesignatedContact.Type.ADMIN, adminResourceKey2), + DesignatedContact.create(DesignatedContact.Type.TECH, techResourceKey1), + DesignatedContact.create(DesignatedContact.Type.TECH, techResourceKey2))) + .setStatusValues(ImmutableSet.of(PENDING_DELETE)) + .build()); + + runCommandForced( + "--client=NewRegistrar", + "--admins=crr-admin2,crr-admin3", + "--techs=crr-tech2,crr-tech3", + "--superuser", + "--force_in_pending_delete", + "example.tld"); + eppVerifier.expectSuperuser().verifySent("domain_update_set_contacts.xml"); + } + @Test void testFailure_cantUpdateRegistryLockedDomainEvenAsSuperuser() { HostResource host = persistActiveHost("ns1.zdns.google"); @@ -356,7 +390,30 @@ class UpdateDomainCommandTest extends EppToolCommandTestCase> nameservers = ImmutableSet.of(host.createVKey()); + persistResource( + newDomainBase("example.tld") + .asBuilder() + .setStatusValues(ImmutableSet.of(PENDING_DELETE)) + .setNameservers(nameservers) + .build()); + + Exception e = + assertThrows( + IllegalArgumentException.class, + () -> + runCommandForced( + "--client=NewRegistrar", + "--statuses=clientRenewProhibited,serverHold", + "--superuser", + "example.tld")); + assertThat(e).hasMessageThat().contains("The domain 'example.tld' has status PENDING_DELETE."); } @Test