Use custom whois message for bsa-blocked domain (#2241)

* Use custom whois message for bsa-blocked domain
This commit is contained in:
Weimin Yu 2024-01-02 14:40:34 -05:00 committed by GitHub
parent 42b508427b
commit ecb39d5899
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 246 additions and 81 deletions

View file

@ -1044,6 +1044,17 @@ public final class RegistryConfig {
return config.registryPolicy.whoisDisclaimer; return config.registryPolicy.whoisDisclaimer;
} }
/**
* Message template for whois response when queried domain is blocked by BSA.
*
* @see google.registry.whois.WhoisResponse
*/
@Provides
@Config("domainBlockedByBsaTemplate")
public static String provideDomainBlockedByBsaTemplate(RegistryConfigSettings config) {
return config.registryPolicy.domainBlockedByBsaTemplate;
}
/** /**
* Maximum QPS for the Google Cloud Monitoring V3 (aka Stackdriver) API. The QPS limit can be * Maximum QPS for the Google Cloud Monitoring V3 (aka Stackdriver) API. The QPS limit can be
* adjusted by contacting Cloud Support. * adjusted by contacting Cloud Support.

View file

@ -105,6 +105,7 @@ public class RegistryConfigSettings {
public String reservedTermsExportDisclaimer; public String reservedTermsExportDisclaimer;
public String whoisRedactedEmailText; public String whoisRedactedEmailText;
public String whoisDisclaimer; public String whoisDisclaimer;
public String domainBlockedByBsaTemplate;
public String rdapTos; public String rdapTos;
public String rdapTosStaticUrl; public String rdapTosStaticUrl;
public String registryName; public String registryName;

View file

@ -130,6 +130,12 @@ registryPolicy:
unlawful behavior. We reserve the right to restrict or deny your access to unlawful behavior. We reserve the right to restrict or deny your access to
the WHOIS database, and may modify these terms at any time. the WHOIS database, and may modify these terms at any time.
# BSA blocked domain name template.
domainBlockedByBsaTemplate: |
Domain Name: %s
>>> This name is not available for registration.
>>> This name has been blocked by a GlobalBlock service.
# RDAP Terms of Service text displayed at the /rdap/help/tos endpoint. # RDAP Terms of Service text displayed at the /rdap/help/tos endpoint.
rdapTos: > rdapTos: >
By querying our Domain Database as part of the RDAP pilot program (RDAP By querying our Domain Database as part of the RDAP pilot program (RDAP

View file

@ -269,11 +269,15 @@ public class DomainFlowUtils {
*/ */
public static void verifyNotBlockedByBsa(String domainLabel, Tld tld, DateTime now) public static void verifyNotBlockedByBsa(String domainLabel, Tld tld, DateTime now)
throws DomainLabelBlockedByBsaException { throws DomainLabelBlockedByBsaException {
if (isEnrolledWithBsa(tld, now) && isLabelBlocked(domainLabel)) { if (isBlockedByBsa(domainLabel, tld, now)) {
throw new DomainLabelBlockedByBsaException(); throw new DomainLabelBlockedByBsaException();
} }
} }
public static boolean isBlockedByBsa(String domainLabel, Tld tld, DateTime now) {
return isEnrolledWithBsa(tld, now) && isLabelBlocked(domainLabel);
}
/** Returns whether a given domain create request is for a valid anchor tenant. */ /** Returns whether a given domain create request is for a valid anchor tenant. */
public static boolean isAnchorTenant( public static boolean isAnchorTenant(
InternetDomainName domainName, InternetDomainName domainName,

View file

@ -14,34 +14,84 @@
package google.registry.whois; package google.registry.whois;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.flows.domain.DomainFlowUtils.isBlockedByBsa;
import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.EppResourceUtils.loadByForeignKeyCached; import static google.registry.model.EppResourceUtils.loadByForeignKeyCached;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.Tlds.getTlds;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Verify;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import google.registry.model.domain.Domain; import google.registry.model.domain.Domain;
import google.registry.model.tld.Tld;
import java.util.Optional; import java.util.Optional;
import org.joda.time.DateTime; import org.joda.time.DateTime;
/** Represents a WHOIS lookup on a domain name (i.e. SLD). */ /** Represents a WHOIS lookup on a domain name (i.e. SLD). */
public class DomainLookupCommand extends DomainOrHostLookupCommand { public class DomainLookupCommand implements WhoisCommand {
private static final String ERROR_PREFIX = "Domain";
@VisibleForTesting final InternetDomainName domainName;
private final boolean fullOutput; private final boolean fullOutput;
private final boolean cached; private final boolean cached;
private final String whoisRedactedEmailText; private final String whoisRedactedEmailText;
private final String domainBlockedByBsaTemplate;
public DomainLookupCommand( public DomainLookupCommand(
InternetDomainName domainName, InternetDomainName domainName,
boolean fullOutput, boolean fullOutput,
boolean cached, boolean cached,
String whoisRedactedEmailText) { String whoisRedactedEmailText,
super(domainName, "Domain"); String domainBlockedByBsaTemplate) {
this.domainName = checkNotNull(domainName, "domainOrHostName");
this.fullOutput = fullOutput; this.fullOutput = fullOutput;
this.cached = cached; this.cached = cached;
this.whoisRedactedEmailText = whoisRedactedEmailText; this.whoisRedactedEmailText = whoisRedactedEmailText;
this.domainBlockedByBsaTemplate = domainBlockedByBsaTemplate;
} }
@Override @Override
protected Optional<WhoisResponse> getResponse(InternetDomainName domainName, DateTime now) { public final WhoisResponse executeQuery(final DateTime now) throws WhoisException {
Optional<InternetDomainName> tld = findTldForName(domainName);
// Google Registry Policy: Do not return records under TLDs for which we're not
// authoritative.
if (!tld.isPresent() || !getTlds().contains(tld.get().toString())) {
throw new WhoisException(now, SC_NOT_FOUND, ERROR_PREFIX + " not found.");
}
// Include `getResponse` and `isBlockedByBsa` in one transaction to reduce latency.
// Must pass the exceptions outside to throw.
ResponseOrException result =
tm().transact(
() -> {
final Optional<WhoisResponse> response = getResponse(domainName, now);
if (response.isPresent()) {
return ResponseOrException.of(response.get());
}
String label = domainName.parts().get(0);
String tldStr = tld.get().toString();
if (isBlockedByBsa(label, Tld.get(tldStr), now)) {
return ResponseOrException.of(
new WhoisException(
now,
SC_NOT_FOUND,
String.format(domainBlockedByBsaTemplate, domainName)));
}
return ResponseOrException.of(
new WhoisException(now, SC_NOT_FOUND, ERROR_PREFIX + " not found."));
});
return result.returnOrThrow();
}
private Optional<WhoisResponse> getResponse(InternetDomainName domainName, DateTime now) {
Optional<Domain> domainResource = Optional<Domain> domainResource =
cached cached
? loadByForeignKeyCached(Domain.class, domainName.toString(), now) ? loadByForeignKeyCached(Domain.class, domainName.toString(), now)
@ -49,4 +99,29 @@ public class DomainLookupCommand extends DomainOrHostLookupCommand {
return domainResource.map( return domainResource.map(
domain -> new DomainWhoisResponse(domain, fullOutput, whoisRedactedEmailText, now)); domain -> new DomainWhoisResponse(domain, fullOutput, whoisRedactedEmailText, now));
} }
@AutoValue
abstract static class ResponseOrException {
abstract Optional<WhoisResponse> whoisResponse();
abstract Optional<WhoisException> exception();
WhoisResponse returnOrThrow() throws WhoisException {
Verify.verify(
whoisResponse().isPresent() || exception().isPresent(),
"Response and exception must not both be missing.");
return whoisResponse().orElseThrow(() -> exception().get());
}
static ResponseOrException of(WhoisResponse response) {
return new AutoValue_DomainLookupCommand_ResponseOrException(
Optional.of(response), Optional.empty());
}
static ResponseOrException of(WhoisException exception) {
return new AutoValue_DomainLookupCommand_ResponseOrException(
Optional.empty(), Optional.of(exception));
}
}
} }

View file

@ -1,55 +0,0 @@
// Copyright 2017 The Nomulus 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.whois;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.Tlds.getTlds;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.net.InternetDomainName;
import java.util.Optional;
import org.joda.time.DateTime;
/** Represents a WHOIS lookup on a domain name (i.e. SLD) or a nameserver. */
public abstract class DomainOrHostLookupCommand implements WhoisCommand {
@VisibleForTesting final InternetDomainName domainOrHostName;
private final String errorPrefix;
DomainOrHostLookupCommand(InternetDomainName domainName, String errorPrefix) {
this.errorPrefix = errorPrefix;
this.domainOrHostName = checkNotNull(domainName, "domainOrHostName");
}
@Override
public final WhoisResponse executeQuery(final DateTime now) throws WhoisException {
Optional<InternetDomainName> tld = findTldForName(domainOrHostName);
// Google Registry Policy: Do not return records under TLDs for which we're not authoritative.
if (tld.isPresent() && getTlds().contains(tld.get().toString())) {
final Optional<WhoisResponse> response = getResponse(domainOrHostName, now);
if (response.isPresent()) {
return response.get();
}
}
throw new WhoisException(now, SC_NOT_FOUND, errorPrefix + " not found.");
}
/** Renders a response record, provided its successfully retrieved entity. */
protected abstract Optional<WhoisResponse> getResponse(
InternetDomainName domainName, DateTime now);
}

View file

@ -14,26 +14,47 @@
package google.registry.whois; package google.registry.whois;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.EppResourceUtils.loadByForeignKeyCached; import static google.registry.model.EppResourceUtils.loadByForeignKeyCached;
import static google.registry.model.tld.Tlds.findTldForName;
import static google.registry.model.tld.Tlds.getTlds;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import google.registry.model.host.Host; import google.registry.model.host.Host;
import java.util.Optional; import java.util.Optional;
import org.joda.time.DateTime; import org.joda.time.DateTime;
/** Represents a WHOIS lookup on a nameserver based on its hostname. */ /** Represents a WHOIS lookup on a nameserver based on its hostname. */
public class NameserverLookupByHostCommand extends DomainOrHostLookupCommand { public class NameserverLookupByHostCommand implements WhoisCommand {
private static final String ERROR_PREFIX = "Nameserver";
@VisibleForTesting final InternetDomainName hostName;
boolean cached; boolean cached;
NameserverLookupByHostCommand(InternetDomainName hostName, boolean cached) { NameserverLookupByHostCommand(InternetDomainName hostName, boolean cached) {
super(hostName, "Nameserver"); this.hostName = checkNotNull(hostName, "hostName");
this.cached = cached; this.cached = cached;
} }
@Override @Override
protected Optional<WhoisResponse> getResponse(InternetDomainName hostName, DateTime now) { public final WhoisResponse executeQuery(final DateTime now) throws WhoisException {
Optional<InternetDomainName> tld = findTldForName(hostName);
// Google Registry Policy: Do not return records under TLDs for which we're not authoritative.
if (tld.isPresent() && getTlds().contains(tld.get().toString())) {
final Optional<WhoisResponse> response = getResponse(hostName, now);
if (response.isPresent()) {
return response.get();
}
}
throw new WhoisException(now, SC_NOT_FOUND, ERROR_PREFIX + " not found.");
}
private Optional<WhoisResponse> getResponse(InternetDomainName hostName, DateTime now) {
Optional<Host> host = Optional<Host> host =
cached cached
? loadByForeignKeyCached(Host.class, hostName.toString(), now) ? loadByForeignKeyCached(Host.class, hostName.toString(), now)

View file

@ -48,8 +48,12 @@ public class WhoisCommandFactory {
/** Returns a new {@link WhoisCommand} to perform a domain lookup on the specified domain name. */ /** Returns a new {@link WhoisCommand} to perform a domain lookup on the specified domain name. */
public WhoisCommand domainLookup( public WhoisCommand domainLookup(
InternetDomainName domainName, boolean fullOutput, String whoisRedactedEmailText) { InternetDomainName domainName,
return new DomainLookupCommand(domainName, fullOutput, cached, whoisRedactedEmailText); boolean fullOutput,
String whoisRedactedEmailText,
String domainBlockedByBsaTemplate) {
return new DomainLookupCommand(
domainName, fullOutput, cached, whoisRedactedEmailText, domainBlockedByBsaTemplate);
} }
/** /**

View file

@ -75,14 +75,17 @@ class WhoisReader {
private final WhoisCommandFactory commandFactory; private final WhoisCommandFactory commandFactory;
private final String whoisRedactedEmailText; private final String whoisRedactedEmailText;
private final String domainBlockedByBsaTemplate;
/** Creates a new WhoisReader that extracts its command from the specified Reader. */ /** Creates a new WhoisReader that extracts its command from the specified Reader. */
@Inject @Inject
WhoisReader( WhoisReader(
@Config("whoisCommandFactory") WhoisCommandFactory commandFactory, @Config("whoisCommandFactory") WhoisCommandFactory commandFactory,
@Config("whoisRedactedEmailText") String whoisRedactedEmailText) { @Config("whoisRedactedEmailText") String whoisRedactedEmailText,
@Config("domainBlockedByBsaTemplate") String domainBlockedByBsaTemplate) {
this.commandFactory = commandFactory; this.commandFactory = commandFactory;
this.whoisRedactedEmailText = whoisRedactedEmailText; this.whoisRedactedEmailText = whoisRedactedEmailText;
this.domainBlockedByBsaTemplate = domainBlockedByBsaTemplate;
} }
/** /**
@ -124,7 +127,8 @@ class WhoisReader {
return commandFactory.domainLookup( return commandFactory.domainLookup(
InternetDomainName.from(canonicalizeHostname(tokens.get(1))), InternetDomainName.from(canonicalizeHostname(tokens.get(1))),
fullOutput, fullOutput,
whoisRedactedEmailText); whoisRedactedEmailText,
domainBlockedByBsaTemplate);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
// If we can't interpret the argument as a host name, then return an error. // If we can't interpret the argument as a host name, then return an error.
throw new WhoisException(now, SC_BAD_REQUEST, String.format( throw new WhoisException(now, SC_BAD_REQUEST, String.format(
@ -202,7 +206,8 @@ class WhoisReader {
// (SLD) and we should do a domain lookup on it. // (SLD) and we should do a domain lookup on it.
if (targetName.parent().equals(tld.get())) { if (targetName.parent().equals(tld.get())) {
logger.atInfo().log("Attempting domain lookup using %s as a domain name.", targetName); logger.atInfo().log("Attempting domain lookup using %s as a domain name.", targetName);
return commandFactory.domainLookup(targetName, fullOutput, whoisRedactedEmailText); return commandFactory.domainLookup(
targetName, fullOutput, whoisRedactedEmailText, domainBlockedByBsaTemplate);
} }
// The target is more than one level above the TLD, so we'll assume it's a nameserver. // The target is more than one level above the TLD, so we'll assume it's a nameserver.

View file

@ -16,6 +16,7 @@ package google.registry.whois;
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.bsa.persistence.BsaLabelTestingUtils.persistBsaLabel;
import static google.registry.model.EppResourceUtils.loadByForeignKeyCached; import static google.registry.model.EppResourceUtils.loadByForeignKeyCached;
import static google.registry.model.registrar.Registrar.State.ACTIVE; import static google.registry.model.registrar.Registrar.State.ACTIVE;
import static google.registry.model.registrar.Registrar.Type.PDT; import static google.registry.model.registrar.Registrar.Type.PDT;
@ -61,6 +62,7 @@ import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.time.Duration; import java.time.Duration;
import java.util.Optional;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
@ -91,7 +93,8 @@ public class WhoisActionTest {
whoisAction.input = new StringReader(input); whoisAction.input = new StringReader(input);
whoisAction.response = response; whoisAction.response = response;
whoisAction.whoisReader = whoisAction.whoisReader =
new WhoisReader(WhoisCommandFactory.createCached(), "Please contact registrar"); new WhoisReader(
WhoisCommandFactory.createCached(), "Please contact registrar", "Blocked by BSA: %s");
whoisAction.whoisMetrics = new WhoisMetrics(); whoisAction.whoisMetrics = new WhoisMetrics();
whoisAction.metricBuilder = WhoisMetric.builderForRequest(clock); whoisAction.metricBuilder = WhoisMetric.builderForRequest(clock);
whoisAction.disclaimer = whoisAction.disclaimer =
@ -164,6 +167,37 @@ public class WhoisActionTest {
assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain.txt")); assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain.txt"));
} }
@Test
void testRun_domainQuery_registeredDomainUnaffectedByBsa() {
persistResource(
Tld.get("lol")
.asBuilder()
.setBsaEnrollStartTime(Optional.of(clock.nowUtc().minusDays(1)))
.build());
persistBsaLabel("cat", clock.nowUtc());
Registrar registrar = persistResource(makeRegistrar("evilregistrar", "Yes Virginia", ACTIVE));
persistResource(makeDomainWithRegistrar(registrar));
persistSimpleResources(makeRegistrarPocs(registrar));
newWhoisAction("domain cat.lol\r\n").run();
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain.txt"));
}
@Test
void testRun_domainQuery_unregisteredDomainShowBsaMessage() {
persistResource(
Tld.get("lol")
.asBuilder()
.setBsaEnrollStartTime(Optional.of(clock.nowUtc().minusDays(1)))
.build());
persistBsaLabel("cat", clock.nowUtc());
newWhoisAction("domain cat.lol\r\n").run();
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain_blocked_by_bsa.txt"));
}
@Test @Test
void testRun_domainAfterTransfer_hasUpdatedEppTimeAndClientId() { void testRun_domainAfterTransfer_hasUpdatedEppTimeAndClientId() {
Registrar registrar = persistResource(makeRegistrar("TheRegistrar", "Yes Virginia", ACTIVE)); Registrar registrar = persistResource(makeRegistrar("TheRegistrar", "Yes Virginia", ACTIVE));

View file

@ -142,7 +142,8 @@ class WhoisCommandFactoryTest {
void testNonCached_DomainLookupCommand() throws Exception { void testNonCached_DomainLookupCommand() throws Exception {
WhoisResponse response = WhoisResponse response =
noncachedFactory noncachedFactory
.domainLookup(InternetDomainName.from("example.tld"), true, "REDACTED") .domainLookup(
InternetDomainName.from("example.tld"), true, "REDACTED", "Blocked by BSA")
.executeQuery(clock.nowUtc()); .executeQuery(clock.nowUtc());
assertThat(response.getResponse(false, "").plainTextOutput()) assertThat(response.getResponse(false, "").plainTextOutput())
.contains("Registrar: The Registrar"); .contains("Registrar: The Registrar");
@ -156,7 +157,8 @@ class WhoisCommandFactoryTest {
.build())); .build()));
response = response =
noncachedFactory noncachedFactory
.domainLookup(InternetDomainName.from("example.tld"), true, "REDACTED") .domainLookup(
InternetDomainName.from("example.tld"), true, "REDACTED", "Blocked by BSA")
.executeQuery(clock.nowUtc()); .executeQuery(clock.nowUtc());
assertThat(response.getResponse(false, "").plainTextOutput()) assertThat(response.getResponse(false, "").plainTextOutput())
.contains("Registrar: OtherRegistrar name"); .contains("Registrar: OtherRegistrar name");
@ -166,7 +168,7 @@ class WhoisCommandFactoryTest {
void testCached_DomainLookupCommand() throws Exception { void testCached_DomainLookupCommand() throws Exception {
WhoisResponse response = WhoisResponse response =
cachedFactory cachedFactory
.domainLookup(InternetDomainName.from("example.tld"), true, "REDACTED") .domainLookup(InternetDomainName.from("example.tld"), true, "REDACTED", "Not tested")
.executeQuery(clock.nowUtc()); .executeQuery(clock.nowUtc());
assertThat(response.getResponse(false, "").plainTextOutput()) assertThat(response.getResponse(false, "").plainTextOutput())
.contains("Registrar: The Registrar"); .contains("Registrar: The Registrar");
@ -180,7 +182,8 @@ class WhoisCommandFactoryTest {
.build())); .build()));
response = response =
cachedFactory cachedFactory
.domainLookup(InternetDomainName.from("example.tld"), true, "REDACTED") .domainLookup(
InternetDomainName.from("example.tld"), true, "REDACTED", "Blocked by BSA")
.executeQuery(clock.nowUtc()); .executeQuery(clock.nowUtc());
assertThat(response.getResponse(false, "").plainTextOutput()) assertThat(response.getResponse(false, "").plainTextOutput())
.contains("Registrar: The Registrar"); .contains("Registrar: The Registrar");

View file

@ -16,6 +16,8 @@ package google.registry.whois;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.bsa.persistence.BsaLabelTestingUtils.persistBsaLabel;
import static google.registry.model.registrar.Registrar.State.ACTIVE;
import static google.registry.testing.DatabaseHelper.createTlds; import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.DatabaseHelper.loadRegistrar; import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DatabaseHelper.persistResource;
@ -45,6 +47,7 @@ import google.registry.testing.FullFieldsTestEntityHelper;
import google.registry.whois.WhoisMetrics.WhoisMetric; import google.registry.whois.WhoisMetrics.WhoisMetric;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.Optional;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -74,7 +77,8 @@ class WhoisHttpActionTest {
whoisAction.requestPath = WhoisHttpAction.PATH + pathInfo; whoisAction.requestPath = WhoisHttpAction.PATH + pathInfo;
whoisAction.response = response; whoisAction.response = response;
whoisAction.whoisReader = whoisAction.whoisReader =
new WhoisReader(WhoisCommandFactory.createCached(), "Please contact registrar"); new WhoisReader(
WhoisCommandFactory.createCached(), "Please contact registrar", "Blocked by BSA: %s");
whoisAction.whoisMetrics = new WhoisMetrics(); whoisAction.whoisMetrics = new WhoisMetrics();
whoisAction.metricBuilder = WhoisMetric.builderForRequest(clock); whoisAction.metricBuilder = WhoisMetric.builderForRequest(clock);
whoisAction.disclaimer = whoisAction.disclaimer =
@ -214,6 +218,51 @@ class WhoisHttpActionTest {
assertThat(response.getPayload()).contains("Domain Name: cat.みんな\r\n"); assertThat(response.getPayload()).contains("Domain Name: cat.みんな\r\n");
} }
@Test
void testRun_domainQuery_registeredDomainUnaffectedByBsa() {
persistResource(
Tld.get("lol")
.asBuilder()
.setBsaEnrollStartTime(Optional.of(clock.nowUtc().minusDays(1)))
.build());
persistBsaLabel("cat", clock.nowUtc());
Registrar registrar = persistResource(makeRegistrar("evilregistrar", "Yes Virginia", ACTIVE));
persistResource(
makeDomain(
"cat.lol",
persistResource(
FullFieldsTestEntityHelper.makeContact(
"5372808-ERL", "Goblin Market", "lol@cat.lol")),
persistResource(
FullFieldsTestEntityHelper.makeContact(
"5372808-IRL", "Santa Claus", "BOFH@cat.lol")),
persistResource(
FullFieldsTestEntityHelper.makeContact("5372808-TRL", "The Raven", "bog@cat.lol")),
persistResource(FullFieldsTestEntityHelper.makeHost("ns1.cat.lol", "1.2.3.4")),
persistResource(
FullFieldsTestEntityHelper.makeHost("ns2.cat.lol", "bad:f00d:cafe::15:beef")),
registrar));
persistSimpleResources(makeRegistrarPocs(registrar));
newWhoisHttpAction("domain cat.lol\r\n").run();
assertThat(response.getStatus()).isEqualTo(200);
assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain.txt"));
}
@Test
void testRun_domainQuery_unregisteredDomainShowBsaMessage() {
persistResource(
Tld.get("lol")
.asBuilder()
.setBsaEnrollStartTime(Optional.of(clock.nowUtc().minusDays(1)))
.build());
persistBsaLabel("cat", clock.nowUtc());
newWhoisHttpAction("domain cat.lol\r\n").run();
assertThat(response.getStatus()).isEqualTo(404);
assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain_blocked_by_bsa.txt"));
}
@Test @Test
void testRun_hostnameOnly_works() { void testRun_hostnameOnly_works() {
persistResource(FullFieldsTestEntityHelper.makeHost("ns1.cat.みんな", "1.2.3.4")); persistResource(FullFieldsTestEntityHelper.makeHost("ns1.cat.みんな", "1.2.3.4"));

View file

@ -49,28 +49,29 @@ class WhoisReaderTest {
@SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"}) @SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
<T> T readCommand(String commandStr) throws Exception { <T> T readCommand(String commandStr) throws Exception {
return (T) return (T)
new WhoisReader(WhoisCommandFactory.createCached(), "Please contact registrar") new WhoisReader(
WhoisCommandFactory.createCached(), "Please contact registrar", "Blocked by BSA")
.readCommand(new StringReader(commandStr), false, clock.nowUtc()); .readCommand(new StringReader(commandStr), false, clock.nowUtc());
} }
void assertLoadsExampleTld(String commandString) throws Exception { void assertLoadsExampleTld(String commandString) throws Exception {
DomainLookupCommand command = readCommand(commandString); DomainLookupCommand command = readCommand(commandString);
assertThat(command.domainOrHostName.toString()).isEqualTo("example.tld"); assertThat(command.domainName.toString()).isEqualTo("example.tld");
} }
void assertLoadsIDN(String commandString) throws Exception { void assertLoadsIDN(String commandString) throws Exception {
DomainLookupCommand command = readCommand(commandString); DomainLookupCommand command = readCommand(commandString);
assertThat(command.domainOrHostName.toString()).isEqualTo("xn--mgbh0fb.xn--kgbechtv"); assertThat(command.domainName.toString()).isEqualTo("xn--mgbh0fb.xn--kgbechtv");
} }
void assertLoadsExampleNs(String commandString) throws Exception { void assertLoadsExampleNs(String commandString) throws Exception {
NameserverLookupByHostCommand command = readCommand(commandString); NameserverLookupByHostCommand command = readCommand(commandString);
assertThat(command.domainOrHostName.toString()).isEqualTo("ns.example.tld"); assertThat(command.hostName.toString()).isEqualTo("ns.example.tld");
} }
void assertLoadsIDNNs(String commandString) throws Exception { void assertLoadsIDNNs(String commandString) throws Exception {
NameserverLookupByHostCommand command = readCommand(commandString); NameserverLookupByHostCommand command = readCommand(commandString);
assertThat(command.domainOrHostName.toString()).isEqualTo("ns.xn--mgbh0fb.xn--kgbechtv"); assertThat(command.hostName.toString()).isEqualTo("ns.xn--mgbh0fb.xn--kgbechtv");
} }
void assertNsLookup(String commandString, String expectedIpAddress) throws Exception { void assertNsLookup(String commandString, String expectedIpAddress) throws Exception {
@ -173,8 +174,8 @@ class WhoisReaderTest {
@Test @Test
void testDeepNameserverLookup() throws Exception { void testDeepNameserverLookup() throws Exception {
NameserverLookupByHostCommand command = readCommand("ns.foo.bar.baz.example.tld\r\n"); NameserverLookupByHostCommand command = readCommand("ns.foo.bar.baz.example.tld\r\n");
assertThat(command.domainOrHostName.toString()).isEqualTo("ns.foo.bar.baz.example.tld"); assertThat(command.hostName.toString()).isEqualTo("ns.foo.bar.baz.example.tld");
assertThat(command.domainOrHostName.toString()).isEqualTo("ns.foo.bar.baz.example.tld"); assertThat(command.hostName.toString()).isEqualTo("ns.foo.bar.baz.example.tld");
} }
@Test @Test

View file

@ -0,0 +1,6 @@
Blocked by BSA: cat.lol
>>> Last update of WHOIS database: 2009-06-29T20:13:00Z <<<
Doodle Disclaimer
I exist so that carriage return
in disclaimer can be tested.