com.novartis.opensource.yada.plugin.AbstractPreprocessor Maven / Gradle / Ivy
/**
* Copyright 2016 Novartis Institutes for BioMedical Research Inc.
* 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 com.novartis.opensource.yada.plugin;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.Cookie;
import com.novartis.opensource.yada.ConnectionFactory;
import com.novartis.opensource.yada.YADAConnectionException;
import com.novartis.opensource.yada.YADAQuery;
import com.novartis.opensource.yada.YADARequest;
import com.novartis.opensource.yada.YADASQLException;
import com.novartis.opensource.yada.util.YADAUtils;
/**
* @author David Varon
* @since 0.4.2
*/
public abstract class AbstractPreprocessor implements Preprocess, Validation, TokenValidator, ExecutionPolicy, ContentPolicy
{
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String AUTH_PATH_RX = "auth.path.rx";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String AUTH_TOKEN = "auth.token";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String TOKEN_VALIDATOR = "token.validator";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String CONTENT_POLICY = "content.policy";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String EXECUTION_POLICY = "execution.policy";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String EXECUTION_POLICY_INTERFACE = "ExecutionPolicy";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String CONTENT_POLICY_INTERFACE = "ContentPolicy";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
protected static final String VOID = "void";
/**
* Constant equal to {@value}.
* The query executed to evaluate authorization.
*/
protected static final String YADA_A11N_QUERY =
"SELECT DISTINCT a.target, a.policy, a.type, a.qname "
+ "FROM YADA_A11N a " // join YADA_QUERY b on (a.target = b.qname OR a.target = b.app) "
+ "WHERE a.target = ?";
/**
* Constant equal to {@value}
* @since 7.0.0
*/
private static final String PLUGIN_PKG = "com.novartis.opensource.yada.plugin.";
/**
* The {@link YADARequest} object processed by the plugin
*/
private YADARequest yadaReq;
/**
* The {@link YADAQuery} object processed by the plugin
*/
private YADAQuery yq;
/**
* The authentication token, e.g., user id
* @since 7.0.0
*/
private Object token = null;
/**
* The {@link TokenValidator}
* @since 7.0.0
*/
private TokenValidator tokenValidator;
/**
* The {@link SecurityPolicy}
* @since 7.0.0
*/
private SecurityPolicy securityPolicy;
/**
* The {@code args} {@link List} from {@link YADARequest#getArgs}
* @since 7.0.0
*/
private List args;
/**
* The {@code preArgs} {@link List} from {@link YADARequest#getPreargs}
* @since 7.0.0
* @deprecated as of 7.1.0
*/
@Deprecated
private List preargs;
/**
* Base implementation, calls {@link #setYADARequest(YADARequest)},
* {@link #setArgs(List)}, {@link #setPreargs(List)}
* and returns {@link #getYADARequest()}
* @see com.novartis.opensource.yada.plugin.Preprocess#engage(com.novartis.opensource.yada.YADARequest)
*/
@Override
public YADARequest engage(YADARequest yadaReq) throws YADAPluginException
{
setYADARequest(yadaReq);
String[] args = getYADAQuery().getYADAQueryParamValue(YADARequest.PS_ARGLIST);
if(args != null && args.length > 0)
setArgs(Arrays.asList(args));
else
{
args = getYADAQuery().getYADAQueryParamValue(YADARequest.PS_PREARGS);
if(args != null && args.length > 0)
setPreargs(Arrays.asList(args));
}
return getYADARequest();
}
/**
* Base implementation, calls {@link #setYADARequest(YADARequest)},
* {@link #setArgs(List)}, {@link #setPreargs(List)} using {@link YADAQuery#getYADAQueryParamValue(String)}
* for the last two.
* @see com.novartis.opensource.yada.plugin.Preprocess#engage(com.novartis.opensource.yada.YADARequest, com.novartis.opensource.yada.YADAQuery)
*/
@Override
public void engage(YADARequest yadaReq, YADAQuery yq) throws YADAPluginException, YADASecurityException
{
setYADARequest(yadaReq);
setYADAQuery(yq);
String[] args = getYADAQuery().getYADAQueryParamValue(YADARequest.PS_ARGLIST);
if(args != null && args.length > 0)
setArgs(Arrays.asList(args[0].split(",")));
else
{
args = getYADAQuery().getYADAQueryParamValue(YADARequest.PS_PREARGS);
if(args != null && args.length > 0)
setPreargs(Arrays.asList(args[0].split(",")));
}
}
/**
* Convenience method with calls {@link #validateURL()}, {@link #validateToken()}, {@link #applyExecutionPolicy()}, and {@link #applyContentPolicy()}
* @since 7.0.0
*/
@Override
public void validateYADARequest() throws YADASecurityException
{
// default impl here looks for arg/prearg
validateURL();
// will use argument to inject, if present, or return gracefully
setTokenValidator();
// default impl does nothing
validateToken();
// will use argument to inject, if present, or use current class,
// if interface is implemented, or return gracefully
setSecurityPolicy(EXECUTION_POLICY);
SecurityPolicy policy = getSecurityPolicy();
if(policy != null)
((ExecutionPolicy)policy).applyExecutionPolicy();
// will use argument to inject, if present, or use current class,
// if interface is implemented, or return gracefully
setSecurityPolicy(CONTENT_POLICY);
policy = getSecurityPolicy();
if(policy != null)
((ContentPolicy)policy).applyContentPolicy();
}
/**
* Throws an exception if the URL returned by {@code req.getRequestURL()} is unauthenticated.
* @throws YADAPluginException if a non-authenticated URL is requested
* @since 7.0.0
*/
@Override
public void validateURL() throws YADASecurityException
{
String pathRx = getArgumentValue(AUTH_PATH_RX);
if(pathRx != null && pathRx.length() > 0)
{
String reqUrl = getYADARequest().getRequest().getRequestURL().toString();
if(!reqUrl.matches("^(http://)*"+pathRx+"$")) {
String msg = "Unauthorized. This query requires use of an authenticated address.";
throw new YADASecurityException(msg);
}
}
}
/**
* Default implementation calls {@link TokenValidator#validate()} via injection
* @since 7.0.0
*/
@Override
public void validateToken() throws YADASecurityException
{
// nothing to do
}
/**
* Returns the value of {@code key} from {@link #args}
* or {@link #preargs} or from {@link System#getProperty(String)}
* @param key
* @return the value mapped to {@code key} or an empty {@link String}
* @since 7.0.0
*/
protected String getArgumentValue(String key)
{
String val = "";
if(this.args == null || this.args.size() == 0)
{
if(this.preargs == null || this.preargs.size() == 0)
{
val = System.getProperty(key);
}
else
{
val = getListEntry(this.preargs,key);
}
}
else
{
val = getListEntry(this.args,key);
}
return val;
}
/**
* Retrieves the value part of an argument passed as a name=value pair
*
* @param list the argument parameter list to review
* @param key the name in the argument name=value pair to retrieve
* @return the value mapped to {@code key} or {@code null}
* @since 7.0.0
*/
private String getListEntry(List list, String key)
{
for(int i=0;i clazz = null;
String name = "";
try
{
name = getArgumentValue(TOKEN_VALIDATOR);
if(name.length() == 0) return;
clazz = Class.forName(name);
}
catch (ClassNotFoundException e)
{
try
{
name = PLUGIN_PKG + getArgumentValue(TOKEN_VALIDATOR);
clazz = Class.forName(name);
}
catch (ClassNotFoundException e1)
{
String msg = "Could not find the specified TokenValidator class: " + name + ".";
throw new YADASecurityException(msg,e1);
}
}
try
{
setTokenValidator((TokenValidator)clazz.newInstance());
}
catch (InstantiationException | IllegalAccessException e) {
String msg = "Could not instantiate the specified TokenValidator class: " + name;
throw new YADASecurityException(msg,e);
}
}
}
/**
* Standard mutator for variable
* @param tokenValidator the {@link TokenValidator} instance
* @since 7.0.0
*/
public void setTokenValidator(TokenValidator tokenValidator)
{
this.tokenValidator = tokenValidator;
}
/**
* Standard accessor for variable
* @return the {@link TokenValidotor} instance
* @since 7.0.0
*/
public TokenValidator getTokenValidator()
{
return this.tokenValidator;
}
/**
* Default implementation of {@link SecurityPolicy#applyPolicy()}, intended for override
* @throws YADASecurityException
* @since 7.0.0
*/
@Override
public void applyPolicy() throws YADASecurityException
{
// nothing to do
}
/**
* Default implementation of {@link SecurityPolicy#applyPolicy(SecurityPolicy)}, intended for override
* @throws YADASecurityException
* @since 7.0.0
*/
@Override
public void applyPolicy(SecurityPolicy securityPolicy) throws YADASecurityException
{
// nothing to do
}
/**
* Default implementation of does nothing, intended for override
* @throws YADASecurityException
* @since 7.0.0
*/
@Override
public void applyExecutionPolicy() throws YADASecurityException
{
// nothing to do
}
/**
* Default implementation of does nothing, intended for override
* @throws YADASecurityException
* @since 7.0.0
*/
@Override
public void applyContentPolicy() throws YADASecurityException
{
// nothing to do
}
/**
* @return the args
* @since 7.0.0
*/
public List getArgs() {
return this.args;
}
/**
* @param args the args to set
* @since 7.0.0
*/
public void setArgs(List args)
{
this.args = args;
}
/**
* @return the preargs
* @since 7.0.0
*/
public List getPreArgs() {
return this.preargs;
}
/**
* @param preargs the preargs to set
* @since 7.0.0
* @deprecated as of 7.1.0
*/
@Deprecated
public void setPreargs(List preargs)
{
this.preargs = preargs;
}
/**
* @return the securityPolicy
*/
public SecurityPolicy getSecurityPolicy()
{
return this.securityPolicy;
}
/**
* @param securityPolicy the securityPolicy to set
*/
public void setSecurityPolicy(SecurityPolicy securityPolicy)
{
this.securityPolicy = securityPolicy;
}
/**
* No arg mutator for variable, gets FQCN from args or properties
* @param policyType either {@link #CONTENT_POLICY} or {@link #EXECUTION_POLICY}
* @throws YADASecurityException
* @since 7.0.0
*/
public void setSecurityPolicy(String policyType) throws YADASecurityException
{
if(getSecurityPolicy() == null)
{
Class> clazz = null;
String name = "";
try
{
// this is where the default query param implementation meets execution.
// the value of the 'execution.policy' or 'content.policy' argument is the
// implementing class name
name = getArgumentValue(policyType);
if(name != null && name.equals(VOID))
{
return;
}
else if(name == null || name.length() == 0)
{
try
{
String iface = policyType.equals(EXECUTION_POLICY) ? EXECUTION_POLICY_INTERFACE : CONTENT_POLICY_INTERFACE;
Class> plugin = Class.forName(PLUGIN_PKG+iface);
if(plugin.isAssignableFrom(getClass()))
setSecurityPolicy(this);
}
catch(ClassNotFoundException e)
{
return;
}
return;
}
clazz = Class.forName(name);
}
catch (ClassNotFoundException e)
{
try
{
name = PLUGIN_PKG + getArgumentValue(policyType);
clazz = Class.forName(name);
}
catch (ClassNotFoundException e1)
{
String msg = "Could not find the specified SecurityPolicy class: " + name + ".";
throw new YADASecurityException(msg,e1);
}
}
try
{
setSecurityPolicy((SecurityPolicy)clazz.newInstance());
}
catch (InstantiationException | IllegalAccessException e) {
String msg = "Could not instantiate the specified SecurityPolicy class: " + name;
throw new YADASecurityException(msg,e);
}
}
}
/**
* Returns {@code true} if the security target is
* associated to a {@link #BLACKLIST} policy type in the
* {@code YADA_A11N} table
*
* @param type
* the value of the {@code TYPE} field in the
* {@code YADA_A11N} table
* @return {@code true} if {@code TYPE} is {@link #BLACKLIST}
*/
@Override
public boolean isBlacklist(String type)
{
return BLACKLIST.equals(type);
}
/**
* Returns {@code true} if the security target is
* associated to a {@link #WHITELIST} policy type in the
* {@code YADA_A11N} table
*
* @param type
* the value of the {@code TYPE} field in the
* {@code YADA_A11N} table
* @return {@code true} if {@code TYPE} is {@link #WHITELIST}
*/
@Override
public boolean isWhitelist(String type)
{
return WHITELIST.equals(type);
}
/**
* Retrieves the row from {@code YADA_A11N} for the desired query.
* @param qname the request query
* @return a {@link HashMap} contaning the security config for the {@code qname}
* @throws YADASecurityException when the security query can't be retrieved
*/
@Override
public List getSecurityPolicyRecords(String securityPolicyCode) throws YADASecurityException
{
List policy = new ArrayList<>();
// get the security params associated to the query
String qname = getYADAQuery().getQname();
try (ResultSet rs = YADAUtils.executePreparedStatement(YADA_A11N_QUERY, new Object[] { qname });)
{
while (rs.next()) {
String tgt = rs.getString(1); // YADA_A11N.TARGET (this is in the query paramaters, no need to pass)
String policyCode = rs.getString(2); // YADA_A11N.POLICY (this is in the method parameters, no need to pass`)
String type = rs.getString(3); // YADA_A11N.TYPE
String a11nQname = rs.getString(4); // YADA_A11N.QNAME (a query name)
if (qname.equals(tgt) && policyCode.equals(securityPolicyCode))
{
policy.add(new SecurityPolicyRecord(tgt,policyCode,type,a11nQname));
}
}
ConnectionFactory.releaseResources(rs);
}
catch (SQLException | YADAConnectionException | YADASQLException e)
{
String msg = "Unauthorized. Could not obtain security query. This could be a temporary problem.";
throw new YADASecurityException(msg, e);
}
if (policy.size() == 0)
{
String msg = "Unauthorized. A security check was configured by has no policy associated to it.";
throw new YADASecurityException(msg);
}
return policy;
}
/**
* Sets the current security policy to {@code null}.
* @since 7.0.0
*/
public void clearSecurityPolicy() {
this.securityPolicy = null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy