diff --git a/java/google/registry/config/RegistryConfig.java b/java/google/registry/config/RegistryConfig.java index 4b5f3e544..97b363b7c 100644 --- a/java/google/registry/config/RegistryConfig.java +++ b/java/google/registry/config/RegistryConfig.java @@ -14,6 +14,7 @@ package google.registry.config; +import static com.google.common.base.Randoms.insecureRandom; import static com.google.common.base.Suppliers.memoize; import static google.registry.config.ConfigUtils.makeUrl; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -34,6 +35,7 @@ import java.lang.annotation.Retention; import java.net.URI; import java.net.URL; import java.util.Optional; +import java.util.Random; import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.inject.Named; @@ -1257,6 +1259,17 @@ public final class RegistryConfig { .build()) .build(); } + + /** + * Returns a singleton random number generator. + * + * @see google.registry.util.UrlFetchUtils + */ + @Singleton + @Provides + public static Random provideRandom() { + return insecureRandom(); + } } /** diff --git a/java/google/registry/tmch/NordnUploadAction.java b/java/google/registry/tmch/NordnUploadAction.java index fb57c0adf..f49b2514c 100644 --- a/java/google/registry/tmch/NordnUploadAction.java +++ b/java/google/registry/tmch/NordnUploadAction.java @@ -80,6 +80,7 @@ public final class NordnUploadAction implements Runnable { private final String actionLogId = String.valueOf(1000000000 + new Random().nextInt(1000000000)); @Inject Clock clock; + @Inject Random random; @Inject LordnRequestInitializer lordnRequestInitializer; @Inject URLFetchService fetchService; @Inject @Config("tmchMarksdbUrl") String tmchMarksdbUrl; @@ -138,7 +139,7 @@ public final class NordnUploadAction implements Runnable { "LORDN upload task %s: Sending to URL: %s ; data: %s", actionLogId, url, csvData); HTTPRequest req = new HTTPRequest(new URL(url), POST, validateCertificate().setDeadline(60d)); lordnRequestInitializer.initialize(req, tld); - setPayloadMultipart(req, "file", "claims.csv", CSV_UTF_8, csvData); + setPayloadMultipart(req, "file", "claims.csv", CSV_UTF_8, csvData, random); HTTPResponse rsp = fetchService.fetch(req); logger.atInfo().log( "LORDN upload task %s response: HTTP response code %d, response data: %s", diff --git a/java/google/registry/util/UrlFetchUtils.java b/java/google/registry/util/UrlFetchUtils.java index 29f8a2575..bf30b0174 100644 --- a/java/google/registry/util/UrlFetchUtils.java +++ b/java/google/registry/util/UrlFetchUtils.java @@ -35,9 +35,6 @@ import java.util.Random; /** Helper methods for the App Engine URL fetch service. */ public final class UrlFetchUtils { - @NonFinalForTesting - private static Random random = new Random(); - /** Returns value of first header matching {@code name}. */ public static Optional getHeaderFirst(HTTPResponse rsp, String name) { return getHeaderFirstInternal(rsp.getHeadersUncombined(), name); @@ -63,11 +60,16 @@ public final class UrlFetchUtils { * *

This is equivalent to running the command: {@code curl -F fieldName=@payload.txt URL} * - * @see RFC2388 - Returning Values from Forms + * @see RFC2388 - Returning Values from Forms */ public static void setPayloadMultipart( - HTTPRequest request, String name, String filename, MediaType contentType, String data) { - String boundary = createMultipartBoundary(); + HTTPRequest request, + String name, + String filename, + MediaType contentType, + String data, + Random random) { + String boundary = createMultipartBoundary(random); checkState( !data.contains(boundary), "Multipart data contains autogenerated boundary: %s", boundary); @@ -87,7 +89,7 @@ public final class UrlFetchUtils { request.setPayload(payload); } - private static String createMultipartBoundary() { + private static String createMultipartBoundary(Random random) { // Generate 192 random bits (24 bytes) to produce 192/log_2(64) = 192/6 = 32 base64 digits. byte[] rand = new byte[24]; random.nextBytes(rand); diff --git a/javatests/google/registry/tmch/NordnUploadActionTest.java b/javatests/google/registry/tmch/NordnUploadActionTest.java index 1295d7bf7..af310d188 100644 --- a/javatests/google/registry/tmch/NordnUploadActionTest.java +++ b/javatests/google/registry/tmch/NordnUploadActionTest.java @@ -14,6 +14,7 @@ package google.registry.tmch; +import static com.google.common.base.Randoms.insecureRandom; import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static com.google.common.net.HttpHeaders.CONTENT_TYPE; import static com.google.common.net.HttpHeaders.LOCATION; @@ -115,6 +116,7 @@ public class NordnUploadActionTest { action.taskQueueUtils = new TaskQueueUtils(new Retrier(new FakeSleeper(clock), 3)); action.tld = "tld"; action.tmchMarksdbUrl = "http://127.0.0.1"; + action.random = insecureRandom(); } @Test diff --git a/javatests/google/registry/util/UrlFetchUtilsTest.java b/javatests/google/registry/util/UrlFetchUtilsTest.java index 7d505a6c1..043a1eca4 100644 --- a/javatests/google/registry/util/UrlFetchUtilsTest.java +++ b/javatests/google/registry/util/UrlFetchUtilsTest.java @@ -52,10 +52,10 @@ public class UrlFetchUtilsTest { @Rule public final InjectRule inject = new InjectRule(); + private final Random random = mock(Random.class); + @Before public void setupRandomZeroes() { - Random random = mock(Random.class); - inject.setStaticField(UrlFetchUtils.class, "random", random); doAnswer( info -> { Arrays.fill((byte[]) info.getArguments()[0], (byte) 0); @@ -69,7 +69,12 @@ public class UrlFetchUtilsTest { public void testSetPayloadMultipart() { HTTPRequest request = mock(HTTPRequest.class); setPayloadMultipart( - request, "lol", "cat", CSV_UTF_8, "The nice people at the store say hello. ヘ(◕。◕ヘ)"); + request, + "lol", + "cat", + CSV_UTF_8, + "The nice people at the store say hello. ヘ(◕。◕ヘ)", + random); ArgumentCaptor headerCaptor = ArgumentCaptor.forClass(HTTPHeader.class); verify(request, times(2)).addHeader(headerCaptor.capture()); List addedHeaders = headerCaptor.getAllValues(); @@ -97,7 +102,7 @@ public class UrlFetchUtilsTest { IllegalStateException thrown = assertThrows( IllegalStateException.class, - () -> setPayloadMultipart(request, "lol", "cat", CSV_UTF_8, payload)); + () -> setPayloadMultipart(request, "lol", "cat", CSV_UTF_8, payload, random)); assertThat(thrown) .hasMessageThat() .contains(