1
0
mirror of https://github.com/google/nomulus synced 2026-06-09 16:33:02 +00:00

Compare commits

..

13 Commits

Author SHA1 Message Date
Ben McIlwain 9479e1e8b9 Rename Spec11 reply-to email and also use it as sending address (#201)
* Rename Spec11 reply-to email and also use it as sending address
2019-07-26 15:30:46 -04:00
Shicong Huang 110bd9c057 Fix deploying to alpha from workstation (#198)
appengineDeployAll requires appengine.deploy.version to be set
otherwiese the deployment would fail.
2019-07-26 14:37:49 -04:00
Lai Jiang 2ae5aba7ff Rename dependency_license.gradle file (#196)
The file name confused the licensee app
(https://github.com/licensee/licensee) that GitHub uses to detect
license files. It thinks this file is also a license file and was not
able to determine is type.
2019-07-26 14:19:08 -04:00
Lai Jiang b878e5acc1 Remove port to protocol map (#200)
There's no need for it. We can get the port from the protocol.
2019-07-25 22:05:12 -04:00
gbrodman 4d0409c924 Add HTML lang tags where possible (#199) 2019-07-25 21:09:32 -04:00
gbrodman 0292887cb9 Store only interesting failures, not login failures (#188)
Login failures will happen any time that we aren't coming from a
whitelisted IP for that particular TLD. Since whitelists are out of date
(and we don't whitelist IPs for every TLD anyway) those failures aren't
interesting. Store and fully-log the interesting failures if one
happened.
2019-07-24 10:55:55 -04:00
Lai Jiang 464f6ba90a Add a missing space (#197) 2019-07-24 10:50:27 -04:00
Lai Jiang 0ab0a8c2e6 Use positive booleans to improve readability (#190)
This allows us to use lgtm.com to scan for vulnerabilities.
2019-07-23 22:30:46 -04:00
Lai Jiang 2cc4e5fa94 Add a badge for LGTM analysis results (#194) 2019-07-23 21:42:19 -04:00
gbrodman 47a890253e Revert "Use parallel Gradle builds by default (#189)" (#195)
This reverts commit 5dfd96d26d.
2019-07-23 18:12:04 -04:00
Lai Jiang b452b0628d Add customized .lgtm.yml (#191)
* Add customized .lgtm.yml
2019-07-23 17:09:05 -04:00
gbrodman 5dfd96d26d Use parallel Gradle builds by default (#189) 2019-07-23 15:27:30 -04:00
Shicong Huang e2a673d914 Bring back the old GoogleCredential for Drive API (#187)
Using the new GoogleCredentials to access Drive API caused 403 forbidden
exception. So, this PR brought back the old GoogleCredential to
temporarily resolve the production issue while we are figuring out the
long term fix.

TESTED=Deployed to alpha and verified exportPremiumTerms succeeded, see
https://paste.googleplex.com/6153215760400384.
2019-07-23 11:31:35 -04:00
23 changed files with 177 additions and 103 deletions
+4
View File
@@ -0,0 +1,4 @@
extraction:
java:
prepare:
packages: "npm"
+3 -3
View File
@@ -1,8 +1,8 @@
# Nomulus
| Internal Build | FOSS Build | License | Code Search |
|----------------|------------|---------|-------------|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[![Build Status for the open source build](https://travis-ci.org/google/nomulus.svg?branch=master)](https://travis-ci.org/google/nomulus)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Source Graph](https://github.com/sourcegraph/sourcegraph/blob/master/ui/assets/img/sourcegraph-logo.svg)](https://sourcegraph.com/github.com/google/nomulus)|
| Internal Build | FOSS Build | LGTM | License | Code Search |
|----------------|------------|------|---------|-------------|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/index.html)|[![Build Status for the open source build](https://travis-ci.org/google/nomulus.svg?branch=master)](https://travis-ci.org/google/nomulus)|[![Total alerts](https://img.shields.io/lgtm/alerts/g/google/nomulus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/google/nomulus/alerts/)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Source Graph](https://github.com/sourcegraph/sourcegraph/blob/master/ui/assets/img/sourcegraph-logo.svg)](https://sourcegraph.com/github.com/google/nomulus)|
![Nomulus logo](./nomulus-logo.png)
+6
View File
@@ -75,6 +75,12 @@ if (project.path == ":services:default") {
appengine {
deploy {
// appengineDeployAll task requires the version to be set. So,
// this config lets gcloud select a version name when deploying
// to alpha from our workstation.
if (environment != 'production' && environment != 'sandbox') {
version = 'GCLOUD_CONFIG'
}
projectId = gcpProject
}
}
+4 -4
View File
@@ -13,7 +13,7 @@
// limitations under the License.
buildscript {
if (project.disableDependencyLocking.toBoolean() == false) {
if (rootProject.enableDependencyLocking.toBoolean()) {
// Lock buildscript dependencies.
configurations.classpath {
resolutionStrategy.activateDependencyLocking()
@@ -75,7 +75,7 @@ reportUploader {
apply from: 'dependencies.gradle'
apply from: 'dependency_license.gradle'
apply from: 'dependency_lic.gradle'
// Custom task to run checkLicense in buildSrc, which is not triggered
// by root project tasks. A shell task is used because buildSrc tasks
@@ -169,7 +169,7 @@ subprojects {
}
}
if (rootProject.disableDependencyLocking.toBoolean() == false) {
if (rootProject.enableDependencyLocking.toBoolean()) {
buildscript {
// Lock buildscript dependencies.
configurations.classpath {
@@ -177,7 +177,7 @@ subprojects {
}
}
// Lock application dependencies except for the gradle-license-report
// plugin. See dependency_license.gradle for more information.
// plugin. See dependency_lic.gradle for more information.
configurations.findAll { it.name != 'dependencyLicenseReport' }.each {
it.resolutionStrategy.activateDependencyLocking()
}
+3 -3
View File
@@ -13,7 +13,7 @@
// limitations under the License.
buildscript {
if (rootProject.disableDependencyLocking.toBoolean() == false) {
if (project.enableDependencyLocking.toBoolean()) {
// Lock buildscript dependencies.
configurations.classpath {
resolutionStrategy.activateDependencyLocking()
@@ -32,7 +32,7 @@ plugins {
id 'com.diffplug.gradle.spotless' version '3.18.0'
}
if (rootProject.disableDependencyLocking.toBoolean() == false) {
if (rootProject.enableDependencyLocking.toBoolean()) {
// Lock application dependencies.
dependencyLocking {
lockAllConfigurations()
@@ -52,7 +52,7 @@ repositories {
}
apply from: '../dependencies.gradle'
apply from: '../dependency_license.gradle'
apply from: '../dependency_lic.gradle'
apply from: '../java_common.gradle'
sourceSets {
+1 -1
View File
@@ -1 +1 @@
disableDependencyLocking=false
enableDependencyLocking=false
@@ -16,6 +16,7 @@ package google.registry.config;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.collect.ImmutableList;
import dagger.Module;
@@ -68,6 +69,29 @@ public abstract class CredentialModule {
return GoogleCredentialsBundle.create(credential);
}
/**
* Provides the default {@link GoogleCredential} from the Google Cloud runtime for G Suite
* Drive API.
* TODO(b/138195359): Deprecate this credential once we figure out how to use
* {@link GoogleCredentials} for G Suite Drive API.
*/
@GSuiteDriveCredential
@Provides
@Singleton
public static GoogleCredential provideGSuiteDriveCredential(
@Config("defaultCredentialOauthScopes") ImmutableList<String> requiredScopes) {
GoogleCredential credential;
try {
credential = GoogleCredential.getApplicationDefault();
} catch (IOException e) {
throw new RuntimeException(e);
}
if (credential.createScopedRequired()) {
credential = credential.createScoped(requiredScopes);
}
return credential;
}
/**
* Provides a {@link GoogleCredentialsBundle} from the service account's JSON key file.
*
@@ -118,6 +142,13 @@ public abstract class CredentialModule {
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultCredential {}
/** Dagger qualifier for the credential for G Suite Drive API. */
@Qualifier
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface GSuiteDriveCredential {}
/**
* Dagger qualifier for a credential from a service account's JSON key, to be used in non-request
* threads.
@@ -894,9 +894,9 @@ public final class RegistryConfig {
* @see google.registry.reporting.spec11.Spec11EmailUtils
*/
@Provides
@Config("spec11ReplyToEmailAddress")
public static InternetAddress provideSpec11ReplyToEmailAddress(RegistryConfigSettings config) {
return parseEmailAddress(config.misc.spec11ReplyToEmailAddress);
@Config("spec11OutgoingEmailAddress")
public static InternetAddress provideSpec11OutgoingEmailAddress(RegistryConfigSettings config) {
return parseEmailAddress(config.misc.spec11OutgoingEmailAddress);
}
/**
@@ -173,7 +173,7 @@ public class RegistryConfigSettings {
public static class Misc {
public String sheetExportId;
public String alertRecipientEmailAddress;
public String spec11ReplyToEmailAddress;
public String spec11OutgoingEmailAddress;
public int asyncDeleteDelaySeconds;
public int transientFailureRetries;
}
@@ -357,9 +357,9 @@ misc:
# Address we send alert summary emails to.
alertRecipientEmailAddress: email@example.com
# Address to which the Spec 11 emails to registrars should be replied. This needs
# to be a deliverable email address in case the registrars want to contact us.
spec11ReplyToEmailAddress: reply-to@example.com
# Address from which Spec 11 emails to registrars are sent. This needs
# to be a deliverable email address to handle replies from registrars as well.
spec11OutgoingEmailAddress: abuse@example.com
# How long to delay processing of asynchronous deletions. This should always
# be longer than eppResourceCachingSeconds, to prevent deleted contacts or
@@ -14,16 +14,16 @@
package google.registry.export;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.drive.Drive;
import dagger.Component;
import dagger.Module;
import dagger.Provides;
import google.registry.config.CredentialModule;
import google.registry.config.CredentialModule.DefaultCredential;
import google.registry.config.CredentialModule.GSuiteDriveCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.storage.drive.DriveConnection;
import google.registry.util.GoogleCredentialsBundle;
import javax.inject.Singleton;
/** Dagger module for Google {@link Drive} service connection objects. */
@@ -32,13 +32,13 @@ public final class DriveModule {
@Provides
static Drive provideDrive(
@DefaultCredential GoogleCredentialsBundle credentialsBundle,
@GSuiteDriveCredential GoogleCredential googleCredential,
@Config("projectId") String projectId) {
return new Drive.Builder(
credentialsBundle.getHttpTransport(),
credentialsBundle.getJsonFactory(),
credentialsBundle.getHttpRequestInitializer())
googleCredential.getTransport(),
googleCredential.getJsonFactory(),
googleCredential)
.setApplicationName(projectId)
.build();
}
@@ -92,27 +92,23 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
@Inject
UpdateRegistrarRdapBaseUrlsAction() {}
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) {
try {
logger.atInfo().log("Logging in to MoSAPI");
HttpRequest request =
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
HttpResponse response = request.execute();
private String loginAndGetId(HttpRequestFactory requestFactory, String tld) throws IOException {
logger.atInfo().log("Logging in to MoSAPI");
HttpRequest request =
requestFactory.buildGetRequest(new GenericUrl(String.format(LOGIN_URL, tld)));
request.getHeaders().setBasicAuthentication(String.format("%s_ry", tld), password);
HttpResponse response = request.execute();
Optional<HttpCookie> idCookie =
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
.findAny();
checkState(
idCookie.isPresent(),
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
response.getStatusCode(),
response.getHeaders());
return idCookie.get().getValue();
} catch (IOException e) {
throw new UncheckedIOException("Error logging in to MoSAPI server: " + e.getMessage(), e);
}
Optional<HttpCookie> idCookie =
HttpCookie.parse(response.getHeaders().getFirstHeaderStringValue("Set-Cookie")).stream()
.filter(cookie -> cookie.getName().equals(COOKIE_ID))
.findAny();
checkState(
idCookie.isPresent(),
"Didn't get the ID cookie from the login response. Code: %s, headers: %s",
response.getStatusCode(),
response.getHeaders());
return idCookie.get().getValue();
}
private void logout(HttpRequestFactory requestFactory, String id, String tld) {
@@ -128,9 +124,8 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
}
}
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(String tld) {
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
String id = loginAndGetId(requestFactory, tld);
private ImmutableSetMultimap<String, String> getRdapBaseUrlsPerIanaIdWithTld(
String tld, String id, HttpRequestFactory requestFactory) {
String content;
try {
HttpRequest request =
@@ -173,11 +168,22 @@ public final class UpdateRegistrarRdapBaseUrlsAction implements Runnable {
checkArgument(!tlds.isEmpty(), "There must exist at least one REAL TLD.");
Throwable finalThrowable = null;
for (String tld : tlds) {
HttpRequestFactory requestFactory = httpTransport.createRequestFactory();
String id;
try {
return getRdapBaseUrlsPerIanaIdWithTld(tld);
id = loginAndGetId(requestFactory, tld);
} catch (Throwable e) {
// Login failures are bad but not unexpected for certain TLDs. We shouldn't store those
// but rather should only store useful Throwables.
logger.atWarning().log("Error logging in to MoSAPI server: " + e.getMessage(), e);
continue;
}
try {
return getRdapBaseUrlsPerIanaIdWithTld(tld, id, requestFactory);
} catch (Throwable throwable) {
logger.atWarning().log(String
.format("Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
logger.atWarning().log(
String.format(
"Error retrieving RDAP urls with TLD %s: %s", tld, throwable.getMessage()));
finalThrowable = throwable;
}
}
@@ -59,22 +59,19 @@ public class Spec11EmailUtils {
private final SendEmailService emailService;
private final InternetAddress outgoingEmailAddress;
private final InternetAddress alertRecipientAddress;
private final InternetAddress spec11ReplyToAddress;
private final ImmutableList<String> spec11WebResources;
private final String registryName;
@Inject
Spec11EmailUtils(
SendEmailService emailService,
@Config("gSuiteOutgoingEmailAddress") InternetAddress outgoingEmailAddress,
@Config("alertRecipientEmailAddress") InternetAddress alertRecipientAddress,
@Config("spec11ReplyToEmailAddress") InternetAddress spec11ReplyToAddress,
@Config("spec11OutgoingEmailAddress") InternetAddress spec11OutgoingEmailAddress,
@Config("spec11WebResources") ImmutableList<String> spec11WebResources,
@Config("registryName") String registryName) {
this.emailService = emailService;
this.outgoingEmailAddress = outgoingEmailAddress;
this.outgoingEmailAddress = spec11OutgoingEmailAddress;
this.alertRecipientAddress = alertRecipientAddress;
this.spec11ReplyToAddress = spec11ReplyToAddress;
this.spec11WebResources = spec11WebResources;
this.registryName = registryName;
}
@@ -149,7 +146,7 @@ public class Spec11EmailUtils {
.setContentType(MediaType.HTML_UTF_8)
.setFrom(outgoingEmailAddress)
.addRecipient(getEmailAddressForRegistrar(registrarThreatMatches.clientId()))
.setBcc(spec11ReplyToAddress)
.setBcc(outgoingEmailAddress)
.build());
}
@@ -172,7 +169,7 @@ public class Spec11EmailUtils {
ImmutableMap.of(
"date", date.toString(),
"registry", registryName,
"replyToEmail", spec11ReplyToAddress.getAddress(),
"replyToEmail", outgoingEmailAddress.getAddress(),
"threats", threatMatchMap,
"resources", spec11WebResources);
renderer.setData(data);
@@ -52,7 +52,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
@Parameter(
names = {"--contact"},
description = "Contact ID for the request. This will be used for registrant, admin contact,"
description = "Contact ID for the request. This will be used for registrant, admin contact, "
+ "and tech contact.",
required = true)
private String contact;
@@ -1,6 +1,6 @@
<!doctype html>
<meta http-equiv="refresh" content="0;URL=/registrar">
<title>Nomulus</title>
<body>
<body lang="en-US">
If this page doesn't change automatically, please go
to <a href="/registrar">https://www.registry.google/registrar</a>
@@ -69,7 +69,7 @@
{@param logoutUrl: string}
{@param logoFilename: string}
{@param productName: string}
<div id="kd-googlebar" role="banner">
<div id="kd-googlebar" role="banner" lang="en-US">
<a class="{css('logo')}" href="/registrar">
<img src="/assets/images/{$logoFilename}" alt="{$productName}">
</a>
@@ -43,7 +43,7 @@
{param analyticsConfig: $analyticsConfig /}
{/call}
{call registry.soy.console.googlebar data="all" /}
<div id="reg-app">
<div id="reg-app" lang="en-US">
<div id="reg-appbar" class="{css('kd-appbar')}">
<div class="{css('kd-description')}">
Accessing <span class="{css('kd-value')}">{$clientId}</span> as{sp}
@@ -29,6 +29,7 @@ import com.google.api.client.testing.http.MockLowLevelHttpRequest;
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonSyntaxException;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.RegistrarAddress;
import google.registry.model.registry.Registry;
@@ -276,6 +277,44 @@ public final class UpdateRegistrarRdapBaseUrlsActionTest extends ShardableTestCa
.isEqualTo("Error contacting MosAPI server. Tried TLDs [secondtld, tld]");
}
@Test
public void testFailureCause_ignoresLoginFailure() {
// Login failures aren't particularly interesting so we should log them, but the final
// throwable should be some other failure if one existed
createTld("secondtld");
httpTransport = new TestHttpTransport();
action.httpTransport = 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 badListResponse = new MockLowLevelHttpResponse();
String badListReply = JSON_LIST_REPLY.substring(50);
badListResponse.setContent(badListReply);
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");
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(loginResponse);
httpTransport.addNextResponse(badListResponse);
httpTransport.addNextResponse(logoutResponse);
httpTransport.addNextResponse(badLoginResponse);
assertThat(assertThrows(RuntimeException.class, action::run))
.hasCauseThat()
.isInstanceOf(JsonSyntaxException.class);
}
private static void addValidResponses(TestHttpTransport httpTransport) {
MockLowLevelHttpResponse loginResponse = new MockLowLevelHttpResponse();
loginResponse.addHeader(
@@ -87,7 +87,7 @@ public class Spec11EmailUtilsTest {
+ "update your abuse contact using your registrar portal account.</p>"
+ ""
+ "<p>If you have any questions regarding this notice, please contact "
+ "my-reply-to@test.com.</p>";
+ "abuse@test.com.</p>";
private static final String MONTHLY_EMAIL_FORMAT =
"Dear registrar partner,"
+ ""
@@ -117,7 +117,7 @@ public class Spec11EmailUtilsTest {
+ "our monthly reporting.</p>"
+ ""
+ "<p>If you have any questions regarding this notice, please contact "
+ "my-reply-to@test.com.</p>";
+ "abuse@test.com.</p>";
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@@ -139,9 +139,8 @@ public class Spec11EmailUtilsTest {
emailUtils =
new Spec11EmailUtils(
emailService,
new InternetAddress("my-sender@test.com"),
new InternetAddress("my-receiver@test.com"),
new InternetAddress("my-reply-to@test.com"),
new InternetAddress("abuse@test.com"),
FAKE_RESOURCES,
"Super Cool Registry");
@@ -164,17 +163,17 @@ public class Spec11EmailUtilsTest {
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
validateMessage(
capturedContents.get(0),
"my-sender@test.com",
"abuse@test.com",
"the.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
String.format(MONTHLY_EMAIL_FORMAT, "<tr><td>a.com</td><td>MALWARE</td></tr>"),
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(1),
"my-sender@test.com",
"abuse@test.com",
"new.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
String.format(
MONTHLY_EMAIL_FORMAT,
@@ -182,7 +181,7 @@ public class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(2),
"my-sender@test.com",
"abuse@test.com",
"my-receiver@test.com",
Optional.empty(),
"Spec11 Pipeline Success 2018-07-15",
@@ -202,17 +201,17 @@ public class Spec11EmailUtilsTest {
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
validateMessage(
capturedMessages.get(0),
"my-sender@test.com",
"abuse@test.com",
"the.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Daily Threat Detector [2018-07-15]",
String.format(DAILY_EMAIL_FORMAT, "<tr><td>a.com</td><td>MALWARE</td></tr>"),
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(1),
"my-sender@test.com",
"abuse@test.com",
"new.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Daily Threat Detector [2018-07-15]",
String.format(
DAILY_EMAIL_FORMAT,
@@ -220,7 +219,7 @@ public class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(2),
"my-sender@test.com",
"abuse@test.com",
"my-receiver@test.com",
Optional.empty(),
"Spec11 Pipeline Success 2018-07-15",
@@ -247,15 +246,15 @@ public class Spec11EmailUtilsTest {
List<EmailMessage> capturedContents = contentCaptor.getAllValues();
validateMessage(
capturedContents.get(0),
"my-sender@test.com",
"abuse@test.com",
"new.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
String.format(MONTHLY_EMAIL_FORMAT, "<tr><td>c.com</td><td>MALWARE</td></tr>"),
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedContents.get(1),
"my-sender@test.com",
"abuse@test.com",
"my-receiver@test.com",
Optional.empty(),
"Spec11 Pipeline Success 2018-07-15",
@@ -292,17 +291,17 @@ public class Spec11EmailUtilsTest {
List<EmailMessage> capturedMessages = contentCaptor.getAllValues();
validateMessage(
capturedMessages.get(0),
"my-sender@test.com",
"abuse@test.com",
"the.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
String.format(MONTHLY_EMAIL_FORMAT, "<tr><td>a.com</td><td>MALWARE</td></tr>"),
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(1),
"my-sender@test.com",
"abuse@test.com",
"new.registrar@example.com",
Optional.of("my-reply-to@test.com"),
Optional.of("abuse@test.com"),
"Super Cool Registry Monthly Threat Detector [2018-07-15]",
String.format(
MONTHLY_EMAIL_FORMAT,
@@ -310,7 +309,7 @@ public class Spec11EmailUtilsTest {
Optional.of(MediaType.HTML_UTF_8));
validateMessage(
capturedMessages.get(2),
"my-sender@test.com",
"abuse@test.com",
"my-receiver@test.com",
Optional.empty(),
"Spec11 Emailing Failure 2018-07-15",
@@ -324,7 +323,7 @@ public class Spec11EmailUtilsTest {
verify(emailService).sendEmail(contentCaptor.capture());
validateMessage(
contentCaptor.getValue(),
"my-sender@test.com",
"abuse@test.com",
"my-receiver@test.com",
Optional.empty(),
"Spec11 Pipeline Alert: 2018-07",
+1 -1
View File
@@ -4,4 +4,4 @@ uploaderDestination=
uploaderCredentialsFile=
uploaderMultithreadedUpload=
flowDocsFile=
disableDependencyLocking=false
enableDependencyLocking=true
@@ -25,8 +25,6 @@ import com.google.api.services.cloudkms.v1.model.DecryptRequest;
import com.google.api.services.storage.Storage;
import com.google.auth.oauth2.AccessToken;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.flogger.LoggerConfig;
import com.google.monitoring.metrics.MetricReporter;
import dagger.Component;
@@ -185,12 +183,6 @@ public class ProxyModule {
return Optional.ofNullable(httpsWhoisPort).orElse(config.webWhois.httpsPort);
}
@Provides
ImmutableMap<Integer, FrontendProtocol> providePortToProtocolMap(
Set<FrontendProtocol> protocolSet) {
return Maps.uniqueIndex(protocolSet, Protocol::port);
}
@Provides
Environment provideEnvironment() {
return env;
@@ -359,7 +351,7 @@ public class ProxyModule {
})
interface ProxyComponent {
ImmutableMap<Integer, FrontendProtocol> portToProtocolMap();
Set<FrontendProtocol> protocols();
MetricReporter metricReporter();
}
@@ -20,7 +20,7 @@ import static google.registry.proxy.handler.RelayHandler.RELAY_CHANNEL_KEY;
import static google.registry.proxy.handler.RelayHandler.writeToRelayChannel;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.monitoring.metrics.MetricReporter;
import google.registry.proxy.Protocol.BackendProtocol;
@@ -51,28 +51,27 @@ import java.util.concurrent.TimeoutException;
import javax.inject.Provider;
/**
* A multi-protocol proxy server that listens on port(s) specified in {@link
* ProxyModule.ProxyComponent#portToProtocolMap()} }.
* A multi-protocol proxy server that listens for protocols in {@link
* ProxyModule.ProxyComponent#protocols()} }.
*/
public class ProxyServer implements Runnable {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
/** Maximum length of the queue of incoming connections. */
private static final int MAX_SOCKET_BACKLOG = 128;
private final ImmutableMap<Integer, FrontendProtocol> portToProtocolMap;
private final ImmutableSet<FrontendProtocol> protocols;
private final HashMap<Integer, Channel> portToChannelMap = new HashMap<>();
private final EventLoopGroup eventGroup = new NioEventLoopGroup();
ProxyServer(ProxyComponent proxyComponent) {
this.portToProtocolMap = proxyComponent.portToProtocolMap();
this.protocols = ImmutableSet.copyOf(proxyComponent.protocols());
}
/**
* A {@link ChannelInitializer} for connections from a client of a certain protocol.
*
* <p>The {@link #initChannel} method does the following:
* <p>The {@link #initChannel(NioSocketChannel)} method does the following:
*
* <ol>
* <li>Determine the {@link FrontendProtocol} of the inbound {@link Channel} from its parent
@@ -263,8 +262,9 @@ public class ProxyServer implements Runnable {
.childOption(ChannelOption.AUTO_READ, false);
// Bind to each port specified in portToHandlersMap.
portToProtocolMap.forEach(
(port, protocol) -> {
protocols.forEach(
protocol -> {
int port = protocol.port();
try {
// Wait for binding to be established for each listening port.
ChannelFuture serverChannelFuture = serverBootstrap.bind(port).sync();