Centralize token generation and formats

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=135313726
This commit is contained in:
ctingue 2016-10-05 19:59:00 -07:00 committed by Ben McIlwain
parent 886d6f8e17
commit 79387f5d1e
21 changed files with 131 additions and 39 deletions

View file

@ -18,6 +18,8 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.model.registry.Registries.findTldForNameOrThrow; import static google.registry.model.registry.Registries.findTldForNameOrThrow;
import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost; import static google.registry.pricing.PricingEngineProxy.getDomainCreateCost;
import static google.registry.util.TokenUtils.TokenType.ANCHOR_TENANT;
import static google.registry.util.TokenUtils.createToken;
import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.DateTimeZone.UTC;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
@ -25,6 +27,7 @@ import com.beust.jcommander.Parameters;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import com.google.template.soy.data.SoyMapData; import com.google.template.soy.data.SoyMapData;
import google.registry.tools.soy.CreateAnchorTenantSoyInfo; import google.registry.tools.soy.CreateAnchorTenantSoyInfo;
import google.registry.util.StringGenerator;
import javax.inject.Inject; import javax.inject.Inject;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -33,7 +36,6 @@ import org.joda.time.DateTime;
@Parameters(separators = " =", commandDescription = "Provision a domain for an anchor tenant.") @Parameters(separators = " =", commandDescription = "Provision a domain for an anchor tenant.")
final class CreateAnchorTenantCommand extends MutatingEppToolCommand { final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
private static final int PASSWORD_LENGTH = 16;
private static final int DEFAULT_ANCHOR_TENANT_PERIOD_YEARS = 2; private static final int DEFAULT_ANCHOR_TENANT_PERIOD_YEARS = 2;
@Parameter( @Parameter(
@ -78,7 +80,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
checkArgument(superuser, "This command must be run as a superuser."); checkArgument(superuser, "This command must be run as a superuser.");
findTldForNameOrThrow(InternetDomainName.from(domainName)); // Check that the tld exists. findTldForNameOrThrow(InternetDomainName.from(domainName)); // Check that the tld exists.
if (isNullOrEmpty(password)) { if (isNullOrEmpty(password)) {
password = passwordGenerator.createString(PASSWORD_LENGTH); password = createToken(ANCHOR_TENANT, passwordGenerator);
} }
Money cost = null; Money cost = null;

View file

@ -22,6 +22,7 @@ import com.beust.jcommander.Parameters;
import com.google.template.soy.data.SoyMapData; import com.google.template.soy.data.SoyMapData;
import google.registry.tools.params.PhoneNumberParameter; import google.registry.tools.params.PhoneNumberParameter;
import google.registry.tools.soy.ContactCreateSoyInfo; import google.registry.tools.soy.ContactCreateSoyInfo;
import google.registry.util.StringGenerator;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;

View file

@ -21,6 +21,7 @@ import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
import com.google.template.soy.data.SoyMapData; import com.google.template.soy.data.SoyMapData;
import google.registry.tools.soy.DomainCreateSoyInfo; import google.registry.tools.soy.DomainCreateSoyInfo;
import google.registry.util.StringGenerator;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;

View file

@ -19,6 +19,7 @@ import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.difference;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.Registries.assertTldExists; import static google.registry.model.registry.Registries.assertTldExists;
import static google.registry.util.TokenUtils.TokenType.LRP;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
@ -34,6 +35,8 @@ import com.googlecode.objectify.Work;
import google.registry.model.domain.LrpToken; import google.registry.model.domain.LrpToken;
import google.registry.tools.Command.RemoteApiCommand; import google.registry.tools.Command.RemoteApiCommand;
import google.registry.tools.params.PathParameter; import google.registry.tools.params.PathParameter;
import google.registry.util.StringGenerator;
import google.registry.util.TokenUtils;
import java.io.StringReader; import java.io.StringReader;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collection; import java.util.Collection;
@ -70,7 +73,6 @@ public final class CreateLrpTokensCommand implements RemoteApiCommand {
@Inject StringGenerator stringGenerator; @Inject StringGenerator stringGenerator;
private static final int TOKEN_LENGTH = 16;
private static final int BATCH_SIZE = 20; private static final int BATCH_SIZE = 20;
@Override @Override
@ -125,7 +127,7 @@ public final class CreateLrpTokensCommand implements RemoteApiCommand {
*/ */
private ImmutableSet<String> generateTokens(int count) { private ImmutableSet<String> generateTokens(int count) {
final ImmutableSet<String> candidates = final ImmutableSet<String> candidates =
ImmutableSet.copyOf(stringGenerator.createStrings(TOKEN_LENGTH, count)); ImmutableSet.copyOf(TokenUtils.createTokens(LRP, stringGenerator, count));
ImmutableSet<Key<LrpToken>> existingTokenKeys = FluentIterable.from(candidates) ImmutableSet<Key<LrpToken>> existingTokenKeys = FluentIterable.from(candidates)
.transform(new Function<String, Key<LrpToken>>() { .transform(new Function<String, Key<LrpToken>>() {
@Override @Override

View file

@ -51,6 +51,7 @@ interface RegistryToolComponent {
void inject(CreateAnchorTenantCommand command); void inject(CreateAnchorTenantCommand command);
void inject(CreateContactCommand command); void inject(CreateContactCommand command);
void inject(CreateDomainCommand command); void inject(CreateDomainCommand command);
void inject(CreateLrpTokensCommand command);
void inject(CreateTldCommand command); void inject(CreateTldCommand command);
void inject(EncryptEscrowDepositCommand command); void inject(EncryptEscrowDepositCommand command);
void inject(GenerateApplicationsReportCommand command); void inject(GenerateApplicationsReportCommand command);

View file

@ -17,6 +17,8 @@ package google.registry.tools;
import dagger.Binds; import dagger.Binds;
import dagger.Module; import dagger.Module;
import dagger.Provides; import dagger.Provides;
import google.registry.util.RandomStringGenerator;
import google.registry.util.StringGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.ProviderException; import java.security.ProviderException;
import java.security.SecureRandom; import java.security.SecureRandom;

View file

@ -28,6 +28,7 @@ import google.registry.model.registrar.Registrar;
import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldState;
import google.registry.tools.Command.RemoteApiCommand; import google.registry.tools.Command.RemoteApiCommand;
import google.registry.tools.params.PathParameter; import google.registry.tools.params.PathParameter;
import google.registry.util.StringGenerator;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package google.registry.tools; package google.registry.util;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
@ -21,7 +21,7 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
/** Random string generator. */ /** Random string generator. */
class RandomStringGenerator extends StringGenerator { public class RandomStringGenerator extends StringGenerator {
private final Random random; private final Random random;

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package google.registry.tools; package google.registry.util;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Strings.isNullOrEmpty;
@ -21,7 +21,7 @@ import com.google.common.collect.ImmutableList;
import java.util.Collection; import java.util.Collection;
/** String generator. */ /** String generator. */
abstract class StringGenerator { public abstract class StringGenerator {
/** A class containing different alphabets used to generate strings. */ /** A class containing different alphabets used to generate strings. */
public static class Alphabets { public static class Alphabets {
@ -37,13 +37,13 @@ abstract class StringGenerator {
protected String alphabet; protected String alphabet;
StringGenerator(String alphabet) { protected StringGenerator(String alphabet) {
checkArgument(!isNullOrEmpty(alphabet), "Alphabet cannot be null or empty."); checkArgument(!isNullOrEmpty(alphabet), "Alphabet cannot be null or empty.");
this.alphabet = alphabet; this.alphabet = alphabet;
} }
/** Generates a string of a specified length. */ /** Generates a string of a specified length. */
abstract String createString(int length); public abstract String createString(int length);
/** Batch-generates an {@link ImmutableList} of strings of a specified length. */ /** Batch-generates an {@link ImmutableList} of strings of a specified length. */
public Collection<String> createStrings(int length, int count) { public Collection<String> createStrings(int length, int count) {

View file

@ -0,0 +1,73 @@
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.util;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
/**
* A utility class for generating various auth tokens using a common prefixed-based format.
* These tokens are generally of the form [TYPE]_[randomstring].
*/
public final class TokenUtils {
/** An enum containing definitions (prefix and length) for token types. */
public enum TokenType {
ANCHOR_TENANT("ANCHOR", 16),
LRP("LRP", 16);
private final String prefix;
private final int length;
private TokenType(String prefix, int length) {
this.prefix = prefix;
this.length = length;
}
/** Returns the prefix for a given type. */
public String getPrefix() {
return prefix;
}
/** Returns the set token length for a given type (not including the prefix). */
public int getLength() {
return length;
}
}
/** Generates a single token of a given {@link TokenType}. */
public static String createToken(TokenType type, StringGenerator generator) {
return Iterables.getOnlyElement(createTokens(type, generator, 1));
}
/** Generates a {@link Collection} of tokens of a given {@link TokenType}. */
public static ImmutableSet<String> createTokens(
final TokenType type,
StringGenerator generator,
int count) {
return FluentIterable.from(generator.createStrings(type.getLength(), count))
.transform(new Function<String, String>() {
@Override
public String apply(String token) {
return String.format("%s_%s", type.getPrefix(), token);
}})
.toSet();
}
private TokenUtils() {}
}

View file

@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package google.registry.tools; package google.registry.testing;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Lists.charactersOf; import static com.google.common.collect.Lists.charactersOf;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import google.registry.util.RandomStringGenerator;
import google.registry.util.StringGenerator;
import java.util.Iterator; import java.util.Iterator;
import javax.inject.Named; import javax.inject.Named;
@ -29,14 +31,14 @@ import javax.inject.Named;
* <p>Note that consecutive calls to createString will continue where the last call left off in * <p>Note that consecutive calls to createString will continue where the last call left off in
* the alphabet. * the alphabet.
*/ */
class DeterministicStringGenerator extends StringGenerator { public class DeterministicStringGenerator extends StringGenerator {
private Iterator<Character> iterator; private Iterator<Character> iterator;
private final Rule rule; private final Rule rule;
private int counter = 0; private int counter = 0;
/** String generation rules. */ /** String generation rules. */
enum Rule { public enum Rule {
/** /**
* Simple string generation, cycling through sequential letters in the alphabet. May produce * Simple string generation, cycling through sequential letters in the alphabet. May produce

View file

@ -20,6 +20,7 @@ import static google.registry.testing.DatastoreHelper.persistResource;
import com.beust.jcommander.ParameterException; import com.beust.jcommander.ParameterException;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.testing.DeterministicStringGenerator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View file

@ -15,6 +15,7 @@
package google.registry.tools; package google.registry.tools;
import com.beust.jcommander.ParameterException; import com.beust.jcommander.ParameterException;
import google.registry.testing.DeterministicStringGenerator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View file

@ -15,6 +15,7 @@
package google.registry.tools; package google.registry.tools;
import com.beust.jcommander.ParameterException; import com.beust.jcommander.ParameterException;
import google.registry.testing.DeterministicStringGenerator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View file

@ -26,7 +26,8 @@ import com.google.common.io.Files;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import google.registry.model.domain.LrpToken; import google.registry.model.domain.LrpToken;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.tools.DeterministicStringGenerator.Rule; import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.DeterministicStringGenerator.Rule;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Set; import java.util.Set;
@ -53,30 +54,32 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
@Test @Test
public void testSuccess_oneAssignee() throws Exception { public void testSuccess_oneAssignee() throws Exception {
runCommand("--assignee=domain.tld", "--tlds=tld"); runCommand("--assignee=domain.tld", "--tlds=tld");
assertLrpTokens(createToken("abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null)); assertLrpTokens(
assertInStdout("domain.tld,abcdefghijklmnop"); createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
} }
@Test @Test
public void testSuccess_oneAssignee_tokenCollision() throws Exception { public void testSuccess_oneAssignee_tokenCollision() throws Exception {
LrpToken existingToken = persistResource(new LrpToken.Builder() LrpToken existingToken = persistResource(new LrpToken.Builder()
.setToken("abcdefghijklmnop") .setToken("LRP_abcdefghijklmnop")
.setAssignee("otherdomain.tld") .setAssignee("otherdomain.tld")
.setValidTlds(ImmutableSet.of("tld")) .setValidTlds(ImmutableSet.of("tld"))
.build()); .build());
runCommand("--assignee=domain.tld", "--tlds=tld"); runCommand("--assignee=domain.tld", "--tlds=tld");
assertLrpTokens( assertLrpTokens(
existingToken, existingToken,
createToken("qrstuvwxyzabcdef", "domain.tld", ImmutableSet.of("tld"), null)); createToken("LRP_qrstuvwxyzabcdef", "domain.tld", ImmutableSet.of("tld"), null));
assertInStdout("domain.tld,qrstuvwxyzabcdef"); assertInStdout("domain.tld,LRP_qrstuvwxyzabcdef");
} }
@Test @Test
public void testSuccess_oneAssignee_byFile() throws Exception { public void testSuccess_oneAssignee_byFile() throws Exception {
Files.write("domain.tld", assigneeFile, UTF_8); Files.write("domain.tld", assigneeFile, UTF_8);
runCommand("--input=" + assigneeFilePath, "--tlds=tld"); runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens(createToken("abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null)); assertLrpTokens(
assertInStdout("domain.tld,abcdefghijklmnop"); createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null));
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
} }
@Test @Test
@ -93,13 +96,13 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
runCommand("--input=" + assigneeFilePath, "--tlds=tld"); runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens( assertLrpTokens(
createToken("abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null), createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null),
createToken("qrstuvwxyzabcdef", "domain2.tld", ImmutableSet.of("tld"), null), createToken("LRP_qrstuvwxyzabcdef", "domain2.tld", ImmutableSet.of("tld"), null),
createToken("ghijklmnopqrstuv", "domain3.tld", ImmutableSet.of("tld"), null)); createToken("LRP_ghijklmnopqrstuv", "domain3.tld", ImmutableSet.of("tld"), null));
assertInStdout("domain1.tld,abcdefghijklmnop"); assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
assertInStdout("domain2.tld,qrstuvwxyzabcdef"); assertInStdout("domain2.tld,LRP_qrstuvwxyzabcdef");
assertInStdout("domain3.tld,ghijklmnopqrstuv"); assertInStdout("domain3.tld,LRP_ghijklmnopqrstuv");
} }
@Test @Test
@ -107,11 +110,11 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
Files.write("domain1.tld\n\ndomain2.tld", assigneeFile, UTF_8); Files.write("domain1.tld\n\ndomain2.tld", assigneeFile, UTF_8);
runCommand("--input=" + assigneeFilePath, "--tlds=tld"); runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens( assertLrpTokens(
createToken("abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null), createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null),
// Second deterministic token (qrstuvwxyzabcdef) still consumed but not assigned // Second deterministic token (LRP_qrstuvwxyzabcdef) still consumed but not assigned
createToken("ghijklmnopqrstuv", "domain2.tld", ImmutableSet.of("tld"), null)); createToken("LRP_ghijklmnopqrstuv", "domain2.tld", ImmutableSet.of("tld"), null));
assertInStdout("domain1.tld,abcdefghijklmnop"); assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
assertInStdout("domain2.tld,ghijklmnopqrstuv"); assertInStdout("domain2.tld,LRP_ghijklmnopqrstuv");
} }
@Test @Test
@ -127,7 +130,7 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
assigneeFileBuilder.append(String.format("domain%d.tld\n", i)); assigneeFileBuilder.append(String.format("domain%d.tld\n", i));
expectedTokens[i] = expectedTokens[i] =
createToken( createToken(
String.format("%04d_abcdefghijklmnop", i), String.format("LRP_%04d_abcdefghijklmnop", i),
String.format("domain%d.tld", i), String.format("domain%d.tld", i),
ImmutableSet.of("tld"), ImmutableSet.of("tld"),
null); null);
@ -136,7 +139,7 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
runCommand("--input=" + assigneeFilePath, "--tlds=tld"); runCommand("--input=" + assigneeFilePath, "--tlds=tld");
assertLrpTokens(expectedTokens); assertLrpTokens(expectedTokens);
for (int i = 0; i < numberOfTokens; i++) { for (int i = 0; i < numberOfTokens; i++) {
assertInStdout(String.format("domain%d.tld,%04d_abcdefghijklmnop", i, i)); assertInStdout(String.format("domain%d.tld,LRP_%04d_abcdefghijklmnop", i, i));
} }
} }

View file

@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableSet;
import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldState;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.util.CidrAddressBlock; import google.registry.util.CidrAddressBlock;
import java.security.cert.CertificateParsingException; import java.security.cert.CertificateParsingException;
import org.joda.time.DateTime; import org.joda.time.DateTime;

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>abcdefghijklmnop</domain:pw> <domain:pw>ANCHOR_abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>abcdefghijklmnop</domain:pw> <domain:pw>ANCHOR_abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>abcdefghijklmnop</domain:pw> <domain:pw>ANCHOR_abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>abcdefghijklmnop</domain:pw> <domain:pw>ANCHOR_abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>

View file

@ -9,7 +9,7 @@
<domain:contact type="admin">jd1234</domain:contact> <domain:contact type="admin">jd1234</domain:contact>
<domain:contact type="tech">jd1234</domain:contact> <domain:contact type="tech">jd1234</domain:contact>
<domain:authInfo> <domain:authInfo>
<domain:pw>abcdefghijklmnop</domain:pw> <domain:pw>ANCHOR_abcdefghijklmnop</domain:pw>
</domain:authInfo> </domain:authInfo>
</domain:create> </domain:create>
</create> </create>