Decouple superuser from SessionMetadata

Superuser should only be settable via the tool (see []
which is merged in here but not diffbased, and which removes
the implicit superuser for CharlestonRoad). It is a property
of the request, not of the session (there are no sessions in the tool).
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=125204707
This commit is contained in:
cgoldfeder 2016-06-17 14:48:46 -07:00 committed by Ben McIlwain
parent e359ab5f52
commit fd6c4888db
44 changed files with 80 additions and 136 deletions

View file

@ -44,6 +44,7 @@ public class EppConsoleAction implements Runnable {
new HttpSessionMetadata(session),
new GaeUserCredentials(getUserService().getCurrentUser()),
false, // This endpoint is never a dry run.
false, // This endpoint is never a superuser.
inputXmlBytes);
}
}

View file

@ -55,6 +55,7 @@ public final class EppController {
SessionMetadata sessionMetadata,
TransportCredentials credentials,
boolean isDryRun,
boolean isSuperuser,
byte[] inputXmlBytes) {
Trid trid = null;
try {
@ -63,7 +64,7 @@ public final class EppController {
ImmutableList<String> targetIds = eppInput.getTargetIds();
metrics.setCommandName(eppInput.getCommandName());
metrics.setClientId(sessionMetadata.getClientId());
metrics.setPrivilegeLevel(sessionMetadata.isSuperuser() ? "SUPERUSER" : "NORMAL");
metrics.setPrivilegeLevel(isSuperuser ? "SUPERUSER" : "NORMAL");
if (!targetIds.isEmpty()) {
metrics.setEppTarget(Joiner.on(",").join(targetIds));
}
@ -74,6 +75,7 @@ public final class EppController {
sessionMetadata,
credentials,
isDryRun,
isSuperuser,
inputXmlBytes,
metrics,
clock);

View file

@ -43,11 +43,12 @@ public class EppRequestHandler {
SessionMetadata sessionMetadata,
TransportCredentials credentials,
boolean isDryRun,
boolean isSuperuser,
byte[] inputXmlBytes) {
try {
response.setPayload(new String(
eppController.handleEppCommand(
sessionMetadata, credentials, isDryRun, inputXmlBytes), UTF_8));
sessionMetadata, credentials, isDryRun, isSuperuser, 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

View file

@ -50,6 +50,7 @@ public class EppTlsAction implements Runnable {
new HttpSessionMetadata(session),
tlsCredentials,
false, // This endpoint is never a dry run.
false, // This endpoint is never a superuser.
inputXmlBytes);
}
}

View file

@ -39,8 +39,8 @@ import javax.servlet.http.HttpServletRequest;
public class EppToolAction implements Runnable {
@Inject @Parameter("clientIdentifier") String clientIdentifier;
@Inject @Parameter("superuser") boolean superuser;
@Inject @Parameter("dryRun") boolean dryRun;
@Inject @Parameter("superuser") boolean isSuperuser;
@Inject @Parameter("dryRun") boolean isDryRun;
@Inject @Parameter("xml") String xml;
@Inject EppRequestHandler eppRequestHandler;
@Inject EppToolAction() {}
@ -50,11 +50,11 @@ public class EppToolAction implements Runnable {
eppRequestHandler.executeEpp(
new StatelessRequestSessionMetadata(
clientIdentifier,
superuser,
ProtocolDefinition.getVisibleServiceExtensionUris(),
SessionSource.TOOL),
new PasswordOnlyTransportCredentials(),
dryRun,
isDryRun,
isSuperuser,
xml.getBytes(UTF_8));
}

View file

@ -48,7 +48,7 @@ public abstract class Flow {
protected byte[] inputXmlBytes;
/** Whether this flow is being run in a superuser mode that can skip some checks. */
protected boolean superuser;
protected boolean isSuperuser;
/** The collection of allowed extensions for the flow. */
private Set<Class<? extends CommandExtension>> validExtensions = new HashSet<>();
@ -103,6 +103,7 @@ public abstract class Flow {
Trid trid,
SessionMetadata sessionMetadata,
TransportCredentials credentials,
boolean isSuperuser,
DateTime now,
byte[] inputXmlBytes) throws EppException {
this.eppInput = eppInput;
@ -110,7 +111,7 @@ public abstract class Flow {
this.sessionMetadata = sessionMetadata;
this.credentials = credentials;
this.now = now;
this.superuser = sessionMetadata.isSuperuser();
this.isSuperuser = isSuperuser;
this.inputXmlBytes = inputXmlBytes;
initFlow();
validExtensions = ImmutableSet.copyOf(validExtensions);

View file

@ -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", 6);
private static final String COMMAND_LOG_FORMAT = "EPP Command" + Strings.repeat("\n\t%s", 7);
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
@ -45,6 +45,7 @@ public class FlowRunner {
private final Trid trid;
private final SessionMetadata sessionMetadata;
private final boolean isDryRun;
private final boolean isSuperuser;
private final TransportCredentials credentials;
private final byte[] inputXmlBytes;
private final EppMetrics metrics;
@ -57,6 +58,7 @@ public class FlowRunner {
SessionMetadata sessionMetadata,
TransportCredentials credentials,
boolean isDryRun,
boolean isSuperuser,
byte[] inputXmlBytes,
final EppMetrics metrics,
Clock clock) {
@ -67,6 +69,7 @@ public class FlowRunner {
this.sessionMetadata = sessionMetadata;
this.credentials = credentials;
this.isDryRun = isDryRun;
this.isSuperuser = isSuperuser;
this.inputXmlBytes = inputXmlBytes;
this.metrics = metrics;
this.clock = clock;
@ -81,7 +84,8 @@ public class FlowRunner {
sessionMetadata,
prettyPrint(inputXmlBytes).replaceAll("\n", "\n\t"),
credentials,
isDryRun ? "DRY_RUN" : "LIVE");
isDryRun ? "DRY_RUN" : "LIVE",
isSuperuser ? "SUPERUSER" : "NORMAL");
if (!isTransactional()) {
if (metrics != null) {
metrics.incrementAttempts();
@ -93,7 +97,7 @@ public class FlowRunner {
// before it could log.
logger.info("EPP_Mutation " + new JsonLogStatement(trid)
.add("client", clientId)
.add("privileges", sessionMetadata.isSuperuser() ? "SUPERUSER" : "NORMAL")
.add("privileges", isSuperuser ? "SUPERUSER" : "NORMAL")
.add("xmlBytes", base64().encode(inputXmlBytes)));
try {
EppOutput flowResult = ofy().transact(new Work<EppOutput>() {
@ -134,6 +138,7 @@ public class FlowRunner {
trid,
sessionMetadata,
credentials,
isSuperuser,
now,
inputXmlBytes);
}

View file

@ -95,7 +95,7 @@ public abstract class LoggedInFlow extends Flow {
getClientId(), getClass().getSimpleName(), undeclaredUris);
}
}
if (sessionMetadata.isSuperuser()) {
if (isSuperuser) {
allowedTlds = getTlds();
} else {
Registrar registrar = verifyNotNull(

View file

@ -31,7 +31,7 @@ public abstract class OwnedResourceMutateFlow
/** Fail if the object doesn't exist or was deleted. */
@Override
protected final void verifyMutationAllowed() throws EppException {
if (!superuser) {
if (!isSuperuser) {
verifyResourceOwnership(getClientId(), existingResource);
}
verifyMutationOnOwnedResourceAllowed();

View file

@ -78,7 +78,7 @@ public abstract class ResourceCreateOrMutateFlow
.setTrid(trid)
.setModificationTime(now)
.setXmlBytes(storeXmlInHistoryEntry() ? inputXmlBytes : null)
.setBySuperuser(superuser)
.setBySuperuser(isSuperuser)
.setReason(getHistoryEntryReason())
.setRequestedByRegistrar(getHistoryEntryRequestedByRegistrar())
.setParent(getResourceKey())

View file

@ -67,7 +67,7 @@ public abstract class ResourceFlow<R extends EppResource, C extends ResourceComm
* a domain) is allowed in the registry phase for the specified TLD that the resource is in.
*/
protected void checkRegistryStateForTld(String tld) throws BadCommandForRegistryPhaseException {
if (!superuser && getDisallowedTldStates().contains(Registry.get(tld).getTldState(now))) {
if (!isSuperuser && getDisallowedTldStates().contains(Registry.get(tld).getTldState(now))) {
throw new BadCommandForRegistryPhaseException();
}
}

View file

@ -61,7 +61,7 @@ public abstract class ResourceUpdateFlow
for (StatusValue statusValue : Sets.union(
command.getInnerAdd().getStatusValues(),
command.getInnerRemove().getStatusValues())) {
if (!superuser && !statusValue.isClientSettable()) { // The superuser can set any status.
if (!isSuperuser && !statusValue.isClientSettable()) { // The superuser can set any status.
throw new StatusNotClientSettableException(statusValue.getXmlName());
}
}
@ -85,7 +85,7 @@ public abstract class ResourceUpdateFlow
protected final void verifyNewStateIsAllowed() throws EppException {
// If the resource is marked with clientUpdateProhibited, and this update did not clear that
// status, then the update must be disallowed (unless a superuser is requesting the change).
if (!superuser
if (!isSuperuser
&& existingResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)
&& newResource.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) {
throw new ResourceHasClientUpdateProhibitedException();

View file

@ -49,9 +49,6 @@ public abstract class SessionMetadata {
/** The key used for looking up the current client id on the session object. */
protected static final String CLIENT_ID_KEY = "CLIENT_ID";
/** The key used for looking up the superuser bit on the session object. */
protected static final String SUPERUSER_KEY = "SUPERUSER";
/** The key used for looking up the service extensions on the session object. */
protected static final String SERVICE_EXTENSIONS_KEY = "SERVICE_EXTENSIONS";
@ -93,10 +90,6 @@ public abstract class SessionMetadata {
return getProperty(String.class, CLIENT_ID_KEY);
}
public boolean isSuperuser() {
return Boolean.TRUE.equals(getProperty(Boolean.class, SUPERUSER_KEY));
}
@SuppressWarnings("unchecked")
public Set<String> getServiceExtensionUris() {
return getProperty(Set.class, SERVICE_EXTENSIONS_KEY);
@ -116,10 +109,6 @@ public abstract class SessionMetadata {
setPropertyChecked(CLIENT_ID_KEY, clientId);
}
public void setSuperuser(boolean superuser) {
setPropertyChecked(SUPERUSER_KEY, superuser);
}
public void setServiceExtensionUris(Set<String> serviceExtensionUris) {
setPropertyChecked(SERVICE_EXTENSIONS_KEY, checkNotNull(serviceExtensionUris));
}
@ -142,7 +131,6 @@ public abstract class SessionMetadata {
return toStringHelper(getClass())
.add("system hash code", System.identityHashCode(this))
.add("clientId", getClientId())
.add("isSuperuser", isSuperuser())
.add("failedLoginAttempts", getFailedLoginAttempts())
.add("sessionSource", getSessionSource())
.add("serviceExtensionUris", Joiner.on('.').join(nullToEmpty(getServiceExtensionUris())))

View file

@ -20,17 +20,14 @@ import java.util.Set;
public class StatelessRequestSessionMetadata extends SessionMetadata {
private final String clientId;
private final boolean isSuperuser;
private final Set<String> serviceExtensionUris;
private final SessionSource sessionSource;
public StatelessRequestSessionMetadata(
String clientId,
boolean isSuperuser,
Set<String> serviceExtensionUris,
SessionSource source) {
this.clientId = clientId;
this.isSuperuser = isSuperuser;
this.serviceExtensionUris = serviceExtensionUris;
this.sessionSource = source;
}
@ -40,11 +37,6 @@ public class StatelessRequestSessionMetadata extends SessionMetadata {
return clientId;
}
@Override
public boolean isSuperuser() {
return isSuperuser;
}
@Override
public Set<String> getServiceExtensionUris() {
return serviceExtensionUris;

View file

@ -77,7 +77,7 @@ public class ContactDeleteFlow extends ResourceAsyncDeleteFlow<ContactResource,
DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID,
getClientId(),
DeleteEppResourceAction.PARAM_IS_SUPERUSER,
Boolean.toString(superuser)),
Boolean.toString(isSuperuser)),
RegistryEnvironment.get().config().getAsyncDeleteFlowMapreduceDelay());
}

View file

@ -187,7 +187,7 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
domainLabel, tld, command.getAuthInfo().getPw().getValue());
// Superusers can create reserved domains, force creations on domains that require a claims
// notice without specifying a claims key, and override blocks on registering premium domains.
if (!superuser) {
if (!isSuperuser) {
boolean isSunriseApplication =
launchCreate != null && !launchCreate.getSignedMarks().isEmpty();
if (!isAnchorTenantViaReservation) {
@ -254,7 +254,7 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
if (launchCreate == null) {
return;
}
if (!superuser) { // Superusers can ignore the phase.
if (!isSuperuser) { // Superusers can ignore the phase.
verifyLaunchPhase(getTld(), launchCreate, now);
}
if (launchCreate.hasCodeMarks()) {
@ -269,7 +269,7 @@ public abstract class BaseDomainCreateFlow<R extends DomainBase, B extends Build
throw new InvalidTrademarkValidatorException();
}
// Superuser can force domain creations regardless of the current date.
if (!superuser) {
if (!isSuperuser) {
if (notice.getExpirationTime().isBefore(now)) {
throw new ExpiredClaimException();
}

View file

@ -73,7 +73,7 @@ public class DomainAllocateFlow extends DomainCreateOrAllocateFlow {
@Override
protected final void verifyDomainCreateIsAllowed() throws EppException {
if (!superuser) {
if (!isSuperuser) {
throw new OnlySuperuserCanAllocateException();
}
if (allocateCreate == null) {

View file

@ -140,7 +140,7 @@ public class DomainApplicationCreateFlow extends BaseDomainCreateFlow<DomainAppl
@Override
protected void verifyDomainCreateIsAllowed() throws EppException {
validateFeeChallenge(targetId, getTld(), now, feeCreate, createCost);
if (tldState == TldState.LANDRUSH && !superuser) {
if (tldState == TldState.LANDRUSH && !isSuperuser) {
// Prohibit creating a landrush application in LANDRUSH (but not in SUNRUSH) if there is
// exactly one sunrise application for the same name.
List<DomainApplication> applications = FluentIterable

View file

@ -66,7 +66,7 @@ public class DomainApplicationDeleteFlow
// Don't allow deleting a sunrise application during landrush.
if (existingResource.getPhase().equals(LaunchPhase.SUNRISE)
&& Registry.get(existingResource.getTld()).getTldState(now).equals(TldState.LANDRUSH)
&& !superuser) {
&& !isSuperuser) {
throw new SunriseApplicationCannotBeDeletedInLandrushException();
}
}

View file

@ -109,7 +109,7 @@ public class DomainCreateFlow extends DomainCreateOrAllocateFlow {
protected final void verifyDomainCreateIsAllowed() throws EppException {
String tld = getTld();
validateFeeChallenge(targetId, tld, now, feeCreate, createCost);
if (!superuser) {
if (!isSuperuser) {
// Prohibit creating a domain if there is an open application for the same name.
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
if (!application.getApplicationStatus().isFinalStatus()) {

View file

@ -97,7 +97,7 @@ public class DomainRestoreRequestFlow extends OwnedResourceMutateFlow<DomainReso
String tld = existingResource.getTld();
checkAllowedAccessToTld(getAllowedTlds(), tld);
if (!superuser) {
if (!isSuperuser) {
verifyNotReserved(InternetDomainName.from(targetId), false);
verifyPremiumNameIsNotBlocked(targetId, now, getClientId());
}

View file

@ -152,7 +152,7 @@ public class DomainTransferRequestFlow
@Override
protected final void verifyTransferRequestIsAllowed() throws EppException {
verifyUnitIsYears(command.getPeriod());
if (!superuser) {
if (!isSuperuser) {
verifyPremiumNameIsNotBlocked(targetId, now, getClientId());
}
validateFeeChallenge(

View file

@ -77,7 +77,7 @@ public class HostDeleteFlow extends ResourceAsyncDeleteFlow<HostResource, Builde
DeleteEppResourceAction.PARAM_REQUESTING_CLIENT_ID,
getClientId(),
DeleteEppResourceAction.PARAM_IS_SUPERUSER,
Boolean.toString(superuser)),
Boolean.toString(isSuperuser)),
RegistryEnvironment.get().config().getAsyncDeleteFlowMapreduceDelay());
}

View file

@ -39,7 +39,6 @@ import google.registry.model.eppoutput.Result.Code;
import google.registry.model.registrar.Registrar;
import google.registry.util.FormattingLogger;
import java.util.Objects;
import java.util.Set;
/**
@ -66,9 +65,6 @@ public class LoginFlow extends Flow {
private static final FormattingLogger logger = FormattingLogger.getLoggerForCallerClass();
/** This is the IANA ID used for the internal account of the registry. */
private static final long INTERNAL_IANA_REGISTRAR_ID = 9999L;
/** Maximum number of failed login attempts allowed per connection. */
private static final int MAX_FAILED_LOGIN_ATTEMPTS_PER_CONNECTION = 3;
@ -134,8 +130,6 @@ public class LoginFlow extends Flow {
// We are in!
sessionMetadata.resetFailedLoginAttempts();
sessionMetadata.setClientId(login.getClientId());
sessionMetadata.setSuperuser(
Objects.equals(INTERNAL_IANA_REGISTRAR_ID, registrar.getIanaIdentifier()));
sessionMetadata.setServiceExtensionUris(serviceExtensionUrisBuilder.build());
return createOutput(Code.Success);
}

View file

@ -110,6 +110,7 @@ final class ValidateLoginCredentialsCommand implements RemoteApiCommand, GtechCo
Optional.of(clientIpAddress),
"placeholder"), // behave as if we have SNI on, since we're validating a cert
false,
false,
inputXmlBytes,
null,
new SystemClock()).run()), UTF_8));

View file

@ -80,7 +80,6 @@ public class CheckApiAction implements Runnable {
private final StatelessRequestSessionMetadata sessionMetadata =
new StatelessRequestSessionMetadata(
RegistryEnvironment.get().config().getCheckApiServletRegistrarClientId(),
false,
ImmutableSet.of(FEE_0_6.getUri()),
SessionSource.HTTP);
@ -121,6 +120,7 @@ public class CheckApiAction implements Runnable {
sessionMetadata,
new PasswordOnlyTransportCredentials(),
false,
false,
inputXmlBytes,
null,
clock)