package org.dcache.gplazma.monitor;
import com.google.common.collect.Sets;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.dcache.gplazma.configuration.ConfigurationItemControl;
import org.dcache.gplazma.monitor.LoginMonitor.Result;
import static com.google.common.base.Preconditions.checkState;
/**
* This class holds a detailed report of the activity when gPlazma processes
* a login request.
*/
public class LoginResult
{
private final AuthPhaseResult _authPhase = new AuthPhaseResult();
private final MapPhaseResult _mapPhase = new MapPhaseResult();
private final AccountPhaseResult _accountPhase = new AccountPhaseResult();
private final SessionPhaseResult _sessionPhase = new SessionPhaseResult();
private Result _validationResult;
private String _validationError = "unknown";
private boolean _validationHasHappened;
public AuthPhaseResult getAuthPhase()
{
return _authPhase;
}
public MapPhaseResult getMapPhase()
{
return _mapPhase;
}
public AccountPhaseResult getAccountPhase()
{
return _accountPhase;
}
public SessionPhaseResult getSessionPhase()
{
return _sessionPhase;
}
public void setValidationResult(Result result)
{
_validationHasHappened = true;
_validationResult = result;
}
public Result getValidationResult()
{
return _validationResult;
}
public boolean hasValidationHappened()
{
return _validationHasHappened;
}
public void setValidationError(String error)
{
_validationError = error;
}
public String getValidationError()
{
checkState(_validationResult == Result.FAIL, "Validation error is "+
"only valid if the plugin has failed");
return _validationError;
}
/**
* Returns whether gPlazma started processing the login request represent
* by this LoginResult object.
*
* A login request may fail before the first phase was attempted. This can
* happen, for examples, if the gPlazma configuration is syntactically
* wrong or one of the plugins fails when being instantiated (throws an
* exception when being instantiated).
*/
public boolean hasStarted()
{
return getAuthPhase().hasHappened();
}
/**
* Returns whether gPlazma finished all four phases of the login process.
*
* This is not the same as the login being successful. This value will
* return true yet the login has failed if the session phase or the final
* validation step fails.
*/
public boolean hasCompleted()
{
return getSessionPhase().hasHappened();
}
/**
* Base class for storing the result of running a phase.
* @param <T> the class for storing the result of running a plugin
*/
public static class PhaseResult<T extends PAMPluginResult>
{
private final List<T> _plugins = new ArrayList<>();
private final String _name;
private SetDiff<Principal> _principals;
private Result _result;
private boolean _hasHappened;
public PhaseResult(String name)
{
_name = name;
}
public String getName()
{
return _name;
}
public void addPluginResult(T result)
{
_plugins.add(result);
}
public List<T> getPluginResults()
{
return _plugins;
}
public boolean hasPlugins()
{
return !_plugins.isEmpty();
}
public T getLastPlugin()
{
return _plugins.get(_plugins.size() - 1);
}
public void setPrincipals(Set<Principal> before, Set<Principal> after)
{
_principals = new SetDiff<>(before, after);
}
public SetDiff<Principal> getPrincipals()
{
return _principals;
}
public void setResult(Result result)
{
_result = result;
_hasHappened = true;
}
public Result getResult()
{
return _result;
}
public boolean hasHappened()
{
return _hasHappened;
}
}
/**
* Class that stores the result of the AUTH phase.
*/
public static class AuthPhaseResult extends PhaseResult<AuthPluginResult>
{
private final Set<Object> _publicCredentials = new HashSet<>();
private final Set<Object> _privateCredentials = new HashSet<>();
public AuthPhaseResult()
{
super("AUTH");
}
public void setPublicCredentials(Set<Object> publicCredentials)
{
_publicCredentials.clear();
_publicCredentials.addAll(publicCredentials);
}
public void setPrivateCredentials(Set<Object> privateCredentials)
{
_privateCredentials.clear();
_privateCredentials.addAll(privateCredentials);
}
public Set<Object> getPublicCredentials()
{
return _publicCredentials;
}
public Set<Object> getPrivateCredentials()
{
return _privateCredentials;
}
}
/**
* Class that stores the result of the MAP phase
*/
public static class MapPhaseResult extends PhaseResult<MapPluginResult>
{
public MapPhaseResult()
{
super("MAP");
}
}
/**
* Class that stores the result of the ACCOUNT phase.
*/
public static class AccountPhaseResult
extends PhaseResult<AccountPluginResult>
{
public AccountPhaseResult()
{
super("ACCOUNT");
}
}
/**
* Class that stores the result of the SESSION phase
*/
public static class SessionPhaseResult
extends PhaseResult<SessionPluginResult>
{
private final Set<Object> _attributes = new HashSet<>();
public SessionPhaseResult()
{
super("SESSION");
}
void setAttributes(Set<Object> attributes)
{
_attributes.clear();
_attributes.addAll(attributes);
}
public Set<Object> getAttributes()
{
return _attributes;
}
}
/**
* Store two sets (with same Generics interface) and allow discovery of
* how the objects has changed.
*/
public static class SetDiff<T>
{
private final Set<T> _before;
private final Set<T> _after;
SetDiff(Iterable<T> before, Iterable<T> after)
{
_before = Sets.newHashSet(before);
_after = Sets.newHashSet(after);
}
public Set<T> getBefore()
{
return _before;
}
public Set<T> getAfter()
{
return _after;
}
public Set<T> getAdded()
{
Set<T> added = new HashSet<>(_after);
added.removeAll(_before);
return added;
}
public Set<T> getRemoved()
{
Set<T> removed = new HashSet<>(_before);
removed.removeAll(_after);
return removed;
}
}
/**
* Class for holding the result of running a PAM-style plugin,
* irrespective of in which phase the plugin was run. This serves as a
* base class for phase-specific result classes
*
* If a plugin fails then there should be an associated error message.
*/
public static class PAMPluginResult
{
private final String _name;
private final ConfigurationItemControl _control;
private Result _result;
private String _error = "unknown";
PAMPluginResult(String name, ConfigurationItemControl control)
{
_name = name;
_control = control;
}
void setResult(Result result)
{
_result = result;
}
void setError(String error)
{
_error = error;
}
public String getName()
{
return _name;
}
public ConfigurationItemControl getControl()
{
return _control;
}
public Result getResult()
{
return _result;
}
/**
* Provide the error message the plugin supplied if a call fails.
*/
public String getError()
{
checkState(_result == Result.FAIL, "error message only available "
+ "if the plugin failed");
return _error;
}
}
/**
* Store the result of an AUTH plugin
*/
public static class AuthPluginResult extends PAMPluginResult
{
private SetDiff<Principal> _identified;
private SetDiff<Object> _publicCredentials;
private SetDiff<Object> _privateCredentials;
AuthPluginResult(String name, ConfigurationItemControl control)
{
super(name, control);
}
public void setIdentified(Set<Principal> before, Set<Principal> after)
{
_identified = new SetDiff<>(before, after);
}
public void setPublicCredentials(Set<Object> before, Set<Object> after)
{
_publicCredentials = new SetDiff<>(before, after);
}
public void setPrivateCredentials(Set<Object> before, Set<Object> after)
{
_privateCredentials = new SetDiff<>(before, after);
}
public SetDiff<Principal> getIdentified()
{
return _identified;
}
public SetDiff<Object> getPublicCredentials()
{
return _publicCredentials;
}
public SetDiff<Object> getPrivateCredentials()
{
return _privateCredentials;
}
}
/**
* Store the result of running a MAP plugin
*/
public static class MapPluginResult extends PAMPluginResult
{
private SetDiff<Principal> _principals;
MapPluginResult(String name, ConfigurationItemControl control)
{
super(name, control);
}
public void setPrincipals(Iterable<Principal> before, Iterable<Principal> after)
{
_principals = new SetDiff<>(before, after);
}
public SetDiff<Principal> getPrincipals()
{
return _principals;
}
}
/**
* Store the result of running an ACCOUNT plugin
*/
public static class AccountPluginResult extends PAMPluginResult
{
private SetDiff<Principal> _authorized;
AccountPluginResult(String name, ConfigurationItemControl control)
{
super(name, control);
}
void setAuthorized(Set<Principal> before, Set<Principal> after)
{
_authorized = new SetDiff<>(before, after);
}
public SetDiff<Principal> getAuthorized()
{
return _authorized;
}
}
/**
* Store the result of running a SESSION plugin.
*/
public static class SessionPluginResult extends PAMPluginResult
{
private SetDiff<Principal> _principals;
private Set<Object> _attributes;
SessionPluginResult(String name, ConfigurationItemControl control)
{
super(name, control);
}
public void setAuthorized(Set<Principal> before, Set<Principal> after)
{
_principals = new SetDiff<>(before, after);
}
public SetDiff<Principal> getAuthorized()
{
return _principals;
}
public void setAttributes(Set<Object> attributes)
{
_attributes = new HashSet<>(attributes);
}
public Set<Object> getAttributes()
{
return _attributes;
}
}
}