mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Create OT&E entities directly, instead of calling sub-commands
This is in preparation for having a web-console endpoint to create OTE. In addition - we streamline the code: - we remove support for different premium lists - we remove support for different DNS writers - we never want a "real" DnsWriter for OTE - we remove support of --eap_only, because we don't need it anymore - We use a single password for all the Registrars ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=225841694
This commit is contained in:
parent
1004ef5621
commit
9d6a7ef66a
6 changed files with 904 additions and 488 deletions
|
@ -15,69 +15,30 @@
|
|||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.tools.CommandUtilities.promptForYes;
|
||||
import static google.registry.util.X509Utils.loadCertificate;
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.re2j.Pattern;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.MoreFiles;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.model.OteAccountBuilder;
|
||||
import google.registry.tools.params.PathParameter;
|
||||
import google.registry.util.Clock;
|
||||
import google.registry.util.StringGenerator;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.joda.money.CurrencyUnit;
|
||||
import org.joda.money.Money;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/** Composite command to set up OT&E TLDs and accounts. */
|
||||
@Parameters(separators = " =", commandDescription = "Set up OT&E TLDs and registrars")
|
||||
final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemoteApi {
|
||||
|
||||
// Regex: 3-14 alphanumeric characters or hyphens, the first of which must be a letter.
|
||||
private static final Pattern REGISTRAR_PATTERN = Pattern.compile("^[a-z][-a-z0-9]{2,13}$");
|
||||
private static final int PASSWORD_LENGTH = 16;
|
||||
|
||||
// Durations are short so that registrars can test with quick transfer (etc.) turnaround.
|
||||
private static final Duration SHORT_ADD_GRACE_PERIOD = Duration.standardMinutes(60);
|
||||
private static final Duration SHORT_REDEMPTION_GRACE_PERIOD = Duration.standardMinutes(10);
|
||||
private static final Duration SHORT_PENDING_DELETE_LENGTH = Duration.standardMinutes(5);
|
||||
|
||||
// Whether to prompt the user on command failures. Set to false for testing of these failures.
|
||||
@VisibleForTesting
|
||||
static boolean interactive = true;
|
||||
|
||||
private static final ImmutableSortedMap<DateTime, Money> EAP_FEE_SCHEDULE =
|
||||
ImmutableSortedMap.of(
|
||||
new DateTime(0),
|
||||
Money.of(CurrencyUnit.USD, 0),
|
||||
DateTime.parse("2018-03-01T00:00:00Z"),
|
||||
Money.of(CurrencyUnit.USD, 100),
|
||||
DateTime.parse("2022-03-01T00:00:00Z"),
|
||||
Money.of(CurrencyUnit.USD, 0));
|
||||
|
||||
private static final String DEFAULT_PREMIUM_LIST = "default_sandbox_list";
|
||||
|
||||
@Inject
|
||||
@Named("dnsWriterNames")
|
||||
Set<String> validDnsWriterNames;
|
||||
|
||||
@Parameter(
|
||||
names = {"-r", "--registrar"},
|
||||
description =
|
||||
|
@ -101,7 +62,7 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
names = {"--email"},
|
||||
description =
|
||||
"the registrar's account to use for console access. "
|
||||
+ "Must be on the registry's G-Suite domain.",
|
||||
+ "Must be on the registry's G Suite domain.",
|
||||
required = true)
|
||||
private String email;
|
||||
|
||||
|
@ -121,252 +82,83 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
private String certHash;
|
||||
|
||||
@Parameter(
|
||||
names = {"--dns_writers"},
|
||||
description = "comma separated list of DNS writers to use on all TLDs",
|
||||
required = true
|
||||
names = {"--overwrite"},
|
||||
description = "whether to replace existing entities if we encounter any, instead of failing"
|
||||
)
|
||||
private List<String> dnsWriters;
|
||||
|
||||
@Parameter(
|
||||
names = {"--premium_list"},
|
||||
description = "premium list to apply to all TLDs"
|
||||
)
|
||||
private String premiumList = DEFAULT_PREMIUM_LIST;
|
||||
|
||||
// TODO: (b/74079782) remove this flag once OT&E for .app is complete.
|
||||
@Parameter(
|
||||
names = {"--eap_only"},
|
||||
description = "whether to only create EAP TLD and registrar"
|
||||
)
|
||||
private boolean eapOnly = false;
|
||||
private boolean overwrite = false;
|
||||
|
||||
@Inject
|
||||
@Config("base64StringGenerator")
|
||||
StringGenerator passwordGenerator;
|
||||
|
||||
/**
|
||||
* Long registrar names are truncated and then have an incrementing digit appended at the end so
|
||||
* that unique ROID suffixes can be generated for all TLDs for the registrar.
|
||||
*/
|
||||
private int roidSuffixCounter = 0;
|
||||
@Inject Clock clock;
|
||||
|
||||
/** Runs a command, clearing the cache before and prompting the user on failures. */
|
||||
private void runCommand(Command command) {
|
||||
ofy().clearSessionCache();
|
||||
try {
|
||||
command.run();
|
||||
} catch (Exception e) {
|
||||
System.err.format("Command failed with error %s\n", e);
|
||||
if (interactive && promptForYes("Continue to next command?")) {
|
||||
return;
|
||||
}
|
||||
Throwables.throwIfUnchecked(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs and runs a CreateTldCommand. */
|
||||
private void createTld(
|
||||
String tldName,
|
||||
TldState initialTldState,
|
||||
Duration addGracePeriod,
|
||||
Duration redemptionGracePeriod,
|
||||
Duration pendingDeleteLength,
|
||||
boolean isEarlyAccess) {
|
||||
CreateTldCommand command = new CreateTldCommand();
|
||||
command.addGracePeriod = addGracePeriod;
|
||||
command.dnsWriters = dnsWriters;
|
||||
command.validDnsWriterNames = validDnsWriterNames;
|
||||
command.force = force;
|
||||
command.initialTldState = initialTldState;
|
||||
command.mainParameters = ImmutableList.of(tldName);
|
||||
command.pendingDeleteLength = pendingDeleteLength;
|
||||
command.premiumListName = Optional.of(premiumList);
|
||||
String tldNameAlphaNumerical = tldName.replaceAll("[^a-z0-9]", "");
|
||||
command.roidSuffix =
|
||||
String.format(
|
||||
"%S%X",
|
||||
tldNameAlphaNumerical.substring(0, Math.min(tldNameAlphaNumerical.length(), 7)),
|
||||
roidSuffixCounter++);
|
||||
command.redemptionGracePeriod = redemptionGracePeriod;
|
||||
if (isEarlyAccess) {
|
||||
command.eapFeeSchedule = EAP_FEE_SCHEDULE;
|
||||
}
|
||||
runCommand(command);
|
||||
}
|
||||
|
||||
/** Constructs and runs a CreateRegistrarCommand */
|
||||
private void createRegistrar(String registrarName, String password, String tld) {
|
||||
CreateRegistrarCommand command = new CreateRegistrarCommand();
|
||||
command.mainParameters = ImmutableList.of(registrarName);
|
||||
command.createGoogleGroups = false; // Don't create Google Groups for OT&E registrars.
|
||||
command.allowedTlds = ImmutableList.of(tld);
|
||||
command.registrarName = registrarName;
|
||||
command.registrarType = Registrar.Type.OTE;
|
||||
command.password = password;
|
||||
command.clientCertificateFilename = certFile;
|
||||
command.clientCertificateHash = certHash;
|
||||
command.ipWhitelist = ipWhitelist;
|
||||
command.street = ImmutableList.of("e-street");
|
||||
command.city = "Neverland";
|
||||
command.state = "NY";
|
||||
command.countryCode = "US";
|
||||
command.zip = "55555";
|
||||
command.email = Optional.of("foo@neverland.com");
|
||||
command.fax = Optional.of("+1.2125550100");
|
||||
command.phone = Optional.of("+1.2125550100");
|
||||
command.icannReferralEmail = "nightmare@registrar.test";
|
||||
command.force = force;
|
||||
runCommand(command);
|
||||
}
|
||||
|
||||
/** Constructs and runs a RegistrarContactCommand */
|
||||
private void createRegistrarContact(String registrarName) {
|
||||
RegistrarContactCommand command = new RegistrarContactCommand();
|
||||
command.mainParameters = ImmutableList.of(registrarName);
|
||||
command.mode = RegistrarContactCommand.Mode.CREATE;
|
||||
command.name = email;
|
||||
command.email = email;
|
||||
command.allowConsoleAccess = true;
|
||||
command.force = force;
|
||||
runCommand(command);
|
||||
}
|
||||
OteAccountBuilder oteAccountBuilder;
|
||||
String password;
|
||||
|
||||
/** Run any pre-execute command checks */
|
||||
@Override
|
||||
protected boolean checkExecutionState() throws Exception {
|
||||
checkArgument(
|
||||
REGISTRAR_PATTERN.matcher(registrar).matches(),
|
||||
"Registrar name is invalid (see usage text for requirements).");
|
||||
|
||||
// Make sure the email is "correct" - as in it's a valid email we can convert to gaeId
|
||||
// There's no need to look at the result - it'll be converted again inside
|
||||
// RegistrarContactCommand.
|
||||
checkNotNull(
|
||||
GaeUserIdConverter.convertEmailAddressToGaeUserId(email),
|
||||
"Email address %s is not associated with any GAE ID",
|
||||
email);
|
||||
|
||||
boolean warned = false;
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.SANDBOX
|
||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||
System.err.printf(
|
||||
"WARNING: Running against %s environment. Are "
|
||||
+ "you sure you didn\'t mean to run this against sandbox (e.g. \"-e SANDBOX\")?%n",
|
||||
RegistryEnvironment.get());
|
||||
warned = true;
|
||||
}
|
||||
|
||||
if (warned && !promptForYes("Proceed despite warnings?")) {
|
||||
System.out.println("Command aborted.");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void init() throws Exception {
|
||||
checkArgument(
|
||||
certFile == null ^ certHash == null,
|
||||
"Must specify exactly one of client certificate file or client certificate hash.");
|
||||
|
||||
// Don't wait for create_registrar to fail if it's a bad certificate file.
|
||||
password = passwordGenerator.createString(PASSWORD_LENGTH);
|
||||
oteAccountBuilder =
|
||||
OteAccountBuilder.forClientId(registrar)
|
||||
.addContact(email)
|
||||
.setPassword(password)
|
||||
.setIpWhitelist(ipWhitelist)
|
||||
.setReplaceExisting(overwrite);
|
||||
|
||||
if (certFile != null) {
|
||||
loadCertificate(certFile.toAbsolutePath());
|
||||
String asciiCert = MoreFiles.asCharSource(certFile, US_ASCII).read();
|
||||
// Don't wait for create_registrar to fail if it's a bad certificate file.
|
||||
loadCertificate(asciiCert);
|
||||
oteAccountBuilder.setCertificate(asciiCert, clock.nowUtc());
|
||||
}
|
||||
|
||||
if (certHash != null) {
|
||||
oteAccountBuilder.setCertificateHash(certHash);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String prompt() {
|
||||
// Each underlying command will confirm its own operation as well, so just provide
|
||||
// a summary of the steps in this command.
|
||||
if (eapOnly) {
|
||||
return "Creating TLD:\n"
|
||||
+ " " + registrar + "-eap\n"
|
||||
+ "Creating registrar:\n"
|
||||
+ " " + registrar + "-5 (access to TLD " + registrar + "-eap)\n"
|
||||
+ "Giving contact access to this registrar:\n"
|
||||
+ " " + email;
|
||||
} else {
|
||||
return "Creating TLDs:\n"
|
||||
+ " " + registrar + "-sunrise\n"
|
||||
+ " " + registrar + "-landrush\n"
|
||||
+ " " + registrar + "-ga\n"
|
||||
+ " " + registrar + "-eap\n"
|
||||
+ "Creating registrars:\n"
|
||||
+ " " + registrar + "-1 (access to TLD " + registrar + "-sunrise)\n"
|
||||
+ " " + registrar + "-2 (access to TLD " + registrar + "-landrush)\n"
|
||||
+ " " + registrar + "-3 (access to TLD " + registrar + "-ga)\n"
|
||||
+ " " + registrar + "-4 (access to TLD " + registrar + "-ga)\n"
|
||||
+ " " + registrar + "-5 (access to TLD " + registrar + "-eap)\n"
|
||||
+ "Giving contact access to these registrars:\n"
|
||||
+ " " + email;
|
||||
ImmutableMap<String, String> registrarToTldMap = oteAccountBuilder.getClientIdToTldMap();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Creating TLDs:");
|
||||
registrarToTldMap.values().forEach(tld -> builder.append("\n ").append(tld));
|
||||
builder.append("\nCreating registrars:");
|
||||
registrarToTldMap.forEach(
|
||||
(clientId, tld) ->
|
||||
builder.append(String.format("\n %s (with access to %s)", clientId, tld)));
|
||||
builder.append("\nGiving contact access to these registrars:").append("\n ").append(email);
|
||||
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.SANDBOX
|
||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||
builder.append(
|
||||
String.format(
|
||||
"\n\nWARNING: Running against %s environment. Are "
|
||||
+ "you sure you didn\'t mean to run this against sandbox (e.g. \"-e SANDBOX\")?",
|
||||
RegistryEnvironment.get()));
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
if (!eapOnly) {
|
||||
createTld(registrar + "-sunrise", TldState.START_DATE_SUNRISE, null, null, null, false);
|
||||
createTld(registrar + "-landrush", TldState.LANDRUSH, null, null, null, false);
|
||||
createTld(
|
||||
registrar + "-ga",
|
||||
TldState.GENERAL_AVAILABILITY,
|
||||
SHORT_ADD_GRACE_PERIOD,
|
||||
SHORT_REDEMPTION_GRACE_PERIOD,
|
||||
SHORT_PENDING_DELETE_LENGTH,
|
||||
false);
|
||||
} else {
|
||||
// Increase ROID suffix counter to not collide with existing TLDs.
|
||||
roidSuffixCounter = roidSuffixCounter + 3;
|
||||
}
|
||||
createTld(
|
||||
registrar + "-eap",
|
||||
TldState.GENERAL_AVAILABILITY,
|
||||
SHORT_ADD_GRACE_PERIOD,
|
||||
SHORT_REDEMPTION_GRACE_PERIOD,
|
||||
SHORT_PENDING_DELETE_LENGTH,
|
||||
true);
|
||||
|
||||
// Storing names and credentials in a list of tuples for later play-back.
|
||||
List<List<String>> registrars = new ArrayList<>();
|
||||
if (!eapOnly) {
|
||||
registrars.add(
|
||||
ImmutableList.of(
|
||||
registrar + "-1",
|
||||
passwordGenerator.createString(PASSWORD_LENGTH),
|
||||
registrar + "-sunrise"));
|
||||
registrars.add(
|
||||
ImmutableList.of(
|
||||
registrar + "-2",
|
||||
passwordGenerator.createString(PASSWORD_LENGTH),
|
||||
registrar + "-landrush"));
|
||||
registrars.add(
|
||||
ImmutableList.of(
|
||||
registrar + "-3",
|
||||
passwordGenerator.createString(PASSWORD_LENGTH),
|
||||
registrar + "-ga"));
|
||||
registrars.add(
|
||||
ImmutableList.of(
|
||||
registrar + "-4",
|
||||
passwordGenerator.createString(PASSWORD_LENGTH),
|
||||
registrar + "-ga"));
|
||||
}
|
||||
registrars.add(
|
||||
ImmutableList.of(
|
||||
registrar + "-5", passwordGenerator.createString(PASSWORD_LENGTH), registrar + "-eap"));
|
||||
|
||||
for (List<String> r : registrars) {
|
||||
createRegistrar(r.get(0), r.get(1), r.get(2));
|
||||
createRegistrarContact(r.get(0));
|
||||
}
|
||||
ImmutableMap<String, String> clientIdToTld = oteAccountBuilder.buildAndPersist();
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
output.append("Copy these usernames/passwords back into the onboarding bug:\n\n");
|
||||
|
||||
for (List<String> r : registrars) {
|
||||
output.append("Login: " + r.get(0) + "\n");
|
||||
output.append("Password: " + r.get(1) + "\n");
|
||||
output.append("TLD: " + r.get(2) + "\n\n");
|
||||
}
|
||||
clientIdToTld.forEach(
|
||||
(clientId, tld) -> {
|
||||
output.append(
|
||||
String.format("Login: %s\nPassword: %s\nTLD: %s\n\n", clientId, password, tld));
|
||||
});
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue