mirror of
https://github.com/google/nomulus.git
synced 2025-06-27 14:54:51 +02:00
Attempt login to MosAPI via all available TLDs (#141)
* Attempt login to MosAPI via all available TLDs There's no reason why we should need a TLD as input here because it doesn't actually matter which one we use (they all have the same password). * Refactor the TLD loop and change cron jobs * Re-throw the last exception if one exists * Fix tests and exception * Remove alpha cron job
This commit is contained in:
parent
012d9d5893
commit
3e473cb239
3 changed files with 106 additions and 40 deletions
|
@ -112,8 +112,6 @@
|
||||||
<target>backend</target>
|
<target>backend</target>
|
||||||
</cron>
|
</cron>
|
||||||
|
|
||||||
<!--
|
|
||||||
TODO(b/134576418) enable this cron job once we're sure the Action works
|
|
||||||
<cron>
|
<cron>
|
||||||
<url><![CDATA[/_dr/task/updateRegistrarRdapBaseUrls]]></url>
|
<url><![CDATA[/_dr/task/updateRegistrarRdapBaseUrls]]></url>
|
||||||
<description>
|
<description>
|
||||||
|
@ -122,7 +120,6 @@
|
||||||
<schedule>every day 02:34</schedule>
|
<schedule>every day 02:34</schedule>
|
||||||
<target>backend</target>
|
<target>backend</target>
|
||||||
</cron>
|
</cron>
|
||||||
-->
|
|
||||||
|
|
||||||
<cron>
|
<cron>
|
||||||
<url><![CDATA[/_dr/task/deleteOldCommitLogs]]></url>
|
<url><![CDATA[/_dr/task/deleteOldCommitLogs]]></url>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
package google.registry.rdap;
|
package google.registry.rdap;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
@ -23,6 +24,7 @@ import com.google.api.client.http.HttpRequest;
|
||||||
import com.google.api.client.http.HttpRequestFactory;
|
import com.google.api.client.http.HttpRequestFactory;
|
||||||
import com.google.api.client.http.HttpResponse;
|
import com.google.api.client.http.HttpResponse;
|
||||||
import com.google.api.client.http.HttpTransport;
|
import com.google.api.client.http.HttpTransport;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
import com.google.common.collect.ImmutableSetMultimap;
|
||||||
import com.google.common.flogger.FluentLogger;
|
import com.google.common.flogger.FluentLogger;
|
||||||
|
@ -34,8 +36,9 @@ import com.google.gson.JsonObject;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.keyring.api.KeyModule;
|
import google.registry.keyring.api.KeyModule;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
|
import google.registry.model.registry.Registries;
|
||||||
|
import google.registry.model.registry.Registry.TldType;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.Parameter;
|
|
||||||
import google.registry.request.auth.Auth;
|
import google.registry.request.auth.Auth;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -56,8 +59,6 @@ import javax.inject.Inject;
|
||||||
* <p>It is a "login/query/logout" system where you login using the ICANN Reporting credentials, get
|
* <p>It is a "login/query/logout" system where you login using the ICANN Reporting credentials, get
|
||||||
* a cookie you then send to get the list and finally logout.
|
* a cookie you then send to get the list and finally logout.
|
||||||
*
|
*
|
||||||
* <p>The username is [TLD]_ry. It could be any "real" TLD.
|
|
||||||
*
|
|
||||||
* <p>For clarity, this is how one would contact this endpoint "manually", from a whitelisted IP
|
* <p>For clarity, this is how one would contact this endpoint "manually", from a whitelisted IP
|
||||||
* server:
|
* server:
|
||||||
*
|
*
|
||||||
|
@ -88,18 +89,10 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||||
@Inject HttpTransport httpTransport;
|
@Inject HttpTransport httpTransport;
|
||||||
@Inject @KeyModule.Key("icannReportingPassword") String password;
|
@Inject @KeyModule.Key("icannReportingPassword") String password;
|
||||||
|
|
||||||
/**
|
|
||||||
* The TLD for which we make the request.
|
|
||||||
*
|
|
||||||
* <p>The actual value doesn't matter, as long as it's a TLD that has access to the ICANN
|
|
||||||
* Reporter. It's just used to login.
|
|
||||||
*/
|
|
||||||
@Inject @Parameter("tld") String tld;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UpdateRegistrarRdapBaseUrlsAction() {}
|
UpdateRegistrarRdapBaseUrlsAction() {}
|
||||||
|
|
||||||
private String loginAndGetId(HttpRequestFactory requestFactory) {
|
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) {
|
||||||
try {
|
try {
|
||||||
logger.atInfo().log("Logging in to MoSAPI");
|
logger.atInfo().log("Logging in to MoSAPI");
|
||||||
HttpRequest request =
|
HttpRequest request =
|
||||||
|
@ -122,7 +115,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logout(HttpRequestFactory requestFactory, String id) {
|
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
|
||||||
try {
|
try {
|
||||||
HttpRequest request =
|
HttpRequest request =
|
||||||
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGOUT_URL, tld)));
|
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGOUT_URL, tld)));
|
||||||
|
@ -135,9 +128,9 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
|
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(String tld) {
|
||||||
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
|
||||||
String id = loginAndGetId(requestFactory);
|
String id = loginAndGetId(requestFactory, tld);
|
||||||
String content;
|
String content;
|
||||||
try {
|
try {
|
||||||
HttpRequest request =
|
HttpRequest request =
|
||||||
|
@ -152,7 +145,7 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||||
throw new UncheckedIOException(
|
throw new UncheckedIOException(
|
||||||
"Error reading RDAP list from MoSAPI server: " + e.getMessage(), e);
|
"Error reading RDAP list from MoSAPI server: " + e.getMessage(), e);
|
||||||
} finally {
|
} finally {
|
||||||
logout(requestFactory, id);
|
logout(requestFactory, id, tld);
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.atInfo().log("list reply: '%s'", content);
|
logger.atInfo().log("list reply: '%s'", content);
|
||||||
|
@ -173,6 +166,25 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaId() {
|
||||||
|
// All TLDs have the same data, so just keep trying until one works
|
||||||
|
// (the expectation is that all / any should work)
|
||||||
|
ImmutableList<String> tlds = ImmutableList.sortedCopyOf(Registries.getTldsOfType(TldType.REAL));
|
||||||
|
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
|
||||||
|
Throwable finalThrowable = null;
|
||||||
|
for (String tld : tlds) {
|
||||||
|
try {
|
||||||
|
return getRdapBaseUrlsPerIanaIdWithTld(tld);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
logger.atWarning().log(String
|
||||||
|
.format("Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
|
||||||
|
finalThrowable = throwable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException(
|
||||||
|
String.format("Error contacting MosAPI server. Tried TLDs %s", tlds), finalThrowable);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ImmutableSetMultimap<String, String> ianaToBaseUrls = getRdapBaseUrlsPerIanaId();
|
ImmutableSetMultimap<String, String> ianaToBaseUrls = getRdapBaseUrlsPerIanaId();
|
||||||
|
|
|
@ -16,8 +16,12 @@ package google.registry.rdap;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.common.truth.Truth8.assertThat;
|
import static com.google.common.truth.Truth8.assertThat;
|
||||||
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
|
import static google.registry.testing.DatastoreHelper.deleteTld;
|
||||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||||
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
import static google.registry.testing.DatastoreHelper.persistSimpleResource;
|
import static google.registry.testing.DatastoreHelper.persistSimpleResource;
|
||||||
|
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
|
|
||||||
import com.google.api.client.http.LowLevelHttpRequest;
|
import com.google.api.client.http.LowLevelHttpRequest;
|
||||||
import com.google.api.client.testing.http.MockHttpTransport;
|
import com.google.api.client.testing.http.MockHttpTransport;
|
||||||
|
@ -27,6 +31,8 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarAddress;
|
import google.registry.model.registrar.RegistrarAddress;
|
||||||
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.registry.Registry.TldType;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.ShardableTestCase;
|
import google.registry.testing.ShardableTestCase;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -95,8 +101,8 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TestHttpTransport httpTransport;
|
private TestHttpTransport httpTransport;
|
||||||
UpdateRegistrarRdapBaseUrlsAction action;
|
private UpdateRegistrarRdapBaseUrlsAction action;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
|
@ -104,27 +110,10 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||||
action = new UpdateRegistrarRdapBaseUrlsAction();
|
action = new UpdateRegistrarRdapBaseUrlsAction();
|
||||||
|
|
||||||
action.password = "myPassword";
|
action.password = "myPassword";
|
||||||
action.tld = "tld";
|
|
||||||
action.httpTransport = httpTransport;
|
action.httpTransport = httpTransport;
|
||||||
|
addValidResponses(httpTransport);
|
||||||
|
|
||||||
MockLowLevelHttpResponse loginResponse = new MockLowLevelHttpResponse();
|
createTld("tld");
|
||||||
loginResponse.addHeader(
|
|
||||||
"Set-Cookie",
|
|
||||||
"id=myAuthenticationId; "
|
|
||||||
+ "Expires=Tue, 11-Jun-2019 16:34:21 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
|
||||||
|
|
||||||
MockLowLevelHttpResponse listResponse = new MockLowLevelHttpResponse();
|
|
||||||
listResponse.setContent(JSON_LIST_REPLY);
|
|
||||||
|
|
||||||
MockLowLevelHttpResponse logoutResponse = new MockLowLevelHttpResponse();
|
|
||||||
loginResponse.addHeader(
|
|
||||||
"Set-Cookie",
|
|
||||||
"id=id; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
|
||||||
|
|
||||||
httpTransport.addNextResponse(loginResponse);
|
|
||||||
httpTransport.addNextResponse(listResponse);
|
|
||||||
httpTransport.addNextResponse(logoutResponse);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCorrectRequestsSent() {
|
private void assertCorrectRequestsSent() {
|
||||||
|
@ -237,4 +226,72 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
|
||||||
assertThat(loadRegistrar("registrar4001").getRdapBaseUrls())
|
assertThat(loadRegistrar("registrar4001").getRdapBaseUrls())
|
||||||
.containsExactly("https://rdap.example.com");
|
.containsExactly("https://rdap.example.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoTlds() {
|
||||||
|
deleteTld("tld");
|
||||||
|
assertThat(assertThrows(IllegalArgumentException.class, action::run)).hasMessageThat()
|
||||||
|
.isEqualTo("There must exist at least one REAL TLD.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnlyTestTlds() {
|
||||||
|
persistResource(Registry.get("tld").asBuilder().setTldType(TldType.TEST).build());
|
||||||
|
assertThat(assertThrows(IllegalArgumentException.class, action::run)).hasMessageThat()
|
||||||
|
.isEqualTo("There must exist at least one REAL TLD.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecondTldSucceeds() {
|
||||||
|
createTld("secondtld");
|
||||||
|
httpTransport = new TestHttpTransport();
|
||||||
|
action.httpTransport = httpTransport;
|
||||||
|
|
||||||
|
// the first TLD request will return a bad cookie but the second will succeed
|
||||||
|
MockLowLevelHttpResponse badLoginResponse = new MockLowLevelHttpResponse();
|
||||||
|
badLoginResponse.addHeader("Set-Cookie",
|
||||||
|
"Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||||
|
|
||||||
|
httpTransport.addNextResponse(badLoginResponse);
|
||||||
|
addValidResponses(httpTransport);
|
||||||
|
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBothFail() {
|
||||||
|
createTld("secondtld");
|
||||||
|
httpTransport = new TestHttpTransport();
|
||||||
|
action.httpTransport = httpTransport;
|
||||||
|
|
||||||
|
MockLowLevelHttpResponse badLoginResponse = new MockLowLevelHttpResponse();
|
||||||
|
badLoginResponse.addHeader("Set-Cookie",
|
||||||
|
"Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||||
|
|
||||||
|
// it should fail for both TLDs
|
||||||
|
httpTransport.addNextResponse(badLoginResponse);
|
||||||
|
httpTransport.addNextResponse(badLoginResponse);
|
||||||
|
|
||||||
|
assertThat(assertThrows(RuntimeException.class, action::run)).hasMessageThat()
|
||||||
|
.isEqualTo("Error contacting MosAPI server. Tried TLDs [secondtld, tld]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addValidResponses(TestHttpTransport httpTransport) {
|
||||||
|
MockLowLevelHttpResponse loginResponse = new MockLowLevelHttpResponse();
|
||||||
|
loginResponse.addHeader(
|
||||||
|
"Set-Cookie",
|
||||||
|
"id=myAuthenticationId; "
|
||||||
|
+ "Expires=Tue, 11-Jun-2019 16:34:21 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||||
|
|
||||||
|
MockLowLevelHttpResponse listResponse = new MockLowLevelHttpResponse();
|
||||||
|
listResponse.setContent(JSON_LIST_REPLY);
|
||||||
|
|
||||||
|
MockLowLevelHttpResponse logoutResponse = new MockLowLevelHttpResponse();
|
||||||
|
logoutResponse.addHeader(
|
||||||
|
"Set-Cookie",
|
||||||
|
"id=id; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/mosapi/v1/app; Secure; HttpOnly");
|
||||||
|
httpTransport.addNextResponse(loginResponse);
|
||||||
|
httpTransport.addNextResponse(listResponse);
|
||||||
|
httpTransport.addNextResponse(logoutResponse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue