unmarshal(inputXmlBytes),
+ Trid.create(null),
+ new HttpSessionMetadata(
+ new TlsCredentials(
clientCertificateHash,
- InetAddresses.forString(clientIpAddress),
- "placeholder")); // behave as if we have SNI on, since we're validating a cert
- }
-
- @Override
- protected void setProperty(String key, Object value) {
- properties.put(key, value);
- }
-
- @Override
- protected Object getProperty(String key) {
- return properties.get(key);
- }
-
- @Override
- public SessionSource getSessionSource() {
- return SessionSource.TOOL;
- }
-
- @Override
- public void invalidate() {}
- },
+ Optional.of(clientIpAddress),
+ "placeholder"), // behave as if we have SNI on, since we're validating a cert
+ new BasicHttpSession()),
inputXmlBytes,
- null),
+ null,
+ new SystemClock()),
CommitMode.DRY_RUN,
UserPrivileges.NORMAL));
}
diff --git a/java/google/registry/ui/server/api/BUILD b/java/google/registry/ui/server/api/BUILD
index 7736648e8..e2a5c7210 100644
--- a/java/google/registry/ui/server/api/BUILD
+++ b/java/google/registry/ui/server/api/BUILD
@@ -11,9 +11,12 @@ java_library(
"//java/com/google/common/base",
"//java/com/google/common/collect",
"//java/com/google/common/net",
+ "//third_party/java/dagger",
+ "//third_party/java/jsr330_inject",
"//java/google/registry/config",
"//java/google/registry/flows",
"//java/google/registry/model",
+ "//java/google/registry/request",
"//java/google/registry/ui/server",
"//java/google/registry/ui/soy/api:soy_java_wrappers",
"//java/google/registry/util",
diff --git a/java/google/registry/ui/server/api/CheckApiServlet.java b/java/google/registry/ui/server/api/CheckApiAction.java
similarity index 77%
rename from java/google/registry/ui/server/api/CheckApiServlet.java
rename to java/google/registry/ui/server/api/CheckApiAction.java
index 893b6c415..46bdca8cb 100644
--- a/java/google/registry/ui/server/api/CheckApiServlet.java
+++ b/java/google/registry/ui/server/api/CheckApiAction.java
@@ -31,6 +31,9 @@ import com.google.common.net.InternetDomainName;
import com.google.common.net.MediaType;
import com.google.template.soy.tofu.SoyTofu;
+import dagger.Module;
+import dagger.Provides;
+
import google.registry.config.RegistryEnvironment;
import google.registry.flows.EppException;
import google.registry.flows.EppXmlTransformer;
@@ -47,37 +50,33 @@ import google.registry.model.eppinput.EppInput;
import google.registry.model.eppoutput.CheckData.DomainCheck;
import google.registry.model.eppoutput.CheckData.DomainCheckData;
import google.registry.model.eppoutput.Response;
+import google.registry.request.Action;
+import google.registry.request.Parameter;
+import google.registry.request.RequestParameters;
import google.registry.ui.soy.api.DomainCheckFeeEppSoyInfo;
+import google.registry.util.Clock;
+import google.registry.util.FormattingLogger;
-import java.io.IOException;
import java.util.Map;
-import javax.servlet.http.HttpServlet;
+import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
/**
* A servlet that returns availability and premium checks as json.
*
- * This servlet returns plain JSON without a safety prefix, so it's vital that the output not be
+ *
This action returns plain JSON without a safety prefix, so it's vital that the output not be
* user controlled, lest it open an XSS vector. Do not modify this to return the domain name in the
* response.
*/
-public class CheckApiServlet extends HttpServlet {
+@Action(path = "/check")
+public class CheckApiAction implements Runnable {
+
+ private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
private static final Supplier TOFU_SUPPLIER =
createTofuSupplier(DomainCheckFeeEppSoyInfo.getInstance());
- @Override
- public void doGet(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
- Map response = doCheck(req.getParameter("domain"));
- rsp.setHeader("Content-Disposition", "attachment");
- rsp.setHeader("X-Content-Type-Options", "nosniff");
- rsp.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
- rsp.setContentType(MediaType.JSON_UTF_8.toString());
- rsp.getWriter().write(toJSONString(response));
- }
-
private StatelessRequestSessionMetadata sessionMetadata = new StatelessRequestSessionMetadata(
RegistryEnvironment.get().config().getCheckApiServletRegistrarClientId(),
false,
@@ -85,6 +84,21 @@ public class CheckApiServlet extends HttpServlet {
ImmutableSet.of(FEE_0_6.getUri()),
SessionSource.HTTP);
+ @Inject @Parameter("domain") String domain;
+ @Inject google.registry.request.Response response;
+ @Inject Clock clock;
+ @Inject CheckApiAction() {}
+
+ @Override
+ public void run() {
+ Map checkResponse = doCheck(domain);
+ response.setHeader("Content-Disposition", "attachment");
+ response.setHeader("X-Content-Type-Options", "nosniff");
+ response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
+ response.setContentType(MediaType.JSON_UTF_8);
+ response.setPayload(toJSONString(checkResponse));
+ }
+
// TODO(rgr): add whitebox instrumentation for this?
private Map doCheck(String domainString) {
try {
@@ -103,10 +117,11 @@ public class CheckApiServlet extends HttpServlet {
Response response = new FlowRunner(
DomainCheckFlow.class,
EppXmlTransformer.unmarshal(inputXmlBytes),
- Trid.create(CheckApiServlet.class.getSimpleName()),
+ Trid.create(getClass().getSimpleName()),
sessionMetadata,
inputXmlBytes,
- null)
+ null,
+ clock)
.run(CommitMode.LIVE, UserPrivileges.NORMAL)
.getResponse();
DomainCheckData checkData = (DomainCheckData) response.getResponseData().get(0);
@@ -127,7 +142,7 @@ public class CheckApiServlet extends HttpServlet {
} catch (EppException e) {
return fail(e.getMessage());
} catch (Exception e) {
- e.printStackTrace();
+ logger.warning(e, "Unknown error");
return fail("Invalid request");
}
}
@@ -137,4 +152,14 @@ public class CheckApiServlet extends HttpServlet {
"status", "error",
"reason", reason);
}
+
+ /** Dagger module for the check api endpoint. */
+ @Module
+ public static final class CheckApiModule {
+ @Provides
+ @Parameter("domain")
+ static String provideDomain(HttpServletRequest req) {
+ return RequestParameters.extractRequiredParameter(req, "domain");
+ }
+ }
}
diff --git a/java/google/registry/ui/server/registrar/ConsoleUiAction.java b/java/google/registry/ui/server/registrar/ConsoleUiAction.java
index c8acb4c37..018492b14 100644
--- a/java/google/registry/ui/server/registrar/ConsoleUiAction.java
+++ b/java/google/registry/ui/server/registrar/ConsoleUiAction.java
@@ -28,7 +28,7 @@ import com.google.template.soy.shared.SoyCssRenamingMap;
import com.google.template.soy.tofu.SoyTofu;
import google.registry.config.ConfigModule.Config;
-import google.registry.flows.EppConsoleServlet;
+import google.registry.flows.EppConsoleAction;
import google.registry.model.registrar.Registrar;
import google.registry.request.Action;
import google.registry.request.Response;
@@ -92,7 +92,7 @@ public final class ConsoleUiAction implements Runnable {
}
Registrar registrar = Registrar.loadByClientId(sessionUtils.getRegistrarClientId(req));
SoyMapData data = new SoyMapData();
- data.put("xsrfToken", XsrfTokenManager.generateToken(EppConsoleServlet.XSRF_SCOPE));
+ data.put("xsrfToken", XsrfTokenManager.generateToken(EppConsoleAction.XSRF_SCOPE));
data.put("clientId", registrar.getClientIdentifier());
data.put("username", userService.getCurrentUser().getNickname());
data.put("isAdmin", userService.isUserAdmin());
diff --git a/java/google/registry/ui/server/registrar/ResourceServlet.java b/java/google/registry/ui/server/registrar/ResourceServlet.java
index 1a101c4bd..1922d398e 100644
--- a/java/google/registry/ui/server/registrar/ResourceServlet.java
+++ b/java/google/registry/ui/server/registrar/ResourceServlet.java
@@ -15,7 +15,7 @@
package google.registry.ui.server.registrar;
import static com.google.appengine.api.users.UserServiceFactory.getUserService;
-import static google.registry.flows.EppConsoleServlet.XSRF_SCOPE;
+import static google.registry.flows.EppConsoleAction.XSRF_SCOPE;
import static google.registry.security.JsonResponseHelper.Status.ERROR;
import com.google.common.base.Optional;
diff --git a/javatests/google/registry/flows/EppConsoleActionTest.java b/javatests/google/registry/flows/EppConsoleActionTest.java
new file mode 100644
index 000000000..2c666838a
--- /dev/null
+++ b/javatests/google/registry/flows/EppConsoleActionTest.java
@@ -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.flows;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import google.registry.testing.AppEngineRule;
+import google.registry.testing.ShardableTestCase;
+import google.registry.testing.UserInfo;
+import google.registry.util.BasicHttpSession;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+
+/** Tests for {@link EppConsoleAction}. */
+@RunWith(JUnit4.class)
+public class EppConsoleActionTest extends ShardableTestCase {
+
+ private static final byte[] INPUT_XML_BYTES = "".getBytes(UTF_8);
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withUserService(UserInfo.create("person@example.com", "12345"))
+ .build();
+
+ private void doTest(boolean superuser) {
+ EppConsoleAction action = new EppConsoleAction();
+ action.inputXmlBytes = INPUT_XML_BYTES;
+ action.session = new BasicHttpSession();
+ action.session.setAttribute("CLIENT_ID", "ClientIdentifier");
+ action.session.setAttribute("SUPERUSER", superuser);
+ action.eppRequestHandler = mock(EppRequestHandler.class);
+ action.run();
+ ArgumentCaptor captor = ArgumentCaptor.forClass(SessionMetadata.class);
+ verify(action.eppRequestHandler).executeEpp(captor.capture(), eq(INPUT_XML_BYTES));
+ SessionMetadata sessionMetadata = captor.getValue();
+ assertThat(((GaeUserCredentials) sessionMetadata.getTransportCredentials()).gaeUser.getEmail())
+ .isEqualTo("person@example.com");
+ assertThat(sessionMetadata.getClientId()).isEqualTo("ClientIdentifier");
+ assertThat(sessionMetadata.isDryRun()).isFalse(); // Should always be false for console.
+ assertThat(sessionMetadata.isSuperuser()).isEqualTo(superuser);
+ }
+
+ @Test
+ public void testSuperuser() throws Exception {
+ doTest(true);
+ }
+
+ @Test
+ public void testNotSuperuser() throws Exception {
+ doTest(false);
+ }
+}
diff --git a/javatests/google/registry/flows/EppControllerTest.java b/javatests/google/registry/flows/EppControllerTest.java
index a5abca449..ef75953bf 100644
--- a/javatests/google/registry/flows/EppControllerTest.java
+++ b/javatests/google/registry/flows/EppControllerTest.java
@@ -14,13 +14,14 @@
package google.registry.flows;
-import static google.registry.flows.EppController.getErrorResponse;
import static google.registry.flows.EppXmlTransformer.marshal;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppoutput.Result;
import google.registry.model.eppoutput.Result.Code;
import google.registry.testing.AppEngineRule;
+import google.registry.testing.ShardableTestCase;
+import google.registry.util.SystemClock;
import google.registry.xml.ValidationMode;
import org.junit.Rule;
@@ -30,7 +31,7 @@ import org.junit.runners.JUnit4;
/** Unit tests for {@link EppController}. */
@RunWith(JUnit4.class)
-public class EppControllerTest {
+public class EppControllerTest extends ShardableTestCase {
@Rule
public AppEngineRule appEngineRule = new AppEngineRule.Builder().build();
@@ -38,13 +39,8 @@ public class EppControllerTest {
@Test
public void testMarshallingUnknownError() throws Exception {
marshal(
- getErrorResponse(Result.create(Code.CommandFailed), Trid.create(null)),
+ EppController.getErrorResponse(
+ new SystemClock(), Result.create(Code.CommandFailed), Trid.create(null)),
ValidationMode.STRICT);
}
-
- // Extra methods so the test runner doesn't produce empty shards.
-
- @Test public void testNothing1() {}
- @Test public void testNothing2() {}
- @Test public void testNothing3() {}
}
diff --git a/javatests/google/registry/flows/EppLifecycleContactTest.java b/javatests/google/registry/flows/EppLifecycleContactTest.java
new file mode 100644
index 000000000..1583ff578
--- /dev/null
+++ b/javatests/google/registry/flows/EppLifecycleContactTest.java
@@ -0,0 +1,87 @@
+// 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.flows;
+
+import com.google.common.collect.ImmutableMap;
+
+import google.registry.testing.AppEngineRule;
+
+import org.joda.time.DateTime;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for contact lifecycle. */
+@RunWith(JUnit4.class)
+public class EppLifecycleContactTest extends EppTestCase {
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withDatastore()
+ .withTaskQueue()
+ .build();
+
+ @Test
+ public void testContactLifecycle() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "contact_create_sh8013.xml",
+ null,
+ "contact_create_response_sh8013.xml",
+ ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
+ DateTime.parse("2000-06-01T00:00:00Z"));
+ assertCommandAndResponse(
+ "contact_info.xml",
+ "contact_info_from_create_response.xml",
+ DateTime.parse("2000-06-01T00:01:00Z"));
+ assertCommandAndResponse("contact_delete_sh8013.xml", "contact_delete_response_sh8013.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testContactTransferPollMessage() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "contact_create_sh8013.xml",
+ ImmutableMap.of(),
+ "contact_create_response_sh8013.xml",
+ ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
+ DateTime.parse("2000-06-01T00:00:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+
+ // Initiate a transfer of the newly created contact.
+ assertCommandAndResponse("login2_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "contact_transfer_request.xml",
+ "contact_transfer_request_response_alternate.xml",
+ DateTime.parse("2000-06-08T22:00:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+
+ // Log back in with the losing registrar, read the poll message, and then ack it.
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "poll.xml",
+ "poll_response_contact_transfer.xml",
+ DateTime.parse("2000-06-08T22:01:00Z"));
+ assertCommandAndResponse(
+ "poll_ack.xml",
+ ImmutableMap.of("ID", "2-1-ROID-3-4"),
+ "poll_ack_response_empty.xml",
+ null,
+ DateTime.parse("2000-06-08T22:02:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+}
diff --git a/javatests/google/registry/flows/EppLifecycleDomainApplicationTest.java b/javatests/google/registry/flows/EppLifecycleDomainApplicationTest.java
new file mode 100644
index 000000000..1a920081b
--- /dev/null
+++ b/javatests/google/registry/flows/EppLifecycleDomainApplicationTest.java
@@ -0,0 +1,118 @@
+// 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.flows;
+
+import static google.registry.testing.DatastoreHelper.createTld;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedMap;
+
+import google.registry.model.registry.Registry.TldState;
+import google.registry.testing.AppEngineRule;
+import google.registry.util.DateTimeUtils;
+
+import org.joda.time.DateTime;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for domain application lifecycle. */
+@RunWith(JUnit4.class)
+public class EppLifecycleDomainApplicationTest extends EppTestCase {
+
+ private static final DateTime START_OF_GA = DateTime.parse("2014-03-01T00:00:00Z");
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withDatastore()
+ .withTaskQueue()
+ .build();
+
+ @Before
+ public void initTld() {
+ createTld("example", ImmutableSortedMap.of(
+ DateTimeUtils.START_OF_TIME, TldState.SUNRISE,
+ START_OF_GA, TldState.GENERAL_AVAILABILITY));
+ }
+
+ /** Create the two administrative contacts and two hosts. */
+ void createContactsAndHosts() throws Exception {
+ DateTime startTime = DateTime.parse("2000-06-01T00:00:00Z");
+ assertCommandAndResponse(
+ "contact_create_sh8013.xml",
+ ImmutableMap.of(),
+ "contact_create_response_sh8013.xml",
+ ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
+ startTime);
+ assertCommandAndResponse(
+ "contact_create_jd1234.xml",
+ "contact_create_response_jd1234.xml",
+ startTime.plusMinutes(1));
+ assertCommandAndResponse(
+ "host_create.xml",
+ "host_create_response.xml",
+ startTime.plusMinutes(2));
+ assertCommandAndResponse(
+ "host_create2.xml",
+ "host_create2_response.xml",
+ startTime.plusMinutes(3));
+ }
+
+ @Test
+ public void testApplicationDuringSunrise_doesntCreateDomainWithoutAllocation() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ createContactsAndHosts();
+ // Note that the trademark is valid from 2013-08-09 to 2017-07-23, hence the creation in 2014.
+ assertCommandAndResponse(
+ "domain_create_sunrise_encoded_mark.xml",
+ "domain_create_sunrise_encoded_signed_mark_response.xml",
+ DateTime.parse("2014-01-01T00:00:00Z"));
+ assertCommandAndResponse(
+ "domain_info_testvalidate.xml",
+ "domain_info_response_testvalidate_doesnt_exist.xml",
+ DateTime.parse("2014-01-01T00:01:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDomainAllocation_succeedsOnlyAsSuperuser() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ createContactsAndHosts();
+ assertCommandAndResponse(
+ "domain_create_sunrise_encoded_mark.xml",
+ "domain_create_sunrise_encoded_signed_mark_response.xml",
+ DateTime.parse("2014-01-01T00:00:00Z"));
+ assertCommandAndResponse(
+ "domain_info_testvalidate.xml",
+ "domain_info_response_testvalidate_doesnt_exist.xml",
+ DateTime.parse("2014-01-01T00:01:00Z"));
+ assertCommandAndResponse(
+ "domain_allocate_testvalidate.xml",
+ "domain_allocate_response_testvalidate_only_superuser.xml",
+ START_OF_GA.plusDays(1));
+ setSuperuser(true);
+ assertCommandAndResponse(
+ "domain_allocate_testvalidate.xml",
+ "domain_allocate_response_testvalidate.xml",
+ START_OF_GA.plusDays(1).plusMinutes(1));
+ setSuperuser(false);
+ assertCommandAndResponse(
+ "domain_info_testvalidate.xml",
+ "domain_info_response_testvalidate_ok.xml",
+ START_OF_GA.plusDays(1).plusMinutes(2));
+ }
+}
diff --git a/javatests/google/registry/flows/EppTlsServletTest.java b/javatests/google/registry/flows/EppLifecycleDomainTest.java
similarity index 56%
rename from javatests/google/registry/flows/EppTlsServletTest.java
rename to javatests/google/registry/flows/EppLifecycleDomainTest.java
index c80ce1aa9..3903ec728 100644
--- a/javatests/google/registry/flows/EppTlsServletTest.java
+++ b/javatests/google/registry/flows/EppLifecycleDomainTest.java
@@ -14,28 +14,27 @@
package google.registry.flows;
-import static google.registry.testing.DatastoreHelper.persistResource;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.mockito.Mockito.when;
+import static google.registry.testing.DatastoreHelper.createTld;
+import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedMap;
import com.google.re2j.Matcher;
import com.google.re2j.Pattern;
-import google.registry.model.registrar.Registrar;
+import google.registry.model.registry.Registry.TldState;
import google.registry.testing.AppEngineRule;
-import google.registry.testing.CertificateSamples;
-import google.registry.testing.FakeServletInputStream;
+import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.junit.runners.JUnit4;
-/** Test setup for EppServletTest subclasses. */
-@RunWith(MockitoJUnitRunner.class)
-public class EppTlsServletTest extends EppServletXmlLoginTestCase {
+/** Tests for domain lifecycle. */
+@RunWith(JUnit4.class)
+public class EppLifecycleDomainTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
@@ -43,79 +42,276 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
.withTaskQueue()
.build();
- String ipAddressAndPort = "192.168.1.100:54321";
- String clientCert = CertificateSamples.SAMPLE_CERT_HASH;
- String clientCert2 = CertificateSamples.SAMPLE_CERT2_HASH;
- String requestedServername = "test.example";
-
- private String gfeRequestClientCertificateHashField;
-
@Before
- public void initTest() throws Exception {
- persistResource(Registrar.loadByClientId("NewRegistrar")
- .asBuilder()
- .setClientCertificateHash(clientCert)
- .build());
-
- persistResource(Registrar.loadByClientId("TheRegistrar")
- .asBuilder()
- .setClientCertificateHash(clientCert2)
- .build());
+ public void initTld() {
+ createTld("example");
}
- @Test
- public void testSetTldViaSni() throws Exception {
- requestedServername = "epp.nic.xn--q9jyb4c";
- assertCommandAndResponse("login2_valid.xml", "login_response.xml");
+ /** Create the two administrative contacts and two hosts. */
+ void createContactsAndHosts() throws Exception {
+ DateTime startTime = DateTime.parse("2000-06-01T00:00:00Z");
assertCommandAndResponse(
"contact_create_sh8013.xml",
ImmutableMap.of(),
"contact_create_response_sh8013.xml",
ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
- "2000-06-01T00:00:00Z");
+ startTime);
assertCommandAndResponse(
- "domain_create_minna.xml",
- "domain_create_response_minna.xml",
- "2000-06-01T01:02:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
+ "contact_create_jd1234.xml",
+ "contact_create_response_jd1234.xml",
+ startTime.plusMinutes(1));
+ assertCommandAndResponse(
+ "host_create.xml",
+ "host_create_response.xml",
+ startTime.plusMinutes(2));
+ assertCommandAndResponse(
+ "host_create2.xml",
+ "host_create2_response.xml",
+ startTime.plusMinutes(3));
+ }
+
+ /** Creates the domain fakesite.example with two nameservers on it. */
+ void createFakesite() throws Exception {
+ createContactsAndHosts();
+ assertCommandAndResponse(
+ "domain_create_fakesite.xml",
+ "domain_create_response_fakesite.xml",
+ DateTime.parse("2000-06-01T00:04:00Z"));
+ assertCommandAndResponse(
+ "domain_info_fakesite.xml",
+ "domain_info_response_fakesite_ok.xml",
+ DateTime.parse("2000-06-06T00:00:00Z"));
+ }
+
+ /** Creates ns3.fakesite.example as a host, then adds it to fakesite. */
+ void createSubordinateHost() throws Exception {
+ // Add the fakesite nameserver (requires that domain is already created).
+ assertCommandAndResponse(
+ "host_create_fakesite.xml",
+ "host_create_response_fakesite.xml",
+ DateTime.parse("2000-06-06T00:01:00Z"));
+ // Add new nameserver to domain.
+ assertCommandAndResponse(
+ "domain_update_add_nameserver_fakesite.xml",
+ "domain_update_add_nameserver_response_fakesite.xml",
+ DateTime.parse("2000-06-08T00:00:00Z"));
+ // Verify new nameserver was added.
+ assertCommandAndResponse(
+ "domain_info_fakesite.xml",
+ "domain_info_response_fakesite_3_nameservers.xml",
+ DateTime.parse("2000-06-08T00:01:00Z"));
+ // Verify that nameserver's data was set correctly.
+ assertCommandAndResponse(
+ "host_info_fakesite.xml",
+ "host_info_response_fakesite.xml",
+ DateTime.parse("2000-06-08T00:02:00Z"));
}
- /** This test requires multiple registrars, which EppConsoleServlet doesn't allow. */
@Test
- public void testContactTransferPollMessage() throws Exception {
+ public void testDomainDeleteRestore() throws Exception {
assertCommandAndResponse("login_valid.xml", "login_response.xml");
+
+ // Create contacts sh8013 and jd1234.
assertCommandAndResponse(
"contact_create_sh8013.xml",
- ImmutableMap.of(),
- "contact_create_response_sh8013.xml",
- ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
- "2000-06-01T00:00:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
-
- // Initiate a transfer of the newly created contact.
- assertCommandAndResponse("login2_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "contact_transfer_request.xml",
- "contact_transfer_request_response_alternate.xml",
- "2000-06-08T22:00:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
-
- // Log back in with the losing registrar, read the poll message, and then ack it.
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "poll.xml",
- "poll_response_contact_transfer.xml",
- "2000-06-08T22:01:00Z");
- assertCommandAndResponse(
- "poll_ack.xml",
- ImmutableMap.of("ID", "2-4-ROID-6-7"),
- "poll_ack_response_empty.xml",
null,
- "2000-06-08T22:02:00Z");
+ "contact_create_response_sh8013.xml",
+ ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
+ DateTime.parse("2000-06-01T00:00:00Z"));
+ assertCommandAndResponse(
+ "contact_create_jd1234.xml",
+ "contact_create_response_jd1234.xml",
+ DateTime.parse("2000-06-01T00:01:00Z"));
+
+ // Create domain example.tld.
+ assertCommandAndResponse(
+ "domain_create_no_hosts_or_dsdata.xml",
+ "domain_create_response.xml",
+ DateTime.parse("2000-06-01T00:02:00Z"));
+
+ // Delete domain example.com after its add grace period has expired.
+ assertCommandAndResponse(
+ "domain_delete.xml",
+ "generic_success_action_pending_response.xml",
+ DateTime.parse("2000-07-01T00:02:00Z"));
+
+ // Restore the domain.
+ assertCommandAndResponse(
+ "domain_update_restore_request.xml",
+ "domain_update_restore_request_response.xml",
+ DateTime.parse("2000-07-01T00:03:00Z"));
+
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDomainDeletion_withinAddGracePeriod() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+
+ // Create contacts sh8013 and jd1234.
+ assertCommandAndResponse(
+ "contact_create_sh8013.xml",
+ null,
+ "contact_create_response_sh8013.xml",
+ ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
+ DateTime.parse("2000-06-01T00:00:00Z"));
+ assertCommandAndResponse(
+ "contact_create_jd1234.xml",
+ "contact_create_response_jd1234.xml",
+ DateTime.parse("2000-06-01T00:01:00Z"));
+
+ // Create domain example.tld.
+ assertCommandAndResponse(
+ "domain_create_no_hosts_or_dsdata.xml",
+ "domain_create_response.xml",
+ DateTime.parse("2000-06-01T00:02:00Z"));
+
+ // Delete domain example.tld after its add grace period has expired.
+ assertCommandAndResponse(
+ "domain_delete.xml",
+ "generic_success_action_pending_response.xml",
+ DateTime.parse("2000-07-01T00:02:00Z"));
+
+ // Poke the domain a little at various times to see its status
+ assertCommandAndResponse(
+ "domain_info.xml",
+ "domain_info_response_pendingdelete.xml",
+ DateTime.parse("2000-08-01T00:02:00Z")); // 1 day out.
+
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDomainDeletionWithSubordinateHost_fails() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ createFakesite();
+ createSubordinateHost();
+ assertCommandAndResponse(
+ "domain_delete_fakesite.xml",
+ "domain_delete_response_prohibited.xml",
+ DateTime.parse("2002-05-30T01:01:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDeletionOfDomain_afterRenameOfSubordinateHost_succeeds() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ createFakesite();
+ createSubordinateHost();
+ // Update the ns3 host to no longer be on fakesite.example domain.
+ assertCommandAndResponse(
+ "host_update_fakesite.xml",
+ "generic_success_response.xml",
+ DateTime.parse("2002-05-30T01:01:00Z"));
+ // Delete the fakesite.example domain (which should succeed since it no longer has subords).
+ assertCommandAndResponse(
+ "domain_delete_fakesite.xml",
+ "generic_success_action_pending_response.xml",
+ DateTime.parse("2002-05-30T01:02:00Z"));
+ // Check info on the renamed host and verify that it's still around and wasn't deleted.
+ assertCommandAndResponse(
+ "host_info_ns9000_example.xml",
+ "host_info_response_ns9000_example.xml",
+ DateTime.parse("2002-06-30T01:03:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDeletionOfDomain_afterUpdateThatCreatesSubordinateHost_fails() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ createFakesite();
+ // Update the ns1 host to be on the fakesite.example domain.
+ assertCommandAndResponse(
+ "host_update_ns1_to_fakesite.xml",
+ "generic_success_response.xml",
+ DateTime.parse("2002-05-30T01:01:00Z"));
+ // Attempt to delete the fakesite.example domain (which should fail since it now has a
+ // subordinate host).
+ assertCommandAndResponse(
+ "domain_delete_fakesite.xml",
+ "domain_delete_response_prohibited.xml",
+ DateTime.parse("2002-05-30T01:02:00Z"));
+ // Check info on the renamed host and verify that it's still around and wasn't deleted.
+ assertCommandAndResponse(
+ "host_info_fakesite.xml",
+ "host_info_response_fakesite_post_update.xml",
+ DateTime.parse("2002-06-30T01:03:00Z"));
+ // Verify that fakesite.example domain is still around and wasn't deleted.
+ assertCommandAndResponse(
+ "domain_info_fakesite.xml",
+ "domain_info_response_fakesite_ok_post_host_update.xml",
+ DateTime.parse("2002-05-30T01:00:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testRenamingHostToExistingHost_fails() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ // Create the two hosts.
+ assertCommandAndResponse(
+ "host_create.xml", "host_create_response.xml", DateTime.parse("2000-06-01T00:02:00Z"));
+ assertCommandAndResponse(
+ "host_create2.xml", "host_create2_response.xml", DateTime.parse("2000-06-01T00:03:00Z"));
+ // Verify that host1 and host2 were created as we expect them.
+ assertCommandAndResponse(
+ "host_info_ns1.xml", "host_info_response_ns1.xml", DateTime.parse("2000-06-01T00:04:00Z"));
+ assertCommandAndResponse(
+ "host_info_ns2.xml", "host_info_response_ns2.xml", DateTime.parse("2000-06-01T00:05:00Z"));
+ // Attempt overwriting of host1 on top of host2 (and verify that it fails).
+ assertCommandAndResponse(
+ "host_update_ns1_to_ns2.xml",
+ "host_update_failed_response.xml",
+ DateTime.parse("2000-06-01T00:06:00Z"));
+ // Verify that host1 and host2 still exist in their unmodified states.
+ assertCommandAndResponse(
+ "host_info_ns1.xml", "host_info_response_ns1.xml", DateTime.parse("2000-06-01T00:07:00Z"));
+ assertCommandAndResponse(
+ "host_info_ns2.xml", "host_info_response_ns2.xml", DateTime.parse("2000-06-01T00:08:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDomainCreation_failsBeforeSunrise() throws Exception {
+ DateTime sunriseDate = DateTime.parse("2000-05-30T00:00:00Z");
+ createTld("example", ImmutableSortedMap.of(
+ START_OF_TIME, TldState.PREDELEGATION,
+ sunriseDate, TldState.SUNRISE,
+ sunriseDate.plusMonths(2), TldState.GENERAL_AVAILABILITY));
+
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+
+ createContactsAndHosts();
+
+ assertCommandAndResponse(
+ "domain_create_sunrise_encoded_mark.xml",
+ "domain_create_testvalidate_invalid_phase.xml",
+ sunriseDate.minusDays(1));
+
+ assertCommandAndResponse(
+ "domain_info_testvalidate.xml",
+ "domain_info_response_testvalidate_doesnt_exist.xml",
+ sunriseDate.plusDays(1));
+
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testDomainCheckFee_succeeds() throws Exception {
+ DateTime gaDate = DateTime.parse("2000-05-30T00:00:00Z");
+ createTld("example", ImmutableSortedMap.of(
+ START_OF_TIME, TldState.PREDELEGATION,
+ gaDate, TldState.GENERAL_AVAILABILITY));
+
+ assertCommandAndResponse("login_valid_fee_extension.xml", "login_response.xml");
+
+ assertCommandAndResponse(
+ "domain_check_fee_premium.xml",
+ "domain_check_fee_premium_response.xml",
+ gaDate.plusDays(1));
+
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
- /** This test requires multiple registrars, which EppConsoleServlet doesn't allow. */
@Test
public void testDomainTransferPollMessage_serverApproved() throws Exception {
// As the losing registrar, create the domain.
@@ -128,7 +324,7 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
String response = assertCommandAndResponse(
"domain_transfer_request_1_year.xml",
"domain_transfer_response_1_year.xml",
- "2001-01-01T00:00:00Z");
+ DateTime.parse("2001-01-01T00:00:00Z"));
Matcher matcher = Pattern.compile("(.*)").matcher(response);
matcher.find();
String transferRequestTrid = matcher.group(1);
@@ -139,25 +335,25 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"poll.xml",
"poll_response_domain_transfer_request.xml",
- "2001-01-01T00:01:00Z");
+ DateTime.parse("2001-01-01T00:01:00Z"));
assertCommandAndResponse(
"poll_ack.xml",
- ImmutableMap.of("ID", "1-C-EXAMPLE-18-22"),
+ ImmutableMap.of("ID", "1-A-EXAMPLE-16-20"),
"poll_ack_response_empty.xml",
null,
- "2001-01-01T00:01:00Z");
+ DateTime.parse("2001-01-01T00:01:00Z"));
// Five days in the future, expect a server approval poll message to the loser, and ack it.
assertCommandAndResponse(
"poll.xml",
"poll_response_domain_transfer_server_approve_loser.xml",
- "2001-01-06T00:01:00Z");
+ DateTime.parse("2001-01-06T00:01:00Z"));
assertCommandAndResponse(
"poll_ack.xml",
- ImmutableMap.of("ID", "1-C-EXAMPLE-18-24"),
+ ImmutableMap.of("ID", "1-A-EXAMPLE-16-22"),
"poll_ack_response_empty.xml",
null,
- "2001-01-06T00:01:00Z");
+ DateTime.parse("2001-01-06T00:01:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Also expect a server approval poll message to the winner, with the transfer request trid.
@@ -167,32 +363,16 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
null,
"poll_response_domain_transfer_server_approve_winner.xml",
ImmutableMap.of("SERVER_TRID", transferRequestTrid),
- "2001-01-06T00:02:00Z");
+ DateTime.parse("2001-01-06T00:02:00Z"));
assertCommandAndResponse(
"poll_ack.xml",
- ImmutableMap.of("ID", "1-C-EXAMPLE-18-23"),
+ ImmutableMap.of("ID", "1-A-EXAMPLE-16-21"),
"poll_ack_response_empty.xml",
null,
- "2001-01-06T00:02:00Z");
+ DateTime.parse("2001-01-06T00:02:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
- @Override
- protected void extendedSessionConfig(String inputFile) throws Exception {
- when(req.getHeader(EppTlsServlet.REQUESTED_SERVERNAME_VIA_SNI_FIELD))
- .thenReturn(requestedServername);
- when(req.getHeader(EppTlsServlet.FORWARDED_FOR_FIELD))
- .thenReturn(ipAddressAndPort);
- if (gfeRequestClientCertificateHashField != null) {
- when(req.getHeader(EppTlsServlet.SSL_CLIENT_CERTIFICATE_HASH_FIELD))
- .thenReturn(gfeRequestClientCertificateHashField);
- } else {
- when(req.getHeader(EppTlsServlet.SSL_CLIENT_CERTIFICATE_HASH_FIELD))
- .thenReturn(inputFile.contains("TheRegistrar") ? clientCert2 : clientCert);
- }
- when(req.getInputStream()).thenReturn(new FakeServletInputStream(inputFile.getBytes(UTF_8)));
- }
-
@Test
public void testIgnoredTransferDuringAutoRenewPeriod_succeeds() throws Exception {
// Register the domain as the first registrar.
@@ -205,19 +385,20 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_request_2_years.xml",
"domain_transfer_response_2_years.xml",
- "2002-05-30T00:00:00Z");
+ DateTime.parse("2002-05-30T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Log back in as the first registrar and verify things.
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "login_valid.xml", "login_response.xml");
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_pending_transfer.xml",
- "2002-05-30T01:00:00Z");
+ DateTime.parse("2002-05-30T01:00:00Z"));
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_pending_transfer_autorenew.xml",
- "2002-06-02T00:00:00Z");
+ DateTime.parse("2002-06-02T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Log back in as the second registrar and verify transfer details.
@@ -226,66 +407,14 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_transfer_period.xml",
- "2002-06-06T00:00:00Z");
+ DateTime.parse("2002-06-06T00:00:00Z"));
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_transfer_complete.xml",
- "2002-06-12T00:00:00Z");
+ DateTime.parse("2002-06-12T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
- @Test
- public void testBadCertificate_failsBadCertificate2200() throws Exception {
- gfeRequestClientCertificateHashField = "laffo";
- assertCommandAndResponse("login_valid.xml", "login_response_bad_certificate.xml");
- }
-
- @Test
- public void testGfeDidntProvideClientCertificate_failsMissingCertificate2200() throws Exception {
- gfeRequestClientCertificateHashField = "";
- assertCommandAndResponse("login_valid.xml", "login_response_missing_certificate.xml");
- }
-
- @Test
- public void testGoodPrimaryCertificate() throws Exception {
- gfeRequestClientCertificateHashField = CertificateSamples.SAMPLE_CERT_HASH;
- persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
- .setClientCertificate(CertificateSamples.SAMPLE_CERT, clock.nowUtc())
- .setFailoverClientCertificate(CertificateSamples.SAMPLE_CERT2, clock.nowUtc())
- .build());
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- }
-
- @Test
- public void testGoodFailoverCertificate() throws Exception {
- gfeRequestClientCertificateHashField = CertificateSamples.SAMPLE_CERT2_HASH;
- persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
- .setClientCertificate(CertificateSamples.SAMPLE_CERT, clock.nowUtc())
- .setFailoverClientCertificate(CertificateSamples.SAMPLE_CERT2, clock.nowUtc())
- .build());
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- }
-
- @Test
- public void testMissingPrimaryCertificateButHasFailover_usesFailover() throws Exception {
- gfeRequestClientCertificateHashField = CertificateSamples.SAMPLE_CERT2_HASH;
- persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
- .setClientCertificate(null, clock.nowUtc())
- .setFailoverClientCertificate(CertificateSamples.SAMPLE_CERT2, clock.nowUtc())
- .build());
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- }
-
- @Test
- public void testRegistrarHasNoCertificatesOnFile_disablesCertChecking() throws Exception {
- gfeRequestClientCertificateHashField = "laffo";
- persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
- .setClientCertificate(null, clock.nowUtc())
- .setFailoverClientCertificate(null, clock.nowUtc())
- .build());
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- }
-
@Test
public void testNameserversTransferWithDomain_successfully() throws Exception {
// Log in as the first registrar and set up domains with hosts.
@@ -299,15 +428,14 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_request_2_years.xml",
"domain_transfer_response_2_years.xml",
- "2002-05-30T00:00:00Z");
+ DateTime.parse("2002-05-30T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Log back in as the first registrar and verify domain is pending transfer.
assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "domain_info_fakesite.xml",
+ assertCommandAndResponse("domain_info_fakesite.xml",
"domain_info_response_fakesite_3_nameservers_pending_transfer.xml",
- "2002-05-30T01:00:00Z");
+ DateTime.parse("2002-05-30T01:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Log back in as second registrar and verify transfer was successful.
@@ -316,14 +444,14 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_3_nameservers_transfer_successful.xml",
- "2002-06-09T00:00:00Z");
+ DateTime.parse("2002-06-09T00:00:00Z"));
// Verify that host's client ID was set to the new registrar and has the transfer date set.
assertCommandAndResponse(
"host_info_fakesite.xml",
null,
"host_info_response_fakesite_post_transfer.xml",
ImmutableMap.of("trDate", "2002-06-04T00:00:00Z"),
- "2002-06-09T00:01:00Z");
+ DateTime.parse("2002-06-09T00:01:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
@@ -339,7 +467,7 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_request_2_years.xml",
"domain_transfer_response_2_years.xml",
- "2002-05-30T00:00:00Z");
+ DateTime.parse("2002-05-30T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Log back in as the first registrar and delete then restore the domain while the transfer
@@ -348,26 +476,26 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_pending_transfer.xml",
- "2002-05-30T01:00:00Z");
+ DateTime.parse("2002-05-30T01:00:00Z"));
assertCommandAndResponse(
"domain_delete_fakesite.xml",
"generic_success_action_pending_response.xml",
- "2002-05-30T01:01:00Z");
+ DateTime.parse("2002-05-30T01:01:00Z"));
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_pending_delete.xml",
- "2002-05-30T01:02:00Z");
+ DateTime.parse("2002-05-30T01:02:00Z"));
assertCommandAndResponse(
"domain_update_restore_fakesite.xml",
"domain_update_restore_request_response.xml",
- "2002-05-30T01:03:00Z");
+ DateTime.parse("2002-05-30T01:03:00Z"));
// Expect domain is ok now, not pending delete or transfer, and has been extended by a year from
// the date of the restore. (Not from the original expiration date.)
assertCommandAndResponse(
"domain_info_fakesite.xml",
"domain_info_response_fakesite_restored_ok.xml",
- "2002-05-30T01:04:00Z");
+ DateTime.parse("2002-05-30T01:04:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
@@ -379,15 +507,14 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_query_fakesite.xml",
"domain_transfer_query_response_no_transfer_history.xml",
- "2000-09-02T00:00:00Z");
+ DateTime.parse("2000-09-02T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Request a transfer of the domain to the second registrar.
assertCommandAndResponse("login2_valid.xml", "login_response.xml");
assertCommandAndResponse(
"domain_transfer_request_1_year.xml",
- "domain_transfer_response_1_year.xml",
- "2001-01-01T00:00:00Z");
+ "domain_transfer_response_1_year.xml", DateTime.parse("2001-01-01T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
assertCommandAndResponse("login_valid.xml", "login_response.xml");
@@ -395,12 +522,12 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_query_fakesite.xml",
"domain_transfer_query_response_fakesite.xml",
- "2001-01-02T00:00:00Z");
+ DateTime.parse("2001-01-02T00:00:00Z"));
// Verify that status went from 'pending' to 'serverApproved'.
assertCommandAndResponse(
"domain_transfer_query_fakesite.xml",
"domain_transfer_query_response_completed_fakesite.xml",
- "2001-01-08T00:00:00Z");
+ DateTime.parse("2001-01-08T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
@@ -419,25 +546,25 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_query_fakesite.xml",
"domain_transfer_query_response_no_transfer_history.xml",
- "2000-09-02T00:00:00Z");
+ DateTime.parse("2000-09-02T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Request a transfer of the domain to the second registrar.
assertCommandAndResponse("login2_valid.xml", "login_response.xml");
assertCommandAndResponse(
"domain_transfer_request_1_year.xml",
"domain_transfer_response_1_year.xml",
- "2001-01-01T00:00:00Z");
+ DateTime.parse("2001-01-01T00:00:00Z"));
// Verify that the lastTransferTime now reflects the superordinate domain's transfer.
assertCommandAndResponse(
"host_info.xml",
ImmutableMap.of("hostname", "ns3.fakesite.example"),
"host_info_response_fakesite_post_transfer.xml",
ImmutableMap.of("trDate", "2001-01-06T00:00:00.000Z"),
- "2001-01-07T00:00:00Z");
+ DateTime.parse("2001-01-07T00:00:00Z"));
assertCommandAndResponse(
"domain_create_secondsite.xml",
"domain_create_response_secondsite.xml",
- "2001-01-08T00:00:00Z");
+ DateTime.parse("2001-01-08T00:00:00Z"));
// Update the host to be subordinate to a different domain by renaming it to
// ns3.secondsite.example
assertCommandAndResponse(
@@ -445,7 +572,7 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
ImmutableMap.of("oldName", "ns3.fakesite.example", "newName", "ns3.secondsite.example"),
"generic_success_response.xml",
null,
- "2002-05-30T01:01:00Z");
+ DateTime.parse("2002-05-30T01:01:00Z"));
// The last transfer time on the host should still be what it was from the transfer.
assertCommandAndResponse(
"host_info.xml",
@@ -454,7 +581,7 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
ImmutableMap.of(
"hostname", "ns3.secondsite.example",
"trDate", "2001-01-06T00:00:00.000Z"),
- "2003-01-07T00:00:00Z");
+ DateTime.parse("2003-01-07T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
@@ -472,21 +599,21 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
assertCommandAndResponse(
"domain_transfer_query_fakesite.xml",
"domain_transfer_query_response_no_transfer_history.xml",
- "2000-09-02T00:00:00Z");
+ DateTime.parse("2000-09-02T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
// Request a transfer of the domain to the second registrar.
assertCommandAndResponse("login2_valid.xml", "login_response.xml");
assertCommandAndResponse(
"domain_transfer_request_1_year.xml",
"domain_transfer_response_1_year.xml",
- "2001-01-01T00:00:00Z");
+ DateTime.parse("2001-01-01T00:00:00Z"));
// Verify that the lastTransferTime now reflects the superordinate domain's transfer.
assertCommandAndResponse(
"host_info_fakesite.xml",
null,
"host_info_response_fakesite_post_transfer.xml",
ImmutableMap.of("trDate", "2001-01-06T00:00:00.000Z"),
- "2001-01-07T00:00:00Z");
+ DateTime.parse("2001-01-07T00:00:00Z"));
// Update the host to be external by renaming it to ns3.notarealsite.external
assertCommandAndResponse(
"host_update_rename_and_remove_addresses.xml",
@@ -495,7 +622,7 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
"newName", "ns3.notarealsite.external"),
"generic_success_response.xml",
null,
- "2002-05-30T01:01:00Z");
+ DateTime.parse("2002-05-30T01:01:00Z"));
// The last transfer time on the host should still be what it was from the transfer.
assertCommandAndResponse(
"host_info.xml",
@@ -504,7 +631,7 @@ public class EppTlsServletTest extends EppServletXmlLoginTestCase
ImmutableMap.of(
"hostname", "ns3.notarealsite.external",
"trDate", "2001-01-06T00:00:00.000Z"),
- "2001-01-07T00:00:00Z");
+ DateTime.parse("2001-01-07T00:00:00Z"));
assertCommandAndResponse("logout.xml", "logout_response.xml");
}
}
diff --git a/javatests/google/registry/flows/EppLifecycleHostTest.java b/javatests/google/registry/flows/EppLifecycleHostTest.java
new file mode 100644
index 000000000..daa1b9f8c
--- /dev/null
+++ b/javatests/google/registry/flows/EppLifecycleHostTest.java
@@ -0,0 +1,71 @@
+// 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.flows;
+
+import google.registry.testing.AppEngineRule;
+
+import org.joda.time.DateTime;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for host lifecycle. */
+@RunWith(JUnit4.class)
+public class EppLifecycleHostTest extends EppTestCase {
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withDatastore()
+ .build();
+
+ @Test
+ public void testRenamingHostToExistingHost_fails() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ // Create the two hosts.
+ assertCommandAndResponse(
+ "host_create.xml",
+ "host_create_response.xml",
+ DateTime.parse("2000-06-01T00:02:00Z"));
+ assertCommandAndResponse(
+ "host_create2.xml",
+ "host_create2_response.xml",
+ DateTime.parse("2000-06-01T00:03:00Z"));
+ // Verify that host1 and host2 were created as we expect them.
+ assertCommandAndResponse(
+ "host_info_ns1.xml",
+ "host_info_response_ns1.xml",
+ DateTime.parse("2000-06-01T00:04:00Z"));
+ assertCommandAndResponse(
+ "host_info_ns2.xml",
+ "host_info_response_ns2.xml",
+ DateTime.parse("2000-06-01T00:05:00Z"));
+ // Attempt overwriting of host1 on top of host2 (and verify that it fails).
+ assertCommandAndResponse(
+ "host_update_ns1_to_ns2.xml",
+ "host_update_failed_response.xml",
+ DateTime.parse("2000-06-01T00:06:00Z"));
+ // Verify that host1 and host2 still exist in their unmodified states.
+ assertCommandAndResponse(
+ "host_info_ns1.xml",
+ "host_info_response_ns1.xml",
+ DateTime.parse("2000-06-01T00:07:00Z"));
+ assertCommandAndResponse(
+ "host_info_ns2.xml",
+ "host_info_response_ns2.xml",
+ DateTime.parse("2000-06-01T00:08:00Z"));
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+}
diff --git a/javatests/google/registry/flows/EppLoggedOutTest.java b/javatests/google/registry/flows/EppLoggedOutTest.java
new file mode 100644
index 000000000..f8a9f0689
--- /dev/null
+++ b/javatests/google/registry/flows/EppLoggedOutTest.java
@@ -0,0 +1,54 @@
+// 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.flows;
+
+import static org.joda.time.DateTimeZone.UTC;
+import static org.joda.time.format.ISODateTimeFormat.dateTimeNoMillis;
+
+import com.google.common.collect.ImmutableMap;
+
+import google.registry.testing.AppEngineRule;
+
+import org.joda.time.DateTime;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test flows without login. */
+@RunWith(JUnit4.class)
+public class EppLoggedOutTest extends EppTestCase {
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withDatastore()
+ .build();
+
+ @Test
+ public void testHello() throws Exception {
+ DateTime now = DateTime.now(UTC);
+ assertCommandAndResponse(
+ "hello.xml",
+ null,
+ "greeting_crr.xml",
+ ImmutableMap.of("DATE", now.toString(dateTimeNoMillis())),
+ now);
+ }
+
+ @Test
+ public void testSyntaxError() throws Exception {
+ assertCommandAndResponse("syntax_error.xml", "syntax_error_response.xml");
+ }
+}
diff --git a/javatests/google/registry/flows/EppConsoleAsAdminServletTest.java b/javatests/google/registry/flows/EppLoginAdminUserTest.java
similarity index 57%
rename from javatests/google/registry/flows/EppConsoleAsAdminServletTest.java
rename to javatests/google/registry/flows/EppLoginAdminUserTest.java
index 55cf18af6..95c824749 100644
--- a/javatests/google/registry/flows/EppConsoleAsAdminServletTest.java
+++ b/javatests/google/registry/flows/EppLoginAdminUserTest.java
@@ -14,10 +14,8 @@
package google.registry.flows;
+import static com.google.appengine.api.users.UserServiceFactory.getUserService;
-import static google.registry.testing.DatastoreHelper.persistResource;
-
-import google.registry.model.registrar.Registrar;
import google.registry.testing.AppEngineRule;
import google.registry.testing.UserInfo;
@@ -25,37 +23,39 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.junit.runners.JUnit4;
-/** Tests for {@link EppConsoleServlet} running in admin mode. */
-@RunWith(MockitoJUnitRunner.class)
-public class EppConsoleAsAdminServletTest extends EppServletXmlLoginTestCase {
+/** Test logging in with appengine admin user credentials. */
+@RunWith(JUnit4.class)
+public class EppLoginAdminUserTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
- .withTaskQueue()
- .withUserService(UserInfo.createAdmin(GAE_USER_EMAIL, GAE_USER_ID))
+ .withUserService(UserInfo.createAdmin("someone@example.com", "12345"))
.build();
- private static final String GAE_USER_ID = "12345";
- private static final String GAE_USER_EMAIL = "someone@example.com";
-
- // Note that the setup done in EppConsoleServletTest, of allowing
- // the test user to login as the Registrar, is not done here.
@Before
- public void initTest() throws Exception {
- persistResource(
- Registrar.loadByClientId("NewRegistrar").asBuilder().setPassword("PwAdminDNKnow").build());
+ public void initTransportCredentials() {
+ setTransportCredentials(new GaeUserCredentials(getUserService().getCurrentUser()));
}
@Test
- public void testNonAuthedLogin() throws Exception {
+ public void testNonAuthedLogin_succeedsAsAdmin() throws Exception {
+ // Login succeeds even though this user isn't listed on the registrar.
assertCommandAndResponse("login2_valid.xml", "login_response.xml");
}
@Test
- public void testMultiLogin() throws Exception {
+ public void testLoginLogout_wrongPasswordStillWorks() throws Exception {
+ // For user-based logins the password in the epp xml is ignored.
+ assertCommandAndResponse("login_invalid_wrong_password.xml", "login_response.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testNonAuthedMultiLogin_succeedsAsAdmin() throws Exception {
+ // The admin can log in as different registrars.
assertCommandAndResponse("login_valid.xml", "login_response.xml");
assertCommandAndResponse("logout.xml", "logout_response.xml");
assertCommandAndResponse("login_valid.xml", "login_response.xml");
diff --git a/javatests/google/registry/flows/EppLoginTlsTest.java b/javatests/google/registry/flows/EppLoginTlsTest.java
new file mode 100644
index 000000000..c936d04a6
--- /dev/null
+++ b/javatests/google/registry/flows/EppLoginTlsTest.java
@@ -0,0 +1,146 @@
+// 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.flows;
+
+import static google.registry.testing.DatastoreHelper.persistResource;
+import static org.joda.time.DateTimeZone.UTC;
+
+import com.google.common.base.Optional;
+
+import google.registry.model.registrar.Registrar;
+import google.registry.testing.AppEngineRule;
+import google.registry.testing.CertificateSamples;
+
+import org.joda.time.DateTime;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test logging in with TLS credentials. */
+@RunWith(JUnit4.class)
+public class EppLoginTlsTest extends EppTestCase {
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withDatastore()
+ .build();
+
+
+ void setClientCertificateHash(String clientCertificateHash) {
+ setTransportCredentials(new TlsCredentials(
+ clientCertificateHash, Optional.of("192.168.1.100:54321"), "test.example"));
+ }
+
+ @Before
+ public void initTest() throws Exception {
+ persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
+ .setClientCertificateHash(CertificateSamples.SAMPLE_CERT_HASH)
+ .build());
+ // Set a cert for the second registrar, or else any cert will be allowed for login.
+ persistResource(Registrar.loadByClientId("TheRegistrar").asBuilder()
+ .setClientCertificateHash(CertificateSamples.SAMPLE_CERT2_HASH)
+ .build());
+ }
+
+ @Test
+ public void testLoginLogout() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT_HASH);
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testLogin_wrongPasswordFails() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT_HASH);
+ // For TLS login, we also check the epp xml password.
+ assertCommandAndResponse(
+ "login_invalid_wrong_password.xml", "login_response_wrong_password.xml");
+ }
+
+ @Test
+ public void testMultiLogin() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT_HASH);
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ assertCommandAndResponse("login2_valid.xml", "login_response_bad_certificate.xml");
+ }
+
+ @Test
+ public void testNonAuthedLogin_fails() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT_HASH);
+ assertCommandAndResponse("login2_valid.xml", "login_response_bad_certificate.xml");
+ }
+
+
+ @Test
+ public void testBadCertificate_failsBadCertificate2200() throws Exception {
+ setClientCertificateHash("laffo");
+ assertCommandAndResponse("login_valid.xml", "login_response_bad_certificate.xml");
+ }
+
+ @Test
+ public void testGfeDidntProvideClientCertificate_failsMissingCertificate2200() throws Exception {
+ setClientCertificateHash("");
+ assertCommandAndResponse("login_valid.xml", "login_response_missing_certificate.xml");
+ }
+
+ @Test
+ public void testGoodPrimaryCertificate() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT_HASH);
+ DateTime now = DateTime.now(UTC);
+ persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
+ .setClientCertificate(CertificateSamples.SAMPLE_CERT, now)
+ .setFailoverClientCertificate(CertificateSamples.SAMPLE_CERT2, now)
+ .build());
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ }
+
+ @Test
+ public void testGoodFailoverCertificate() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT2_HASH);
+ DateTime now = DateTime.now(UTC);
+ persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
+ .setClientCertificate(CertificateSamples.SAMPLE_CERT, now)
+ .setFailoverClientCertificate(CertificateSamples.SAMPLE_CERT2, now)
+ .build());
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ }
+
+ @Test
+ public void testMissingPrimaryCertificateButHasFailover_usesFailover() throws Exception {
+ setClientCertificateHash(CertificateSamples.SAMPLE_CERT2_HASH);
+ DateTime now = DateTime.now(UTC);
+ persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
+ .setClientCertificate(null, now)
+ .setFailoverClientCertificate(CertificateSamples.SAMPLE_CERT2, now)
+ .build());
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ }
+
+ @Test
+ public void testRegistrarHasNoCertificatesOnFile_disablesCertChecking() throws Exception {
+ setClientCertificateHash("laffo");
+ DateTime now = DateTime.now(UTC);
+ persistResource(Registrar.loadByClientId("NewRegistrar").asBuilder()
+ .setClientCertificate(null, now)
+ .setFailoverClientCertificate(null, now)
+ .build());
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ }
+}
diff --git a/javatests/google/registry/flows/EppConsoleServletTest.java b/javatests/google/registry/flows/EppLoginUserTest.java
similarity index 59%
rename from javatests/google/registry/flows/EppConsoleServletTest.java
rename to javatests/google/registry/flows/EppLoginUserTest.java
index 317278ab7..031d7ea4d 100644
--- a/javatests/google/registry/flows/EppConsoleServletTest.java
+++ b/javatests/google/registry/flows/EppLoginUserTest.java
@@ -14,9 +14,10 @@
package google.registry.flows;
-
+import static com.google.appengine.api.users.UserServiceFactory.getUserService;
import static google.registry.testing.DatastoreHelper.persistResource;
+import com.google.appengine.api.users.User;
import com.google.common.collect.ImmutableSet;
import google.registry.model.registrar.Registrar;
@@ -28,36 +29,38 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.junit.runners.JUnit4;
-/** Tests for {@link EppConsoleServlet}. */
-@RunWith(MockitoJUnitRunner.class)
-public class EppConsoleServletTest extends EppServletXmlLoginTestCase {
+/** Test logging in with appengine user credentials, such as via the console. */
+@RunWith(JUnit4.class)
+public class EppLoginUserTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
- .withTaskQueue()
- .withUserService(UserInfo.create(GAE_USER_EMAIL, GAE_USER_ID))
+ .withUserService(UserInfo.create("person@example.com", "12345"))
.build();
- private static final String GAE_USER_ID = "12345";
- private static final String GAE_USER_EMAIL = "person@example.com";
-
@Before
public void initTest() throws Exception {
- Registrar registrar = Registrar.loadByClientId("NewRegistrar");
- RegistrarContact contact = new RegistrarContact.Builder()
- .setParent(registrar)
- .setEmailAddress(GAE_USER_EMAIL)
+ User user = getUserService().getCurrentUser();
+ persistResource(new RegistrarContact.Builder()
+ .setParent(Registrar.loadByClientId("NewRegistrar"))
+ .setEmailAddress(user.getEmail())
+ .setGaeUserId(user.getUserId())
.setTypes(ImmutableSet.of(RegistrarContact.Type.ADMIN))
- .setGaeUserId(GAE_USER_ID)
- .build();
- persistResource(contact);
+ .build());
+ setTransportCredentials(new GaeUserCredentials(user));
}
@Test
- public void testNonAuthedLogin() throws Exception {
+ public void testLoginLogout() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testNonAuthedLogin_fails() throws Exception {
assertCommandAndResponse("login2_valid.xml", "login_response_unauthorized_role.xml");
}
@@ -69,4 +72,11 @@ public class EppConsoleServletTest extends EppServletXmlLoginTestCase The EppXXXServlet class to test.
- */
-public abstract class EppServletTestCase {
-
- @Rule
- public final InjectRule inject = new InjectRule();
-
- @Mock
- HttpServletRequest req;
-
- @Mock
- HttpServletResponse rsp;
-
- @Mock
- ModulesService modulesService;
-
- HttpSession session;
-
- FakeClock clock = new FakeClock();
-
- private String currentTld = null;
- private Optional isSuperuser = Optional. absent();
- private Optional clientIdentifier = Optional. absent();
-
- void setSuperuser(boolean isSuperuser) {
- this.isSuperuser = Optional.of(isSuperuser);
- }
-
- void setClientIdentifier(String clientIdentifier) {
- this.clientIdentifier = Optional.of(clientIdentifier);
- }
-
- static final DateTime START_OF_GA = DateTime.parse("2014-03-01T00:00:00Z");
-
- @Before
- public final void init() throws Exception {
- inject.setStaticField(Ofy.class, "clock", clock); // For transactional flows.
- inject.setStaticField(FlowRunner.class, "clock", clock); // For non-transactional flows.
- inject.setStaticField(Metrics.class, "modulesService", modulesService);
- when(modulesService.getVersionHostname("backend", null)).thenReturn("backend.hostname");
-
- // Create RegistryData for all TLDs used in these tests.
- // We want to create all of these even for tests that don't use them to make sure that
- // tld-selection works correctly.
- createTlds("net", "xn--q9jyb4c", "example");
- ofy().saveWithoutBackup().entity(new ClaimsListSingleton()).now();
-
- session = new BasicHttpSession();
- persistResource(
- Registrar.loadByClientId("NewRegistrar")
- .asBuilder()
- .setAllowedTlds(ImmutableSet.of("net", "example", "xn--q9jyb4c"))
- .build());
-
- persistResource(
- Registrar.loadByClientId("TheRegistrar")
- .asBuilder()
- .setAllowedTlds(ImmutableSet.of("net", "example", "xn--q9jyb4c"))
- .build());
- }
-
- void assertCommandAndResponse(
- String inputFilename,
- Map inputSubstitutions,
- String outputFilename,
- Map outputSubstitutions) throws Exception {
- assertCommandAndResponse(
- inputFilename,
- inputSubstitutions,
- outputFilename,
- outputSubstitutions,
- DateTime.now(UTC));
- }
-
- String assertCommandAndResponse(String inputFilename, String outputFilename) throws Exception {
- return assertCommandAndResponse(inputFilename, outputFilename, DateTime.now(UTC));
- }
-
- String assertCommandAndResponse(
- String inputFilename,
- Map inputSubstitutions,
- String outputFilename,
- Map outputSubstitutions,
- String nowString) throws Exception {
- return assertCommandAndResponse(
- inputFilename,
- inputSubstitutions,
- outputFilename,
- outputSubstitutions,
- DateTime.parse(nowString));
- }
-
- String assertCommandAndResponse(String inputFilename, String outputFilename, String nowString)
- throws Exception {
- return assertCommandAndResponse(inputFilename, outputFilename, DateTime.parse(nowString));
- }
-
- String assertCommandAndResponse(String inputFilename, String outputFilename, DateTime now)
- throws Exception {
- return assertCommandAndResponse(inputFilename, null, outputFilename, null, now);
- }
-
- String assertCommandAndResponse(
- String inputFilename,
- Map inputSubstitutions,
- String outputFilename,
- Map outputSubstitutions,
- DateTime now) throws Exception {
- String outputFile =
- loadFileWithSubstitutions(EppServletTestCase.class, outputFilename, outputSubstitutions);
- String actualOutput = expectXmlCommand(loadFileWithSubstitutions(
- EppServletTestCase.class, inputFilename, inputSubstitutions), now);
- assertXmlEqualsWithMessage(
- outputFile,
- actualOutput,
- "Running " + inputFilename + " => " + outputFilename,
- "epp.response.resData.infData.roid",
- "epp.response.trID.svTRID");
- ofy().clearSessionCache(); // Clear the cache like OfyFilter would.
- return actualOutput;
- }
-
- HttpSession getOrRenewSession() {
- // Try an idempotent op on the session to see if it's valid.
- try {
- session.getAttribute(null);
- return session;
- } catch (IllegalStateException e) {
- // Session is invalid.
- session = new BasicHttpSession();
- return session;
- }
- }
-
- @SuppressWarnings("resource")
- String expectXmlCommand(String inputFile, DateTime now) throws Exception {
- clock.setTo(now); // Makes Ofy use 'now' as its time
- reset(req, rsp);
- HttpServlet servlet = new TypeInstantiator(getClass()){}.instantiate();
- if (servlet instanceof XsrfProtectedServlet) {
- when(req.getHeader(X_CSRF_TOKEN))
- .thenReturn(generateToken(((XsrfProtectedServlet) servlet).getScope()));
- }
- when(req.getInputStream()).thenReturn(new FakeServletInputStream(inputFile.getBytes(UTF_8)));
- when(req.getParameter("xml")).thenReturn(inputFile);
- if (isSuperuser.isPresent()) {
- when(req.getParameter("superuser")).thenReturn(isSuperuser.get().toString());
- }
- if (clientIdentifier.isPresent()) {
- when(req.getParameter("clientIdentifier")).thenReturn(clientIdentifier.get());
- }
- when(req.getParameter("tld")).thenReturn(currentTld);
- when(req.getServletPath()).thenReturn("");
- when(req.getMethod()).thenReturn("POST");
- when(req.getHeader("X-Requested-With")).thenReturn("XMLHttpRequest");
- when(req.getSession(true)).thenAnswer(new Answer() {
- @Override
- public HttpSession answer(InvocationOnMock invocation) {
- return getOrRenewSession();
- }});
- final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- when(rsp.getOutputStream()).thenReturn(new ServletOutputStream() {
- @Override
- public void write(int b) {
- byteArrayOutputStream.write(b);
- }});
- extendedSessionConfig(inputFile);
-
- servlet.init(mock(ServletConfig.class));
- servlet.service(req, rsp);
- verify(rsp).setStatus(HttpServletResponse.SC_OK);
- String result = new String(byteArrayOutputStream.toByteArray(), UTF_8);
- // Run the resulting xml through the unmarshaller to verify that it was valid.
- EppXmlTransformer.validateOutput(result);
- return result;
- }
-
- /** Create the two administrative contacts and two hosts that are used by a lot of our tests. */
- protected void createContactsAndHosts() throws Exception {
- DateTime startTime = DateTime.parse("2000-06-01T00:00:00Z");
- assertCommandAndResponse(
- "contact_create_sh8013.xml",
- ImmutableMap.of(),
- "contact_create_response_sh8013.xml",
- ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
- startTime);
- assertCommandAndResponse(
- "contact_create_jd1234.xml",
- "contact_create_response_jd1234.xml",
- startTime.plusMinutes(1));
- assertCommandAndResponse(
- "host_create.xml",
- "host_create_response.xml",
- startTime.plusMinutes(2));
- assertCommandAndResponse(
- "host_create2.xml",
- "host_create2_response.xml",
- startTime.plusMinutes(3));
- }
-
- /**
- * Creates the domain fakesite.example with two nameservers on it.
- */
- protected void createFakesite() throws Exception {
- createContactsAndHosts();
- assertCommandAndResponse(
- "domain_create_fakesite.xml",
- "domain_create_response_fakesite.xml",
- "2000-06-01T00:04:00Z");
- assertCommandAndResponse(
- "domain_info_fakesite.xml",
- "domain_info_response_fakesite_ok.xml",
- "2000-06-06T00:00:00Z");
- }
-
- // Adds ns3.fakesite.example as a host, then adds it to fakesite.
- protected void createSubordinateHost() throws Exception {
- // Add the fakesite nameserver (requires that domain is already created).
- assertCommandAndResponse(
- "host_create_fakesite.xml",
- "host_create_response_fakesite.xml",
- "2000-06-06T00:01:00Z");
- // Add new nameserver to domain.
- assertCommandAndResponse(
- "domain_update_add_nameserver_fakesite.xml",
- "domain_update_add_nameserver_response_fakesite.xml",
- "2000-06-08T00:00:00Z");
- // Verify new nameserver was added.
- assertCommandAndResponse(
- "domain_info_fakesite.xml",
- "domain_info_response_fakesite_3_nameservers.xml",
- "2000-06-08T00:01:00Z");
- // Verify that nameserver's data was set correctly.
- assertCommandAndResponse(
- "host_info_fakesite.xml",
- "host_info_response_fakesite.xml",
- "2000-06-08T00:02:00Z");
- }
-
- /** For subclasses to further setup the session. */
- protected void extendedSessionConfig(
- @SuppressWarnings("unused") String inputFile) throws Exception {}
-}
diff --git a/javatests/google/registry/flows/EppServletXmlLoginTestCase.java b/javatests/google/registry/flows/EppServletXmlLoginTestCase.java
deleted file mode 100644
index 65dc8960f..000000000
--- a/javatests/google/registry/flows/EppServletXmlLoginTestCase.java
+++ /dev/null
@@ -1,358 +0,0 @@
-// 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.flows;
-
-import static google.registry.testing.DatastoreHelper.createTld;
-import static google.registry.util.DateTimeUtils.START_OF_TIME;
-import static org.joda.time.DateTimeZone.UTC;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedMap;
-
-import google.registry.model.registry.Registry.TldState;
-import google.registry.util.DateTimeUtils;
-
-import org.joda.time.DateTime;
-import org.joda.time.format.ISODateTimeFormat;
-import org.junit.Test;
-
-import javax.servlet.http.HttpServlet;
-
-/**
- * Test setup for EppServletTest subclasses which use XML-based authentication.
- *
- * @param The EppXXXServlet class to test.
- */
-public abstract class EppServletXmlLoginTestCase extends
- EppServletTestCase {
-
- @Test
- public void testHello() throws Exception {
- DateTime now = DateTime.now(UTC);
- assertCommandAndResponse(
- "hello.xml",
- null,
- "greeting_crr.xml",
- ImmutableMap.of("DATE", now.toString(ISODateTimeFormat.dateTimeNoMillis())),
- now);
- }
-
- @Test
- public void testLoginLogout() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testPdtLogin() throws Exception {
- assertCommandAndResponse("pdt_login.xml", "login_response.xml");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testSyntaxError() throws Exception {
- assertCommandAndResponse("syntax_error.xml", "syntax_error_response.xml");
- }
-
- @Test
- public void testContactLifecycle() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "contact_create_sh8013.xml",
- ImmutableMap.of(),
- "contact_create_response_sh8013.xml",
- ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
- "2000-06-01T00:00:00Z");
- assertCommandAndResponse(
- "contact_info.xml",
- "contact_info_from_create_response.xml",
- "2000-06-01T00:01:00Z");
- assertCommandAndResponse("contact_delete_sh8013.xml", "contact_delete_response_sh8013.xml");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDomainDeleteRestore() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- // Create contacts sh8013 and jd1234.
- assertCommandAndResponse(
- "contact_create_sh8013.xml",
- ImmutableMap.of(),
- "contact_create_response_sh8013.xml",
- ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
- "2000-06-01T00:00:00Z");
-
- assertCommandAndResponse(
- "contact_create_jd1234.xml",
- "contact_create_response_jd1234.xml",
- "2000-06-01T00:01:00Z");
-
- // Create domain example.tld.
- assertCommandAndResponse(
- "domain_create_no_hosts_or_dsdata.xml",
- "domain_create_response.xml",
- "2000-06-01T00:02:00Z");
-
- // Delete domain example.com after its add grace period has expired.
- assertCommandAndResponse(
- "domain_delete.xml",
- "generic_success_action_pending_response.xml",
- "2000-07-01T00:02:00Z");
-
- // Restore the domain.
- assertCommandAndResponse(
- "domain_update_restore_request.xml",
- "domain_update_restore_request_response.xml",
- "2000-07-01T00:03:00Z");
-
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDomainDeletion_withinAddGracePeriod() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
-
- // Create contacts sh8013 and jd1234.
- assertCommandAndResponse(
- "contact_create_sh8013.xml",
- ImmutableMap.of(),
- "contact_create_response_sh8013.xml",
- ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"),
- "2000-06-01T00:00:00Z");
-
- assertCommandAndResponse(
- "contact_create_jd1234.xml",
- "contact_create_response_jd1234.xml",
- "2000-06-01T00:01:00Z");
-
- // Create domain example.tld.
- assertCommandAndResponse(
- "domain_create_no_hosts_or_dsdata.xml",
- "domain_create_response.xml",
- "2000-06-01T00:02:00Z");
-
- // Delete domain example.tld after its add grace period has expired.
- assertCommandAndResponse(
- "domain_delete.xml",
- "generic_success_action_pending_response.xml",
- "2000-07-01T00:02:00Z");
-
- // Poke the domain a little at various times to see its status
- assertCommandAndResponse(
- "domain_info.xml",
- "domain_info_response_pendingdelete.xml",
- "2000-08-01T00:02:00Z"); // 1 day out.
-
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDomainDeletionWithSubordinateHost_fails() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- createFakesite();
- createSubordinateHost();
- assertCommandAndResponse(
- "domain_delete_fakesite.xml",
- "domain_delete_response_prohibited.xml",
- "2002-05-30T01:01:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDeletionOfDomain_afterRenameOfSubordinateHost_succeeds() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- createFakesite();
- createSubordinateHost();
- // Update the ns3 host to no longer be on fakesite.example domain.
- assertCommandAndResponse(
- "host_update_fakesite.xml",
- "generic_success_response.xml",
- "2002-05-30T01:01:00Z");
- // Delete the fakesite.example domain (which should succeed since it no longer has subords).
- assertCommandAndResponse(
- "domain_delete_fakesite.xml",
- "generic_success_action_pending_response.xml",
- "2002-05-30T01:02:00Z");
- // Check info on the renamed host and verify that it's still around and wasn't deleted.
- assertCommandAndResponse(
- "host_info_ns9000_example.xml",
- "host_info_response_ns9000_example.xml",
- "2002-06-30T01:03:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDeletionOfDomain_afterUpdateThatCreatesSubordinateHost_fails() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- createFakesite();
- // Update the ns1 host to be on the fakesite.example domain.
- assertCommandAndResponse(
- "host_update_ns1_to_fakesite.xml",
- "generic_success_response.xml",
- "2002-05-30T01:01:00Z");
- // Attempt to delete the fakesite.example domain (which should fail since it now has a
- // subordinate host).
- assertCommandAndResponse(
- "domain_delete_fakesite.xml",
- "domain_delete_response_prohibited.xml",
- "2002-05-30T01:02:00Z");
- // Check info on the renamed host and verify that it's still around and wasn't deleted.
- assertCommandAndResponse(
- "host_info_fakesite.xml",
- "host_info_response_fakesite_post_update.xml",
- "2002-06-30T01:03:00Z");
- // Verify that fakesite.example domain is still around and wasn't deleted.
- assertCommandAndResponse(
- "domain_info_fakesite.xml",
- "domain_info_response_fakesite_ok_post_host_update.xml",
- "2002-05-30T01:00:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testRenamingHostToExistingHost_fails() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- // Create the two hosts.
- assertCommandAndResponse(
- "host_create.xml",
- "host_create_response.xml",
- "2000-06-01T00:02:00Z");
- assertCommandAndResponse(
- "host_create2.xml",
- "host_create2_response.xml",
- "2000-06-01T00:03:00Z");
- // Verify that host1 and host2 were created as we expect them.
- assertCommandAndResponse(
- "host_info_ns1.xml",
- "host_info_response_ns1.xml",
- "2000-06-01T00:04:00Z");
- assertCommandAndResponse(
- "host_info_ns2.xml",
- "host_info_response_ns2.xml",
- "2000-06-01T00:05:00Z");
- // Attempt overwriting of host1 on top of host2 (and verify that it fails).
- assertCommandAndResponse(
- "host_update_ns1_to_ns2.xml",
- "host_update_failed_response.xml",
- "2000-06-01T00:06:00Z");
- // Verify that host1 and host2 still exist in their unmodified states.
- assertCommandAndResponse(
- "host_info_ns1.xml",
- "host_info_response_ns1.xml",
- "2000-06-01T00:07:00Z");
- assertCommandAndResponse(
- "host_info_ns2.xml",
- "host_info_response_ns2.xml",
- "2000-06-01T00:08:00Z");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testApplicationDuringSunrise_doesntCreateDomainWithoutAllocation() throws Exception {
- ImmutableSortedMap transitions = ImmutableSortedMap.of(
- DateTimeUtils.START_OF_TIME, TldState.SUNRISE,
- START_OF_GA, TldState.GENERAL_AVAILABILITY);
- createTld("example", transitions);
-
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- createContactsAndHosts();
- // Note that the trademark is valid from 2013-08-09 to 2017-07-23, hence the domain creation
- // in 2014.
- assertCommandAndResponse(
- "domain_create_sunrise_encoded_mark.xml",
- "domain_create_sunrise_encoded_signed_mark_response.xml",
- "2014-01-01T00:00:00Z");
- assertCommandAndResponse(
- "domain_info_testvalidate.xml",
- "domain_info_response_testvalidate_doesnt_exist.xml",
- "2014-01-01T00:01:00Z");
-
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDomainCreation_failsBeforeSunrise() throws Exception {
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
-
- DateTime sunriseDate = DateTime.parse("2000-05-30T00:00:00Z");
- ImmutableSortedMap transitions = ImmutableSortedMap.of(
- START_OF_TIME, TldState.PREDELEGATION,
- sunriseDate, TldState.SUNRISE,
- sunriseDate.plusMonths(2), TldState.GENERAL_AVAILABILITY);
- createTld("example", transitions);
-
- setClientIdentifier("NewRegistrar");
- createContactsAndHosts();
- assertCommandAndResponse(
- "domain_create_sunrise_encoded_mark.xml",
- "domain_create_testvalidate_invalid_phase.xml",
- sunriseDate.minusDays(1));
-
- assertCommandAndResponse(
- "domain_info_testvalidate.xml",
- "domain_info_response_testvalidate_doesnt_exist.xml",
- sunriseDate.plusDays(1));
-
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testDomainCheckFee_succeeds() throws Exception {
- assertCommandAndResponse("login_valid_fee_extension.xml", "login_response.xml");
-
- DateTime gaDate = DateTime.parse("2000-05-30T00:00:00Z");
- ImmutableSortedMap transitions = ImmutableSortedMap.of(
- START_OF_TIME, TldState.PREDELEGATION,
- gaDate, TldState.GENERAL_AVAILABILITY);
- createTld("example", transitions);
-
- assertCommandAndResponse(
- "domain_check_fee_premium.xml",
- "domain_check_fee_premium_response.xml",
- gaDate.plusDays(1));
-
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testRemoteXmlExternalEntity() throws Exception {
- // Check go/XXE
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "contact_create_remote_xxe.xml",
- "contact_create_remote_response_xxe.xml");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testLocalXmlExternalEntity() throws Exception {
- // Check go/XXE
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "contact_create_local_xxe.xml",
- "contact_create_local_response_xxe.xml");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-
- @Test
- public void testBillionLaughsAttack() throws Exception {
- // Check go/XXE
- assertCommandAndResponse("login_valid.xml", "login_response.xml");
- assertCommandAndResponse(
- "contact_create_billion_laughs.xml",
- "contact_create_response_billion_laughs.xml");
- assertCommandAndResponse("logout.xml", "logout_response.xml");
- }
-}
diff --git a/javatests/google/registry/flows/EppTestCase.java b/javatests/google/registry/flows/EppTestCase.java
new file mode 100644
index 000000000..c329bcb18
--- /dev/null
+++ b/javatests/google/registry/flows/EppTestCase.java
@@ -0,0 +1,130 @@
+// 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.flows;
+
+import static com.google.common.truth.Truth.assertThat;
+import static google.registry.model.ofy.ObjectifyService.ofy;
+import static google.registry.testing.TestDataHelper.loadFileWithSubstitutions;
+import static google.registry.xml.XmlTestUtils.assertXmlEqualsWithMessage;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+import static org.joda.time.DateTimeZone.UTC;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.net.MediaType;
+
+import google.registry.model.ofy.Ofy;
+import google.registry.monitoring.whitebox.EppMetrics;
+import google.registry.testing.FakeClock;
+import google.registry.testing.FakeResponse;
+import google.registry.testing.InjectRule;
+import google.registry.testing.ShardableTestCase;
+import google.registry.testing.TestSessionMetadata;
+
+import org.joda.time.DateTime;
+import org.junit.Before;
+import org.junit.Rule;
+
+import java.util.Map;
+
+public class EppTestCase extends ShardableTestCase {
+
+ private static final MediaType APPLICATION_EPP_XML_UTF8 =
+ MediaType.create("application", "epp+xml").withCharset(UTF_8);
+
+ @Rule
+ public final InjectRule inject = new InjectRule();
+
+ private final FakeClock clock = new FakeClock();
+
+ private TestSessionMetadata sessionMetadata;
+ private TransportCredentials credentials;
+ private boolean superuser;
+
+ @Before
+ public void initTestCase() {
+ inject.setStaticField(Ofy.class, "clock", clock); // For transactional flows.
+ }
+
+ /**
+ * Set the transport credentials.
+ *
+ * When the credentials are null, the login flow still checks the EPP password from the xml,
+ * which is sufficient for all tests that aren't explicitly testing a form of login credentials
+ * such as {@link EppLoginUserTest}, {@link EppLoginAdminUserTest} and {@link EppLoginTlsTest}.
+ * Therefore, only those tests should call this method.
+ */
+ protected void setTransportCredentials(TransportCredentials credentials) {
+ this.credentials = credentials;
+ }
+
+ protected void setSuperuser(boolean superuser) {
+ this.superuser = superuser;
+ }
+
+ String assertCommandAndResponse(String inputFilename, String outputFilename) throws Exception {
+ return assertCommandAndResponse(inputFilename, outputFilename, DateTime.now(UTC));
+ }
+
+ String assertCommandAndResponse(String inputFilename, String outputFilename, DateTime now)
+ throws Exception {
+ return assertCommandAndResponse(inputFilename, null, outputFilename, null, now);
+ }
+
+ String assertCommandAndResponse(
+ String inputFilename,
+ Map inputSubstitutions,
+ String outputFilename,
+ Map outputSubstitutions,
+ DateTime now) throws Exception {
+ clock.setTo(now);
+ String input = loadFileWithSubstitutions(getClass(), inputFilename, inputSubstitutions);
+ String expectedOutput =
+ loadFileWithSubstitutions(getClass(), outputFilename, outputSubstitutions);
+ if (sessionMetadata == null) {
+ sessionMetadata = new TestSessionMetadata();
+ sessionMetadata.setTransportCredentials(credentials);
+ }
+ sessionMetadata.setSuperuser(superuser);
+ String actualOutput = executeXmlCommand(input);
+ if (!sessionMetadata.isValid()) {
+ sessionMetadata = null;
+ }
+ assertXmlEqualsWithMessage(
+ expectedOutput,
+ actualOutput,
+ "Running " + inputFilename + " => " + outputFilename,
+ "epp.response.resData.infData.roid",
+ "epp.response.trID.svTRID");
+ ofy().clearSessionCache(); // Clear the cache like OfyFilter would.
+ return actualOutput;
+ }
+
+ private String executeXmlCommand(String inputXml) throws Exception {
+ EppRequestHandler handler = new EppRequestHandler();
+ FakeResponse response = new FakeResponse();
+ handler.response = response;
+ handler.eppController = new EppController();
+ handler.eppController.clock = clock;
+ handler.eppController.metrics = mock(EppMetrics.class);
+ handler.executeEpp(sessionMetadata, inputXml.getBytes(UTF_8));
+ assertThat(response.getStatus()).isEqualTo(SC_OK);
+ assertThat(response.getContentType()).isEqualTo(APPLICATION_EPP_XML_UTF8);
+ String result = response.getPayload();
+ // Run the resulting xml through the unmarshaller to verify that it was valid.
+ EppXmlTransformer.validateOutput(result);
+ return result;
+ }
+}
diff --git a/javatests/google/registry/flows/EppTlsActionTest.java b/javatests/google/registry/flows/EppTlsActionTest.java
new file mode 100644
index 000000000..2eb1f10ed
--- /dev/null
+++ b/javatests/google/registry/flows/EppTlsActionTest.java
@@ -0,0 +1,67 @@
+// 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.flows;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import google.registry.testing.ShardableTestCase;
+import google.registry.util.BasicHttpSession;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+
+/** Tests for {@link EppTlsAction}. */
+@RunWith(JUnit4.class)
+public class EppTlsActionTest extends ShardableTestCase {
+
+ private static final byte[] INPUT_XML_BYTES = "".getBytes(UTF_8);
+
+ private void doTest(boolean superuser) {
+ EppTlsAction action = new EppTlsAction();
+ action.inputXmlBytes = INPUT_XML_BYTES;
+ action.tlsCredentials = mock(TlsCredentials.class);
+ when(action.tlsCredentials.hasSni()).thenReturn(true);
+ action.session = new BasicHttpSession();
+ action.session.setAttribute("CLIENT_ID", "ClientIdentifier");
+ action.session.setAttribute("SUPERUSER", superuser);
+ action.eppRequestHandler = mock(EppRequestHandler.class);
+ action.run();
+ ArgumentCaptor captor = ArgumentCaptor.forClass(SessionMetadata.class);
+ verify(action.eppRequestHandler).executeEpp(captor.capture(), eq(INPUT_XML_BYTES));
+ SessionMetadata sessionMetadata = captor.getValue();
+ assertThat(sessionMetadata.getClientId()).isEqualTo("ClientIdentifier");
+ assertThat(sessionMetadata.isDryRun()).isFalse(); // Should always be false for TLS.
+ assertThat(sessionMetadata.isSuperuser()).isEqualTo(superuser);
+ assertThat(sessionMetadata.getTransportCredentials()).isSameAs(action.tlsCredentials);
+ }
+
+ @Test
+ public void testSuperuser() throws Exception {
+ doTest(true);
+ }
+
+ @Test
+ public void testNotSuperuser() throws Exception {
+ doTest(false);
+ }
+}
diff --git a/javatests/google/registry/flows/EppToolActionTest.java b/javatests/google/registry/flows/EppToolActionTest.java
new file mode 100644
index 000000000..347042af3
--- /dev/null
+++ b/javatests/google/registry/flows/EppToolActionTest.java
@@ -0,0 +1,68 @@
+// 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.flows;
+
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+
+/** Tests for {@link EppToolAction}. */
+@RunWith(JUnit4.class)
+public class EppToolActionTest {
+
+ private void doTest(boolean dryRun, boolean superuser) {
+ EppToolAction action = new EppToolAction();
+ action.clientIdentifier = "ClientIdentifier";
+ action.dryRun = dryRun;
+ action.superuser = superuser;
+ action.eppRequestHandler = mock(EppRequestHandler.class);
+ action.xml = "";
+ action.run();
+ ArgumentCaptor captor = ArgumentCaptor.forClass(SessionMetadata.class);
+ verify(action.eppRequestHandler).executeEpp(captor.capture(), eq(action.xml.getBytes(UTF_8)));
+ SessionMetadata sessionMetadata = captor.getValue();
+ assertThat(sessionMetadata.getClientId()).isEqualTo("ClientIdentifier");
+ assertThat(sessionMetadata.isDryRun()).isEqualTo(dryRun);
+ assertThat(sessionMetadata.isSuperuser()).isEqualTo(superuser);
+ }
+
+ @Test
+ public void testDryRunAndSuperuser() throws Exception {
+ doTest(true, true);
+ }
+
+ @Test
+ public void testDryRun() throws Exception {
+ doTest(true, false);
+ }
+
+ @Test
+ public void testSuperuser() throws Exception {
+ doTest(false, true);
+ }
+
+ @Test
+ public void testNeitherDryRunNorSuperuser() throws Exception {
+ doTest(false, false);
+ }
+}
diff --git a/javatests/google/registry/flows/EppToolServletTest.java b/javatests/google/registry/flows/EppToolServletTest.java
deleted file mode 100644
index 4937d596a..000000000
--- a/javatests/google/registry/flows/EppToolServletTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-// 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.flows;
-
-import static google.registry.testing.DatastoreHelper.createTld;
-import static google.registry.testing.DatastoreHelper.persistResource;
-import static google.registry.util.DateTimeUtils.START_OF_TIME;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedMap;
-
-import google.registry.model.registrar.Registrar;
-import google.registry.model.registrar.RegistrarContact;
-import google.registry.model.registry.Registry.TldState;
-import google.registry.testing.AppEngineRule;
-import google.registry.testing.UserInfo;
-
-import org.joda.time.DateTime;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.runners.MockitoJUnitRunner;
-
-/** Tests for {@link EppToolServlet}. */
-@RunWith(MockitoJUnitRunner.class)
-public class EppToolServletTest extends EppServletTestCase {
-
- @Rule
- public final AppEngineRule appEngine = AppEngineRule.builder()
- .withDatastore()
- .withTaskQueue()
- .withUserService(UserInfo.createAdmin(GAE_USER_EMAIL, GAE_USER_ID))
- .build();
-
- private static final String GAE_USER_ID = "12345";
- private static final String GAE_USER_EMAIL = "person@example.com";
-
- @Before
- public void initTest() throws Exception {
- Registrar registrar = Registrar.loadByClientId("NewRegistrar");
- persistResource(
- new RegistrarContact.Builder()
- .setParent(registrar)
- .setEmailAddress(GAE_USER_EMAIL)
- .setTypes(ImmutableSet.of(RegistrarContact.Type.ADMIN))
- .setGaeUserId(GAE_USER_ID)
- .build());
- }
-
- @Test
- public void testDomainAllocation_succeedsOnlyAsSuperuser() throws Exception {
- ImmutableSortedMap transitions = ImmutableSortedMap.of(
- START_OF_TIME, TldState.SUNRISE,
- START_OF_GA, TldState.GENERAL_AVAILABILITY);
- createTld("example", transitions);
-
- setClientIdentifier("NewRegistrar");
- setSuperuser(false);
- createContactsAndHosts();
- // Note that the trademark is valid from 20130809 to 20170723, hence the domain creation
- // in 2014.
- assertCommandAndResponse(
- "domain_create_sunrise_encoded_mark.xml",
- "domain_create_sunrise_encoded_signed_mark_response.xml",
- "2014-01-01T00:00:00Z");
- assertCommandAndResponse(
- "domain_info_testvalidate.xml",
- "domain_info_response_testvalidate_doesnt_exist.xml",
- "2014-01-01T00:01:00Z");
- assertCommandAndResponse(
- "domain_allocate_testvalidate.xml",
- "domain_allocate_response_testvalidate_only_superuser.xml",
- START_OF_GA.plusDays(1));
- setSuperuser(true);
- assertCommandAndResponse(
- "domain_allocate_testvalidate.xml",
- "domain_allocate_response_testvalidate.xml",
- START_OF_GA.plusDays(1).plusMinutes(1));
- setSuperuser(false);
- assertCommandAndResponse(
- "domain_info_testvalidate.xml",
- "domain_info_response_testvalidate_ok.xml",
- START_OF_GA.plusDays(1).plusMinutes(2));
- }
-
- @Test
- public void testDomainCreation_failsBeforeSunrise() throws Exception {
- DateTime sunriseDate = DateTime.parse("2000-05-30T00:00:00Z");
- ImmutableSortedMap transitions = ImmutableSortedMap.of(
- START_OF_TIME, TldState.PREDELEGATION,
- sunriseDate, TldState.SUNRISE,
- sunriseDate.plusMonths(2), TldState.GENERAL_AVAILABILITY);
- createTld("example", transitions);
-
- setClientIdentifier("NewRegistrar");
- createContactsAndHosts();
- assertCommandAndResponse(
- "domain_create_sunrise_encoded_mark.xml",
- "domain_create_testvalidate_invalid_phase.xml",
- sunriseDate.minusDays(1));
- assertCommandAndResponse(
- "domain_info_testvalidate.xml",
- "domain_info_response_testvalidate_doesnt_exist.xml",
- sunriseDate.plusDays(1));
- }
-
- @Test
- public void testDomainCheckFee_succeeds() throws Exception {
- DateTime gaDate = DateTime.parse("2000-05-30T00:00:00Z");
- ImmutableSortedMap transitions = ImmutableSortedMap.of(
- START_OF_TIME, TldState.PREDELEGATION,
- gaDate, TldState.GENERAL_AVAILABILITY);
- createTld("example", transitions);
-
- setClientIdentifier("NewRegistrar");
- assertCommandAndResponse(
- "domain_check_fee_premium.xml",
- "domain_check_fee_premium_response.xml",
- gaDate.plusDays(1));
- }
-
- // Extra method so the test runner doesn't produce empty shards.
- @Test public void testNothing1() {}
-}
diff --git a/javatests/google/registry/flows/EppXxeAttackTest.java b/javatests/google/registry/flows/EppXxeAttackTest.java
new file mode 100644
index 000000000..8bb95ac90
--- /dev/null
+++ b/javatests/google/registry/flows/EppXxeAttackTest.java
@@ -0,0 +1,58 @@
+// 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.flows;
+
+import google.registry.testing.AppEngineRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class EppXxeAttackTest extends EppTestCase {
+
+ @Rule
+ public final AppEngineRule appEngine = AppEngineRule.builder()
+ .withDatastore()
+ .build();
+
+ @Test
+ public void testRemoteXmlExternalEntity() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "contact_create_remote_xxe.xml",
+ "contact_create_remote_response_xxe.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testLocalXmlExtrernalEntity() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "contact_create_local_xxe.xml",
+ "contact_create_local_response_xxe.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+
+ @Test
+ public void testBillionLaughsAttack() throws Exception {
+ assertCommandAndResponse("login_valid.xml", "login_response.xml");
+ assertCommandAndResponse(
+ "contact_create_billion_laughs.xml",
+ "contact_create_response_billion_laughs.xml");
+ assertCommandAndResponse("logout.xml", "logout_response.xml");
+ }
+}
diff --git a/javatests/google/registry/flows/FlowTestCase.java b/javatests/google/registry/flows/FlowTestCase.java
index 83735693f..01443afd3 100644
--- a/javatests/google/registry/flows/FlowTestCase.java
+++ b/javatests/google/registry/flows/FlowTestCase.java
@@ -99,7 +99,6 @@ public abstract class FlowTestCase {
sessionMetadata.setSessionSource(SessionSource.NONE);
ofy().saveWithoutBackup().entity(new ClaimsListSingleton()).now();
inject.setStaticField(Ofy.class, "clock", clock); // For transactional flows.
- inject.setStaticField(FlowRunner.class, "clock", clock); // For non-transactional flows.
}
protected void removeServiceExtensionUri(String uri) {
@@ -139,7 +138,8 @@ public abstract class FlowTestCase {
getTrid(),
sessionMetadata,
"".getBytes(),
- null);
+ null,
+ clock);
}
protected Trid getTrid() throws Exception {
diff --git a/javatests/google/registry/flows/session/LoginFlowViaConsoleTest.java b/javatests/google/registry/flows/session/LoginFlowViaConsoleTest.java
index 1ec8056bf..3f47df188 100644
--- a/javatests/google/registry/flows/session/LoginFlowViaConsoleTest.java
+++ b/javatests/google/registry/flows/session/LoginFlowViaConsoleTest.java
@@ -22,9 +22,9 @@ import com.google.apphosting.api.ApiProxy;
import com.google.apphosting.api.ApiProxy.Environment;
import com.google.common.collect.ImmutableSet;
-import google.registry.flows.EppConsoleServlet.GaeUserCredentials;
-import google.registry.flows.EppConsoleServlet.GaeUserCredentials.BadGaeUserIdException;
-import google.registry.flows.EppConsoleServlet.GaeUserCredentials.UserNotLoggedInException;
+import google.registry.flows.GaeUserCredentials;
+import google.registry.flows.GaeUserCredentials.BadGaeUserIdException;
+import google.registry.flows.GaeUserCredentials.UserNotLoggedInException;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarContact;
diff --git a/javatests/google/registry/flows/session/LoginFlowViaTlsTest.java b/javatests/google/registry/flows/session/LoginFlowViaTlsTest.java
index 310f10407..2ab04238b 100644
--- a/javatests/google/registry/flows/session/LoginFlowViaTlsTest.java
+++ b/javatests/google/registry/flows/session/LoginFlowViaTlsTest.java
@@ -16,6 +16,7 @@ package google.registry.flows.session;
import static google.registry.testing.DatastoreHelper.persistResource;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.net.InetAddresses;
@@ -30,21 +31,22 @@ import google.registry.util.CidrAddressBlock;
import org.junit.Test;
-import java.net.InetAddress;
-
/** Unit tests for {@link LoginFlow} when accessed via a TLS transport. */
public class LoginFlowViaTlsTest extends LoginFlowTestCase {
+
private static final String GOOD_CERT = CertificateSamples.SAMPLE_CERT_HASH;
private static final String BAD_CERT = CertificateSamples.SAMPLE_CERT2_HASH;
- private static final InetAddress GOOD_IP = InetAddresses.forString("192.168.1.1");
- private static final InetAddress BAD_IP = InetAddresses.forString("1.1.1.1");
+ private static final Optional GOOD_IP = Optional.of("192.168.1.1");
+ private static final Optional BAD_IP = Optional.of("1.1.1.1");
+ private static final Optional GOOD_IPV6 = Optional.of("2001:db8::1");
+ private static final Optional BAD_IPV6 = Optional.of("2001:db8::2");
@Override
protected Registrar.Builder getRegistrarBuilder() {
return super.getRegistrarBuilder()
.setClientCertificateHash(GOOD_CERT)
.setIpAddressWhitelist(ImmutableList.of(
- CidrAddressBlock.create(GOOD_IP, 32)));
+ CidrAddressBlock.create(InetAddresses.forString(GOOD_IP.get()), 32)));
}
@Test
@@ -62,7 +64,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
CidrAddressBlock.create("2001:db8:0:0:0:0:1:1/32")))
.build());
sessionMetadata.setTransportCredentials(
- new TlsCredentials(GOOD_CERT, InetAddresses.forString("2001:db8::1"), "goo.example"));
+ new TlsCredentials(GOOD_CERT, GOOD_IPV6, "goo.example"));
doSuccessfulTest("login_valid.xml");
}
@@ -74,7 +76,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
CidrAddressBlock.create("2001:db8:0:0:0:0:1:1/32")))
.build());
sessionMetadata.setTransportCredentials(
- new TlsCredentials(GOOD_CERT, InetAddresses.forString("2001:db8::1"), "goo.example"));
+ new TlsCredentials(GOOD_CERT, GOOD_IPV6, "goo.example"));
doSuccessfulTest("login_valid.xml");
}
@@ -85,8 +87,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
.setIpAddressWhitelist(ImmutableList.of(
CidrAddressBlock.create("192.168.1.255/24")))
.build());
- sessionMetadata.setTransportCredentials(
- new TlsCredentials(GOOD_CERT, InetAddresses.forString("192.168.1.1"), "goo.example"));
+ sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, GOOD_IP, "goo.example"));
doSuccessfulTest("login_valid.xml");
}
@@ -119,7 +120,8 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
CidrAddressBlock.create(InetAddresses.forString("192.168.1.1"), 32),
CidrAddressBlock.create(InetAddresses.forString("2001:db8::1"), 128)))
.build());
- sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, null, "goo.example"));
+ sessionMetadata.setTransportCredentials(
+ new TlsCredentials(GOOD_CERT, Optional.empty(), "goo.example"));
doFailingTest("login_valid.xml", BadRegistrarIpAddressException.class);
}
@@ -143,8 +145,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
CidrAddressBlock.create(InetAddresses.forString("192.168.1.1"), 32),
CidrAddressBlock.create(InetAddresses.forString("2001:db8::1"), 128)))
.build());
- sessionMetadata.setTransportCredentials(
- new TlsCredentials(GOOD_CERT, InetAddresses.forString("2001:db8::2"), "goo.example"));
+ sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, BAD_IPV6, "goo.example"));
doFailingTest("login_valid.xml", BadRegistrarIpAddressException.class);
}
}
diff --git a/javatests/google/registry/flows/testdata/domain_allocate_testvalidate.xml b/javatests/google/registry/flows/testdata/domain_allocate_testvalidate.xml
index 36da6e718..ed5298e92 100644
--- a/javatests/google/registry/flows/testdata/domain_allocate_testvalidate.xml
+++ b/javatests/google/registry/flows/testdata/domain_allocate_testvalidate.xml
@@ -19,7 +19,7 @@
- D-EXAMPLE
+ A-EXAMPLE
2014-01-01T00:00:00Z
diff --git a/javatests/google/registry/flows/testdata/domain_create_sunrise_encoded_signed_mark_response.xml b/javatests/google/registry/flows/testdata/domain_create_sunrise_encoded_signed_mark_response.xml
index c1bbcb13d..79311e553 100644
--- a/javatests/google/registry/flows/testdata/domain_create_sunrise_encoded_signed_mark_response.xml
+++ b/javatests/google/registry/flows/testdata/domain_create_sunrise_encoded_signed_mark_response.xml
@@ -14,7 +14,7 @@
sunrise
- D-EXAMPLE
+ A-EXAMPLE
diff --git a/javatests/google/registry/flows/testdata/pdt_login.xml b/javatests/google/registry/flows/testdata/login_invalid_wrong_password.xml
similarity index 60%
rename from javatests/google/registry/flows/testdata/pdt_login.xml
rename to javatests/google/registry/flows/testdata/login_invalid_wrong_password.xml
index 9de8a8037..bb95c0274 100644
--- a/javatests/google/registry/flows/testdata/pdt_login.xml
+++ b/javatests/google/registry/flows/testdata/login_invalid_wrong_password.xml
@@ -1,21 +1,19 @@
-
+
NewRegistrar
- foo-BAR2
+ incorrect
1.0
en
+ urn:ietf:params:xml:ns:host-1.0
urn:ietf:params:xml:ns:domain-1.0
urn:ietf:params:xml:ns:contact-1.0
- urn:ietf:params:xml:ns:host-1.0
- urn:ietf:params:xml:ns:secDNS-1.1
+ urn:ietf:params:xml:ns:launch-1.0
+ urn:ietf:params:xml:ns:rgp-1.0
diff --git a/javatests/google/registry/flows/testdata/login_response_unauthorized_tld.xml b/javatests/google/registry/flows/testdata/login_response_unauthorized_tld.xml
deleted file mode 100644
index ae24dbf30..000000000
--- a/javatests/google/registry/flows/testdata/login_response_unauthorized_tld.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- Registrar is not authorized to access this TLD
-
-
- ABC-12345
- Mt2PuhrJTKO1nM/MbHxT4g==-2a
-
-
-
diff --git a/javatests/google/registry/flows/testdata/login_response_wrong_password.xml b/javatests/google/registry/flows/testdata/login_response_wrong_password.xml
new file mode 100644
index 000000000..d71584c3c
--- /dev/null
+++ b/javatests/google/registry/flows/testdata/login_response_wrong_password.xml
@@ -0,0 +1,11 @@
+
+
+
+ Registrar password is incorrect
+
+
+ ABC-12345
+ server-trid
+
+
+
diff --git a/javatests/google/registry/flows/testdata/poll_response_contact_transfer.xml b/javatests/google/registry/flows/testdata/poll_response_contact_transfer.xml
index ef148c442..5c38f5b85 100644
--- a/javatests/google/registry/flows/testdata/poll_response_contact_transfer.xml
+++ b/javatests/google/registry/flows/testdata/poll_response_contact_transfer.xml
@@ -3,7 +3,7 @@
Command completed successfully; ack to dequeue
-
+
2000-06-08T22:00:00Z
Transfer requested.
diff --git a/javatests/google/registry/flows/testdata/poll_response_domain_transfer_request.xml b/javatests/google/registry/flows/testdata/poll_response_domain_transfer_request.xml
index e5fc66cb3..472dd18b7 100644
--- a/javatests/google/registry/flows/testdata/poll_response_domain_transfer_request.xml
+++ b/javatests/google/registry/flows/testdata/poll_response_domain_transfer_request.xml
@@ -3,7 +3,7 @@
Command completed successfully; ack to dequeue
-
+
2001-01-01T00:00:00Z
Transfer requested.
diff --git a/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_loser.xml b/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_loser.xml
index 6661620c9..640babb06 100644
--- a/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_loser.xml
+++ b/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_loser.xml
@@ -3,7 +3,7 @@
Command completed successfully; ack to dequeue
-
+
2001-01-06T00:00:00Z
Transfer approved.
diff --git a/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_winner.xml b/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_winner.xml
index ec3000b21..ed2c57b8e 100644
--- a/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_winner.xml
+++ b/javatests/google/registry/flows/testdata/poll_response_domain_transfer_server_approve_winner.xml
@@ -4,7 +4,7 @@
Command completed successfully; ack to dequeue
-
+
2001-01-06T00:00:00Z
Transfer approved.
diff --git a/javatests/google/registry/model/EppResourceUtilsTest.java b/javatests/google/registry/model/EppResourceUtilsTest.java
index 67e3b6ac7..0b7dbaee4 100644
--- a/javatests/google/registry/model/EppResourceUtilsTest.java
+++ b/javatests/google/registry/model/EppResourceUtilsTest.java
@@ -87,7 +87,8 @@ public class EppResourceUtilsTest {
Trid.create(null, "server-trid"),
sessionMetadata,
"".getBytes(),
- null)
+ null,
+ clock)
.run(CommitMode.LIVE, UserPrivileges.NORMAL);
}
diff --git a/javatests/google/registry/server/RegistryTestServer.java b/javatests/google/registry/server/RegistryTestServer.java
index 3dcd2b36c..bdcec0cc5 100644
--- a/javatests/google/registry/server/RegistryTestServer.java
+++ b/javatests/google/registry/server/RegistryTestServer.java
@@ -29,11 +29,16 @@ public final class RegistryTestServer {
public static final ImmutableMap RUNFILES =
new ImmutableMap.Builder()
- .put("/index.html", Paths.get("java/google/registry/ui/html/index.html"))
- .put("/error.html", Paths.get("java/google/registry/ui/html/error.html"))
+ .put(
+ "/index.html",
+ Paths.get("java/google/registry/ui/html/index.html"))
+ .put(
+ "/error.html",
+ Paths.get("java/google/registry/ui/html/error.html"))
.put("/assets/js/*", Paths.get("java/google/registry/ui"))
.put("/assets/css/*", Paths.get("java/google/registry/ui/css"))
- .put("/assets/sources/deps.js",
+ .put(
+ "/assets/sources/deps.js",
Paths.get("java/google/registry/ui/deps.js"))
.put("/assets/sources/*", Paths.get(""))
.put("/assets/*", Paths.get("java/google/registry/ui/assets"))
@@ -43,11 +48,11 @@ public final class RegistryTestServer {
// Frontend Services
route("/whois/*", google.registry.module.frontend.FrontendServlet.class),
route("/rdap/*", google.registry.module.frontend.FrontendServlet.class),
- route("/registrar-xhr", google.registry.flows.EppConsoleServlet.class),
- route("/check", google.registry.ui.server.api.CheckApiServlet.class),
+ route("/registrar-xhr", google.registry.module.frontend.FrontendServlet.class),
+ route("/check", google.registry.module.frontend.FrontendServlet.class),
// Proxy Services
- route("/_dr/epp", google.registry.flows.EppTlsServlet.class),
+ route("/_dr/epp", google.registry.module.frontend.FrontendServlet.class),
route("/_dr/whois", google.registry.module.frontend.FrontendServlet.class),
// Registry Data Escrow (RDE)
diff --git a/javatests/google/registry/testing/ShardableTestCase.java b/javatests/google/registry/testing/ShardableTestCase.java
new file mode 100644
index 000000000..af3d5d81c
--- /dev/null
+++ b/javatests/google/registry/testing/ShardableTestCase.java
@@ -0,0 +1,34 @@
+// 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.testing;
+
+import org.junit.Test;
+
+/**
+ * Test case with 3 empty methods.
+ *
+ * The sharding test runner fails if it produces an empty shard, and we shard 4 ways. This makes
+ * sure that we never produces empty shards.
+ */
+public abstract class ShardableTestCase {
+ @Test
+ public void testNothing1() {}
+
+ @Test
+ public void testNothing2() {}
+
+ @Test
+ public void testNothing3() {}
+}
diff --git a/javatests/google/registry/testing/TestDataHelper.java b/javatests/google/registry/testing/TestDataHelper.java
index ed666a8bd..67cfca694 100644
--- a/javatests/google/registry/testing/TestDataHelper.java
+++ b/javatests/google/registry/testing/TestDataHelper.java
@@ -14,7 +14,7 @@
package google.registry.testing;
-import static google.registry.util.CollectionUtils.isNullOrEmpty;
+import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import java.util.Map;
@@ -32,10 +32,8 @@ public final class TestDataHelper {
public static String loadFileWithSubstitutions(
Class> context, String filename, Map substitutions) {
String fileContents = readResourceUtf8(context, "testdata/" + filename);
- if (!isNullOrEmpty(substitutions)) {
- for (Entry entry : substitutions.entrySet()) {
- fileContents = fileContents.replaceAll("%" + entry.getKey() + "%", entry.getValue());
- }
+ for (Entry entry : nullToEmpty(substitutions).entrySet()) {
+ fileContents = fileContents.replaceAll("%" + entry.getKey() + "%", entry.getValue());
}
return fileContents;
}
diff --git a/javatests/google/registry/testing/TestSessionMetadata.java b/javatests/google/registry/testing/TestSessionMetadata.java
index a965d5999..5537a71ce 100644
--- a/javatests/google/registry/testing/TestSessionMetadata.java
+++ b/javatests/google/registry/testing/TestSessionMetadata.java
@@ -56,4 +56,8 @@ public class TestSessionMetadata extends SessionMetadata {
public void setSessionSource(SessionSource source) {
sessionSource = source;
}
+
+ public boolean isValid() {
+ return isValid;
+ }
}
diff --git a/javatests/google/registry/ui/server/api/BUILD b/javatests/google/registry/ui/server/api/BUILD
index 80eddd528..b9b6c4f2f 100644
--- a/javatests/google/registry/ui/server/api/BUILD
+++ b/javatests/google/registry/ui/server/api/BUILD
@@ -21,6 +21,7 @@ java_library(
"//third_party/java/truth",
"//java/google/registry/model",
"//java/google/registry/ui/server/api",
+ "//java/google/registry/util",
"//javatests/google/registry/testing",
],
)
diff --git a/javatests/google/registry/ui/server/api/CheckApiServletTest.java b/javatests/google/registry/ui/server/api/CheckApiActionTest.java
similarity index 63%
rename from javatests/google/registry/ui/server/api/CheckApiServletTest.java
rename to javatests/google/registry/ui/server/api/CheckApiActionTest.java
index 5f2775939..c15084ace 100644
--- a/javatests/google/registry/ui/server/api/CheckApiServletTest.java
+++ b/javatests/google/registry/ui/server/api/CheckApiActionTest.java
@@ -19,45 +19,34 @@ import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
import static google.registry.testing.DatastoreHelper.persistReservedList;
import static google.registry.testing.DatastoreHelper.persistResource;
-import static org.mockito.Mockito.when;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import google.registry.model.registrar.Registrar;
import google.registry.model.registry.Registry;
import google.registry.testing.AppEngineRule;
+import google.registry.testing.FakeResponse;
+import google.registry.util.SystemClock;
import org.json.simple.JSONValue;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.junit.runners.JUnit4;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/** Tests for {@link CheckApiServlet}. */
-@RunWith(MockitoJUnitRunner.class)
-public class CheckApiServletTest {
+/** Tests for {@link CheckApiAction}. */
+@RunWith(JUnit4.class)
+public class CheckApiActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
- @Mock HttpServletRequest req;
- @Mock HttpServletResponse rsp;
-
- private final StringWriter writer = new StringWriter();
-
- private final CheckApiServlet servlet = new CheckApiServlet();
+ final CheckApiAction action = new CheckApiAction();
@Before
public void init() throws Exception {
@@ -67,51 +56,50 @@ public class CheckApiServletTest {
.asBuilder()
.setReservedLists(persistReservedList("example-reserved", "foo,FULLY_BLOCKED"))
.build());
- when(rsp.getWriter()).thenReturn(new PrintWriter(writer));
}
- private void doTest(Map expected) throws Exception {
- servlet.doGet(req, rsp);
- assertThat(JSONValue.parse(writer.toString())).isEqualTo(expected);
+ @SuppressWarnings("unchecked")
+ private Map getCheckResponse(String domain) {
+ action.domain = domain;
+ action.response = new FakeResponse();
+ action.clock = new SystemClock();
+ action.run();
+ return (Map) JSONValue.parse(((FakeResponse) action.response).getPayload());
}
@Test
public void testFailure_nullDomain() throws Exception {
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse(null)).containsExactly(
"status", "error",
- "reason", "Must supply a valid domain name on an authoritative TLD"));
+ "reason", "Must supply a valid domain name on an authoritative TLD");
}
@Test
public void testFailure_emptyDomain() throws Exception {
- when(req.getParameter("domain")).thenReturn("");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("")).containsExactly(
"status", "error",
- "reason", "Must supply a valid domain name on an authoritative TLD"));
+ "reason", "Must supply a valid domain name on an authoritative TLD");
}
@Test
public void testFailure_invalidDomain() throws Exception {
- when(req.getParameter("domain")).thenReturn("@#$%^");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("@#$%^")).containsExactly(
"status", "error",
- "reason", "Must supply a valid domain name on an authoritative TLD"));
+ "reason", "Must supply a valid domain name on an authoritative TLD");
}
@Test
public void testFailure_singlePartDomain() throws Exception {
- when(req.getParameter("domain")).thenReturn("foo");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("foo")).containsExactly(
"status", "error",
- "reason", "Must supply a valid domain name on an authoritative TLD"));
+ "reason", "Must supply a valid domain name on an authoritative TLD");
}
@Test
public void testFailure_nonExistentTld() throws Exception {
- when(req.getParameter("domain")).thenReturn("foo.bar");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("foo.bar")).containsExactly(
"status", "error",
- "reason", "Must supply a valid domain name on an authoritative TLD"));
+ "reason", "Must supply a valid domain name on an authoritative TLD");
}
@Test
@@ -122,73 +110,65 @@ public class CheckApiServletTest {
.asBuilder()
.setAllowedTlds(ImmutableSet.of("foo"))
.build());
- when(req.getParameter("domain")).thenReturn("timmy.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("timmy.example")).containsExactly(
"status", "error",
- "reason", "Registrar is not authorized to access the TLD example"));
+ "reason", "Registrar is not authorized to access the TLD example");
}
@Test
public void testSuccess_availableStandard() throws Exception {
- when(req.getParameter("domain")).thenReturn("somedomain.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("somedomain.example")).containsExactly(
"status", "success",
"available", true,
- "tier", "standard"));
+ "tier", "standard");
}
@Test
public void testSuccess_availableCapital() throws Exception {
- when(req.getParameter("domain")).thenReturn("SOMEDOMAIN.EXAMPLE");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("SOMEDOMAIN.EXAMPLE")).containsExactly(
"status", "success",
"available", true,
- "tier", "standard"));
+ "tier", "standard");
}
@Test
public void testSuccess_availableUnicode() throws Exception {
- when(req.getParameter("domain")).thenReturn("ééé.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("ééé.example")).containsExactly(
"status", "success",
"available", true,
- "tier", "standard"));
+ "tier", "standard");
}
@Test
public void testSuccess_availablePunycode() throws Exception {
- when(req.getParameter("domain")).thenReturn("xn--9caaa.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("xn--9caaa.example")).containsExactly(
"status", "success",
"available", true,
- "tier", "standard"));
+ "tier", "standard");
}
@Test
public void testSuccess_availablePremium() throws Exception {
- when(req.getParameter("domain")).thenReturn("rich.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("rich.example")).containsExactly(
"status", "success",
"available", true,
- "tier", "premium"));
+ "tier", "premium");
}
@Test
public void testSuccess_alreadyRegistered() throws Exception {
persistActiveDomain("somedomain.example");
- when(req.getParameter("domain")).thenReturn("somedomain.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("somedomain.example")).containsExactly(
"status", "success",
"available", false,
- "reason", "In use"));
+ "reason", "In use");
}
@Test
public void testSuccess_reserved() throws Exception {
- when(req.getParameter("domain")).thenReturn("foo.example");
- doTest(ImmutableMap.of(
+ assertThat(getCheckResponse("foo.example")).containsExactly(
"status", "success",
"available", false,
- "reason", "Reserved"));
+ "reason", "Reserved");
}
}