From 4999a72d96bb057830a1de2db3655673bb52b579 Mon Sep 17 00:00:00 2001 From: Lai Jiang Date: Mon, 31 Mar 2025 12:21:50 -0400 Subject: [PATCH] Save session data directly in a cookie (#2732) --- .../registry/flows/CookieSessionMetadata.java | 155 +++++++++++++ .../registry/flows/EppRequestHandler.java | 2 + .../google/registry/flows/EppTlsAction.java | 10 +- .../registry/flows/HttpSessionMetadata.java | 13 +- .../registry/flows/SessionMetadata.java | 38 +++- .../StatelessRequestSessionMetadata.java | 14 +- .../flows/CookieSessionMetadataTest.java | 211 ++++++++++++++++++ .../registry/flows/EppTlsActionTest.java | 28 ++- jetty/deploy-nomulus-for-env.sh | 11 - .../handler/SslServerInitializerTest.java | 7 - 10 files changed, 420 insertions(+), 69 deletions(-) create mode 100644 core/src/main/java/google/registry/flows/CookieSessionMetadata.java create mode 100644 core/src/test/java/google/registry/flows/CookieSessionMetadataTest.java diff --git a/core/src/main/java/google/registry/flows/CookieSessionMetadata.java b/core/src/main/java/google/registry/flows/CookieSessionMetadata.java new file mode 100644 index 000000000..f3344b9f3 --- /dev/null +++ b/core/src/main/java/google/registry/flows/CookieSessionMetadata.java @@ -0,0 +1,155 @@ +// Copyright 2025 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.flows; + +import static java.nio.charset.StandardCharsets.US_ASCII; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableSet; +import com.google.common.flogger.FluentLogger; +import com.google.common.io.BaseEncoding; +import google.registry.request.Response; +import jakarta.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A metadata class that saves the data directly in cookies. + * + *

Unlike {@link HttpSessionMetadata}, this class does not rely on a session manager to translate + * an opaque session cookie into the metadata. This means that the locality of the session manager + * is irrelevant and as long as the client (the proxy) respects the {@code Set-Cookie} headers and + * sets the respective cookies in subsequent requests in a session, the metadata will be available + * to all servers, not just the one that created the session. + * + *

The string representation of the metadata is saved in Base64 URL-safe format in a cookie named + * {@code SESSION_INFO}. + */ +public class CookieSessionMetadata extends SessionMetadata { + + protected static final String COOKIE_NAME = "SESSION_INFO"; + protected static final String REGISTRAR_ID = "clientId"; + protected static final String SERVICE_EXTENSIONS = "serviceExtensionUris"; + protected static final String FAILED_LOGIN_ATTEMPTS = "failedLoginAttempts"; + + private static final Pattern COOKIE_PATTERN = Pattern.compile("SESSION_INFO=([^;\\s]+)?"); + private static final Pattern REGISTRAR_ID_PATTERN = Pattern.compile("clientId=([^,\\s]+)?"); + private static final Pattern SERVICE_EXTENSIONS_PATTERN = + Pattern.compile("serviceExtensionUris=([^,\\s}]+)?"); + private static final Pattern FAILED_LOGIN_ATTEMPTS_PATTERN = + Pattern.compile("failedLoginAttempts=([^,\\s]+)?"); + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + private final Map data = new HashMap<>(); + + public CookieSessionMetadata(HttpServletRequest request) { + Optional.ofNullable(request.getHeader("Cookie")) + .ifPresent( + cookie -> { + Matcher matcher = COOKIE_PATTERN.matcher(cookie); + if (matcher.find()) { + String sessionInfo = decode(matcher.group(1)); + logger.atInfo().log("SESSION INFO: %s", sessionInfo); + matcher = REGISTRAR_ID_PATTERN.matcher(sessionInfo); + if (matcher.find()) { + String registrarId = matcher.group(1); + if (!registrarId.equals("null")) { + data.put(REGISTRAR_ID, registrarId); + } + } + matcher = SERVICE_EXTENSIONS_PATTERN.matcher(sessionInfo); + if (matcher.find()) { + String serviceExtensions = matcher.group(1); + if (serviceExtensions != null) { + data.put(SERVICE_EXTENSIONS, serviceExtensions); + } + } + matcher = FAILED_LOGIN_ATTEMPTS_PATTERN.matcher(sessionInfo); + if (matcher.find()) { + String failedLoginAttempts = matcher.group(1); + data.put(FAILED_LOGIN_ATTEMPTS, failedLoginAttempts); + } + } + }); + } + + @Override + public void invalidate() { + data.clear(); + } + + @Override + public String getRegistrarId() { + return data.getOrDefault(REGISTRAR_ID, null); + } + + @Override + public Set getServiceExtensionUris() { + return Optional.ofNullable(data.getOrDefault(SERVICE_EXTENSIONS, null)) + .map(s -> Splitter.on('.').splitToList(s)) + .map(ImmutableSet::copyOf) + .orElse(ImmutableSet.of()); + } + + @Override + public int getFailedLoginAttempts() { + return Optional.ofNullable(data.getOrDefault(FAILED_LOGIN_ATTEMPTS, null)) + .map(Integer::parseInt) + .orElse(0); + } + + @Override + public void setRegistrarId(String registrarId) { + data.put(REGISTRAR_ID, registrarId); + } + + @Override + public void setServiceExtensionUris(Set serviceExtensionUris) { + if (serviceExtensionUris == null || serviceExtensionUris.isEmpty()) { + data.remove(SERVICE_EXTENSIONS); + } else { + data.put(SERVICE_EXTENSIONS, Joiner.on('.').join(serviceExtensionUris)); + } + } + + @Override + public void incrementFailedLoginAttempts() { + data.put(FAILED_LOGIN_ATTEMPTS, String.valueOf(getFailedLoginAttempts() + 1)); + } + + @Override + public void resetFailedLoginAttempts() { + data.remove(FAILED_LOGIN_ATTEMPTS); + } + + @Override + public void save(Response response) { + String value = encode(toString()); + response.setHeader("Set-Cookie", COOKIE_NAME + "=" + value); + } + + protected static String encode(String plainText) { + return BaseEncoding.base64Url().encode(plainText.getBytes(US_ASCII)); + } + + protected static String decode(String cipherText) { + return new String(BaseEncoding.base64Url().decode(cipherText), US_ASCII); + } +} diff --git a/core/src/main/java/google/registry/flows/EppRequestHandler.java b/core/src/main/java/google/registry/flows/EppRequestHandler.java index fa073f5f3..7784e63ea 100644 --- a/core/src/main/java/google/registry/flows/EppRequestHandler.java +++ b/core/src/main/java/google/registry/flows/EppRequestHandler.java @@ -78,6 +78,8 @@ public class EppRequestHandler { } catch (Exception e) { logger.atWarning().withCause(e).log("handleEppCommand general exception."); response.setStatus(SC_BAD_REQUEST); + } finally { + sessionMetadata.save(response); } } } diff --git a/core/src/main/java/google/registry/flows/EppTlsAction.java b/core/src/main/java/google/registry/flows/EppTlsAction.java index 2d3cbcf91..e97450695 100644 --- a/core/src/main/java/google/registry/flows/EppTlsAction.java +++ b/core/src/main/java/google/registry/flows/EppTlsAction.java @@ -20,7 +20,7 @@ import google.registry.request.Action.Method; import google.registry.request.Payload; import google.registry.request.auth.Auth; import jakarta.inject.Inject; -import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpServletRequest; /** * Establishes a transport for EPP+TLS over HTTP. All commands and responses are EPP XML according @@ -35,18 +35,18 @@ public class EppTlsAction implements Runnable { @Inject @Payload byte[] inputXmlBytes; @Inject TlsCredentials tlsCredentials; - @Inject HttpSession session; + @Inject HttpServletRequest request; @Inject EppRequestHandler eppRequestHandler; @Inject EppTlsAction() {} @Override public void run() { eppRequestHandler.executeEpp( - new HttpSessionMetadata(session), + new CookieSessionMetadata(request), tlsCredentials, EppRequestSource.TLS, - false, // This endpoint is never a dry run. - false, // This endpoint is never a superuser. + false, // This endpoint is never a dry run. + false, // This endpoint is never a superuser. inputXmlBytes); } } diff --git a/core/src/main/java/google/registry/flows/HttpSessionMetadata.java b/core/src/main/java/google/registry/flows/HttpSessionMetadata.java index 4d8aecfda..44d7e1436 100644 --- a/core/src/main/java/google/registry/flows/HttpSessionMetadata.java +++ b/core/src/main/java/google/registry/flows/HttpSessionMetadata.java @@ -14,16 +14,14 @@ package google.registry.flows; -import static com.google.common.base.MoreObjects.toStringHelper; import static google.registry.util.CollectionUtils.nullToEmpty; -import com.google.common.base.Joiner; import jakarta.servlet.http.HttpSession; import java.util.Optional; import java.util.Set; /** A metadata class that is a wrapper around {@link HttpSession}. */ -public class HttpSessionMetadata implements SessionMetadata { +public class HttpSessionMetadata extends SessionMetadata { private static final String REGISTRAR_ID = "REGISTRAR_ID"; private static final String SERVICE_EXTENSIONS = "SERVICE_EXTENSIONS"; @@ -75,13 +73,4 @@ public class HttpSessionMetadata implements SessionMetadata { public void resetFailedLoginAttempts() { session.removeAttribute(FAILED_LOGIN_ATTEMPTS); } - - @Override - public String toString() { - return toStringHelper(getClass()) - .add("clientId", getRegistrarId()) - .add("failedLoginAttempts", getFailedLoginAttempts()) - .add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris()))) - .toString(); - } } diff --git a/core/src/main/java/google/registry/flows/SessionMetadata.java b/core/src/main/java/google/registry/flows/SessionMetadata.java index c9c8cd3b5..6f410e44c 100644 --- a/core/src/main/java/google/registry/flows/SessionMetadata.java +++ b/core/src/main/java/google/registry/flows/SessionMetadata.java @@ -14,29 +14,45 @@ package google.registry.flows; +import static com.google.common.base.MoreObjects.toStringHelper; +import static google.registry.util.CollectionUtils.nullToEmpty; + +import com.google.common.base.Joiner; +import google.registry.request.Response; import java.util.Set; /** Object to allow setting and retrieving session information in flows. */ -public interface SessionMetadata { +public abstract class SessionMetadata { /** * Invalidates the session. A new instance must be created after this for future sessions. - * Attempts to invoke methods of this class after this method has been called will throw - * {@code IllegalStateException}. + * Attempts to invoke methods of this class after this method has been called will throw {@code + * IllegalStateException}. */ - void invalidate(); + public abstract void invalidate(); - String getRegistrarId(); + public abstract String getRegistrarId(); - Set getServiceExtensionUris(); + public abstract Set getServiceExtensionUris(); - int getFailedLoginAttempts(); + public abstract int getFailedLoginAttempts(); - void setRegistrarId(String registrarId); + public abstract void setRegistrarId(String registrarId); - void setServiceExtensionUris(Set serviceExtensionUris); + public abstract void setServiceExtensionUris(Set serviceExtensionUris); - void incrementFailedLoginAttempts(); + public abstract void incrementFailedLoginAttempts(); - void resetFailedLoginAttempts(); + public abstract void resetFailedLoginAttempts(); + + @Override + public String toString() { + return toStringHelper(getClass()) + .add("clientId", getRegistrarId()) + .add("failedLoginAttempts", getFailedLoginAttempts()) + .add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris()))) + .toString(); + } + + public void save(Response response) {} } diff --git a/core/src/main/java/google/registry/flows/StatelessRequestSessionMetadata.java b/core/src/main/java/google/registry/flows/StatelessRequestSessionMetadata.java index 5b237665a..758d2ebb8 100644 --- a/core/src/main/java/google/registry/flows/StatelessRequestSessionMetadata.java +++ b/core/src/main/java/google/registry/flows/StatelessRequestSessionMetadata.java @@ -14,16 +14,13 @@ package google.registry.flows; -import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.util.CollectionUtils.nullToEmpty; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableSet; import java.util.Set; /** A read-only {@link SessionMetadata} that doesn't support login/logout. */ -public class StatelessRequestSessionMetadata implements SessionMetadata { +public class StatelessRequestSessionMetadata extends SessionMetadata { private final String registrarId; private final ImmutableSet serviceExtensionUris; @@ -74,13 +71,6 @@ public class StatelessRequestSessionMetadata implements SessionMetadata { throw new UnsupportedOperationException(); } - @Override - public String toString() { - return toStringHelper(getClass()) - .add("clientId", getRegistrarId()) - .add("failedLoginAttempts", getFailedLoginAttempts()) - .add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris()))) - .toString(); - } + } diff --git a/core/src/test/java/google/registry/flows/CookieSessionMetadataTest.java b/core/src/test/java/google/registry/flows/CookieSessionMetadataTest.java new file mode 100644 index 000000000..82335fb71 --- /dev/null +++ b/core/src/test/java/google/registry/flows/CookieSessionMetadataTest.java @@ -0,0 +1,211 @@ +// Copyright 2025 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.flows; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.flows.CookieSessionMetadata.COOKIE_NAME; +import static google.registry.flows.CookieSessionMetadata.decode; +import static google.registry.flows.CookieSessionMetadata.encode; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableSet; +import google.registry.testing.FakeResponse; +import jakarta.servlet.http.HttpServletRequest; +import org.junit.jupiter.api.Test; + +/** Unit tests for {@link CookieSessionMetadata}. */ +public class CookieSessionMetadataTest { + + private HttpServletRequest request = mock(HttpServletRequest.class); + private FakeResponse response = new FakeResponse(); + private CookieSessionMetadata cookieSessionMetadata = new CookieSessionMetadata(request); + + @Test + void testNoCookie() { + assertThat(cookieSessionMetadata.getRegistrarId()).isNull(); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(0); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty(); + } + + @Test + void testCookieWithAllFields() { + when(request.getHeader("Cookie")) + .thenReturn( + "THIS_COOKIE=foo; SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=A.B.C}") + + "; THAT_COOKIE=bar"); + cookieSessionMetadata = new CookieSessionMetadata(request); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("A", "B", "C"); + } + + @Test + void testCookieWithNullRegistrar() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=null, failedLoginAttempts=5, " + + " serviceExtensionUris=A.B.C}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + assertThat(cookieSessionMetadata.getRegistrarId()).isNull(); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("A", "B", "C"); + } + + @Test + void testCookieWithEmptyExtension() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty(); + } + + @Test + void testCookieWithSingleExtension() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo"); + } + + @Test + void testIncrementFailedLoginAttempts() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + cookieSessionMetadata.incrementFailedLoginAttempts(); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(6); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo"); + } + + @Test + void testResetFailedLoginAttempts() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + cookieSessionMetadata.resetFailedLoginAttempts(); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(0); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo"); + } + + @Test + void testSetRegistrarId() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + cookieSessionMetadata.setRegistrarId("new_registrar"); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("new_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Foo"); + } + + @Test + void testSetExtensions() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + cookieSessionMetadata.setServiceExtensionUris(ImmutableSet.of("Bar", "Baz")); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).containsExactly("Bar", "Baz"); + } + + @Test + void testSetEmptyExtensions() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + cookieSessionMetadata.setServiceExtensionUris(ImmutableSet.of()); + assertThat(cookieSessionMetadata.getRegistrarId()).isEqualTo("test_registrar"); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(5); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty(); + } + + @Test + void testInvalidate() { + when(request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + encode( + "CookieSessionMetadata{clientId=test_registrar, failedLoginAttempts=5, " + + " serviceExtensionUris=Foo}")); + cookieSessionMetadata = new CookieSessionMetadata(request); + cookieSessionMetadata.invalidate(); + assertThat(cookieSessionMetadata.getRegistrarId()).isNull(); + assertThat(cookieSessionMetadata.getFailedLoginAttempts()).isEqualTo(0); + assertThat(cookieSessionMetadata.getServiceExtensionUris()).isEmpty(); + } + + @Test + void testSave() { + cookieSessionMetadata.save(response); + String value = + decode( + response.getHeaders().get("Set-Cookie").toString().substring(COOKIE_NAME.length() + 1)); + assertThat(value) + .isEqualTo( + "CookieSessionMetadata{clientId=null, failedLoginAttempts=0, serviceExtensionUris=}"); + cookieSessionMetadata.setRegistrarId("new_registrar"); + cookieSessionMetadata.setServiceExtensionUris(ImmutableSet.of("Bar", "Baz")); + cookieSessionMetadata.incrementFailedLoginAttempts(); + cookieSessionMetadata.save(response); + value = + decode( + response.getHeaders().get("Set-Cookie").toString().substring(COOKIE_NAME.length() + 1)); + assertThat(value) + .isEqualTo( + "CookieSessionMetadata{clientId=new_registrar, failedLoginAttempts=1," + + " serviceExtensionUris=Bar.Baz}"); + } +} diff --git a/core/src/test/java/google/registry/flows/EppTlsActionTest.java b/core/src/test/java/google/registry/flows/EppTlsActionTest.java index 33cb52ccd..c71f9bf9b 100644 --- a/core/src/test/java/google/registry/flows/EppTlsActionTest.java +++ b/core/src/test/java/google/registry/flows/EppTlsActionTest.java @@ -12,17 +12,19 @@ // 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.US_ASCII; import static java.nio.charset.StandardCharsets.UTF_8; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -import google.registry.testing.FakeHttpSession; +import com.google.common.io.BaseEncoding; +import jakarta.servlet.http.HttpServletRequest; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -36,18 +38,22 @@ class EppTlsActionTest { EppTlsAction action = new EppTlsAction(); action.inputXmlBytes = INPUT_XML_BYTES; action.tlsCredentials = mock(TlsCredentials.class); - action.session = new FakeHttpSession(); - action.session.setAttribute("REGISTRAR_ID", "ClientIdentifier"); + action.request = mock(HttpServletRequest.class); + when(action.request.getHeader("Cookie")) + .thenReturn( + "SESSION_INFO=" + + BaseEncoding.base64Url().encode("clientId=ClientIdentifier".getBytes(US_ASCII))); action.eppRequestHandler = mock(EppRequestHandler.class); action.run(); ArgumentCaptor captor = ArgumentCaptor.forClass(SessionMetadata.class); - verify(action.eppRequestHandler).executeEpp( - captor.capture(), - same(action.tlsCredentials), - eq(EppRequestSource.TLS), - eq(false), - eq(false), - eq(INPUT_XML_BYTES)); + verify(action.eppRequestHandler) + .executeEpp( + captor.capture(), + same(action.tlsCredentials), + eq(EppRequestSource.TLS), + eq(false), + eq(false), + eq(INPUT_XML_BYTES)); assertThat(captor.getValue().getRegistrarId()).isEqualTo("ClientIdentifier"); } } diff --git a/jetty/deploy-nomulus-for-env.sh b/jetty/deploy-nomulus-for-env.sh index ea98c5dc2..a47287c46 100755 --- a/jetty/deploy-nomulus-for-env.sh +++ b/jetty/deploy-nomulus-for-env.sh @@ -62,15 +62,4 @@ do kubectl apply -f - done -# Restart proxies -while read line -do - parts=(${line}) - echo "Updating cluster ${parts[0]} in location ${parts[1]}..." - gcloud container clusters get-credentials ${parts[0]} \ - --project ${project} --location ${parts[1]} - kubectl rollout restart deployment/proxy-deployment - kubectl rollout restart deployment/proxy-deployment-canary -done < <(gcloud container clusters list --project ${project} | grep proxy-cluster) - kubectl config use-context "$current_context" diff --git a/networking/src/test/java/google/registry/networking/handler/SslServerInitializerTest.java b/networking/src/test/java/google/registry/networking/handler/SslServerInitializerTest.java index 509c6745b..d1736bfa8 100644 --- a/networking/src/test/java/google/registry/networking/handler/SslServerInitializerTest.java +++ b/networking/src/test/java/google/registry/networking/handler/SslServerInitializerTest.java @@ -42,7 +42,6 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Stream; @@ -272,17 +271,11 @@ class SslServerInitializerTest { getClientHandler( sslProvider, serverSsc.cert(), clientSsc.key(), clientSsc.cert(), "TLSv1.1", null)); - ImmutableList jdkVersion = - Arrays.stream(System.getProperty("java.version").split("\\.")) - .map(Integer::parseInt) - .collect(ImmutableList.toImmutableList()); - // In JDK v11.0.11 and above, TLS 1.1 is not supported anymore, in which case attempting to // connect with TLS 1.1 results in a ClosedChannelException instead of a SSLHandShakeException. // See https://www.oracle.com/java/technologies/javase/11-0-11-relnotes.html#JDK-8202343 Class rootCause = sslProvider == SslProvider.JDK - && compareSemanticVersion(jdkVersion, ImmutableList.of(11, 0, 11)) ? ClosedChannelException.class : SSLHandshakeException.class;