mirror of
https://github.com/google/nomulus
synced 2025-12-23 14:25:44 +00:00
Save session data directly in a cookie (#2732)
This commit is contained in:
@@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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<String, String> 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<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,14 +35,14 @@ 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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> getServiceExtensionUris();
|
||||
public abstract Set<String> getServiceExtensionUris();
|
||||
|
||||
int getFailedLoginAttempts();
|
||||
public abstract int getFailedLoginAttempts();
|
||||
|
||||
void setRegistrarId(String registrarId);
|
||||
public abstract void setRegistrarId(String registrarId);
|
||||
|
||||
void setServiceExtensionUris(Set<String> serviceExtensionUris);
|
||||
public abstract void setServiceExtensionUris(Set<String> 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) {}
|
||||
}
|
||||
|
||||
@@ -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<String> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
@@ -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,12 +38,16 @@ 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<SessionMetadata> captor = ArgumentCaptor.forClass(SessionMetadata.class);
|
||||
verify(action.eppRequestHandler).executeEpp(
|
||||
verify(action.eppRequestHandler)
|
||||
.executeEpp(
|
||||
captor.capture(),
|
||||
same(action.tlsCredentials),
|
||||
eq(EppRequestSource.TLS),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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<Integer> 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<? extends Exception> rootCause =
|
||||
sslProvider == SslProvider.JDK
|
||||
&& compareSemanticVersion(jdkVersion, ImmutableList.of(11, 0, 11))
|
||||
? ClosedChannelException.class
|
||||
: SSLHandshakeException.class;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user