mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Decouple SessionMetadata and TransportCredentials
TransportCredentials are per-request, not per-session, and there's no reason to carry them within SessionMetadata. While I'm in here, get rid of "null" credentials. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=125202213
This commit is contained in:
parent
fe1cd06da8
commit
3ae646d687
26 changed files with 134 additions and 120 deletions
|
@ -41,7 +41,8 @@ public class EppConsoleAction implements Runnable {
|
|||
@Override
|
||||
public void run() {
|
||||
eppRequestHandler.executeEpp(
|
||||
new HttpSessionMetadata(new GaeUserCredentials(getUserService().getCurrentUser()), session),
|
||||
new HttpSessionMetadata(session),
|
||||
new GaeUserCredentials(getUserService().getCurrentUser()),
|
||||
inputXmlBytes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,10 @@ public final class EppController {
|
|||
* Read an EPP envelope from the client, find the matching flow, execute it, and return
|
||||
* the response marshalled to a byte array.
|
||||
*/
|
||||
public byte[] handleEppCommand(SessionMetadata sessionMetadata, byte[] inputXmlBytes) {
|
||||
public byte[] handleEppCommand(
|
||||
SessionMetadata sessionMetadata,
|
||||
TransportCredentials credentials,
|
||||
byte[] inputXmlBytes) {
|
||||
Trid trid = null;
|
||||
try {
|
||||
EppInput eppInput = unmarshal(EppInput.class, inputXmlBytes);
|
||||
|
@ -68,6 +71,7 @@ public final class EppController {
|
|||
eppInput,
|
||||
trid,
|
||||
sessionMetadata,
|
||||
credentials,
|
||||
inputXmlBytes,
|
||||
metrics,
|
||||
clock);
|
||||
|
|
|
@ -39,10 +39,13 @@ public class EppRequestHandler {
|
|||
@Inject EppRequestHandler() {}
|
||||
|
||||
/** Handle an EPP request and write out a servlet response. */
|
||||
public void executeEpp(SessionMetadata sessionMetadata, byte[] inputXmlBytes) {
|
||||
public void executeEpp(
|
||||
SessionMetadata sessionMetadata,
|
||||
TransportCredentials credentials,
|
||||
byte[] inputXmlBytes) {
|
||||
try {
|
||||
response.setPayload(new String(
|
||||
eppController.handleEppCommand(sessionMetadata, inputXmlBytes), UTF_8));
|
||||
eppController.handleEppCommand(sessionMetadata, credentials, inputXmlBytes), UTF_8));
|
||||
response.setContentType(APPLICATION_EPP_XML);
|
||||
// Note that we always return 200 (OK) even if the EppController returns an error response.
|
||||
// This is because returning an non-OK HTTP status code will cause the proxy server to
|
||||
|
|
|
@ -46,7 +46,7 @@ public class EppTlsAction implements Runnable {
|
|||
if (!tlsCredentials.hasSni()) {
|
||||
logger.warning("Request did not include required SNI header.");
|
||||
}
|
||||
eppRequestHandler.executeEpp(new HttpSessionMetadata(tlsCredentials, session), inputXmlBytes);
|
||||
eppRequestHandler.executeEpp(new HttpSessionMetadata(session), tlsCredentials, inputXmlBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ public class EppToolAction implements Runnable {
|
|||
dryRun,
|
||||
ProtocolDefinition.getVisibleServiceExtensionUris(),
|
||||
SessionSource.TOOL),
|
||||
new PasswordOnlyTransportCredentials(),
|
||||
xml.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ public abstract class Flow {
|
|||
|
||||
protected EppInput eppInput;
|
||||
protected SessionMetadata sessionMetadata;
|
||||
protected TransportCredentials credentials;
|
||||
protected Trid trid;
|
||||
protected DateTime now;
|
||||
protected byte[] inputXmlBytes;
|
||||
|
@ -101,11 +102,13 @@ public abstract class Flow {
|
|||
EppInput eppInput,
|
||||
Trid trid,
|
||||
SessionMetadata sessionMetadata,
|
||||
TransportCredentials credentials,
|
||||
DateTime now,
|
||||
byte[] inputXmlBytes) throws EppException {
|
||||
this.eppInput = eppInput;
|
||||
this.trid = trid;
|
||||
this.sessionMetadata = sessionMetadata;
|
||||
this.credentials = credentials;
|
||||
this.now = now;
|
||||
this.superuser = sessionMetadata.isSuperuser();
|
||||
this.inputXmlBytes = inputXmlBytes;
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.joda.time.DateTime;
|
|||
/** Run a flow, either transactionally or not, with logging and retrying as needed. */
|
||||
public class FlowRunner {
|
||||
|
||||
private static final String COMMAND_LOG_FORMAT = "EPP Command" + Strings.repeat("\n\t%s", 4);
|
||||
private static final String COMMAND_LOG_FORMAT = "EPP Command" + Strings.repeat("\n\t%s", 5);
|
||||
|
||||
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
|
||||
|
||||
|
@ -44,6 +44,7 @@ public class FlowRunner {
|
|||
private final EppInput eppInput;
|
||||
private final Trid trid;
|
||||
private final SessionMetadata sessionMetadata;
|
||||
private final TransportCredentials credentials;
|
||||
private final byte[] inputXmlBytes;
|
||||
private final EppMetrics metrics;
|
||||
private final Clock clock;
|
||||
|
@ -53,13 +54,16 @@ public class FlowRunner {
|
|||
EppInput eppInput,
|
||||
Trid trid,
|
||||
SessionMetadata sessionMetadata,
|
||||
TransportCredentials credentials,
|
||||
byte[] inputXmlBytes,
|
||||
final EppMetrics metrics,
|
||||
Clock clock) {
|
||||
credentials.toString();
|
||||
this.flowClass = flowClass;
|
||||
this.eppInput = eppInput;
|
||||
this.trid = trid;
|
||||
this.sessionMetadata = sessionMetadata;
|
||||
this.credentials = credentials;
|
||||
this.inputXmlBytes = inputXmlBytes;
|
||||
this.metrics = metrics;
|
||||
this.clock = clock;
|
||||
|
@ -72,7 +76,8 @@ public class FlowRunner {
|
|||
trid.getServerTransactionId(),
|
||||
clientId,
|
||||
sessionMetadata,
|
||||
prettyPrint(inputXmlBytes).replaceAll("\n", "\n\t"));
|
||||
prettyPrint(inputXmlBytes).replaceAll("\n", "\n\t"),
|
||||
credentials);
|
||||
if (!isTransactional()) {
|
||||
if (metrics != null) {
|
||||
metrics.incrementAttempts();
|
||||
|
@ -124,6 +129,7 @@ public class FlowRunner {
|
|||
eppInput,
|
||||
trid,
|
||||
sessionMetadata,
|
||||
credentials,
|
||||
now,
|
||||
inputXmlBytes);
|
||||
}
|
||||
|
|
|
@ -38,12 +38,8 @@ public class GaeUserCredentials implements TransportCredentials {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean performsLoginCheck() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Registrar r) throws AuthenticationErrorException {
|
||||
public void validate(Registrar registrar, String ignoredPassword)
|
||||
throws AuthenticationErrorException {
|
||||
if (gaeUser == null) {
|
||||
throw new UserNotLoggedInException();
|
||||
}
|
||||
|
@ -53,7 +49,7 @@ public class GaeUserCredentials implements TransportCredentials {
|
|||
}
|
||||
// Check Registrar's contacts to see if any are associated with this gaeUserId.
|
||||
final String gaeUserId = gaeUser.getUserId();
|
||||
for (RegistrarContact rc : r.getContacts()) {
|
||||
for (RegistrarContact rc : registrar.getContacts()) {
|
||||
if (gaeUserId.equals(rc.getGaeUserId())) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,9 +24,8 @@ public class HttpSessionMetadata extends SessionMetadata {
|
|||
private final HttpSession session;
|
||||
private boolean isValid = true;
|
||||
|
||||
public HttpSessionMetadata(TransportCredentials credentials, HttpSession session) {
|
||||
public HttpSessionMetadata(HttpSession session) {
|
||||
this.session = session;
|
||||
setTransportCredentials(credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2016 The Domain Registry 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 google.registry.flows.EppException.AuthenticationErrorException;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
|
||||
/** A transport credentials that validates the registrar's EPP password and nothing else. */
|
||||
public class PasswordOnlyTransportCredentials implements TransportCredentials {
|
||||
@Override
|
||||
public void validate(Registrar r, String password) throws AuthenticationErrorException {
|
||||
if (!r.testPassword(password)) {
|
||||
throw new BadRegistrarPasswordException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,8 +46,6 @@ public abstract class SessionMetadata {
|
|||
NONE
|
||||
}
|
||||
|
||||
private TransportCredentials credentials;
|
||||
|
||||
/** The key used for looking up the current client id on the session object. */
|
||||
protected static final String CLIENT_ID_KEY = "CLIENT_ID";
|
||||
|
||||
|
@ -91,16 +89,6 @@ public abstract class SessionMetadata {
|
|||
return clazz.cast(getProperty(key));
|
||||
}
|
||||
|
||||
public TransportCredentials getTransportCredentials() {
|
||||
checkValid();
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public void setTransportCredentials(TransportCredentials credentials) {
|
||||
checkValid();
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return getProperty(String.class, CLIENT_ID_KEY);
|
||||
}
|
||||
|
@ -164,7 +152,6 @@ public abstract class SessionMetadata {
|
|||
.add("failedLoginAttempts", getFailedLoginAttempts())
|
||||
.add("sessionSource", getSessionSource())
|
||||
.add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris())))
|
||||
.add("transportCredentials", getTransportCredentials())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,11 +68,6 @@ public class StatelessRequestSessionMetadata extends SessionMetadata {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransportCredentials(TransportCredentials credentials) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setProperty(String key, Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
|
@ -86,20 +86,16 @@ public class TlsCredentials implements TransportCredentials {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performsLoginCheck() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if frontend passed us the requested server name. */
|
||||
boolean hasSni() {
|
||||
return !isNullOrEmpty(sni);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(Registrar registrar) throws AuthenticationErrorException {
|
||||
public void validate(Registrar registrar, String password) throws AuthenticationErrorException {
|
||||
validateIp(registrar);
|
||||
validateCertificate(registrar);
|
||||
validatePassword(registrar, password);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,6 +156,13 @@ public class TlsCredentials implements TransportCredentials {
|
|||
}
|
||||
}
|
||||
|
||||
private void validatePassword(Registrar registrar, String password)
|
||||
throws BadRegistrarPasswordException {
|
||||
if (!registrar.testPassword(password)) {
|
||||
throw new BadRegistrarPasswordException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(getClass())
|
||||
|
|
|
@ -17,23 +17,21 @@ package google.registry.flows;
|
|||
import google.registry.flows.EppException.AuthenticationErrorException;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
|
||||
/**
|
||||
* A marker interface for objects containing registrar credentials provided via an EPP transport.
|
||||
*/
|
||||
/** Interface for objects containing registrar credentials provided via an EPP transport. */
|
||||
public interface TransportCredentials {
|
||||
|
||||
/**
|
||||
* Indicates whether the transport takes the place of EPP login checks, in which case LoginFlow
|
||||
* will not check the password. Alternatively, if the password should be checked, it MUST match
|
||||
* the user's and GAE's isUserAdmin should not be used to bypass this check as internal
|
||||
* connections over RPC will have this property for all registrars.
|
||||
* Check that these credentials are valid for the registrar and optionally check the password.
|
||||
*
|
||||
* Called by {@link google.registry.flows.session.LoginFlow LoginFlow} to check the transport
|
||||
* credentials against the stored registrar's credentials. If they do not match, throw an
|
||||
* {@link AuthenticationErrorException}.
|
||||
*/
|
||||
boolean performsLoginCheck();
|
||||
void validate(Registrar registrar, String password) throws AuthenticationErrorException;
|
||||
|
||||
/**
|
||||
* Called by {@link google.registry.flows.session.LoginFlow LoginFlow}
|
||||
* to check the transport credentials against the stored registrar's credentials.
|
||||
* If they do not match, throw an AuthenticationErrorException.
|
||||
*/
|
||||
void validate(Registrar r) throws AuthenticationErrorException;
|
||||
/** Registrar password is incorrect. */
|
||||
static class BadRegistrarPasswordException extends AuthenticationErrorException {
|
||||
public BadRegistrarPasswordException() {
|
||||
super("Registrar password is incorrect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import google.registry.flows.EppException.UnimplementedExtensionException;
|
|||
import google.registry.flows.EppException.UnimplementedObjectServiceException;
|
||||
import google.registry.flows.EppException.UnimplementedOptionException;
|
||||
import google.registry.flows.Flow;
|
||||
import google.registry.flows.TransportCredentials;
|
||||
import google.registry.model.eppcommon.ProtocolDefinition;
|
||||
import google.registry.model.eppcommon.ProtocolDefinition.ServiceExtension;
|
||||
import google.registry.model.eppinput.EppInput.Login;
|
||||
|
@ -55,9 +54,9 @@ import java.util.Set;
|
|||
* @error {@link google.registry.flows.TlsCredentials.BadRegistrarIpAddressException}
|
||||
* @error {@link google.registry.flows.TlsCredentials.MissingRegistrarCertificateException}
|
||||
* @error {@link google.registry.flows.TlsCredentials.NoSniException}
|
||||
* @error {@link google.registry.flows.TransportCredentials.BadRegistrarPasswordException}
|
||||
* @error {@link LoginFlow.AlreadyLoggedInException}
|
||||
* @error {@link LoginFlow.BadRegistrarClientIdException}
|
||||
* @error {@link LoginFlow.BadRegistrarPasswordException}
|
||||
* @error {@link LoginFlow.TooManyFailedLoginsException}
|
||||
* @error {@link LoginFlow.PasswordChangesNotSupportedException}
|
||||
* @error {@link LoginFlow.RegistrarAccountNotActiveException}
|
||||
|
@ -114,24 +113,15 @@ public class LoginFlow extends Flow {
|
|||
throw new BadRegistrarClientIdException(login.getClientId());
|
||||
}
|
||||
|
||||
TransportCredentials credentials = sessionMetadata.getTransportCredentials();
|
||||
// AuthenticationErrorExceptions will propagate up through here.
|
||||
if (credentials != null) { // Allow no-credential logins, for load-testing and RDE.
|
||||
try {
|
||||
credentials.validate(registrar);
|
||||
credentials.validate(registrar, login.getPassword());
|
||||
} catch (AuthenticationErrorException e) {
|
||||
sessionMetadata.incrementFailedLoginAttempts();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
final boolean requiresLoginCheck = credentials == null || !credentials.performsLoginCheck();
|
||||
if (requiresLoginCheck && !registrar.testPassword(login.getPassword())) {
|
||||
sessionMetadata.incrementFailedLoginAttempts();
|
||||
if (sessionMetadata.getFailedLoginAttempts() > MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION) {
|
||||
throw new TooManyFailedLoginsException();
|
||||
} else {
|
||||
throw new BadRegistrarPasswordException();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (registrar.getState().equals(Registrar.State.PENDING)) {
|
||||
|
@ -157,13 +147,6 @@ public class LoginFlow extends Flow {
|
|||
}
|
||||
}
|
||||
|
||||
/** Registrar password is incorrect. */
|
||||
static class BadRegistrarPasswordException extends AuthenticationErrorException {
|
||||
public BadRegistrarPasswordException() {
|
||||
super("Registrar password is incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
/** Registrar login failed too many times. */
|
||||
static class TooManyFailedLoginsException extends AuthenticationErrorClosingConnectionException {
|
||||
public TooManyFailedLoginsException() {
|
||||
|
|
|
@ -104,12 +104,11 @@ final class ValidateLoginCredentialsCommand implements RemoteApiCommand, GtechCo
|
|||
LoginFlow.class,
|
||||
unmarshal(EppInput.class, inputXmlBytes),
|
||||
Trid.create(null),
|
||||
new HttpSessionMetadata(
|
||||
new HttpSessionMetadata(new BasicHttpSession()),
|
||||
new TlsCredentials(
|
||||
clientCertificateHash,
|
||||
Optional.of(clientIpAddress),
|
||||
"placeholder"), // behave as if we have SNI on, since we're validating a cert
|
||||
new BasicHttpSession()),
|
||||
inputXmlBytes,
|
||||
null,
|
||||
new SystemClock()).run()), UTF_8));
|
||||
|
|
|
@ -38,6 +38,7 @@ import dagger.Provides;
|
|||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.flows.EppException;
|
||||
import google.registry.flows.FlowRunner;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.flows.SessionMetadata.SessionSource;
|
||||
import google.registry.flows.StatelessRequestSessionMetadata;
|
||||
import google.registry.flows.domain.DomainCheckFlow;
|
||||
|
@ -119,6 +120,7 @@ public class CheckApiAction implements Runnable {
|
|||
unmarshal(EppInput.class, inputXmlBytes),
|
||||
Trid.create(getClass().getSimpleName()),
|
||||
sessionMetadata,
|
||||
new PasswordOnlyTransportCredentials(),
|
||||
inputXmlBytes,
|
||||
null,
|
||||
clock)
|
||||
|
|
|
@ -51,11 +51,14 @@ public class EppConsoleActionTest extends ShardableTestCase {
|
|||
action.session.setAttribute("SUPERUSER", superuser);
|
||||
action.eppRequestHandler = mock(EppRequestHandler.class);
|
||||
action.run();
|
||||
ArgumentCaptor<SessionMetadata> captor = ArgumentCaptor.forClass(SessionMetadata.class);
|
||||
verify(action.eppRequestHandler).executeEpp(captor.capture(), eq(INPUT_XML_BYTES));
|
||||
SessionMetadata sessionMetadata = captor.getValue();
|
||||
assertThat(((GaeUserCredentials) sessionMetadata.getTransportCredentials()).gaeUser.getEmail())
|
||||
ArgumentCaptor<TransportCredentials> credentialsCaptor =
|
||||
ArgumentCaptor.forClass(TransportCredentials.class);
|
||||
ArgumentCaptor<SessionMetadata> metadataCaptor = ArgumentCaptor.forClass(SessionMetadata.class);
|
||||
verify(action.eppRequestHandler).executeEpp(
|
||||
metadataCaptor.capture(), credentialsCaptor.capture(), eq(INPUT_XML_BYTES));
|
||||
assertThat(((GaeUserCredentials) credentialsCaptor.getValue()).gaeUser.getEmail())
|
||||
.isEqualTo("person@example.com");
|
||||
SessionMetadata sessionMetadata = metadataCaptor.getValue();
|
||||
assertThat(sessionMetadata.getClientId()).isEqualTo("ClientIdentifier");
|
||||
assertThat(sessionMetadata.isDryRun()).isFalse(); // Should always be false for console.
|
||||
assertThat(sessionMetadata.isSuperuser()).isEqualTo(superuser);
|
||||
|
|
|
@ -50,8 +50,8 @@ public class EppTestCase extends ShardableTestCase {
|
|||
private final FakeClock clock = new FakeClock();
|
||||
|
||||
private TestSessionMetadata sessionMetadata;
|
||||
private TransportCredentials credentials;
|
||||
private boolean superuser;
|
||||
private TransportCredentials credentials = new PasswordOnlyTransportCredentials();
|
||||
private boolean isSuperuser;
|
||||
|
||||
@Before
|
||||
public void initTestCase() {
|
||||
|
@ -70,8 +70,8 @@ public class EppTestCase extends ShardableTestCase {
|
|||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
protected void setSuperuser(boolean superuser) {
|
||||
this.superuser = superuser;
|
||||
protected void setSuperuser(boolean isSuperuser) {
|
||||
this.isSuperuser = isSuperuser;
|
||||
}
|
||||
|
||||
String assertCommandAndResponse(String inputFilename, String outputFilename) throws Exception {
|
||||
|
@ -95,9 +95,8 @@ public class EppTestCase extends ShardableTestCase {
|
|||
loadFileWithSubstitutions(getClass(), outputFilename, outputSubstitutions);
|
||||
if (sessionMetadata == null) {
|
||||
sessionMetadata = new TestSessionMetadata();
|
||||
sessionMetadata.setTransportCredentials(credentials);
|
||||
}
|
||||
sessionMetadata.setSuperuser(superuser);
|
||||
sessionMetadata.setSuperuser(isSuperuser);
|
||||
String actualOutput = executeXmlCommand(input);
|
||||
if (!sessionMetadata.isValid()) {
|
||||
sessionMetadata = null;
|
||||
|
@ -119,7 +118,7 @@ public class EppTestCase extends ShardableTestCase {
|
|||
handler.eppController = new EppController();
|
||||
handler.eppController.clock = clock;
|
||||
handler.eppController.metrics = mock(EppMetrics.class);
|
||||
handler.executeEpp(sessionMetadata, inputXml.getBytes(UTF_8));
|
||||
handler.executeEpp(sessionMetadata, credentials, inputXml.getBytes(UTF_8));
|
||||
assertThat(response.getStatus()).isEqualTo(SC_OK);
|
||||
assertThat(response.getContentType()).isEqualTo(APPLICATION_EPP_XML_UTF8);
|
||||
String result = response.getPayload();
|
||||
|
|
|
@ -17,7 +17,8 @@ package google.registry.flows;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.same;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -47,12 +48,12 @@ public class EppTlsActionTest extends ShardableTestCase {
|
|||
action.eppRequestHandler = mock(EppRequestHandler.class);
|
||||
action.run();
|
||||
ArgumentCaptor<SessionMetadata> captor = ArgumentCaptor.forClass(SessionMetadata.class);
|
||||
verify(action.eppRequestHandler).executeEpp(captor.capture(), eq(INPUT_XML_BYTES));
|
||||
verify(action.eppRequestHandler)
|
||||
.executeEpp(captor.capture(), same(action.tlsCredentials), eq(INPUT_XML_BYTES));
|
||||
SessionMetadata sessionMetadata = captor.getValue();
|
||||
assertThat(sessionMetadata.getClientId()).isEqualTo("ClientIdentifier");
|
||||
assertThat(sessionMetadata.isDryRun()).isFalse(); // Should always be false for TLS.
|
||||
assertThat(sessionMetadata.isSuperuser()).isEqualTo(superuser);
|
||||
assertThat(sessionMetadata.getTransportCredentials()).isSameAs(action.tlsCredentials);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -16,7 +16,8 @@ package google.registry.flows;
|
|||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isA;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
|
@ -38,7 +39,10 @@ public class EppToolActionTest {
|
|||
action.xml = "<xml>";
|
||||
action.run();
|
||||
ArgumentCaptor<SessionMetadata> captor = ArgumentCaptor.forClass(SessionMetadata.class);
|
||||
verify(action.eppRequestHandler).executeEpp(captor.capture(), eq(action.xml.getBytes(UTF_8)));
|
||||
verify(action.eppRequestHandler).executeEpp(
|
||||
captor.capture(),
|
||||
isA(PasswordOnlyTransportCredentials.class),
|
||||
eq(action.xml.getBytes(UTF_8)));
|
||||
SessionMetadata sessionMetadata = captor.getValue();
|
||||
assertThat(sessionMetadata.getClientId()).isEqualTo("ClientIdentifier");
|
||||
assertThat(sessionMetadata.isDryRun()).isEqualTo(dryRun);
|
||||
|
|
|
@ -93,6 +93,7 @@ public abstract class FlowTestCase<F extends Flow> {
|
|||
protected Class<? extends Flow> flowClass;
|
||||
protected TestSessionMetadata sessionMetadata;
|
||||
protected FakeClock clock = new FakeClock(DateTime.now(UTC));
|
||||
protected TransportCredentials credentials = new PasswordOnlyTransportCredentials();
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
|
@ -141,6 +142,7 @@ public abstract class FlowTestCase<F extends Flow> {
|
|||
eppInput,
|
||||
getTrid(),
|
||||
sessionMetadata,
|
||||
credentials,
|
||||
"<xml></xml>".getBytes(),
|
||||
null,
|
||||
clock);
|
||||
|
|
|
@ -22,9 +22,9 @@ import google.registry.flows.EppException.UnimplementedExtensionException;
|
|||
import google.registry.flows.EppException.UnimplementedObjectServiceException;
|
||||
import google.registry.flows.EppException.UnimplementedProtocolVersionException;
|
||||
import google.registry.flows.FlowTestCase;
|
||||
import google.registry.flows.TransportCredentials.BadRegistrarPasswordException;
|
||||
import google.registry.flows.session.LoginFlow.AlreadyLoggedInException;
|
||||
import google.registry.flows.session.LoginFlow.BadRegistrarClientIdException;
|
||||
import google.registry.flows.session.LoginFlow.BadRegistrarPasswordException;
|
||||
import google.registry.flows.session.LoginFlow.PasswordChangesNotSupportedException;
|
||||
import google.registry.flows.session.LoginFlow.RegistrarAccountNotActiveException;
|
||||
import google.registry.flows.session.LoginFlow.TooManyFailedLoginsException;
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
package google.registry.flows.session;
|
||||
|
||||
|
||||
import static com.google.appengine.api.users.UserServiceFactory.getUserService;
|
||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||
|
||||
import com.google.appengine.api.users.UserServiceFactory;
|
||||
import com.google.apphosting.api.ApiProxy;
|
||||
import com.google.apphosting.api.ApiProxy.Environment;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -150,15 +150,13 @@ public class LoginFlowViaConsoleTest extends LoginFlowTestCase {
|
|||
return envAttr;
|
||||
}
|
||||
});
|
||||
sessionMetadata.setTransportCredentials(new GaeUserCredentials(
|
||||
UserServiceFactory.getUserService().getCurrentUser()));
|
||||
credentials = new GaeUserCredentials(getUserService().getCurrentUser());
|
||||
return oldEnv;
|
||||
}
|
||||
|
||||
void noLogin() {
|
||||
oldEnv = ApiProxy.getCurrentEnvironment();
|
||||
sessionMetadata.setTransportCredentials(new GaeUserCredentials(
|
||||
UserServiceFactory.getUserService().getCurrentUser()));
|
||||
credentials = new GaeUserCredentials(getUserService().getCurrentUser());
|
||||
}
|
||||
|
||||
void persistLinkedAccount(String email, String gaeUserId) {
|
||||
|
|
|
@ -52,7 +52,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
@Test
|
||||
public void testSuccess_withGoodCredentials() throws Exception {
|
||||
persistResource(getRegistrarBuilder().build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, GOOD_IP, "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, GOOD_IP, "goo.example");
|
||||
doSuccessfulTest("login_valid.xml");
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
.setIpAddressWhitelist(ImmutableList.of(
|
||||
CidrAddressBlock.create("2001:db8:0:0:0:0:1:1/32")))
|
||||
.build());
|
||||
sessionMetadata.setTransportCredentials(
|
||||
new TlsCredentials(GOOD_CERT, GOOD_IPV6, "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, GOOD_IPV6, "goo.example");
|
||||
doSuccessfulTest("login_valid.xml");
|
||||
}
|
||||
|
||||
|
@ -75,8 +74,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
.setIpAddressWhitelist(ImmutableList.of(
|
||||
CidrAddressBlock.create("2001:db8:0:0:0:0:1:1/32")))
|
||||
.build());
|
||||
sessionMetadata.setTransportCredentials(
|
||||
new TlsCredentials(GOOD_CERT, GOOD_IPV6, "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, GOOD_IPV6, "goo.example");
|
||||
doSuccessfulTest("login_valid.xml");
|
||||
}
|
||||
|
||||
|
@ -87,28 +85,28 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
.setIpAddressWhitelist(ImmutableList.of(
|
||||
CidrAddressBlock.create("192.168.1.255/24")))
|
||||
.build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, GOOD_IP, "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, GOOD_IP, "goo.example");
|
||||
doSuccessfulTest("login_valid.xml");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_incorrectClientCertificateHash() throws Exception {
|
||||
persistResource(getRegistrarBuilder().build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(BAD_CERT, GOOD_IP, "goo.example"));
|
||||
credentials = new TlsCredentials(BAD_CERT, GOOD_IP, "goo.example");
|
||||
doFailingTest("login_valid.xml", BadRegistrarCertificateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_missingClientCertificateHash() throws Exception {
|
||||
persistResource(getRegistrarBuilder().build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(null, GOOD_IP, "goo.example"));
|
||||
credentials = new TlsCredentials(null, GOOD_IP, "goo.example");
|
||||
doFailingTest("login_valid.xml", MissingRegistrarCertificateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailure_noSniAndCertRequired() throws Exception {
|
||||
persistResource(getRegistrarBuilder().build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(null, GOOD_IP, null));
|
||||
credentials = new TlsCredentials(null, GOOD_IP, null);
|
||||
doFailingTest("login_valid.xml", NoSniException.class);
|
||||
}
|
||||
|
||||
|
@ -120,8 +118,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
CidrAddressBlock.create(InetAddresses.forString("192.168.1.1"), 32),
|
||||
CidrAddressBlock.create(InetAddresses.forString("2001:db8::1"), 128)))
|
||||
.build());
|
||||
sessionMetadata.setTransportCredentials(
|
||||
new TlsCredentials(GOOD_CERT, Optional.<String>absent(), "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, Optional.<String>absent(), "goo.example");
|
||||
doFailingTest("login_valid.xml", BadRegistrarIpAddressException.class);
|
||||
}
|
||||
|
||||
|
@ -133,7 +130,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
CidrAddressBlock.create(InetAddresses.forString("192.168.1.1"), 32),
|
||||
CidrAddressBlock.create(InetAddresses.forString("2001:db8::1"), 128)))
|
||||
.build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, BAD_IP, "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, BAD_IP, "goo.example");
|
||||
doFailingTest("login_valid.xml", BadRegistrarIpAddressException.class);
|
||||
}
|
||||
|
||||
|
@ -145,7 +142,7 @@ public class LoginFlowViaTlsTest extends LoginFlowTestCase {
|
|||
CidrAddressBlock.create(InetAddresses.forString("192.168.1.1"), 32),
|
||||
CidrAddressBlock.create(InetAddresses.forString("2001:db8::1"), 128)))
|
||||
.build());
|
||||
sessionMetadata.setTransportCredentials(new TlsCredentials(GOOD_CERT, BAD_IPV6, "goo.example"));
|
||||
credentials = new TlsCredentials(GOOD_CERT, BAD_IPV6, "goo.example");
|
||||
doFailingTest("login_valid.xml", BadRegistrarIpAddressException.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import static org.joda.time.Duration.standardDays;
|
|||
import com.googlecode.objectify.Key;
|
||||
|
||||
import google.registry.flows.FlowRunner;
|
||||
import google.registry.flows.PasswordOnlyTransportCredentials;
|
||||
import google.registry.flows.SessionMetadata;
|
||||
import google.registry.model.domain.DomainResource;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
|
@ -84,6 +85,7 @@ public class EppResourceUtilsTest {
|
|||
eppLoader.getEpp(),
|
||||
Trid.create(null, "server-trid"),
|
||||
sessionMetadata,
|
||||
new PasswordOnlyTransportCredentials(),
|
||||
"<xml></xml>".getBytes(),
|
||||
null,
|
||||
clock)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue