VIVO-660 Add an Authorization tabs to the developer panel

This commit is contained in:
j2blake 2014-01-07 15:08:30 -05:00
parent 0f0cac5d35
commit 54509b1aee
7 changed files with 285 additions and 60 deletions

View file

@ -0,0 +1,176 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.policy;
import static edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization.INCONCLUSIVE;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
import edu.cornell.mannlib.vitro.webapp.utils.developer.DeveloperSettings;
import edu.cornell.mannlib.vitro.webapp.utils.developer.Key;
/**
* If enabled in the developer settings (and log levels), log each
* PolicyDecision (subject to restrictions).
*
* Some restrictions apply to the logger as a whole. Others apply to the
* particular policy or the particular decision.
*/
public class PolicyDecisionLogger {
private static final Log log = LogFactory
.getLog(PolicyDecisionLogger.class);
private static final Pattern NEVER_MATCHES = Pattern.compile("^__NEVER__$");
private static final BasicPolicyDecision NULL_DECISION = new BasicPolicyDecision(
INCONCLUSIVE, "The decision was null.");
private final DeveloperSettings settings;
private final RequestedAction whatToAuth;
private final IdentifierBundle whoToAuth;
private final boolean enabled;
private final Pattern policyRestriction;
private final boolean skipInconclusive;
private final boolean includeIdentifiers;
public PolicyDecisionLogger(IdentifierBundle whoToAuth,
RequestedAction whatToAuth) {
this.settings = DeveloperSettings.getInstance();
this.whoToAuth = whoToAuth;
this.whatToAuth = whatToAuth;
this.enabled = figureEnabled();
this.policyRestriction = figurePolicyRestriction();
this.skipInconclusive = figureSkipInconclusive();
this.includeIdentifiers = figureIncludeIdentifiers();
}
private boolean figureEnabled() {
return log.isInfoEnabled()
&& settings.getBoolean(Key.AUTHORIZATION_LOG_DECISIONS_ENABLE)
&& passesUserRestriction() && passesActionRestriction();
}
/**
* The identifier bundle passes if there is no restriction, or if the
* restriction pattern is found within concatenated string of the identifier
* bundle.
*
* If the restriction is invalid, the action fails.
*/
private boolean passesUserRestriction() {
Pattern userRestriction = compilePatternFromSetting(Key.AUTHORIZATION_LOG_DECISIONS_USER_RESTRICTION);
return userRestriction == null
|| userRestriction.matcher(String.valueOf(whoToAuth)).find();
}
/**
* The requested action passes if there is no restriction, or if the
* restriction pattern is found within the class name of the action.
*
* If the restriction is invalid, the action fails.
*/
private boolean passesActionRestriction() {
Pattern actionRestriction = compilePatternFromSetting(Key.AUTHORIZATION_LOG_DECISIONS_ACTION_RESTRICTION);
return actionRestriction == null
|| actionRestriction.matcher(String.valueOf(whatToAuth)).find();
}
/**
* Only compile the policy restriction pattern once.
*/
private Pattern figurePolicyRestriction() {
return compilePatternFromSetting(Key.AUTHORIZATION_LOG_DECISIONS_POLICY_RESTRICTION);
}
/**
* Do we log inconclusive decisions?
*/
private boolean figureSkipInconclusive() {
return settings
.getBoolean(Key.AUTHORIZATION_LOG_DECISIONS_SKIP_INCONCLUSIVE);
}
/**
* Do we include Identifiers in the log record?
*/
private boolean figureIncludeIdentifiers() {
return settings
.getBoolean(Key.AUTHORIZATION_LOG_DECISIONS_ADD_IDENTIFERS);
}
/**
* If no pattern was provided, return null. If an invalid pattern was
* provided, return a pattern that never matches.
*/
private Pattern compilePatternFromSetting(Key key) {
String setting = settings.getString(key);
if (setting.isEmpty()) {
return null;
} else {
try {
return Pattern.compile(setting);
} catch (Exception e) {
return NEVER_MATCHES;
}
}
}
/**
* If the logger and the policy and the decision all pass the restrictions,
* write to the log. A null decision is treated as inconclusive.
*/
public void log(PolicyIface policy, PolicyDecision pd) {
if (passesRestrictions(String.valueOf(policy), pd)) {
if (this.includeIdentifiers) {
log.info(String.format(
"Decision on %s by %s was %s; user is %s",
this.whatToAuth, policy, pd, this.whoToAuth));
} else {
log.info(String.format("Decision on %s by %s was %s",
this.whatToAuth, policy, pd));
}
}
}
private boolean passesRestrictions(String policyString, PolicyDecision pd) {
if (pd == null) {
pd = NULL_DECISION;
}
return enabled && passesPolicyRestriction(policyString)
&& passesConclusiveRestriction(pd);
}
private boolean passesPolicyRestriction(String policyString) {
return this.policyRestriction == null
|| this.policyRestriction.matcher(policyString).find();
}
private boolean passesConclusiveRestriction(PolicyDecision pd) {
return !(skipInconclusive && isInconclusive(pd));
}
private boolean isInconclusive(PolicyDecision pd) {
return pd == null || pd.getAuthorized() == INCONCLUSIVE;
}
public void logNoDecision(PolicyDecision pd) {
if (enabled) {
if (this.includeIdentifiers) {
log.info(pd.getMessage() + "; user is " + this.whoToAuth);
} else {
log.info(pd.getMessage());
}
}
}
}

View file

@ -103,14 +103,16 @@ public class PolicyList extends ArrayList<PolicyIface> implements PolicyIface{
protected PolicyDecision checkAgainstPolicys( IdentifierBundle whoToAuth, RequestedAction whatToAuth){
PolicyDecision pd = null;
PolicyDecisionLogger logger = new PolicyDecisionLogger(whoToAuth, whatToAuth);
for(PolicyIface policy : this){
try{
pd = policy.isAuthorized(whoToAuth, whatToAuth);
logger.log(policy, pd);
if( pd != null ){
if( pd.getAuthorized() == Authorization.AUTHORIZED )
break;
return pd;
if( pd.getAuthorized() == Authorization.UNAUTHORIZED )
break;
return pd;
if( pd.getAuthorized() == Authorization.INCONCLUSIVE )
continue;
} else{
@ -120,8 +122,11 @@ public class PolicyList extends ArrayList<PolicyIface> implements PolicyIface{
log.error("ignoring exception in policy " + policy.toString(), th );
}
}
log.debug("decision " + pd + " for " + whatToAuth);
return pd;
pd = new BasicPolicyDecision(Authorization.INCONCLUSIVE,
"No policy returned a conclusive decision on " + whatToAuth);
logger.logNoDecision(pd);
return pd;
}
}

View file

@ -205,6 +205,7 @@ public class DeveloperSettings {
Properties dsProps = new Properties();
dsProps.load(reader);
devSettings.updateFromProperties(dsProps);
log.info(devSettings);
ss.info(this, "Loaded the 'developer.properties' file: "
+ devSettings);
} catch (FileNotFoundException e) {

View file

@ -24,7 +24,7 @@ public enum Key {
ENABLED("developer.enabled", true),
/**
* If the developer panel is enabled, can a non-logged-in user change the
* If the developer panel is enabled, may an anonymous user change the
* settings?
*/
PERMIT_ANONYMOUS_CONTROL("developer.permitAnonymousControl", true),
@ -84,7 +84,45 @@ public enum Key {
* Tell the ShortViewLogger to note the use of non-default short views.
*/
PAGE_CONTENTS_LOG_CUSTOM_SHORT_VIEW(
"developer.pageContents.logCustomShortView", true);
"developer.pageContents.logCustomShortView", true),
/**
* Enable the PolicyDecisionLogger.
*/
AUTHORIZATION_LOG_DECISIONS_ENABLE(
"developer.authorization.logDecisions.enable", true),
/**
* Enable the PolicyDecisionLogger.
*/
AUTHORIZATION_LOG_DECISIONS_ADD_IDENTIFERS(
"developer.authorization.logDecisions.addIdentifiers", true),
/**
* Enable the PolicyDecisionLogger.
*/
AUTHORIZATION_LOG_DECISIONS_SKIP_INCONCLUSIVE(
"developer.authorization.logDecisions.skipInconclusive", true),
/**
* Don't log policy decisions unless the requested action meets this
* restriction.
*/
AUTHORIZATION_LOG_DECISIONS_ACTION_RESTRICTION(
"developer.authorization.logDecisions.actionRestriction", false),
/**
* Don't log policy decisions unless the identifier bundle meets this
* restriction.
*/
AUTHORIZATION_LOG_DECISIONS_USER_RESTRICTION(
"developer.authorization.logDecisions.userRestriction", false),
/**
* Don't log policy decisions unless the policy meets this restriction.
*/
AUTHORIZATION_LOG_DECISIONS_POLICY_RESTRICTION(
"developer.authorization.logDecisions.policyRestriction", false);
private static final Log log = LogFactory.getLog(Key.class);
private final String propertyName;