import javax.servlet.http.HttpServletResponse;
import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
import org.onap.aaf.cadi.CadiException;
import org.onap.aaf.cadi.CadiWrap;
import org.onap.aaf.cadi.LocatorException;
import org.onap.aaf.cadi.PropAccess;
import org.onap.aaf.cadi.ServletContextAccess;
import org.onap.aaf.cadi.TrustChecker;
-import org.onap.aaf.cadi.Access.Level;
import org.onap.aaf.cadi.config.Config;
import org.onap.aaf.cadi.config.Get;
import org.onap.aaf.cadi.taf.TafResp;
import org.onap.aaf.cadi.taf.TafResp.RESP;
+import org.onap.aaf.cadi.util.Timing;
/**
* CadiFilter
*
*/
public class CadiFilter implements Filter {
- private static CadiHTTPManip httpChecker;
- private static String[] pathExceptions;
- private static List<Pair> mapPairs;
- private Access access;
- private Object[] additionalTafLurs;
- private Filter oauthFilter;
- private static int count=0;
-
- public Lur getLur() {
- return httpChecker.getLur();
- }
-
- /**
- * Construct a viable Filter
- *
- * Due to the vagaries of many containers, there is a tendency to create Objects and call "Init" on
- * them at a later time. Therefore, this object creates with an object that denies all access
- * until appropriate Init happens, just in case the container lets something slip by in the meantime.
- *
- */
- public CadiFilter() {
- additionalTafLurs = CadiHTTPManip.noAdditional;
- }
+ private static CadiHTTPManip httpChecker;
+ private static String[] pathExceptions;
+ private static List<Pair> mapPairs;
+ private Access access;
+ private Object[] additionalTafLurs;
+ private Filter oauthFilter;
+ private static int count=0;
+
+ public Lur getLur() {
+ return httpChecker.getLur();
+ }
+
+ /**
+ * Construct a viable Filter
+ *
+ * Due to the vagaries of many containers, there is a tendency to create Objects and call "Init" on
+ * them at a later time. Therefore, this object creates with an object that denies all access
+ * until appropriate Init happens, just in case the container lets something slip by in the meantime.
+ *
+ */
+ public CadiFilter() {
+ additionalTafLurs = CadiHTTPManip.noAdditional;
+ }
- /**
- * This constructor to be used when directly constructing and placing in HTTP Engine
- *
- * @param access
- * @param moreTafLurs
- * @throws ServletException
- */
- public CadiFilter(Access access, Object ... moreTafLurs) throws ServletException {
- additionalTafLurs = moreTafLurs;
- init(new AccessGetter(this.access = access));
- }
+ /**
+ * This constructor to be used when directly constructing and placing in HTTP Engine
+ *
+ * @param access
+ * @param moreTafLurs
+ * @throws ServletException
+ */
+ public CadiFilter(Access access, Object ... moreTafLurs) throws ServletException {
+ additionalTafLurs = moreTafLurs;
+ init(new AccessGetter(this.access = access));
+ }
- /**
- * Use this to pass in a PreContructed CADI Filter, but with initializing... let Servlet do it
- * @param init
- * @param access
- * @param moreTafLurs
- * @throws ServletException
- */
- public CadiFilter(boolean init, PropAccess access, Object ... moreTafLurs) throws ServletException {
- this.access = access;
- additionalTafLurs = moreTafLurs;
- if(init) {
- init(new AccessGetter(access));
- }
- }
+ /**
+ * Use this to pass in a PreContructed CADI Filter, but with initializing... let Servlet do it
+ * @param init
+ * @param access
+ * @param moreTafLurs
+ * @throws ServletException
+ */
+ public CadiFilter(boolean init, PropAccess access, Object ... moreTafLurs) throws ServletException {
+ this.access = access;
+ additionalTafLurs = moreTafLurs;
+ if (init) {
+ init(new AccessGetter(access));
+ }
+ }
- /**
- * Init
- *
- * Standard Filter "init" call with FilterConfig to obtain properties. POJOs can construct a
- * FilterConfig with the mechanism of their choice, and standard J2EE Servlet engines utilize this
- * mechanism already.
- */
- //TODO Always validate changes against Tomcat AbsCadiValve and Jaspi CadiSAM Init functions
- public void init(FilterConfig filterConfig) throws ServletException {
- // need the Context for Logging, instantiating ClassLoader, etc
- ServletContextAccess sca=new ServletContextAccess(filterConfig);
- if(access==null) {
- access = sca;
- }
-
- // Set Protected getter with base Access, for internal class instantiations
- init(new FCGet(access, sca.context(), filterConfig));
- }
-
+ /**
+ * Init
+ *
+ * Standard Filter "init" call with FilterConfig to obtain properties. POJOs can construct a
+ * FilterConfig with the mechanism of their choice, and standard J2EE Servlet engines utilize this
+ * mechanism already.
+ */
+ //TODO Always validate changes against Tomcat AbsCadiValve and Jaspi CadiSAM Init functions
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // need the Context for Logging, instantiating ClassLoader, etc
+ ServletContextAccess sca=new ServletContextAccess(filterConfig);
+ if (access==null) {
+ access = sca;
+ }
+
+ // Set Protected getter with base Access, for internal class instantiations
+ init(new FCGet(access, sca.context(), filterConfig));
+ }
+
- @SuppressWarnings("unchecked")
- private void init(Get getter) throws ServletException {
+ @SuppressWarnings("unchecked")
+ private void init(Get getter) throws ServletException {
// Start with the assumption of "Don't trust anyone".
- TrustChecker tc = TrustChecker.NOTRUST; // default position
- try {
- Class<TrustChecker> ctc = (Class<TrustChecker>) Class.forName("org.onap.aaf.cadi.aaf.v2_0.AAFTrustChecker");
- if(ctc!=null) {
- Constructor<TrustChecker> contc = ctc.getConstructor(Access.class);
- if(contc!=null) {
- tc = contc.newInstance(access);
- }
- }
- } catch (Exception e) {
- access.log(Level.INIT, "AAFTrustChecker cannot be loaded",e.getMessage());
- }
-
- try {
- Class<Filter> cf=null;
- try {
- cf= (Class<Filter>) Class.forName("org.onap.aaf.cadi.oauth.OAuthFilter");
- oauthFilter = cf.newInstance();
- } catch (ClassNotFoundException e) {
- oauthFilter = new Filter() { // Null Filter
- @Override
- public void destroy() {
- }
-
- @Override
- public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)throws IOException, ServletException {
- chain.doFilter(req, resp);
- }
-
- @Override
- public void init(FilterConfig arg0) throws ServletException {
- }
- };
- }
- } catch (Exception e) {
- access.log(Level.INIT, "AAFTrustChecker cannot be loaded",e.getMessage());
- }
+ TrustChecker tc = TrustChecker.NOTRUST; // default position
+ try {
+ Class<TrustChecker> ctc = (Class<TrustChecker>) Class.forName("org.onap.aaf.cadi.aaf.v2_0.AAFTrustChecker");
+ if (ctc!=null) {
+ Constructor<TrustChecker> contc = ctc.getConstructor(Access.class);
+ if (contc!=null) {
+ tc = contc.newInstance(access);
+ }
+ }
+ } catch (Exception e) {
+ access.log(Level.INIT, "AAFTrustChecker cannot be loaded",e.getMessage());
+ }
+
+ try {
+ Class<Filter> cf=null;
+ try {
+ cf= (Class<Filter>) Class.forName("org.onap.aaf.cadi.oauth.OAuthFilter");
+ oauthFilter = cf.newInstance();
+ } catch (ClassNotFoundException e) {
+ oauthFilter = new Filter() { // Null Filter
+ @Override
+ public void destroy() {
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)throws IOException, ServletException {
+ chain.doFilter(req, resp);
+ }
+
+ @Override
+ public void init(FilterConfig arg0) throws ServletException {
+ }
+ };
+ }
+ } catch (Exception e) {
+ access.log(Level.INIT, "AAFTrustChecker cannot be loaded",e.getMessage());
+ }
// Synchronize, because some instantiations call init several times on the same object
// In this case, the epiTaf will be changed to a non-NullTaf, and thus not instantiate twice.
- synchronized(CadiHTTPManip.noAdditional /*will always remain same Object*/) {
- ++count;
- if(httpChecker == null) {
- if(access==null) {
- access = new PropAccess();
- }
- try {
- httpChecker = new CadiHTTPManip(access,null /*reuseable Con*/,tc, additionalTafLurs);
- } catch (CadiException | LocatorException e1) {
- throw new ServletException(e1);
- }
- } else if(access==null) {
- access= httpChecker.getAccess();
- }
+ synchronized(CadiHTTPManip.noAdditional /*will always remain same Object*/) {
+ ++count;
+ if (httpChecker == null) {
+ if (access==null) {
+ access = new PropAccess();
+ }
+ try {
+ httpChecker = new CadiHTTPManip(access,null /*reuseable Con*/,tc, additionalTafLurs);
+ } catch (CadiException | LocatorException e1) {
+ throw new ServletException(e1);
+ }
+ } else if (access==null) {
+ access= httpChecker.getAccess();
+ }
- /*
- * Setup Authn Path Exceptions
- */
- if(pathExceptions==null) {
- String str = getter.get(Config.CADI_NOAUTHN, null, true);
- if(str!=null) {
- pathExceptions = str.split("\\s*:\\s*");
- }
- }
-
- /*
- * SETUP Permission Converters... those that can take Strings from a Vendor Product, and convert to appropriate AAF Permissions
- */
- if(mapPairs==null) {
- String str = getter.get(Config.AAF_PERM_MAP, null, true);
- if(str!=null) {
- String mstr = getter.get(Config.AAF_PERM_MAP, null, true);
- if(mstr!=null) {
- String map[] = mstr.split("\\s*:\\s*");
- if(map.length>0) {
- MapPermConverter mpc=null;
- int idx;
- mapPairs = new ArrayList<Pair>();
- for(String entry : map) {
- if((idx=entry.indexOf('='))<0) { // it's a Path, so create a new converter
- access.log(Level.INIT,"Loading Perm Conversions for:",entry);
- mapPairs.add(new Pair(entry,mpc=new MapPermConverter()));
- } else {
- if(mpc!=null) {
- mpc.map().put(entry.substring(0,idx),entry.substring(idx+1));
- } else {
- access.log(Level.ERROR,"cadi_perm_map is malformed; ",entry, "is skipped");
- }
- }
- }
- }
- }
- }
- }
- }
+ /*
+ * Setup Authn Path Exceptions
+ */
+ if (pathExceptions==null) {
+ String str = getter.get(Config.CADI_NOAUTHN, null, true);
+ if (str!=null) {
+ pathExceptions = str.split("\\s*:\\s*");
+ }
+ }
+
+ /*
+ * SETUP Permission Converters... those that can take Strings from a Vendor Product, and convert to appropriate AAF Permissions
+ */
+ if (mapPairs==null) {
+ String str = getter.get(Config.AAF_PERM_MAP, null, true);
+ if (str!=null) {
+ String mstr = getter.get(Config.AAF_PERM_MAP, null, true);
+ if (mstr!=null) {
+ String map[] = mstr.split("\\s*:\\s*");
+ if (map.length>0) {
+ MapPermConverter mpc=null;
+ int idx;
+ mapPairs = new ArrayList<>();
+ for (String entry : map) {
+ if ((idx=entry.indexOf('='))<0) { // it's a Path, so create a new converter
+ access.log(Level.INIT,"Loading Perm Conversions for:",entry);
+ mapPairs.add(new Pair(entry,mpc=new MapPermConverter()));
+ } else {
+ if (mpc!=null) {
+ mpc.map().put(entry.substring(0,idx),entry.substring(idx+1));
+ } else {
+ access.log(Level.ERROR,"cadi_perm_map is malformed; ",entry, "is skipped");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
- // Remove Getter
+ // Remove Getter
getter = Get.NULL;
- }
+ }
- /**
- * Containers call "destroy" when time to cleanup
- */
- public void destroy() {
- // Synchronize, in case multiCadiFilters are used.
- synchronized(CadiHTTPManip.noAdditional) {
- if(--count<=0 && httpChecker!=null) {
- httpChecker.destroy();
- httpChecker=null;
- access=null;
- pathExceptions=null;
- }
- }
- }
+ /**
+ * Containers call "destroy" when time to cleanup
+ */
+ public void destroy() {
+ // Synchronize, in case multiCadiFilters are used.
+ synchronized(CadiHTTPManip.noAdditional) {
+ if (--count<=0 && httpChecker!=null) {
+ httpChecker.destroy();
+ httpChecker=null;
+ access=null;
+ pathExceptions=null;
+ }
+ }
+ }
- /**
- * doFilter
- *
- * This is the standard J2EE invocation. Analyze the request, modify response as necessary, and
- * only call the next item in the filterChain if request is suitably Authenticated.
- */
- //TODO Always validate changes against Tomcat AbsCadiValve and Jaspi CadiSAM functions
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- try {
- HttpServletRequest hreq = (HttpServletRequest)request;
- if(noAuthn(hreq)) {
- chain.doFilter(request, response);
- } else {
- HttpServletResponse hresp = (HttpServletResponse)response;
- TafResp tresp = httpChecker.validate(hreq, hresp, hreq);
- if(tresp.isAuthenticated()==RESP.IS_AUTHENTICATED) {
- CadiWrap cw = new CadiWrap(hreq, tresp, httpChecker.getLur(),getConverter(hreq));
- if(httpChecker.notCadi(cw, hresp)) {
- oauthFilter.doFilter(cw,response,chain);
- }
- }
- }
- } catch (ClassCastException e) {
- throw new ServletException("CadiFilter expects Servlet to be an HTTP Servlet",e);
- }
- }
+ /**
+ * doFilter
+ *
+ * This is the standard J2EE invocation. Analyze the request, modify response as necessary, and
+ * only call the next item in the filterChain if request is suitably Authenticated.
+ */
+ //TODO Always validate changes against Tomcat AbsCadiValve and Jaspi CadiSAM functions
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ final long startAll = System.nanoTime();
+ long startCode, startValidate;
+ float code=0f, validate=0f;
+ String user = "n/a";
+ String tag = "";
+ try {
+ HttpServletRequest hreq = (HttpServletRequest)request;
+ if (noAuthn(hreq)) {
+ startCode=System.nanoTime();
+ chain.doFilter(request, response);
+ code = Timing.millis(startCode);
+ } else {
+ HttpServletResponse hresp = (HttpServletResponse)response;
+ startValidate=System.nanoTime();
+ TafResp tresp = httpChecker.validate(hreq, hresp, hreq);
+ validate = Timing.millis(startValidate);
+ if (tresp.isAuthenticated()==RESP.IS_AUTHENTICATED) {
+ user = tresp.getPrincipal().personalName();
+ tag = tresp.getPrincipal().tag();
+ CadiWrap cw = new CadiWrap(hreq, tresp, httpChecker.getLur(),getConverter(hreq));
+ if (httpChecker.notCadi(cw, hresp)) {
+ startCode=System.nanoTime();
+ oauthFilter.doFilter(cw,response,chain);
+ code = Timing.millis(startCode);
+ }
+ }
+ }
+ } catch (ClassCastException e) {
+ throw new ServletException("CadiFilter expects Servlet to be an HTTP Servlet",e);
+ } finally {
+ access.printf(Level.WARN, "Trans: user=%s[%s],ip=%s,ms=%f,validate=%f,code=%f",
+ user,tag,request.getRemoteAddr(),
+ Timing.millis(startAll),validate,code);
+ }
+ }
- /**
- * If PathExceptions exist, report if these should not have Authn applied.
- * @param hreq
- * @return
- */
- private boolean noAuthn(HttpServletRequest hreq) {
- if(pathExceptions!=null) {
- String pi = hreq.getPathInfo();
- if(pi==null) return false; // JBoss sometimes leaves null
- for(String pe : pathExceptions) {
- if(pi.startsWith(pe))return true;
- }
- }
- return false;
- }
-
- /**
- * Get Converter by Path
- */
- private PermConverter getConverter(HttpServletRequest hreq) {
- if(mapPairs!=null) {
- String pi = hreq.getPathInfo();
- if(pi !=null) {
- for(Pair p: mapPairs) {
- if(pi.startsWith(p.name))return p.pc;
- }
- }
- }
- return NullPermConverter.singleton();
- }
-
- /**
- * store PermConverters by Path prefix
- * @author Jonathan
- *
- */
- private class Pair {
- public Pair(String key, PermConverter pc) {
- name = key;
- this.pc = pc;
- }
- public String name;
- public PermConverter pc;
- }
+ /**
+ * If PathExceptions exist, report if these should not have Authn applied.
+ * @param hreq
+ * @return
+ */
+ private boolean noAuthn(HttpServletRequest hreq) {
+ if (pathExceptions!=null) {
+ String pi = hreq.getPathInfo();
+ if (pi==null) return false; // JBoss sometimes leaves null
+ for (String pe : pathExceptions) {
+ if (pi.startsWith(pe))return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get Converter by Path
+ */
+ private PermConverter getConverter(HttpServletRequest hreq) {
+ if (mapPairs!=null) {
+ String pi = hreq.getPathInfo();
+ if (pi !=null) {
+ for (Pair p: mapPairs) {
+ if (pi.startsWith(p.name))return p.pc;
+ }
+ }
+ }
+ return NullPermConverter.singleton();
+ }
+
+ /**
+ * store PermConverters by Path prefix
+ * @author Jonathan
+ *
+ */
+ private class Pair {
+ public Pair(String key, PermConverter pc) {
+ name = key;
+ this.pc = pc;
+ }
+ public String name;
+ public PermConverter pc;
+ }
}