CADI Enforcement Point 49/72349/1
authorInstrumental <jonathan.gathman@att.com>
Fri, 9 Nov 2018 23:50:40 +0000 (17:50 -0600)
committerInstrumental <jonathan.gathman@att.com>
Fri, 9 Nov 2018 23:50:46 +0000 (17:50 -0600)
Issue-ID: AAF-623
Change-Id: Ib49b68fe8323af895b80a90537e7d1c75bc46b70
Signed-off-by: Instrumental <jonathan.gathman@att.com>
auth/auth-core/src/main/java/org/onap/aaf/auth/validation/Validator.java
cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/PermEval.java
cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFTaf.java
cadi/aaf/src/test/java/org/onap/aaf/cadi/aaf/test/JU_PermEval.java
cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java
cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiApiEnforcementFilter.java [new file with mode: 0644]
cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java
cadi/core/src/main/java/org/onap/aaf/cadi/filter/SideChain.java [new file with mode: 0644]

index 1c9f412..7e861ed 100644 (file)
@@ -155,7 +155,7 @@ public class Validator {
     }
 
     public final Validator permInstance(String instance) {
-        if (nob(instance,instChars)) {
+       if(!"/".equals(instance) && nob(instance,instChars)) {
             msg("Perm Instance [" + instance + "] is invalid.");
         }
         return this;
index c12b2e6..2c7aa12 100644 (file)
@@ -77,7 +77,7 @@ public class PermEval {
                                 if (pass=sItem.length()==0) {
                                     break;                                  // Both Empty, keep checking
                                 }
-                            } else if (sItem.charAt(0)==START_REGEX_CHAR) { // Check Server side when wildcarding like *
+                            } else if (sItem.length()>0 && sItem.charAt(0)==START_REGEX_CHAR) { // Check Server side when wildcarding like *
                                 if (pass=pkeys[i].matches(sItem.substring(1))) {
                                     break;                                  // Matches, keep checking
                                 }
index c27dd12..ea40440 100644 (file)
@@ -93,8 +93,9 @@ public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpT
         } else {
                try {
                                mapIds = new MapBathConverter(access, new CSV(csvFile));
+                               access.log(Level.INIT,"Basic Auth Conversion using",csvFile,"enabled" );
                        } catch (IOException | CadiException e) {
-                               access.log(e,"Bath Map Conversion is not initialzed (non fatal)");
+                               access.log(e,"Bath Map Conversion is not initialized (non fatal)");
                        }
         }
 
index a6c0f91..3e137c2 100644 (file)
@@ -74,6 +74,8 @@ public class JU_PermEval {
 
         // Accept matching empty keys
         assertThat(PermEval.evalInstance(":", ":"), is(true));
+        assertThat(PermEval.evalInstance("/", "/"), is(true));
+        assertThat(PermEval.evalInstance("/something/", "/something/"), is(true));
 
         // Reject non-matching empty keys
         assertThat(PermEval.evalInstance(":fred", ":"), is(false));
index 3d668c4..0e4f72b 100644 (file)
@@ -103,7 +103,10 @@ public class Config {
     public static final String CADI_PROTOCOLS = "cadi_protocols";
     public static final String CADI_NOAUTHN = "cadi_noauthn";
     public static final String CADI_LOC_LIST = "cadi_loc_list";
+    
+    // Special Behaviors
     public static final String CADI_BATH_CONVERT = "cadi_bath_convert";
+    public static final String CADI_API_ENFORCEMENT = "cadi_api_enforcement";
     
     public static final String CADI_USER_CHAIN_TAG = "cadi_user_chain";
     public static final String CADI_USER_CHAIN = "USER_CHAIN";
@@ -410,7 +413,7 @@ public class Config {
                     oadtClss = Class.forName(OAUTH_DIRECT_TAF);
                 } catch (ClassNotFoundException e1) {
                     oadtClss = null;
-                    access.log(Level.INIT, e1);
+                    access.log(Level.DEBUG, e1);
                 }
                 if (additionalTafLurs!=null && additionalTafLurs.length>0 && (oadtClss!=null && additionalTafLurs[0].getClass().isAssignableFrom(oadtClss))) {
                     htlist.add((HttpTaf)additionalTafLurs[0]);
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiApiEnforcementFilter.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiApiEnforcementFilter.java
new file mode 100644 (file)
index 0000000..495131b
--- /dev/null
@@ -0,0 +1,132 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ */
+package org.onap.aaf.cadi.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.ServletContextAccess;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.util.Split;
+
+/**
+ * This filter allows one to protect the APIs from data stored in AAF
+ * 
+ * @author Instrumental(Jonathan)
+ */
+public class CadiApiEnforcementFilter implements Filter {
+       private String type;
+       private Map<String,List<String>> publicPaths;
+       private Access access;
+                       
+       
+       public CadiApiEnforcementFilter(Access access, String enforce) throws ServletException {
+               this.access = access;
+               init(enforce);
+       }
+
+
+       @Override
+       public void init(FilterConfig fc) throws ServletException {
+               init(fc.getInitParameter(Config.CADI_API_ENFORCEMENT));
+        // need the Context for Logging, instantiating ClassLoader, etc
+        ServletContextAccess sca=new ServletContextAccess(fc); 
+        if (access==null) {
+            access = sca;
+        }
+       }
+       
+       private void init(final String ptypes) throws ServletException {
+               if(ptypes==null) {
+                       throw new ServletException("CadiApiEnforcement requires " + Config.CADI_API_ENFORCEMENT + " property");
+               }
+               String[] full = Split.splitTrim(';', ptypes);
+               if(full.length==0) {
+                       throw new ServletException(Config.CADI_API_ENFORCEMENT + " property is empty");
+               }
+               if(full.length>0) {
+                       type=full[0];
+               }
+               publicPaths = new TreeMap<String,List<String>>();
+               if(full.length>1) {
+                       for(int i=1;i<full.length;++i) {
+                               String pubArray[] = Split.split(':', full[i]);
+                               if(pubArray.length==2) {
+                                       List<String> ls = publicPaths.get(pubArray[0]);
+                                       if(ls==null) {
+                                               ls = new ArrayList<String>();
+                                               publicPaths.put(pubArray[0], ls);
+                                       }
+                                       ls.add(pubArray[1]);
+                               }
+                       }
+               }
+       }
+
+
+       @Override
+       public void doFilter(ServletRequest req, ServletResponse resp, FilterChain fc) throws IOException, ServletException {
+               HttpServletRequest hreq = (HttpServletRequest)req;
+               final String meth = hreq.getMethod();
+               final String path = hreq.getContextPath()+hreq.getPathInfo();
+               List<String> list = publicPaths.get(meth);
+               if(list!=null) {
+                       for( String p : publicPaths.get(meth)) {
+                               if(path.startsWith(p)) {
+                                       access.printf(Level.INFO, "%s accessed public API %s %s\n",
+                                                       hreq.getUserPrincipal().getName(),
+                                                       meth,
+                                                       path);
+                                               fc.doFilter(req, resp);
+                                               return;
+                               }
+                       }
+               }
+               if(hreq.isUserInRole(type + '|'+path+'|'+meth)) {
+                       access.printf(Level.INFO, "%s is allowed access to %s %s\n",
+                               hreq.getUserPrincipal().getName(),
+                               meth,
+                               path);
+                       fc.doFilter(req, resp);
+               } else {
+                       access.printf(Level.AUDIT, "%s is denied access to %s %s\n",
+                                       hreq.getUserPrincipal().getName(),
+                                       meth,
+                                       path);
+               }
+       }
+
+       @Override
+       public void destroy() {
+       }
+}
index cd48556..2305eac 100644 (file)
@@ -71,7 +71,7 @@ public class CadiFilter implements Filter {
     private static List<Pair> mapPairs;
     private Access access;
     private Object[] additionalTafLurs;
-    private Filter oauthFilter;
+    private SideChain sideChain;
     private static int count=0;
     
     public Lur getLur() {
@@ -140,6 +140,7 @@ public class CadiFilter implements Filter {
 
     @SuppressWarnings("unchecked")
     private void init(Get getter) throws ServletException {
+       sideChain = new SideChain();
         // Start with the assumption of "Don't trust anyone".
        TrustChecker tc = TrustChecker.NOTRUST; // default position
        try {
@@ -158,22 +159,9 @@ public class CadiFilter implements Filter {
            Class<Filter> cf=null;
            try {
                cf= (Class<Filter>) Class.forName("org.onap.aaf.cadi.oauth.OAuthFilter");
-               oauthFilter = cf.newInstance();
+               sideChain.add(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 {
-                    }
-               };
+                  access.log(Level.DEBUG, "OAuthFilter not enabled");
            }
        } catch (Exception e) {
            access.log(Level.INIT, "AAFTrustChecker cannot be loaded",e.getMessage());
@@ -238,6 +226,11 @@ public class CadiFilter implements Filter {
             }
         }
 
+        // Add API Enforcement Point
+        String enforce = getter.get(Config.CADI_API_ENFORCEMENT, null, true); 
+        if(enforce!=null && enforce.length()>0) {
+               sideChain.add(new CadiApiEnforcementFilter(access,enforce));
+        }
         // Remove Getter
         getter = Get.NULL;
     }
@@ -287,7 +280,7 @@ public class CadiFilter implements Filter {
                     CadiWrap cw = new CadiWrap(hreq, tresp, httpChecker.getLur(),getConverter(hreq));
                     if (httpChecker.notCadi(cw, hresp)) {
                         startCode=System.nanoTime();
-                        oauthFilter.doFilter(cw,response,chain);
+                        sideChain.doFilter(cw,response,chain);
                         code = Timing.millis(startCode);
                     }
                 }
diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/SideChain.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/SideChain.java
new file mode 100644 (file)
index 0000000..8283b4d
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ */
+
+package org.onap.aaf.cadi.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.xml.ws.Holder;
+
+/**
+ * Add various Filters by CADI Property not in the official Chain
+ * 
+ * @author Instrumental(Jonathan)
+ *
+ */
+public class SideChain {
+       private List<Filter> sideChain;
+       
+       public SideChain() {
+               sideChain = new ArrayList<Filter>();
+       }
+       
+       public void add(Filter f) {
+               sideChain.add(f);
+       }
+       
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
+       final Holder<Boolean> hbool = new Holder<Boolean>(Boolean.TRUE);
+       FilterChain truth = new FilterChain() {
+                       @Override
+                       public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
+                          hbool.value=Boolean.TRUE;
+                       }
+                       public String toString() {
+                               return hbool.value.toString();
+                       }
+       };
+       for(Filter f : sideChain) {
+                       hbool.value=Boolean.FALSE;
+               f.doFilter(request, response, truth);
+               if(!hbool.value) {
+                       return;
+               }
+       }
+       if(hbool.value) {
+               chain.doFilter(request, response);
+       }
+    }
+}