Add nameserver validation in domain update related flows

When updating domains, make sure that if the domains are nameserver restricted, the updated nameservers set on the domains are still consistent with the restriction.

When updating domains of a domain created restricted TLD, validate if the domain is still on the reserved list with nameserver restricted reservation. If it is not, there's likely some conflicting states of the domain that needs to be reconciled (e. g.the domain is removed from the reserved list after being created). Throws an exception in this case.

Also added missing tests for TLDs with nameserver whitelist.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=150781935
This commit is contained in:
jianglai 2017-03-21 11:50:13 -07:00 committed by Ben McIlwain
parent a958d0a6c3
commit 37440d6b29
7 changed files with 517 additions and 8 deletions

View file

@ -275,6 +275,11 @@ the domain to convert to a normal create and be billed for accordingly.
* Linked resource in pending delete prohibits operation. * Linked resource in pending delete prohibits operation.
* Nameservers are not whitelisted for this TLD. * Nameservers are not whitelisted for this TLD.
* Nameservers not specified for domain on TLD with nameserver whitelist. * Nameservers not specified for domain on TLD with nameserver whitelist.
* Nameservers are not whitelisted for this domain.
* Nameservers not specified for domain with nameserver-restricted
reservation.
* Requested domain does not have nameserver-restricted reservation for a
TLD that requires such a reservation to create domains.
* Registrant is not whitelisted for this TLD. * Registrant is not whitelisted for this TLD.
* 2306 * 2306
* Cannot add and remove the same value. * Cannot add and remove the same value.
@ -759,6 +764,12 @@ application. Updates cannot change the domain name that is being applied for.
clear that status. clear that status.
* Resource status prohibits this operation. * Resource status prohibits this operation.
* Nameservers are not whitelisted for this TLD. * Nameservers are not whitelisted for this TLD.
* Nameservers not specified for domain on TLD with nameserver whitelist.
* Nameservers are not whitelisted for this domain.
* Nameservers not specified for domain with nameserver-restricted
reservation.
* Requested domain does not have nameserver-restricted reservation for a
TLD that requires such a reservation to create domains.
* Registrant is not whitelisted for this TLD. * Registrant is not whitelisted for this TLD.
* Application status prohibits this domain update. * Application status prohibits this domain update.
* 2306 * 2306

View file

@ -29,8 +29,10 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
import static google.registry.flows.domain.DomainFlowUtils.updateDsData; import static google.registry.flows.domain.DomainFlowUtils.updateDsData;
import static google.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes; import static google.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld;
import static google.registry.flows.domain.DomainFlowUtils.validateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateDsData;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnDomain;
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld;
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld;
import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts;
@ -41,6 +43,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNot
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
import static google.registry.model.EppResourceUtils.loadDomainApplication; import static google.registry.model.EppResourceUtils.loadDomainApplication;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.CollectionUtils.nullToEmpty;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -56,7 +59,6 @@ import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId; import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeOperationException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeOperationException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainApplication;
import google.registry.model.domain.DomainCommand.Update; import google.registry.model.domain.DomainCommand.Update;
@ -99,7 +101,11 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.MissingAdminContactException} * @error {@link DomainFlowUtils.MissingAdminContactException}
* @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.MissingContactTypeException}
* @error {@link DomainFlowUtils.MissingTechnicalContactException} * @error {@link DomainFlowUtils.MissingTechnicalContactException}
* @error {@link NameserversNotAllowedForTldException} * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException}
* @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException}
* @error {@link DomainFlowUtils.NameserversNotAllowedForDomainException}
* @error {@link DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException}
* @error {@link DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.SecDnsAllUsageException} * @error {@link DomainFlowUtils.SecDnsAllUsageException}
@ -179,8 +185,9 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
throw new ApplicationStatusProhibitsUpdateException( throw new ApplicationStatusProhibitsUpdateException(
existingApplication.getApplicationStatus()); existingApplication.getApplicationStatus());
} }
Registry registry = Registry.get(tld);
FeesAndCredits feesAndCredits = FeesAndCredits feesAndCredits =
pricingLogic.getApplicationUpdatePrice(Registry.get(tld), existingApplication, now); pricingLogic.getApplicationUpdatePrice(registry, existingApplication, now);
FeeUpdateCommandExtension feeUpdate = FeeUpdateCommandExtension feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class); eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
// If the fee extension is present, validate it (even if the cost is zero, to check for price // If the fee extension is present, validate it (even if the cost is zero, to check for price
@ -201,6 +208,13 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow {
validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId()); validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId());
validateNameserversAllowedOnTld( validateNameserversAllowedOnTld(
tld, add.getNameserverFullyQualifiedHostNames()); tld, add.getNameserverFullyQualifiedHostNames());
InternetDomainName domainName =
InternetDomainName.from(existingApplication.getFullyQualifiedDomainName());
if (registry.getDomainCreateRestricted()) {
validateDomainAllowedOnCreateRestrictedTld(domainName);
}
validateNameserversAllowedOnDomain(
domainName, nullToEmpty(add.getNameserverFullyQualifiedHostNames()));
} }
private HistoryEntry buildHistory(DomainApplication existingApplication, DateTime now) { private HistoryEntry buildHistory(DomainApplication existingApplication, DateTime now) {

View file

@ -375,7 +375,8 @@ public class DomainFlowUtils {
} }
/** Validates if the requested domain can be reated on a domain create restricted TLD. */ /** Validates if the requested domain can be reated on a domain create restricted TLD. */
static void validateDomainCreateAllowed(InternetDomainName domainName) throws EppException { static void validateDomainAllowedOnCreateRestrictedTld(InternetDomainName domainName)
throws EppException {
ImmutableSet<ReservationType> reservationTypes = getReservationTypes(domainName); ImmutableSet<ReservationType> reservationTypes = getReservationTypes(domainName);
if (!reservationTypes.contains(NAMESERVER_RESTRICTED)) { if (!reservationTypes.contains(NAMESERVER_RESTRICTED)) {
throw new DomainNotAllowedForTldWithCreateRestrictionException(domainName.toString()); throw new DomainNotAllowedForTldWithCreateRestrictionException(domainName.toString());
@ -782,7 +783,7 @@ public class DomainFlowUtils {
validateNameserversCountForTld(tld, domainName, fullyQualifiedHostNames.size()); validateNameserversCountForTld(tld, domainName, fullyQualifiedHostNames.size());
validateNameserversAllowedOnTld(tld, fullyQualifiedHostNames); validateNameserversAllowedOnTld(tld, fullyQualifiedHostNames);
if (registry.getDomainCreateRestricted()) { if (registry.getDomainCreateRestricted()) {
validateDomainCreateAllowed(domainName); validateDomainAllowedOnCreateRestrictedTld(domainName);
} }
validateNameserversAllowedOnDomain(domainName, fullyQualifiedHostNames); validateNameserversAllowedOnDomain(domainName, fullyQualifiedHostNames);
} }

View file

@ -29,8 +29,10 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
import static google.registry.flows.domain.DomainFlowUtils.updateDsData; import static google.registry.flows.domain.DomainFlowUtils.updateDsData;
import static google.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes; import static google.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes;
import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld;
import static google.registry.flows.domain.DomainFlowUtils.validateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateDsData;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnDomain;
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld;
import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld;
import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts;
@ -39,6 +41,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRequiredConta
import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited; import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited;
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.DateTimeUtils.earliestOf; import static google.registry.util.DateTimeUtils.earliestOf;
import com.google.common.base.Optional; import com.google.common.base.Optional;
@ -116,6 +119,9 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.MissingTechnicalContactException} * @error {@link DomainFlowUtils.MissingTechnicalContactException}
* @error {@link DomainFlowUtils.NameserversNotAllowedForTldException} * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException}
* @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException} * @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException}
* @error {@link DomainFlowUtils.NameserversNotAllowedForDomainException}
* @error {@link DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException}
* @error {@link DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.SecDnsAllUsageException} * @error {@link DomainFlowUtils.SecDnsAllUsageException}
@ -209,13 +215,14 @@ public final class DomainUpdateFlow implements TransactionalFlow {
verifyAllStatusesAreClientSettable(union(add.getStatusValues(), remove.getStatusValues())); verifyAllStatusesAreClientSettable(union(add.getStatusValues(), remove.getStatusValues()));
} }
String tld = existingDomain.getTld(); String tld = existingDomain.getTld();
Registry registry = Registry.get(tld);
checkAllowedAccessToTld(clientId, tld); checkAllowedAccessToTld(clientId, tld);
FeeTransformCommandExtension feeUpdate = FeeTransformCommandExtension feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class); eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
// If the fee extension is present, validate it (even if the cost is zero, to check for price // If the fee extension is present, validate it (even if the cost is zero, to check for price
// mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because // mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because
// it throws an error if the name is premium, and we don't want to do that here. // it throws an error if the name is premium, and we don't want to do that here.
FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(Registry.get(tld), targetId, now); FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(registry, targetId, now);
if (feeUpdate != null) { if (feeUpdate != null) {
validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, feesAndCredits); validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, feesAndCredits);
} else if (!feesAndCredits.getTotalCost().isZero()) { } else if (!feesAndCredits.getTotalCost().isZero()) {
@ -231,6 +238,13 @@ public final class DomainUpdateFlow implements TransactionalFlow {
validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId()); validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId());
validateNameserversAllowedOnTld( validateNameserversAllowedOnTld(
tld, add.getNameserverFullyQualifiedHostNames()); tld, add.getNameserverFullyQualifiedHostNames());
InternetDomainName domainName =
InternetDomainName.from(existingDomain.getFullyQualifiedDomainName());
if (registry.getDomainCreateRestricted()) {
validateDomainAllowedOnCreateRestrictedTld(domainName);
}
validateNameserversAllowedOnDomain(
domainName, nullToEmpty(add.getNameserverFullyQualifiedHostNames()));
} }
private HistoryEntry buildHistoryEntry(DomainResource existingDomain, DateTime now) { private HistoryEntry buildHistoryEntry(DomainResource existingDomain, DateTime now) {

View file

@ -24,6 +24,7 @@ import static google.registry.testing.DatastoreHelper.generateNewDomainRoid;
import static google.registry.testing.DatastoreHelper.newDomainApplication; import static google.registry.testing.DatastoreHelper.newDomainApplication;
import static google.registry.testing.DatastoreHelper.persistActiveContact; import static google.registry.testing.DatastoreHelper.persistActiveContact;
import static google.registry.testing.DatastoreHelper.persistActiveHost; import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistReservedList;
import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.DomainApplicationSubject.assertAboutApplications; import static google.registry.testing.DomainApplicationSubject.assertAboutApplications;
import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME;
@ -39,6 +40,7 @@ import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException; import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException;
import google.registry.flows.domain.DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException; import google.registry.flows.domain.DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException;
import google.registry.flows.domain.DomainFlowUtils.ApplicationDomainNameMismatchException; import google.registry.flows.domain.DomainFlowUtils.ApplicationDomainNameMismatchException;
import google.registry.flows.domain.DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException;
import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException; import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException;
import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException; import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException;
import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException; import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
@ -47,7 +49,10 @@ import google.registry.flows.domain.DomainFlowUtils.MaxSigLifeChangeNotSupported
import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException;
import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException;
import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForDomainException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException;
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import google.registry.flows.domain.DomainFlowUtils.SecDnsAllUsageException; import google.registry.flows.domain.DomainFlowUtils.SecDnsAllUsageException;
@ -671,6 +676,241 @@ public class DomainApplicationUpdateFlowTest
doSuccessfulTest(); doSuccessfulTest();
} }
@Test
public void testFailure_tldWithNameserverWhitelist_removeLastNameserver() throws Exception {
setEppInput("domain_update_sunrise_remove_nameserver.xml");
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns2.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserversNotSpecifiedForTldWithNameserverWhitelistException.class);
runFlow();
}
@Test
public void testSuccess_tldWithNameserverWhitelist_removeNameserver() throws Exception {
setEppInput("domain_update_sunrise_remove_nameserver.xml");
persistReferencedEntities();
persistApplication();
persistResource(
reloadDomainApplication()
.asBuilder()
.addNameservers(
ImmutableSet.of(
Key.create(
loadByForeignKey(HostResource.class, "ns2.example.tld", clock.nowUtc()))))
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns2.example.tld"))
.build());
clock.advanceOneMilli();
doSuccessfulTest();
}
@Test
public void testSuccess_domainNameserverRestricted_addedNameserverAllowed() throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
doSuccessfulTest();
}
@Test
public void testFailure_domainNameserverRestricted_addedNameserverDisallowed() throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns3.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.tld");
runFlow();
}
@Test
public void testFailure_domainNameserverRestricted_removeLastNameserver() throws Exception {
setEppInput("domain_update_sunrise_remove_nameserver.xml");
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserversNotSpecifiedForNameserverRestrictedDomainException.class);
runFlow();
}
@Test
public void testSuccess_domainNameserverRestricted_removeNameservers() throws Exception {
setEppInput("domain_update_sunrise_remove_nameserver.xml");
persistReferencedEntities();
persistApplication();
persistResource(
reloadDomainApplication()
.asBuilder()
.addNameservers(
ImmutableSet.of(
Key.create(
loadByForeignKey(HostResource.class, "ns2.example.tld", clock.nowUtc()))))
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
doSuccessfulTest();
}
@Test
public void testSuccess_domainCreateRestricted_addedNameserverAllowed() throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setDomainCreateRestricted(true)
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
doSuccessfulTest();
}
@Test
public void testSuccess_addedNameserversAllowedInTldAndDomainNameserversWhitelists()
throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns2.example.tld"))
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
doSuccessfulTest();
}
@Test
public void testFailure_addedNameserversAllowedInTld_disallowedInDomainNameserversWhitelists()
throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns2.example.tld"))
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns3.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.tld");
runFlow();
}
@Test
public void testFailure_addedNameserversDisallowedInTld_AllowedInDomainNameserversWhitelists()
throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns3.example.tld"))
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserversNotAllowedForTldException.class, "ns2.example.tld");
runFlow();
}
@Test
public void testFailure_tldNameserversAllowed_domainCreateRestricted_domainNotReserved()
throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setDomainCreateRestricted(true)
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns2.example.tld"))
.setReservedLists(
persistReservedList(
"reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(DomainNotAllowedForTldWithCreateRestrictionException.class);
runFlow();
}
@Test
public void testFailure_domainCreateRestricted_domainNotReserved() throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setDomainCreateRestricted(true)
.setReservedLists(
persistReservedList(
"reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
thrown.expect(DomainNotAllowedForTldWithCreateRestrictionException.class);
runFlow();
}
@Test
public void testSuccess_domainCreateNotRestricted_domainNotReserved() throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld"))
.build());
clock.advanceOneMilli();
doSuccessfulTest();
}
@Test @Test
public void testFailure_customPricingLogic_feeMismatch() throws Exception { public void testFailure_customPricingLogic_feeMismatch() throws Exception {
persistReferencedEntities(); persistReferencedEntities();

View file

@ -29,6 +29,7 @@ import static google.registry.testing.DatastoreHelper.persistActiveDomain;
import static google.registry.testing.DatastoreHelper.persistActiveHost; import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistActiveSubordinateHost; import static google.registry.testing.DatastoreHelper.persistActiveSubordinateHost;
import static google.registry.testing.DatastoreHelper.persistDeletedDomain; import static google.registry.testing.DatastoreHelper.persistDeletedDomain;
import static google.registry.testing.DatastoreHelper.persistReservedList;
import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.DomainResourceSubject.assertAboutDomains; import static google.registry.testing.DomainResourceSubject.assertAboutDomains;
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries; import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
@ -46,6 +47,7 @@ import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException;
import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException;
import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException; import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException;
import google.registry.flows.domain.DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException;
import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException; import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException;
import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException; import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException;
import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException; import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
@ -56,7 +58,9 @@ import google.registry.flows.domain.DomainFlowUtils.MaxSigLifeChangeNotSupported
import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException;
import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException;
import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForDomainException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException;
import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException;
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
@ -1145,7 +1149,7 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
} }
@Test @Test
public void testSuccess_removeNameserverWhitelisted() throws Exception { public void testSuccess_tldWithNameserverWhitelist_removeNameserver() throws Exception {
setEppInput("domain_update_remove_nameserver.xml"); setEppInput("domain_update_remove_nameserver.xml");
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1168,7 +1172,7 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
} }
@Test @Test
public void testFailure_removeLastNameserverWhitelisted() throws Exception { public void testFailure_tldWithNameserverWhitelist_removeLastNameserver() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
setEppInput("domain_update_remove_nameserver.xml"); setEppInput("domain_update_remove_nameserver.xml");
@ -1180,6 +1184,196 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
runFlow(); runFlow();
} }
@Test
public void testSuccess_domainNameserverRestricted_addedNameserverAllowed() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
doSuccessfulTest();
}
@Test
public void testFailure_domainNameserverRestricted_addedNameserverDisallowed() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns3.example.foo"))
.build());
thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.foo");
runFlow();
}
@Test
public void testFailure_domainNameserverRestricted_removeLastNameserver() throws Exception {
persistReferencedEntities();
persistDomain();
setEppInput("domain_update_remove_nameserver.xml");
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
thrown.expect(NameserversNotSpecifiedForNameserverRestrictedDomainException.class);
runFlow();
}
@Test
public void testSuccess_domainNameserverRestricted_removeNameservers() throws Exception {
setEppInput("domain_update_remove_nameserver.xml");
persistReferencedEntities();
persistDomain();
persistResource(
reloadResourceByForeignKey()
.asBuilder()
.addNameservers(
ImmutableSet.of(
Key.create(
loadByForeignKey(HostResource.class, "ns2.example.foo", clock.nowUtc()))))
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
assertThat(reloadResourceByForeignKey().getNameservers())
.contains(
Key.create(loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc())));
clock.advanceOneMilli();
runFlow();
assertThat(reloadResourceByForeignKey().getNameservers())
.doesNotContain(
Key.create(loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc())));
}
@Test
public void testSuccess_domainCreateRestricted_addedNameserverAllowed() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns3.example.foo"))
.build());
thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.foo");
runFlow();
}
@Test
public void testSuccess_addedNameserversAllowedInTldAndDomainNameserversWhitelists()
throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.foo", "ns2.example.foo"))
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
doSuccessfulTest();
}
@Test
public void testFailure_addedNameserversAllowedInTld_disallowedInDomainNameserversWhitelists()
throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.foo", "ns2.example.foo"))
.setReservedLists(
persistReservedList("reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo"))
.build());
thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.foo");
runFlow();
}
@Test
public void testFailure_addedNameserversDisallowedInTld_AllowedInDomainNameserversWhitelists()
throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.foo"))
.setReservedLists(
persistReservedList(
"reserved", "example,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
thrown.expect(NameserversNotAllowedForTldException.class, "ns2.example.foo");
runFlow();
}
@Test
public void testFailure_tldNameserversAllowed_domainCreateRestricted_domainNotReserved()
throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setDomainCreateRestricted(true)
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.foo", "ns2.example.foo"))
.setReservedLists(
persistReservedList(
"reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
thrown.expect(DomainNotAllowedForTldWithCreateRestrictionException.class);
runFlow();
}
@Test
public void testFailure_domainCreateRestricted_domainNotReserved() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setDomainCreateRestricted(true)
.setReservedLists(
persistReservedList(
"reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
thrown.expect(DomainNotAllowedForTldWithCreateRestrictionException.class);
runFlow();
}
@Test
public void testSuccess_domainCreateNotRestricted_domainNotReserved() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld")
.asBuilder()
.setReservedLists(
persistReservedList(
"reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.foo:ns2.example.foo"))
.build());
doSuccessfulTest();
}
@Test @Test
public void testFailure_freePremium_wrongFee() throws Exception { public void testFailure_freePremium_wrongFee() throws Exception {
setEppInput("domain_update_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11")); setEppInput("domain_update_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));

View file

@ -0,0 +1,35 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<update>
<domain:update
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.tld</domain:name>
<domain:add>
<domain:contact type="tech">mak21</domain:contact>
<domain:status s="clientHold"
lang="en">Payment overdue.</domain:status>
</domain:add>
<domain:rem>
<domain:ns>
<domain:hostObj>ns1.example.tld</domain:hostObj>
</domain:ns>
<domain:contact type="tech">sh8013</domain:contact>
<domain:status s="clientUpdateProhibited"/>
</domain:rem>
<domain:chg>
<domain:registrant>sh8013</domain:registrant>
<domain:authInfo>
<domain:pw>2BARfoo</domain:pw>
</domain:authInfo>
</domain:chg>
</domain:update>
</update>
<extension>
<launch:update xmlns:launch="urn:ietf:params:xml:ns:launch-1.0">
<launch:phase name="landrush">sunrise</launch:phase>
<launch:applicationID>1-TLD</launch:applicationID>
</launch:update>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>