package org.ovirt.engine.api.restapi.security.auth;
import java.util.List;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.annotations.interception.Precedence;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.interception.PostProcessInterceptor;
import org.ovirt.engine.api.common.security.auth.Validator;
import org.ovirt.engine.api.common.security.auth.Principal;
import org.ovirt.engine.api.common.invocation.Current;
import org.ovirt.engine.api.common.invocation.MetaData;
import org.ovirt.engine.api.restapi.util.SessionHelper;
import org.ovirt.engine.core.common.action.LoginUserParameters;
import org.ovirt.engine.core.common.action.LogoutUserParameters;
import org.ovirt.engine.core.common.action.VdcActionType;
import org.ovirt.engine.core.common.action.VdcReturnValueBase;
import org.ovirt.engine.core.common.interfaces.BackendLocal;
import org.ovirt.engine.core.common.users.VdcUser;
import org.ovirt.engine.core.compat.LogCompat;
import org.ovirt.engine.core.compat.LogFactoryCompat;
@Provider
@ServerInterceptor
@Precedence("SECURITY")
public class LoginValidator implements Validator, PostProcessInterceptor {
protected static final LogCompat LOG = LogFactoryCompat.getLog(LoginValidator.class);
// do not log passwords
protected static final String LOGIN_SUCCESS = "Login success, user: {0} domain: {1}";
protected static final String LOGIN_FAILURE = "Login failure, user: {0} domain: {1} reason: {2}";
protected static final String NO_DOMAIN = "Missing domain component in User Principal Name (UPN)";
private BackendLocal backend;
private Current current;
private SessionHelper sessionHelper;
public void setBackend(BackendLocal backend) {
this.backend = backend;
}
public void setCurrent(Current current) {
this.current = current;
}
public void setSessionHelper(SessionHelper sessionHelper) {
this.sessionHelper = sessionHelper;
}
@Override
public boolean validate(Principal principal) {
if (principal.getDomain() == null) {
return loginFailure(principal, NO_DOMAIN);
}
LoginUserParameters params = new LoginUserParameters(principal.getUser(),
principal.getSecret(),
principal.getDomain(),
null, null, null);
params.setActionType(VdcActionType.LoginAdminUser);
VdcReturnValueBase ret = backend.Login(sessionHelper.sessionize(params, principal));
if (ret.getCanDoAction() && ret.getSucceeded()) {
return loginSuccess(principal, ret);
} else {
return loginFailure(principal, reasons(ret));
}
}
private boolean loginSuccess(Principal principal, VdcReturnValueBase ret) {
LOG.debugFormat(LOGIN_SUCCESS, principal.getUser(), principal.getDomain());
// cache VdcUser in Current so that it will be available
// for logoff action on postProcess() traversal
current.set(ret.getActionReturnValue());
return true;
}
private boolean loginFailure(Principal principal, List<String> reasons) {
return loginFailure(principal, reasons != null ? reasons.toString() : null);
}
private boolean loginFailure(Principal principal, String reason) {
LOG.infoFormat(LOGIN_FAILURE, principal.getUser(), principal.getDomain(), reason);
return false;
}
private List<String> reasons(VdcReturnValueBase ret) {
return ret.getCanDoAction() ? ret.getExecuteFailedMessages() : ret.getCanDoActionMessages();
}
@Override
public void postProcess(ServerResponse response) {
if (!current.get(MetaData.class).hasKey("async") ||
((Boolean)current.get(MetaData.class).get("async")) != Boolean.TRUE) {
VdcUser user = current.get(VdcUser.class);
if (user != null) {
backend.Logoff(
sessionHelper.sessionize(new LogoutUserParameters(user.getUserId())));
}
sessionHelper.clean();
}
}
}