Adds the ability to whitelist registrants and nameservers on a TLD

This is needed for ROCC TLDs like .foo
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=118404870
This commit is contained in:
cgoldfeder 2016-03-28 16:16:42 -07:00 committed by Justine Tunney
parent f9e1bab1d2
commit ec2daec412
17 changed files with 576 additions and 85 deletions

View file

@ -22,6 +22,7 @@ import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDo
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDsData; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDsData;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNameservers; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNameservers;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRegistrantAllowedOnTld;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyLaunchPhase; import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyLaunchPhase;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
@ -207,9 +208,10 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
command.getRegistrant(), command.getRegistrant(),
command.getNameservers()); command.getNameservers());
validateContactsHaveTypes(command.getContacts()); validateContactsHaveTypes(command.getContacts());
validateRegistrantAllowedOnTld(tld, command.getRegistrant());
validateNoDuplicateContacts(command.getContacts()); validateNoDuplicateContacts(command.getContacts());
validateRequiredContactsPresent(command.getRegistrant(), command.getContacts()); validateRequiredContactsPresent(command.getRegistrant(), command.getContacts());
validateNameservers(command.getNameservers()); validateNameservers(tld, command.getNameservers());
validateLaunchCreateExtension(); validateLaunchCreateExtension();
// If a signed mark was provided, then it must match the desired domain label. // If a signed mark was provided, then it must match the desired domain label.
// We do this after validating the launch create extension so that flows which don't allow any // We do this after validating the launch create extension so that flows which don't allow any

View file

@ -22,6 +22,7 @@ import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateCo
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDsData; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateDsData;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNameservers; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNameservers;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRegistrantAllowedOnTld;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent; import static com.google.domain.registry.flows.domain.DomainFlowUtils.validateRequiredContactsPresent;
import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static com.google.domain.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete;
@ -121,7 +122,8 @@ public abstract class BaseDomainUpdateFlow<R extends DomainBase, B extends Build
validateNoDuplicateContacts(newResource.getContacts()); validateNoDuplicateContacts(newResource.getContacts());
validateRequiredContactsPresent(newResource.getRegistrant(), newResource.getContacts()); validateRequiredContactsPresent(newResource.getRegistrant(), newResource.getContacts());
validateDsData(newResource.getDsData()); validateDsData(newResource.getDsData());
validateNameservers(newResource.getNameservers()); validateRegistrantAllowedOnTld(newResource.getTld(), newResource.getRegistrant());
validateNameservers(newResource.getTld(), newResource.getNameservers());
} }
/** The secDNS:all element must have value 'true' if present. */ /** The secDNS:all element must have value 'true' if present. */

View file

@ -90,8 +90,10 @@ import java.util.List;
* @error {@link DomainFlowUtils.LeadingDashException} * @error {@link DomainFlowUtils.LeadingDashException}
* @error {@link DomainFlowUtils.LinkedResourceDoesNotExistException} * @error {@link DomainFlowUtils.LinkedResourceDoesNotExistException}
* @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.MissingContactTypeException}
* @error {@link DomainFlowUtils.NameserverNotAllowedException}
* @error {@link DomainFlowUtils.NoMarksFoundMatchingDomainException} * @error {@link DomainFlowUtils.NoMarksFoundMatchingDomainException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.SignedMarksMustBeEncodedException} * @error {@link DomainFlowUtils.SignedMarksMustBeEncodedException}
* @error {@link DomainFlowUtils.SignedMarkCertificateExpiredException} * @error {@link DomainFlowUtils.SignedMarkCertificateExpiredException}
* @error {@link DomainFlowUtils.SignedMarkCertificateInvalidException} * @error {@link DomainFlowUtils.SignedMarkCertificateInvalidException}

View file

@ -49,6 +49,8 @@ import com.google.domain.registry.model.reporting.HistoryEntry;
* @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 DomainFlowUtils.NameserverNotAllowedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.TooManyDsRecordsException} * @error {@link DomainFlowUtils.TooManyDsRecordsException}
* @error {@link DomainFlowUtils.TooManyNameserversException} * @error {@link DomainFlowUtils.TooManyNameserversException}
* @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException} * @error {@link DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException}

View file

@ -80,7 +80,9 @@ import java.util.Set;
* @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.MissingContactTypeException}
* @error {@link DomainFlowUtils.MissingRegistrantException} * @error {@link DomainFlowUtils.MissingRegistrantException}
* @error {@link DomainFlowUtils.MissingTechnicalContactException} * @error {@link DomainFlowUtils.MissingTechnicalContactException}
* @error {@link DomainFlowUtils.NameserverNotAllowedException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.TldDoesNotExistException} * @error {@link DomainFlowUtils.TldDoesNotExistException}
* @error {@link DomainFlowUtils.TooManyDsRecordsException} * @error {@link DomainFlowUtils.TooManyDsRecordsException}
* @error {@link DomainFlowUtils.TooManyNameserversException} * @error {@link DomainFlowUtils.TooManyNameserversException}

View file

@ -259,6 +259,7 @@ public class DomainFlowUtils {
private static void verifyNotInPendingDelete( private static void verifyNotInPendingDelete(
ReferenceUnion<? extends EppResource> resourceRef) throws EppException { ReferenceUnion<? extends EppResource> resourceRef) throws EppException {
EppResource resource = resourceRef.getLinked().get(); EppResource resource = resourceRef.getLinked().get();
if (resource.getStatusValues().contains(StatusValue.PENDING_DELETE)) { if (resource.getStatusValues().contains(StatusValue.PENDING_DELETE)) {
throw new LinkedResourceInPendingDeleteProhibitsOperationException(resource.getForeignKey()); throw new LinkedResourceInPendingDeleteProhibitsOperationException(resource.getForeignKey());
@ -274,12 +275,26 @@ public class DomainFlowUtils {
} }
} }
static void validateNameservers(Set<ReferenceUnion<HostResource>> nameservers) /** Return a foreign key for a {@link ReferenceUnion} from memory or datastore as needed. */
private static String resolveForeignKey(ReferenceUnion<?> ref) {
return Optional.fromNullable(ref.getForeignKey()).or(ref.getLinked().get().getForeignKey());
}
static void validateNameservers(String tld, Set<ReferenceUnion<HostResource>> nameservers)
throws EppException { throws EppException {
if (nameservers != null && nameservers.size() > MAX_NAMESERVERS_PER_DOMAIN) { if (nameservers != null && nameservers.size() > MAX_NAMESERVERS_PER_DOMAIN) {
throw new TooManyNameserversException(String.format( throw new TooManyNameserversException(String.format(
"Only %d nameservers are allowed per domain", MAX_NAMESERVERS_PER_DOMAIN)); "Only %d nameservers are allowed per domain", MAX_NAMESERVERS_PER_DOMAIN));
} }
ImmutableSet<String> whitelist = Registry.get(tld).getAllowedFullyQualifiedHostNames();
if (!whitelist.isEmpty()) { // Empty whitelists are ignored.
for (ReferenceUnion<HostResource> nameserver : nameservers) {
String foreignKey = resolveForeignKey(nameserver);
if (!whitelist.contains(foreignKey)) {
throw new NameserverNotAllowedException(foreignKey);
}
}
}
} }
static void validateNoDuplicateContacts(Set<DesignatedContact> contacts) static void validateNoDuplicateContacts(Set<DesignatedContact> contacts)
@ -311,6 +326,15 @@ public class DomainFlowUtils {
} }
} }
static void validateRegistrantAllowedOnTld(String tld, ReferenceUnion<ContactResource> registrant)
throws RegistrantNotAllowedException {
ImmutableSet<String> whitelist = Registry.get(tld).getAllowedRegistrantContactIds();
// Empty whitelists are ignored.
if (!whitelist.isEmpty() && !whitelist.contains(resolveForeignKey(registrant))) {
throw new RegistrantNotAllowedException(registrant.toString());
}
}
static void verifyNotReserved( static void verifyNotReserved(
InternetDomainName domainName, boolean isSunriseApplication) throws EppException { InternetDomainName domainName, boolean isSunriseApplication) throws EppException {
if (isReserved(domainName, isSunriseApplication)) { if (isReserved(domainName, isSunriseApplication)) {
@ -963,4 +987,18 @@ public class DomainFlowUtils {
super("Registrar is not authorized to access the TLD " + tld); super("Registrar is not authorized to access the TLD " + tld);
} }
} }
/** Registrant is not whitelisted for this TLD. */
public static class RegistrantNotAllowedException extends StatusProhibitsOperationException {
public RegistrantNotAllowedException(String contactId) {
super(String.format("Registrant with id %s is not whitelisted for this TLD", contactId));
}
}
/** Nameserver is not whitelisted for this TLD. */
public static class NameserverNotAllowedException extends StatusProhibitsOperationException {
public NameserverNotAllowedException(String fullyQualifiedHostName) {
super(String.format("Nameserver %s is not whitelisted for this TLD", fullyQualifiedHostName));
}
}
} }

View file

@ -60,6 +60,8 @@ import java.util.Set;
* @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 DomainFlowUtils.NameserverNotAllowedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.TooManyDsRecordsException} * @error {@link DomainFlowUtils.TooManyDsRecordsException}
* @error {@link DomainFlowUtils.TooManyNameserversException} * @error {@link DomainFlowUtils.TooManyNameserversException}
*/ */

View file

@ -343,6 +343,12 @@ public class Registry extends BackupGroupRoot implements Buildable {
/** The end of the claims period (at or after this time, claims no longer applies). */ /** The end of the claims period (at or after this time, claims no longer applies). */
DateTime claimsPeriodEnd = END_OF_TIME; DateTime claimsPeriodEnd = END_OF_TIME;
/** A whitelist of clients allowed to be used on domains on this TLD (ignored if empty). */
Set<String> allowedRegistrantContactIds;
/** A whitelist of hosts allowed to be used on domains on this TLD (ignored if empty). */
Set<String> allowedFullyQualifiedHostNames;
public String getTldStr() { public String getTldStr() {
return tldStr; return tldStr;
} }
@ -521,6 +527,14 @@ public class Registry extends BackupGroupRoot implements Buildable {
return claimsPeriodEnd; return claimsPeriodEnd;
} }
public ImmutableSet<String> getAllowedRegistrantContactIds() {
return nullToEmptyImmutableCopy(allowedRegistrantContactIds);
}
public ImmutableSet<String> getAllowedFullyQualifiedHostNames() {
return nullToEmptyImmutableCopy(allowedFullyQualifiedHostNames);
}
@Override @Override
public Builder asBuilder() { public Builder asBuilder() {
return new Builder(clone(this)); return new Builder(clone(this));
@ -734,6 +748,18 @@ public class Registry extends BackupGroupRoot implements Buildable {
return this; return this;
} }
public Builder setAllowedRegistrantContactIds(
ImmutableSet<String> allowedRegistrantContactIds) {
getInstance().allowedRegistrantContactIds = allowedRegistrantContactIds;
return this;
}
public Builder setAllowedFullyQualifiedHostNames(
ImmutableSet<String> allowedFullyQualifiedHostNames) {
getInstance().allowedFullyQualifiedHostNames = allowedFullyQualifiedHostNames;
return this;
}
@Override @Override
public Registry build() { public Registry build() {
final Registry instance = getInstance(); final Registry instance = getInstance();

View file

@ -15,18 +15,22 @@
package com.google.domain.registry.tools; package com.google.domain.registry.tools;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Sets.difference;
import static com.google.common.collect.Sets.intersection;
import static com.google.common.collect.Sets.union;
import static com.google.domain.registry.model.RoidSuffixes.isRoidSuffixUsed; import static com.google.domain.registry.model.RoidSuffixes.isRoidSuffixUsed;
import static com.google.domain.registry.util.CollectionUtils.findDuplicates; import static com.google.domain.registry.util.CollectionUtils.findDuplicates;
import static com.google.domain.registry.util.CollectionUtils.nullToEmpty; import static com.google.domain.registry.util.CollectionUtils.nullToEmpty;
import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName; import static com.google.domain.registry.util.DomainNameUtils.canonicalizeDomainName;
import com.google.common.base.CharMatcher; import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Sets;
import com.google.domain.registry.model.registry.Registries; import com.google.domain.registry.model.registry.Registries;
import com.google.domain.registry.model.registry.Registry; import com.google.domain.registry.model.registry.Registry;
import com.google.domain.registry.model.registry.Registry.TldState; import com.google.domain.registry.model.registry.Registry.TldState;
@ -44,7 +48,6 @@ import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -180,6 +183,18 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
description = "A comma-separated list of reserved list names to be applied to the TLD") description = "A comma-separated list of reserved list names to be applied to the TLD")
List<String> reservedListNames; List<String> reservedListNames;
@Nullable
@Parameter(
names = "--allowed_registrants",
description = "A comma-separated list of allowed registrants for the TLD")
List<String> allowedRegistrants;
@Nullable
@Parameter(
names = "--allowed_nameservers",
description = "A comma-separated list of allowed nameservers for the TLD")
List<String> allowedNameservers;
@Parameter( @Parameter(
names = {"-o", "--override_reserved_list_rules"}, names = {"-o", "--override_reserved_list_rules"},
description = "Override restrictions on reserved list naming") description = "Override restrictions on reserved list naming")
@ -197,6 +212,18 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
@Nullable @Nullable
Set<String> reservedListNamesToRemove; Set<String> reservedListNamesToRemove;
@Nullable
Set<String> allowedRegistrantsToAdd;
@Nullable
Set<String> allowedRegistrantsToRemove;
@Nullable
Set<String> allowedNameserversToAdd;
@Nullable
Set<String> allowedNameserversToRemove;
/** Returns the existing registry (for update) or null (for creates). */ /** Returns the existing registry (for update) or null (for creates). */
@Nullable @Nullable
abstract Registry getOldRegistry(String tld); abstract Registry getOldRegistry(String tld);
@ -309,54 +336,6 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
builder.setClaimsPeriodEnd(claimsPeriodEnd); builder.setClaimsPeriodEnd(claimsPeriodEnd);
} }
if (reservedListNames != null
|| reservedListNamesToAdd != null
|| reservedListNamesToRemove != null) {
Set<String> listsToApply = new HashSet<>();
if (reservedListNames != null) {
listsToApply = ImmutableSet.copyOf(reservedListNames);
checkReservedListValidityForTld(tld, listsToApply);
} else {
checkArgument(
Sets
.intersection(
nullToEmpty(reservedListNamesToAdd),
nullToEmpty(reservedListNamesToRemove))
.isEmpty(),
"Adding and removing the same reserved list simultaneously doesn't make sense");
for (Key<ReservedList> key : oldRegistry.getReservedLists()) {
listsToApply.add(key.getName());
}
Set<String> duplicateNames =
Sets.intersection(listsToApply, nullToEmpty(reservedListNamesToAdd));
checkArgument(
duplicateNames.isEmpty(),
"Cannot add reserved list(s) %s to TLD %s because they're already on it",
Joiner.on(", ").join(duplicateNames),
tld);
if (reservedListNamesToAdd != null) {
checkReservedListValidityForTld(tld, reservedListNamesToAdd);
listsToApply.addAll(reservedListNamesToAdd);
}
if (reservedListNamesToRemove != null) {
for (String name : reservedListNamesToRemove) {
checkArgument(
listsToApply.contains(name),
"Cannot remove reserved list %s from TLD %s because it isn't on it",
name,
tld);
listsToApply.remove(name);
}
}
}
builder.setReservedListsByName(listsToApply);
}
if (premiumListName != null) { if (premiumListName != null) {
if (premiumListName.isPresent()) { if (premiumListName.isPresent()) {
Optional<PremiumList> premiumList = PremiumList.get(premiumListName.get()); Optional<PremiumList> premiumList = PremiumList.get(premiumListName.get());
@ -368,12 +347,78 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand {
} }
} }
ImmutableSet<String> newReservedListNames =
formUpdatedList(
"reserved lists",
oldRegistry == null ? ImmutableSet.<String>of() : FluentIterable
.from(oldRegistry.getReservedLists())
.transform(
new Function<Key<ReservedList>, String>() {
@Override
public String apply(Key<ReservedList> key) {
return key.getName();
}})
.toSet(),
reservedListNames,
reservedListNamesToAdd,
reservedListNamesToRemove);
checkReservedListValidityForTld(tld, newReservedListNames);
builder.setReservedListsByName(newReservedListNames);
builder.setAllowedRegistrantContactIds(
formUpdatedList(
"allowed registrants",
oldRegistry == null
? ImmutableSet.<String>of()
: oldRegistry.getAllowedRegistrantContactIds(),
allowedRegistrants,
allowedRegistrantsToAdd,
allowedRegistrantsToRemove));
builder.setAllowedFullyQualifiedHostNames(
formUpdatedList(
"allowed nameservers",
oldRegistry == null
? ImmutableSet.<String>of()
: oldRegistry.getAllowedFullyQualifiedHostNames(),
allowedNameservers,
allowedNameserversToAdd,
allowedNameserversToRemove));
// Update the Registry object. // Update the Registry object.
setCommandSpecificProperties(builder); setCommandSpecificProperties(builder);
stageEntityChange(oldRegistry, builder.build()); stageEntityChange(oldRegistry, builder.build());
} }
} }
private ImmutableSet<String> formUpdatedList(
String description,
ImmutableSet<String> originals,
List<String> toReplace,
Set<String> toAdd,
Set<String> toRemove) {
if (toReplace != null) {
return ImmutableSet.copyOf(toReplace);
}
toAdd = nullToEmpty(toAdd);
toRemove = nullToEmpty(toRemove);
checkIsEmpty(
intersection(toAdd, toRemove),
String.format(
"Adding and removing the same %s simultaneously doesn't make sense", description));
checkIsEmpty(
intersection(originals, toAdd),
String.format("Cannot add %s that were previously present", description));
checkIsEmpty(
difference(toRemove, originals),
String.format("Cannot remove %s that were not previously present", description));
return ImmutableSet.copyOf(difference(union(originals, toAdd), toRemove));
}
private void checkIsEmpty(Set<String> set, String errorString) {
checkArgument(set.isEmpty(), String.format("%s: %s", errorString, set));
}
@Override @Override
public String execute() throws Exception { public String execute() throws Exception {
try { try {

View file

@ -43,6 +43,30 @@ class UpdateTldCommand extends CreateOrUpdateTldCommand {
description = "A comma-separated list of reserved list names to be removed from the TLD") description = "A comma-separated list of reserved list names to be removed from the TLD")
List<String> reservedListsRemove; List<String> reservedListsRemove;
@Nullable
@Parameter(
names = "--add_allowed_registrants",
description = "A comma-separated list of allowed registrants to be added to the TLD")
List<String> allowedRegistrantsAdd;
@Nullable
@Parameter(
names = "--remove_allowed_registrants",
description = "A comma-separated list of allowed registrants to be removed from the TLD")
List<String> allowedRegistrantsRemove;
@Nullable
@Parameter(
names = "--add_allowed_nameservers",
description = "A comma-separated list of allowed nameservers to be added to the TLD")
List<String> allowedNameserversAdd;
@Nullable
@Parameter(
names = "--remove_allowed_nameservers",
description = "A comma-separated list of allowed nameservers to be removed from the TLD")
List<String> allowedNameserversRemove;
@Override @Override
Registry getOldRegistry(String tld) { Registry getOldRegistry(String tld) {
return Registry.get(assertTldExists(tld)); return Registry.get(assertTldExists(tld));
@ -50,11 +74,26 @@ class UpdateTldCommand extends CreateOrUpdateTldCommand {
@Override @Override
protected void initTldCommand() throws Exception { protected void initTldCommand() throws Exception {
checkArgument(reservedListsAdd == null || reservedListNames == null, checkConflicts("reserved_lists", reservedListNames, reservedListsAdd, reservedListsRemove);
"Don't pass both --reserved_lists and --add_reserved_lists"); checkConflicts(
"allowed_registrants", allowedRegistrants, allowedRegistrantsAdd, allowedRegistrantsRemove);
checkConflicts(
"allowed_nameservers", allowedNameservers, allowedNameserversAdd, allowedNameserversRemove);
reservedListNamesToAdd = ImmutableSet.copyOf(nullToEmpty(reservedListsAdd)); reservedListNamesToAdd = ImmutableSet.copyOf(nullToEmpty(reservedListsAdd));
checkArgument(reservedListsRemove == null || reservedListNames == null,
"Don't pass both --reserved_lists and --remove_reserved_lists");
reservedListNamesToRemove = ImmutableSet.copyOf(nullToEmpty(reservedListsRemove)); reservedListNamesToRemove = ImmutableSet.copyOf(nullToEmpty(reservedListsRemove));
allowedRegistrantsToAdd = ImmutableSet.copyOf(nullToEmpty(allowedRegistrantsAdd));
allowedRegistrantsToRemove = ImmutableSet.copyOf(nullToEmpty(allowedRegistrantsRemove));
allowedNameserversToAdd = ImmutableSet.copyOf(nullToEmpty(allowedNameserversAdd));
allowedNameserversToRemove = ImmutableSet.copyOf(nullToEmpty(allowedNameserversRemove));
}
private void checkConflicts(
String baseFlagName, Object overwriteValue, Object addValue, Object removeValue) {
checkNotBoth(baseFlagName, overwriteValue, "add_" + baseFlagName, addValue);
checkNotBoth(baseFlagName, overwriteValue, "remove_" + baseFlagName, removeValue);
}
private void checkNotBoth(String nameA, Object valueA, String nameB, Object valueB) {
checkArgument(valueA == null || valueB == null, "Don't pass both --%s and --%s", nameA, nameB);
} }
} }

View file

@ -78,9 +78,11 @@ import com.google.domain.registry.flows.domain.DomainFlowUtils.LaunchPhaseMismat
import com.google.domain.registry.flows.domain.DomainFlowUtils.LeadingDashException; import com.google.domain.registry.flows.domain.DomainFlowUtils.LeadingDashException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.LinkedResourceDoesNotExistException; import com.google.domain.registry.flows.domain.DomainFlowUtils.LinkedResourceDoesNotExistException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NameserverNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NoMarksFoundMatchingDomainException; import com.google.domain.registry.flows.domain.DomainFlowUtils.NoMarksFoundMatchingDomainException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import com.google.domain.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateExpiredException; import com.google.domain.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateExpiredException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateInvalidException; import com.google.domain.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateInvalidException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateNotYetValidException; import com.google.domain.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateNotYetValidException;
@ -1170,6 +1172,41 @@ public class DomainApplicationCreateFlowTest
} }
} }
@Test
public void testFailure_registrantNotWhitelisted() throws Exception {
persistActiveContact("someone");
persistContactsAndHosts();
persistResource(Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("someone"))
.build());
thrown.expect(RegistrantNotAllowedException.class);
runFlow();
}
@Test
public void testFailure_nameserverNotWhitelisted() throws Exception {
persistActiveHost("ns1.example.com");
persistContactsAndHosts();
persistResource(Registry.get("tld").asBuilder()
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.someone.tld"))
.build());
thrown.expect(NameserverNotAllowedException.class);
runFlow();
}
@Test
public void testSuccess_nameserverAndRegistrantWhitelisted() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("jd1234"))
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.net", "ns2.example.net"))
.build());
persistContactsAndHosts();
clock.advanceOneMilli();
doSuccessfulTest("domain_create_sunrise_encoded_signed_mark_response.xml", true);
assertAboutApplications().that(getOnlyGlobalResource(DomainApplication.class))
.hasApplicationStatus(ApplicationStatus.VALIDATED);
}
/** /**
* There is special logic that disallows a failfast for domains in add grace period and sunrush * There is special logic that disallows a failfast for domains in add grace period and sunrush
* add grace period, so make sure that they fail anyways in the actual flow. * add grace period, so make sure that they fail anyways in the actual flow.

View file

@ -49,7 +49,9 @@ import com.google.domain.registry.flows.domain.DomainFlowUtils.LinkedResourceDoe
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingAdminContactException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NameserverNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyNameserversException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
import com.google.domain.registry.model.contact.ContactResource; import com.google.domain.registry.model.contact.ContactResource;
@ -63,6 +65,7 @@ import com.google.domain.registry.model.domain.secdns.DelegationSignerData;
import com.google.domain.registry.model.eppcommon.StatusValue; import com.google.domain.registry.model.eppcommon.StatusValue;
import com.google.domain.registry.model.host.HostResource; import com.google.domain.registry.model.host.HostResource;
import com.google.domain.registry.model.registrar.Registrar; import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.model.registry.Registry;
import com.google.domain.registry.model.registry.Registry.TldState; import com.google.domain.registry.model.registry.Registry.TldState;
import com.google.domain.registry.model.reporting.HistoryEntry; import com.google.domain.registry.model.reporting.HistoryEntry;
@ -622,4 +625,43 @@ public class DomainApplicationUpdateFlowTest
.build()); .build());
runFlow(); runFlow();
} }
@Test
public void testFailure_newRegistrantNotWhitelisted() throws Exception {
setEppInput("domain_update_sunrise_registrant_to_tech.xml");
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("sha8013"))
.build());
clock.advanceOneMilli();
thrown.expect(RegistrantNotAllowedException.class);
runFlow();
}
@Test
public void testFailure_newNameserverNotWhitelisted() throws Exception {
persistReferencedEntities();
persistApplication();
persistResource(
Registry.get("tld").asBuilder()
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.foo"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserverNotAllowedException.class);
runFlow();
}
@Test
public void testSuccess_nameserverAndRegistrantWhitelisted() throws Exception {
persistResource(
Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("sh8013"))
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns2.example.tld"))
.build());
persistReferencedEntities();
persistApplication();
doSuccessfulTest();
}
} }

View file

@ -87,8 +87,10 @@ import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingAdminConta
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingRegistrantException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingRegistrantException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NameserverNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import com.google.domain.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyNameserversException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
@ -1226,4 +1228,36 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertSuccessfulCreate("tld", true); assertSuccessfulCreate("tld", true);
assertClaimsLordn(); assertClaimsLordn();
} }
@Test
public void testFailure_registrantNotWhitelisted() throws Exception {
persistActiveContact("someone");
persistContactsAndHosts();
persistResource(Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("someone"))
.build());
thrown.expect(RegistrantNotAllowedException.class);
runFlow();
}
@Test
public void testFailure_nameserverNotWhitelisted() throws Exception {
persistActiveHost("ns1.example.com");
persistContactsAndHosts();
persistResource(Registry.get("tld").asBuilder()
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.someone.tld"))
.build());
thrown.expect(NameserverNotAllowedException.class);
runFlow();
}
@Test
public void testSuccess_nameserverAndRegistrantWhitelisted() throws Exception {
persistResource(Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("jd1234"))
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.net", "ns2.example.net"))
.build());
persistContactsAndHosts();
doSuccessfulTest();
}
} }

View file

@ -58,7 +58,9 @@ import com.google.domain.registry.flows.domain.DomainFlowUtils.LinkedResourceInP
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingAdminContactException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingContactTypeException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; import com.google.domain.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NameserverNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import com.google.domain.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyNameserversException; import com.google.domain.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
import com.google.domain.registry.model.billing.BillingEvent; import com.google.domain.registry.model.billing.BillingEvent;
@ -1068,4 +1070,43 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow,
clock.advanceOneMilli(); clock.advanceOneMilli();
runFlow(); runFlow();
} }
@Test
public void testFailure_newRegistrantNotWhitelisted() throws Exception {
setEppInput("domain_update_registrant_to_tech.xml");
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("sha8013"))
.build());
clock.advanceOneMilli();
thrown.expect(RegistrantNotAllowedException.class);
runFlow();
}
@Test
public void testFailure_newNameserverNotWhitelisted() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld").asBuilder()
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.foo"))
.build());
clock.advanceOneMilli();
thrown.expect(NameserverNotAllowedException.class);
runFlow();
}
@Test
public void testSuccess_nameserverAndRegistrantWhitelisted() throws Exception {
persistReferencedEntities();
persistDomain();
persistResource(
Registry.get("tld").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("sh8013"))
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns2.example.foo"))
.build());
doSuccessfulTest();
}
} }

View file

@ -673,6 +673,8 @@ class com.google.domain.registry.model.registry.Registry {
java.lang.String tldStr; java.lang.String tldStr;
java.lang.String tldUnicode; java.lang.String tldUnicode;
java.util.Set<com.googlecode.objectify.Key<com.google.domain.registry.model.registry.label.ReservedList>> reservedLists; java.util.Set<com.googlecode.objectify.Key<com.google.domain.registry.model.registry.label.ReservedList>> reservedLists;
java.util.Set<java.lang.String> allowedFullyQualifiedHostNames;
java.util.Set<java.lang.String> allowedRegistrantContactIds;
org.joda.money.CurrencyUnit currency; org.joda.money.CurrencyUnit currency;
org.joda.money.Money createBillingCost; org.joda.money.Money createBillingCost;
org.joda.money.Money restoreBillingCost; org.joda.money.Money restoreBillingCost;

View file

@ -255,6 +255,23 @@ public class CreateTldCommandTest extends CommandTestCase<CreateTldCommand> {
runCommandForced("1foo", "--roid_suffix=1FOO"); runCommandForced("1foo", "--roid_suffix=1FOO");
} }
@Test
public void testSuccess_setAllowedRegistrants() throws Exception {
runCommandForced("--allowed_registrants=alice,bob", "--roid_suffix=Q9JYB4C", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedRegistrantContactIds())
.containsExactly("alice", "bob");
}
@Test
public void testSuccess_setAllowedNameservers() throws Exception {
runCommandForced(
"--allowed_nameservers=ns1.example.com,ns2.example.com",
"--roid_suffix=Q9JYB4C",
"xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedFullyQualifiedHostNames())
.containsExactly("ns1.example.com", "ns2.example.com");
}
@Test @Test
public void testSuccess_setCommonReservedListOnTld() throws Exception { public void testSuccess_setCommonReservedListOnTld() throws Exception {
runSuccessfulReservedListsTest("common_abuse"); runSuccessfulReservedListsTest("common_abuse");

View file

@ -271,43 +271,144 @@ public class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
} }
@Test @Test
public void testSuccess_setReservedListsOverwritesCorrectly() throws Exception { public void testSuccess_setReservedListsOverwrites() throws Exception {
Registry registry = addTwoReservedListsToRegistry(); persistResource(Registry.get("xn--q9jyb4c").asBuilder()
.setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"))
.build());
runCommandForced("--reserved_lists=xn--q9jyb4c_r2", "xn--q9jyb4c"); runCommandForced("--reserved_lists=xn--q9jyb4c_r2", "xn--q9jyb4c");
registry = Registry.get("xn--q9jyb4c"); assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION))
assertThat(registry.getReservedLists()).hasSize(1); .containsExactly("xn--q9jyb4c_r2");
assertThat(registry.getReservedLists().asList().get(0).getName()).isEqualTo("xn--q9jyb4c_r2");
} }
@Test @Test
public void testSuccess_addReservedListsWorksCorrectly() throws Exception { public void testSuccess_addReservedLists() throws Exception {
runCommandForced("--add_reserved_lists=xn--q9jyb4c_r1,xn--q9jyb4c_r2", "xn--q9jyb4c"); persistResource(Registry.get("xn--q9jyb4c").asBuilder()
.setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1"))
.build());
runCommandForced("--add_reserved_lists=xn--q9jyb4c_r2", "xn--q9jyb4c");
assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION))
.containsExactly("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"); .containsExactly("xn--q9jyb4c_r1", "xn--q9jyb4c_r2");
} }
@Test @Test
public void testSuccess_removeAllReservedListsWorksCorrectly() throws Exception { public void testSuccess_removeAllReservedLists() throws Exception {
addTwoReservedListsToRegistry(); persistResource(Registry.get("xn--q9jyb4c").asBuilder()
.setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"))
.build());
runCommandForced("--remove_reserved_lists=xn--q9jyb4c_r1,xn--q9jyb4c_r2", "xn--q9jyb4c"); runCommandForced("--remove_reserved_lists=xn--q9jyb4c_r1,xn--q9jyb4c_r2", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getReservedLists()).isEmpty(); assertThat(Registry.get("xn--q9jyb4c").getReservedLists()).isEmpty();
} }
@Test @Test
public void testSuccess_removeSomeReservedListsWorksCorrectly() throws Exception { public void testSuccess_removeSomeReservedLists() throws Exception {
addTwoReservedListsToRegistry(); persistResource(Registry.get("xn--q9jyb4c").asBuilder()
.setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"))
.build());
runCommandForced("--remove_reserved_lists=xn--q9jyb4c_r1", "xn--q9jyb4c"); runCommandForced("--remove_reserved_lists=xn--q9jyb4c_r1", "xn--q9jyb4c");
assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION)) assertThat(transform(Registry.get("xn--q9jyb4c").getReservedLists(), GET_NAME_FUNCTION))
.containsExactly("xn--q9jyb4c_r2"); .containsExactly("xn--q9jyb4c_r2");
} }
private Registry addTwoReservedListsToRegistry() throws Exception { @Test
public void testSuccess_setAllowedRegistrants() throws Exception {
runCommandForced("--allowed_registrants=alice,bob", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedRegistrantContactIds())
.containsExactly("alice", "bob");
}
@Test
public void testSuccess_setAllowedRegistrantsOverwrites() throws Exception {
persistResource( persistResource(
Registry.get("xn--q9jyb4c") Registry.get("xn--q9jyb4c").asBuilder()
.asBuilder() .setAllowedRegistrantContactIds(ImmutableSet.of("jane", "john"))
.setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"))
.build()); .build());
return Registry.get("xn--q9jyb4c"); runCommandForced("--allowed_registrants=alice,bob", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedRegistrantContactIds())
.containsExactly("alice", "bob");
}
@Test
public void testSuccess_addAllowedRegistrants() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("alice"))
.build());
runCommandForced("--add_allowed_registrants=bob", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedRegistrantContactIds())
.containsExactly("alice", "bob");
}
@Test
public void testSuccess_removeAllAllowedRegistrants() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("alice", "bob"))
.build());
runCommandForced("--remove_allowed_registrants=alice,bob", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedRegistrantContactIds()).isEmpty();
}
@Test
public void testSuccess_removeSomeAllowedRegistrants() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("alice", "bob"))
.build());
runCommandForced("--remove_allowed_registrants=alice", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedRegistrantContactIds()).containsExactly("bob");
}
@Test
public void testSuccess_setAllowedNameservers() throws Exception {
runCommandForced("--allowed_nameservers=ns1.example.com,ns2.example.com", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedFullyQualifiedHostNames())
.containsExactly("ns1.example.com", "ns2.example.com");
}
@Test
public void testSuccess_setAllowedNameserversOverwrites() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.tld", "ns2.example.tld"))
.build());
runCommandForced("--allowed_nameservers=ns1.example.com,ns2.example.com", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedFullyQualifiedHostNames())
.containsExactly("ns1.example.com", "ns2.example.com");
}
@Test
public void testSuccess_addAllowedNameservers() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.com"))
.build());
runCommandForced("--add_allowed_nameservers=ns2.example.com", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedFullyQualifiedHostNames())
.containsExactly("ns1.example.com", "ns2.example.com");
}
@Test
public void testSuccess_removeAllAllowedNameservers() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.com", "ns2.example.com"))
.build());
runCommandForced("--remove_allowed_nameservers=ns1.example.com,ns2.example.com", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedFullyQualifiedHostNames()).isEmpty();
}
@Test
public void testSuccess_removeSomeAllowedNameservers() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.com", "ns2.example.com"))
.build());
runCommandForced("--remove_allowed_nameservers=ns1.example.com", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getAllowedFullyQualifiedHostNames())
.containsExactly("ns2.example.com");
} }
@Test @Test
@ -445,34 +546,91 @@ public class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
@Test @Test
public void testFailure_cantAddDuplicateReservedList() throws Exception { public void testFailure_cantAddDuplicateReservedList() throws Exception {
thrown.expect( persistResource(Registry.get("xn--q9jyb4c").asBuilder()
IllegalArgumentException.class, .setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"))
"Cannot add reserved list(s) xn--q9jyb4c_r1 to TLD xn--q9jyb4c " .build());
+ "because they're already on it"); thrown.expect(IllegalArgumentException.class, "xn--q9jyb4c_r1");
addTwoReservedListsToRegistry();
runCommandForced("--add_reserved_lists=xn--q9jyb4c_r1", "xn--q9jyb4c"); runCommandForced("--add_reserved_lists=xn--q9jyb4c_r1", "xn--q9jyb4c");
} }
@Test @Test
public void testFailure_cantRemoveReservedListThatIsntPresent() throws Exception { public void testFailure_cantRemoveReservedListThatIsntPresent() throws Exception {
thrown.expect( persistResource(Registry.get("xn--q9jyb4c").asBuilder()
IllegalArgumentException.class, .setReservedListsByName(ImmutableSet.of("xn--q9jyb4c_r1", "xn--q9jyb4c_r2"))
"Cannot remove reserved list xn--q9jyb4c_Z from TLD xn--q9jyb4c because it isn't on it"); .build());
addTwoReservedListsToRegistry(); thrown.expect(IllegalArgumentException.class, "xn--q9jyb4c_Z");
runCommandForced("--remove_reserved_lists=xn--q9jyb4c_Z", "xn--q9jyb4c"); runCommandForced("--remove_reserved_lists=xn--q9jyb4c_Z", "xn--q9jyb4c");
} }
@Test @Test
public void testFailure_cantAddAndRemoveSameReservedListSimultaneously() throws Exception { public void testFailure_cantAddAndRemoveSameReservedListSimultaneously() throws Exception {
thrown.expect( thrown.expect(IllegalArgumentException.class, "xn--q9jyb4c_r1");
IllegalArgumentException.class,
"Adding and removing the same reserved list simultaneously doesn't make sense");
runCommandForced( runCommandForced(
"--add_reserved_lists=xn--q9jyb4c_r1", "--add_reserved_lists=xn--q9jyb4c_r1",
"--remove_reserved_lists=xn--q9jyb4c_r1", "--remove_reserved_lists=xn--q9jyb4c_r1",
"xn--q9jyb4c"); "xn--q9jyb4c");
} }
@Test
public void testFailure_cantAddDuplicateAllowedRegistrants() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("alice", "bob"))
.build());
thrown.expect(IllegalArgumentException.class, "alice");
runCommandForced("--add_allowed_registrants=alice", "xn--q9jyb4c");
}
@Test
public void testFailure_cantRemoveAllowedRegistrantThatIsntPresent() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedRegistrantContactIds(ImmutableSet.of("alice"))
.build());
thrown.expect(IllegalArgumentException.class, "bob");
runCommandForced("--remove_allowed_registrants=bob", "xn--q9jyb4c");
}
@Test
public void testFailure_cantAddAndRemoveSameAllowedRegistrantsSimultaneously() throws Exception {
thrown.expect(IllegalArgumentException.class, "alice");
runCommandForced(
"--add_allowed_registrants=alice",
"--remove_allowed_registrants=alice",
"xn--q9jyb4c");
}
@Test
public void testFailure_cantAddDuplicateAllowedNameservers() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.com", "ns2.example.com"))
.build());
thrown.expect(IllegalArgumentException.class, "ns1.example.com");
runCommandForced("--add_allowed_nameservers=ns1.example.com", "xn--q9jyb4c");
}
@Test
public void testFailure_cantRemoveAllowedNameserverThatIsntPresent() throws Exception {
persistResource(
Registry.get("xn--q9jyb4c").asBuilder()
.setAllowedFullyQualifiedHostNames(
ImmutableSet.of("ns1.example.com"))
.build());
thrown.expect(IllegalArgumentException.class, "ns2.example.com");
runCommandForced("--remove_allowed_nameservers=ns2.example.com", "xn--q9jyb4c");
}
@Test
public void testFailure_cantAddAndRemoveSameAllowedNameserversSimultaneously() throws Exception {
thrown.expect(IllegalArgumentException.class, "ns1.example.com");
runCommandForced(
"--add_allowed_nameservers=ns1.example.com",
"--remove_allowed_nameservers=ns1.example.com",
"xn--q9jyb4c");
}
@Test @Test
public void testFailure_roidSuffixAlreadyInUse() throws Exception { public void testFailure_roidSuffixAlreadyInUse() throws Exception {
createTld("foo", "BLAH"); createTld("foo", "BLAH");