Add documentation to aaf authz 15/15615/1
authorsg481n <sg481n@att.com>
Tue, 26 Sep 2017 15:18:31 +0000 (15:18 +0000)
committersg481n <sg481n@att.com>
Tue, 26 Sep 2017 15:18:39 +0000 (15:18 +0000)
Issue-id: AAF-59
Change-Id: I1408740737048e884c08b93544d18da94d689aeb
Signed-off-by: sg481n <sg481n@att.com>
docs/AAF-API-Documentation/Connecting-to-AAF.rst [new file with mode: 0644]
docs/index.rst

diff --git a/docs/AAF-API-Documentation/Connecting-to-AAF.rst b/docs/AAF-API-Documentation/Connecting-to-AAF.rst
new file mode 100644 (file)
index 0000000..2c13f3e
--- /dev/null
@@ -0,0 +1,353 @@
+=================\r
+Connecting to AAF\r
+=================\r
+\r
+Methods to Connect\r
+==================\r
+\r
+\95      If you are a Servlet in a Container, use CADI Framework with AAF Plugin.  It's very easy, and includes BasicAuth for Services.  \r
+\95      Java Technologies\r
+\95      Technologies using Servlet Filters\r
+\95      DME2 (and other Servlet Containers) can use Servlet Filters\r
+\95      Any WebApp can plug in CADI as a Servlet Filter\r
+\95      Jetty can attach a Servlet Filter with Code, or as WebApp\r
+\95      Tomcat 7 has a "Valve" plugin, which is similar and supported\r
+\95      Use the AAFLur Code directly (shown)\r
+\95      All Java Technologies utilize Configuration to set what Security elements are required\r
+\95      example: Global Login can be turned on/off, AAF Client needs information to connect to AAF Service\r
+\95      There are several specialty cases, which AAF can work with, including embedding all properties in a Web.xml, but the essentials needed are:\r
+\95      CADI Jars\r
+\95      cadi.properties file (configured the same for all technologies)\r
+\95      Encrypt passwords with included CADI technology, so that there are no Clear Text Passwords in Config Files (ASPR)\r
+\95      See CADI Deployment on how to perform this with several different technologies.\r
+\95      AAF Restfully (see RESTFul APIS)\r
+\r
+IMPORTANT: If Direct RESTFul API is used, then it is the Client's responsibility to Cache and avoid making an AAF Service Calls too often\r
+Example: A Tool like Cassandra will ask for Authentication hundreds of times a second for the same identity during a transaction.  Calling the AAF Service for each would be slow for the client, and wasteful of Network and AAF Service Capacities.  \r
+Rogue Clients can and will be denied access to AAF.\r
+\r
+\r
+J2EE (Servlet Filter) Method\r
+============================\r
+\r
+1.     Per J2EE design, the Filter will deny any unauthenticated HTTP/S call; the Servlet will not even be invoked.\r
+a.     Therefore, the Servlet can depend on any transaction making it to their code set is Authenticated.\r
+b.     Identity can be viewed based on the HttpServletRequest Object (request.getUserPrincipal() )\r
+2.     Per J2EE design, AAF Filter overloads the HttpServletRequest for a String related to "Role".  (request.isUserInRole("...") )\r
+a.     For AAF, do not put in "Role", but the three parts of requested "Permission", separated by "|", i.e.  "org.onap.aaf.myapp.myperm|myInstance|myAction".\r
+3.     NOT REQUIRED: An added benefit, but not required, is a JASPI like interface, where you can add an Annotation to your Servlet. \r
+a.     When used, no transaction will come into your code if the listed Permissions are not Granted to the Incoming Transaction.  \r
+b.     This might be helpful for covering separate Management Servlet implementations.\r
+\r
+\r
+\r
+Servlet Code Snippet\r
+=========================\r
+\r
+public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {\r
+    HttpServletRequest request;\r
+    try {\r
+        request = (HttpServletRequest)req;\r
+    } catch (ClassCastException e) {\r
+        throw new ServletException("Only serving HTTP today",e);\r
+    }\r
+     \r
+    // Note: CADI is OVERLOADING the concept of "isUserInRole".. You need to think "doesUserHavePermssion()"\r
+    // Assume that you have CREATED and GRANTED An AAF Permission in YOUR Namespace\r
+    // Example Permission:   "org.onap.aaf.myapp.myPerm * write"\r
\r
+    // Think in your head, "Does user have write permission on any instance of org.onap.aaf.myapp.myPerm\r
+    if(request.isUserInRole("org.onap.aaf.myapp.myPerm|*|write")) { \r
+        // *** Do something here that someone with "myPerm write" permissions is allowed to do\r
+    } else {\r
+        // *** Do something reasonable if user is denied, like an Error Message\r
+    }\r
\r
+}\r
+\r
+Here is a working TestServlet, where you can play with different Permissions that you own on the URL, i.e.:\r
+https://<your machine:port>/caditest/testme?PERM=org.onap.aaf.myapp.myPerm|*|write\r
+\r
+Sample Servlet (Working example)\r
+================================\r
+package org.onap.aaf.cadi.debug;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.net.InetAddress;\r
+import java.net.UnknownHostException;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+import java.util.Map.Entry;\r
+import java.util.Properties;\r
+import javax.servlet.Servlet;\r
+import javax.servlet.ServletConfig;\r
+import javax.servlet.ServletException;\r
+import javax.servlet.ServletRequest;\r
+import javax.servlet.ServletResponse;\r
+import javax.servlet.http.HttpServletRequest;\r
+import org.eclipse.jetty.server.Server;\r
+import org.eclipse.jetty.server.ServerConnector;\r
+import org.eclipse.jetty.server.handler.ContextHandler;\r
+import org.eclipse.jetty.servlet.FilterHolder;\r
+import org.eclipse.jetty.servlet.FilterMapping;\r
+import org.eclipse.jetty.servlet.ServletContextHandler;\r
+import org.eclipse.jetty.servlet.ServletHandler;\r
+import org.onap.aaf.cadi.filter.CadiFilter;\r
+import org.onap.aaf.cadi.filter.RolesAllowed;\r
+import org.onap.aaf.cadi.jetty.MiniJASPIWrap;\r
\r
+public class CSPServletTest {\r
+    public static void main(String[] args) {\r
+        // Go ahead and print Test reports in cadi-core first\r
+        Test.main(args);\r
+        String hostname=null;\r
+        try {\r
+            hostname = InetAddress.getLocalHost().getHostName();\r
+        } catch (UnknownHostException e) {\r
+            e.printStackTrace();\r
+            System.exit(1);\r
+        }\r
+        Properties props = new Properties();\r
+        Map<String,String> map = new HashMap<String,String>();\r
+        try {\r
+            FileInputStream fis = new FileInputStream("run/cadi.properties");\r
+            try {\r
+                props.load(fis);\r
+                String key,value;\r
+                for( Entry<Object, Object> es  : props.entrySet()) {\r
+                    key = es.getKey().toString();\r
+                    value = es.getValue().toString();\r
+                    map.put(key,value);\r
+                    if(key.startsWith("AFT_") || key.startsWith("DME2")) {\r
+                        System.setProperty(key,value);\r
+                    }\r
+                }\r
+            } finally {\r
+                fis.close();\r
+            }\r
+        } catch(IOException e) {\r
+            System.err.println("Cannot load run/cadi.properties");\r
+            System.exit(1);\r
+        }\r
+        String portStr = System.getProperty("port");\r
+        int port = portStr==null?8080:Integer.parseInt(portStr);\r
+        try {\r
+            // Add ServletHolder(s) and Filter(s) to a ServletHandler\r
+            ServletHandler shand = new ServletHandler();\r
+             \r
+            FilterHolder cfh = new FilterHolder(CadiFilter.class);\r
+            cfh.setInitParameters(map);\r
+             \r
+            shand.addFilterWithMapping(cfh, "/*", FilterMapping.ALL);\r
+            shand.addServletWithMapping(new MiniJASPIWrap(MyServlet.class),"/*");\r
+            // call initialize after start\r
+             \r
+            ContextHandler ch = new ServletContextHandler();\r
+            ch.setContextPath("/caditest");\r
+            ch.setHandler(shand);\r
+            for( Entry<Object,Object> es : props.entrySet()) {\r
+                ch.getInitParams().put(es.getKey().toString(), es.getValue().toString());\r
+            }\r
+            //ch.setErrorHandler(new MyErrorHandler());\r
+             \r
+            // Create Server and Add Context Handler\r
+            final Server server = new Server();\r
+            ServerConnector http = new ServerConnector(server);\r
+            http.setPort(port);\r
+            server.addConnector(http);\r
+            server.setHandler(ch);\r
+         \r
+            // Start\r
+            server.start();\r
+            shand.initialize();\r
+             \r
+            System.out.println("To test, put http://"+ hostname + ':' + port + "/caditest/testme in a browser or 'curl'");\r
+            // if we were really a server, we'd block the main thread with this join...\r
+            // server.join();\r
+            // But... since we're a test service, we'll block on StdIn\r
+            System.out.println("Press <Return> to end service...");\r
+            System.in.read();\r
+            server.stop();\r
+            System.out.println("All done, have a good day!");\r
+        } catch (Exception e) {\r
+            e.printStackTrace();\r
+            System.exit(1);\r
+        }\r
+    }\r
+    @RolesAllowed({"org.onap.aaf.myapp.myPerm|myInstance|myAction"})\r
+    public static class MyServlet implements Servlet {\r
+        private ServletConfig servletConfig;\r
+     \r
+        public void init(ServletConfig config) throws ServletException {\r
+            servletConfig = config;\r
+        }\r
+     \r
+        public ServletConfig getServletConfig() {\r
+            return servletConfig;\r
+        }\r
+     \r
+        public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {\r
+            HttpServletRequest request;\r
+            try {\r
+                request = (HttpServletRequest)req;\r
+            } catch (ClassCastException e) {\r
+                throw new ServletException("Only serving HTTP today",e);\r
+            }\r
+             \r
+            res.getOutputStream().print("<html><header><title>CSP Servlet Test</title></header><body><h1>You're good to go!</h1><pre>" +\r
+                    request.getUserPrincipal());\r
+             \r
+            String perm = request.getParameter("PERM");\r
+            if(perm!=null)\r
+                if(request.isUserInRole(perm)) {\r
+                    if(perm.indexOf('|')<0) \r
+                        res.getOutputStream().print("\nCongrats!, You are in Role " + perm);\r
+                      else\r
+                        res.getOutputStream().print("\nCongrats!, You have Permission " + perm);\r
+                } else {\r
+                    if(perm.indexOf('|')<0) \r
+                        res.getOutputStream().print("\nSorry, you are NOT in Role " + perm);\r
+                      else\r
+                        res.getOutputStream().print("\nSorry, you do NOT have Permission " + perm);\r
+                }\r
+             \r
+            res.getOutputStream().print("</pre></body></html>");\r
+             \r
+        }\r
+     \r
+        public String getServletInfo() {\r
+            return "MyServlet";\r
+        }\r
+     \r
+        public void destroy() {\r
+        }\r
+    }\r
+}\r
\r
+Java Direct (AAFLur) Method\r
+===========================\r
+The AAFLur is the exact component used within all the Plugins mentioned above.  It is written so that it can be called standalone as well, see the Example as follows\r
+package org.onap.aaf.example;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Properties;\r
+\r
+import org.onap.aaf.cadi.Access;\r
+import org.onap.aaf.cadi.Permission;\r
+import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn;\r
+import org.onap.aaf.cadi.aaf.v2_0.AAFCon;\r
+import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;\r
+import org.onap.aaf.cadi.config.Config;\r
+import org.onap.aaf.cadi.lur.aaf.AAFPermission;\r
+import org.onap.aaf.cadi.lur.aaf.test.TestAccess;\r
+\r
+public class ExamplePerm2_0 {\r
+       public static void main(String args[]) {\r
+               // Normally, these should be set in environment.  Setting here for clarity\r
+               Properties props = System.getProperties();\r
+               props.setProperty("AFT_LATITUDE", "32.780140");\r
+               props.setProperty("AFT_LONGITUDE", "-96.800451");\r
+               props.setProperty("AFT_ENVIRONMENT", "AFTUAT");\r
+               props.setProperty(Config.AAF_URL,\r
+               "https://DME2RESOLVE/service=org.onap.aaf.authz.AuthorizationService/version=2.0/envContext=TEST/routeOffer=BAU_SE"\r
+                               );\r
+               props.setProperty(Config.AAF_USER_EXPIRES,Integer.toString(5*60000));   // 5 minutes for found items to live in cache\r
+               props.setProperty(Config.AAF_HIGH_COUNT,Integer.toString(400));         // Maximum number of items in Cache);\r
+               props.setProperty(Config.CADI_KEYFILE,"keyfile"); //Note: Be sure to generate with java -jar <cadi_path>/lib/cadi-core*.jar keygen keyfile\r
+//             props.setProperty("DME2_EP_REGISTRY_CLASS","DME2FS");\r
+//             props.setProperty("AFT_DME2_EP_REGISTRY_FS_DIR","../../authz/dme2reg");\r
+\r
+               \r
+               // Link or reuse to your Logging mechanism\r
+               Access myAccess = new TestAccess(); // \r
+               \r
+               // \r
+               try {\r
+                       AAFCon<?> con = new AAFConDME2(myAccess);\r
+                       \r
+                       // AAFLur has pool of DME clients as needed, and Caches Client lookups\r
+                       AAFLurPerm aafLur = con.newLur();\r
+                       // Note: If you need both Authn and Authz construct the following:\r
+                       AAFAuthn<?> aafAuthn = con.newAuthn(aafLur);\r
+\r
+                       // Do not set Mech ID until after you construct AAFAuthn,\r
+                       // because we initiate  "401" info to determine the Realm of \r
+                       // of the service we're after.\r
+                       con.basicAuth("xxxx@aaf.abc.com", "XXXXXX");\r
+\r
+                       try {\r
+                               \r
+                               // Normally, you obtain Principal from Authentication System.\r
+                               // For J2EE, you can ask the HttpServletRequest for getUserPrincipal()\r
+                               // If you use CADI as Authenticator, it will get you these Principals from\r
+                               // CSP or BasicAuth mechanisms.\r
+                               String id = "xxxx@aaf.abc.com"; //"cluster_admin@gridcore.abc.com";\r
+\r
+                               // If Validate succeeds, you will get a Null, otherwise, you will a String for the reason.\r
+                               String ok = aafAuthn.validate(id, "XXXXXX");\r
+                               if(ok!=null)System.out.println(ok);\r
+                               \r
+                               ok = aafAuthn.validate(id, "wrongPass");\r
+                               if(ok!=null)System.out.println(ok);\r
+\r
+\r
+                               // AAF Style permissions are in the form\r
+                               // Type, Instance, Action \r
+                               AAFPermission perm = new AAFPermission("org.onap.aaf.grid.core.coh",":dev_cluster", "WRITE");\r
+                               \r
+                               // Now you can ask the LUR (Local Representative of the User Repository about Authorization\r
+                               // With CADI, in J2EE, you can call isUserInRole("org.onap.aaf.mygroup|mytype|write") on the Request Object \r
+                               // instead of creating your own LUR\r
+                               System.out.println("Does " + id + " have " + perm);\r
+                               if(aafLur.fish(id, perm)) {\r
+                                       System.out.println("Yes, you have permission");\r
+                               } else {\r
+                                       System.out.println("No, you don't have permission");\r
+                               }\r
+\r
+                               System.out.println("Does Bogus have " + perm);\r
+                               if(aafLur.fish("Bogus", perm)) {\r
+                                       System.out.println("Yes, you have permission");\r
+                               } else {\r
+                                       System.out.println("No, you don't have permission");\r
+                               }\r
+\r
+                               // Or you can all for all the Permissions available\r
+                               List<Permission> perms = new ArrayList<Permission>();\r
+                               \r
+                               aafLur.fishAll(id,perms);\r
+                               for(Permission prm : perms) {\r
+                                       System.out.println(prm.getKey());\r
+                               }\r
+                               \r
+                               // It might be helpful in some cases to clear the User's identity from the Cache\r
+                               aafLur.remove(id);\r
+                       } finally {\r
+                               aafLur.destroy();\r
+                       }\r
+               } catch (Exception e) {\r
+                       e.printStackTrace();\r
+               }\r
+\r
+       }\r
+}\r
+\r
+There are two current AAF Lurs which you can utilize:\r
+\95      Org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm is the default, and will fish based on the Three-fold "Permission" standard in AAF\r
+To run this code, you will need from a SWM deployment (org.onap.aaf.cadi:cadi, then soft link to jars needed):\r
+\95      cadi-core-<version>.jar\r
+\95      cadi-aaf-<version>-full.jar\r
+   or by Maven\r
+<dependency>\r
+<groupId>org.onap.aaf.cadi</groupId>\r
+<artifactId>cadi-aaf</artifactId>\r
+<version>THE_LATEST_VERSION</version>\r
+<classifier>full</classifier> \r
+</dependency>\r
+   If you need the Java Client definitions only, \r
\r
+   Also needed are the DME2 Client libraries:\r
+\95      dme2-<version>.jar\r
+\95      discovery-clt-<version>.jar\r
+\r
index 86c6035..6ddddc5 100644 (file)
@@ -18,6 +18,7 @@ To be effective during a computer transaction, Security must not only be secure,
    :maxdepth: 2
    
    AAF-API-Documentation/AAF-API-Documentation
+    AAF-API-Documentation/Connecting-to-AAF
 
    
 Introduction
@@ -26,7 +27,7 @@ AAF contains some elements of Role Based Authorization, but includes Attribute B
 
 |image0|
 
-.. |image0| image:: aaf-object-model.jpeg
+.. |image0| image:: aaf-object-model.jpg
    :height: 600px
    :width: 800px