mirror of
https://github.com/google/nomulus.git
synced 2025-05-15 17:07:15 +02:00
Add new reserved domain creation from allocation tokens mechanism
Note that this gets rid of anchor tenant codes in reserved lists (yay!), which are no longer valid. They have to come from allocation tokens now. This removes support for LRP from domain application create flow (that's fine, we never used it and I'm going to delete all of LRP later). It also uses allocation tokens from EPP authcodes as a fallback, for now, but that will be removed later once we switch fully to the allocation token mechanism. This doesn't yet allow registration of RESERVED_FOR_SPECIFIC_USE domains using the allocation token extension; that will come in the next CL. Ditto for showing these reserved domains as available on domain checks when the allocation token is specified. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=209019617
This commit is contained in:
parent
782643ce33
commit
d2f849ac0f
19 changed files with 184 additions and 346 deletions
|
@ -21,7 +21,6 @@ import static google.registry.flows.domain.DomainFlowUtils.COLLISION_MESSAGE;
|
|||
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables;
|
||||
|
@ -31,7 +30,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
|||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
import static google.registry.model.EppResourceUtils.loadDomainApplication;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
|
@ -200,11 +198,6 @@ public class DomainAllocateFlow implements TransactionalFlow {
|
|||
updateApplication(application),
|
||||
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
|
||||
EppResourceIndex.create(Key.create(newDomain)));
|
||||
// Anchor tenant registrations override LRP.
|
||||
String authInfoToken = authInfo.getPw().getValue();
|
||||
if (hasLrpToken(domainName, registry, authInfoToken, now)) {
|
||||
entitiesToSave.add(prepareMarkedLrpTokenEntity(authInfoToken, domainName, historyEntry));
|
||||
}
|
||||
ofy().save().entities(entitiesToSave.build());
|
||||
enqueueTasks(allocateCreate, newDomain);
|
||||
return responseBuilder
|
||||
|
@ -387,12 +380,6 @@ public class DomainAllocateFlow implements TransactionalFlow {
|
|||
.build();
|
||||
}
|
||||
|
||||
private boolean hasLrpToken(
|
||||
InternetDomainName domainName, Registry registry, String authInfoToken, DateTime now) {
|
||||
return registry.getLrpPeriod().contains(now)
|
||||
&& !matchesAnchorTenantReservation(domainName, authInfoToken);
|
||||
}
|
||||
|
||||
private void enqueueTasks(AllocateCreateExtension allocateCreate, DomainResource newDomain) {
|
||||
if (newDomain.shouldPublishToDns()) {
|
||||
dnsQueue.get().addDomainRefreshTask(newDomain.getFullyQualifiedDomainName());
|
||||
|
|
|
@ -22,6 +22,7 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist
|
|||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainName;
|
||||
|
@ -42,7 +43,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
|||
import static google.registry.model.EppResourceUtils.createDomainRepoId;
|
||||
import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -223,7 +223,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow {
|
|||
eppInput.getSingleExtension(LaunchCreateExtension.class).get();
|
||||
validateLaunchCreateExtension(launchCreate, registry, domainName, now);
|
||||
boolean isAnchorTenant =
|
||||
matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue());
|
||||
isAnchorTenant(domainName, Optional.empty(), authInfo.getPw().getValue(), Optional.empty());
|
||||
// Superusers can create reserved domains, force creations on domains that require a claims
|
||||
// notice without specifying a claims key, and override blocks on registering premium domains.
|
||||
if (!isSuperuser) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
|
|||
import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld;
|
||||
|
@ -50,7 +51,6 @@ import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRIS
|
|||
import static google.registry.model.registry.Registry.TldState.SUNRISE;
|
||||
import static google.registry.model.registry.Registry.TldState.SUNRUSH;
|
||||
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
|
||||
import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
|
||||
|
||||
|
@ -251,8 +251,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
validateDomainAllowedOnCreateRestrictedTld(domainName);
|
||||
}
|
||||
TldState tldState = registry.getTldState(now);
|
||||
boolean isAnchorTenant = isAnchorTenant(domainName);
|
||||
verifyAnchorTenantValidPeriod(isAnchorTenant, years);
|
||||
Optional<LaunchCreateExtension> launchCreate =
|
||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||
boolean hasSignedMarks =
|
||||
|
@ -263,6 +261,15 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
validateLaunchCreateNotice(launchCreate.get().getNotice(), domainLabel, isSuperuser, now);
|
||||
}
|
||||
boolean isSunriseCreate = hasSignedMarks && SUNRISE_STATES.contains(tldState);
|
||||
Optional<AllocationToken> allocationToken =
|
||||
verifyAllocationTokenIfPresent(command, registry, clientId, now);
|
||||
boolean isAnchorTenant =
|
||||
isAnchorTenant(
|
||||
domainName,
|
||||
allocationToken,
|
||||
authInfo.getPw().getValue(),
|
||||
eppInput.getSingleExtension(MetadataExtension.class));
|
||||
verifyAnchorTenantValidPeriod(isAnchorTenant, years);
|
||||
// Superusers can create reserved domains, force creations on domains that require a claims
|
||||
// notice without specifying a claims key, ignore the registry phase, and override blocks on
|
||||
// registering premium domains.
|
||||
|
@ -294,8 +301,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
.verifySignedMarks(launchCreate.get().getSignedMarks(), domainLabel, now)
|
||||
.getId();
|
||||
}
|
||||
Optional<AllocationToken> allocationToken =
|
||||
verifyAllocationTokenIfPresent(command, registry, clientId, now);
|
||||
flowCustomLogic.afterValidation(
|
||||
DomainCreateFlowCustomLogic.AfterValidationParameters.newBuilder()
|
||||
.setDomainName(domainName)
|
||||
|
@ -400,13 +405,6 @@ public class DomainCreateFlow implements TransactionalFlow {
|
|||
.build();
|
||||
}
|
||||
|
||||
private boolean isAnchorTenant(InternetDomainName domainName) {
|
||||
Optional<MetadataExtension> metadataExtension =
|
||||
eppInput.getSingleExtension(MetadataExtension.class);
|
||||
return matchesAnchorTenantReservation(domainName, authInfo.getPw().getValue())
|
||||
|| (metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that signed marks are only sent during sunrise.
|
||||
*
|
||||
|
|
|
@ -30,6 +30,7 @@ import static google.registry.model.registry.Registries.getTlds;
|
|||
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||
import static google.registry.model.registry.label.ReservationType.NAMESERVER_RESTRICTED;
|
||||
import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_ANCHOR_TENANT;
|
||||
import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_SPECIFIC_USE;
|
||||
import static google.registry.model.registry.label.ReservedList.getAllowedNameservers;
|
||||
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
|
||||
import static google.registry.tldconfig.idn.IdnLabelValidator.findValidIdnTableForTld;
|
||||
|
@ -93,12 +94,14 @@ import google.registry.model.domain.launch.LaunchExtension;
|
|||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.launch.LaunchNotice.InvalidChecksumException;
|
||||
import google.registry.model.domain.launch.LaunchPhase;
|
||||
import google.registry.model.domain.metadata.MetadataExtension;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
import google.registry.model.domain.secdns.SecDnsCreateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsInfoExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Add;
|
||||
import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||
import google.registry.model.host.HostResource;
|
||||
|
@ -142,7 +145,7 @@ public class DomainFlowUtils {
|
|||
.put(LaunchPhase.OPEN, TldState.GENERAL_AVAILABILITY)
|
||||
.build();
|
||||
|
||||
/** Reservation types that are allowed in sunrise by policy. */
|
||||
/** Reservation types that are only allowed in sunrise by policy. */
|
||||
public static final ImmutableSet<ReservationType> TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE =
|
||||
Sets.immutableEnumSet(
|
||||
ReservationType.ALLOWED_IN_SUNRISE,
|
||||
|
@ -247,6 +250,37 @@ public class DomainFlowUtils {
|
|||
return idnTableName.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the information for a given domain create request is for a valid anchor tenant.
|
||||
*/
|
||||
public static boolean isAnchorTenant(
|
||||
InternetDomainName domainName,
|
||||
Optional<AllocationToken> token,
|
||||
String authInfoPw,
|
||||
Optional<MetadataExtension> metadataExtension) {
|
||||
// If the domain is reserved for anchor tenants, then check if the allocation token exists and
|
||||
// is for this domain.
|
||||
if (getReservationTypes(domainName).contains(RESERVED_FOR_ANCHOR_TENANT)) {
|
||||
// If there wasn't an allocation token specified, then use the fallback of attempting to load
|
||||
// the token with the specified EPP authcode.
|
||||
// TODO(b/111827374): Remove the authInfoPw fallback and only accept an allocation token.
|
||||
if (!token.isPresent()) {
|
||||
token =
|
||||
Optional.ofNullable(
|
||||
ofy().load().key(Key.create(AllocationToken.class, authInfoPw)).now());
|
||||
}
|
||||
// If the token exists, check if it's valid for this domain.
|
||||
if (token.isPresent()
|
||||
&& token.get().getDomainName().isPresent()
|
||||
&& token.get().getDomainName().get().equals(domainName.toString())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Otherwise check whether the metadata extension is being used by a superuser to specify that
|
||||
// it's an anchor tenant creation.
|
||||
return metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant();
|
||||
}
|
||||
|
||||
/** Check if the registrar running the flow has access to the TLD in question. */
|
||||
public static void checkAllowedAccessToTld(String clientId, String tld) throws EppException {
|
||||
if (!Registrar.loadByClientIdCached(clientId).get().getAllowedTlds().contains(tld)) {
|
||||
|
@ -411,10 +445,12 @@ public class DomainFlowUtils {
|
|||
}
|
||||
}
|
||||
|
||||
private static final ImmutableSet<ReservationType> RESERVED_TYPES =
|
||||
ImmutableSet.of(RESERVED_FOR_SPECIFIC_USE, RESERVED_FOR_ANCHOR_TENANT, FULLY_BLOCKED);
|
||||
|
||||
private static boolean isReserved(InternetDomainName domainName, boolean isSunrise) {
|
||||
ImmutableSet<ReservationType> types = getReservationTypes(domainName);
|
||||
return types.contains(FULLY_BLOCKED)
|
||||
|| types.contains(RESERVED_FOR_ANCHOR_TENANT)
|
||||
return !Sets.intersection(types, RESERVED_TYPES).isEmpty()
|
||||
|| !(isSunrise || intersection(TYPES_ALLOWED_FOR_CREATE_ONLY_IN_SUNRISE, types).isEmpty());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue