863c75fd813c0b5f8b092fb91499a24c3ff30760
[aaf/authz.git] / docs / AAF-API-Documentation / Connecting-to-AAF.rst
1 =================\r
2 Connecting to AAF\r
3 =================\r
4 \r
5 Methods to Connect\r
6 ==================\r
7 \r
8 -       If you are a Servlet in a Container, use CADI Framework with AAF Plugin.  It's very easy, and includes BasicAuth for Services.  \r
9 -       Java Technologies\r
10 -       Technologies using Servlet Filters\r
11 -       DME2 (and other Servlet Containers) can use Servlet Filters\r
12 -       Any WebApp can plug in CADI as a Servlet Filter\r
13 -       Jetty can attach a Servlet Filter with Code, or as WebApp\r
14 -       Tomcat 7 has a "Valve" plugin, which is similar and supported\r
15 -       Use the AAFLur Code directly (shown)\r
16 -       All Java Technologies utilize Configuration to set what Security elements are required\r
17 -       example: Global Login can be turned on/off, AAF Client needs information to connect to AAF Service\r
18 -       There are several specialty cases, which AAF can work with, including embedding all properties in a Web.xml, but the essentials needed are:\r
19 -       CADI Jars\r
20 -       cadi.properties file (configured the same for all technologies)\r
21 -       Encrypt passwords with included CADI technology, so that there are no Clear Text Passwords in Config Files (ASPR)\r
22 -       See CADI Deployment on how to perform this with several different technologies.\r
23 -       AAF Restfully (see RESTFul APIS)\r
24 \r
25 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
26 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
27 Rogue Clients can and will be denied access to AAF.\r
28 \r
29 \r
30 J2EE (Servlet Filter) Method\r
31 ============================\r
32 \r
33 1.      Per J2EE design, the Filter will deny any unauthenticated HTTP/S call; the Servlet will not even be invoked.\r
34 a.      Therefore, the Servlet can depend on any transaction making it to their code set is Authenticated.\r
35 b.      Identity can be viewed based on the HttpServletRequest Object (request.getUserPrincipal() )\r
36 2.      Per J2EE design, AAF Filter overloads the HttpServletRequest for a String related to "Role".  (request.isUserInRole("...") )\r
37 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
38 3.      NOT REQUIRED: An added benefit, but not required, is a JASPI like interface, where you can add an Annotation to your Servlet. \r
39 a.      When used, no transaction will come into your code if the listed Permissions are not Granted to the Incoming Transaction.  \r
40 b.      This might be helpful for covering separate Management Servlet implementations.\r
41 \r
42 \r
43 \r
44 Servlet Code Snippet\r
45 =========================\r
46 \r
47         .. code:: bash\r
48         \r
49                 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {\r
50                 HttpServletRequest request;\r
51                 try {\r
52                         request = (HttpServletRequest)req;\r
53                 } catch (ClassCastException e) {\r
54         throw new ServletException("Only serving HTTP today",e);\r
55                 }\r
56      \r
57                 // Note: CADI is OVERLOADING the concept of "isUserInRole".. You need to think "doesUserHavePermssion()"\r
58                 // Assume that you have CREATED and GRANTED An AAF Permission in YOUR Namespace\r
59                 // Example Permission:   "org.onap.aaf.myapp.myPerm * write"\r
60  \r
61                 // Think in your head, "Does user have write permission on any instance of org.onap.aaf.myapp.myPerm\r
62                 if(request.isUserInRole("org.onap.aaf.myapp.myPerm|*|write")) { \r
63         // *** Do something here that someone with "myPerm write" permissions is allowed to do\r
64                 } else {\r
65         // *** Do something reasonable if user is denied, like an Error Message\r
66                 }\r
67  \r
68                 }\r
69 \r
70 Here is a working TestServlet, where you can play with different Permissions that you own on the URL, i.e.:\r
71 https://<your machine:port>/caditest/testme?PERM=org.onap.aaf.myapp.myPerm|*|write\r
72 \r
73 Sample Servlet (Working example)\r
74 ================================\r
75 \r
76         .. code:: bash\r
77         \r
78                 package org.onap.aaf.cadi.debug;\r
79                 import java.io.FileInputStream;\r
80                 import java.io.IOException;\r
81                 import java.net.InetAddress;\r
82                 import java.net.UnknownHostException;\r
83                 import java.util.HashMap;\r
84                 import java.util.Map;\r
85                 import java.util.Map.Entry;\r
86                 import java.util.Properties;\r
87                 import javax.servlet.Servlet;\r
88                 import javax.servlet.ServletConfig;\r
89                 import javax.servlet.ServletException;\r
90                 import javax.servlet.ServletRequest;\r
91                 import javax.servlet.ServletResponse;\r
92                 import javax.servlet.http.HttpServletRequest;\r
93                 import org.eclipse.jetty.server.Server;\r
94                 import org.eclipse.jetty.server.ServerConnector;\r
95                 import org.eclipse.jetty.server.handler.ContextHandler;\r
96                 import org.eclipse.jetty.servlet.FilterHolder;\r
97                 import org.eclipse.jetty.servlet.FilterMapping;\r
98                 import org.eclipse.jetty.servlet.ServletContextHandler;\r
99                 import org.eclipse.jetty.servlet.ServletHandler;\r
100                 import org.onap.aaf.cadi.filter.CadiFilter;\r
101                 import org.onap.aaf.cadi.filter.RolesAllowed;\r
102                 import org.onap.aaf.cadi.jetty.MiniJASPIWrap;\r
103                  \r
104                 public class CSPServletTest {\r
105                         public static void main(String[] args) {\r
106                                 // Go ahead and print Test reports in cadi-core first\r
107                                 Test.main(args);\r
108                                 String hostname=null;\r
109                                 try {\r
110                                         hostname = InetAddress.getLocalHost().getHostName();\r
111                                 } catch (UnknownHostException e) {\r
112                                         e.printStackTrace();\r
113                                         System.exit(1);\r
114                                 }\r
115                                 Properties props = new Properties();\r
116                                 Map<String,String> map = new HashMap<String,String>();\r
117                                 try {\r
118                                         FileInputStream fis = new FileInputStream("run/cadi.properties");\r
119                                         try {\r
120                                                 props.load(fis);\r
121                                                 String key,value;\r
122                                                 for( Entry<Object, Object> es  : props.entrySet()) {\r
123                                                         key = es.getKey().toString();\r
124                                                         value = es.getValue().toString();\r
125                                                         map.put(key,value);\r
126                                                         if(key.startsWith("AFT_") || key.startsWith("DME2")) {\r
127                                                                 System.setProperty(key,value);\r
128                                                         }\r
129                                                 }\r
130                                         } finally {\r
131                                                 fis.close();\r
132                                         }\r
133                                 } catch(IOException e) {\r
134                                         System.err.println("Cannot load run/cadi.properties");\r
135                                         System.exit(1);\r
136                                 }\r
137                                 String portStr = System.getProperty("port");\r
138                                 int port = portStr==null?8080:Integer.parseInt(portStr);\r
139                                 try {\r
140                                         // Add ServletHolder(s) and Filter(s) to a ServletHandler\r
141                                         ServletHandler shand = new ServletHandler();\r
142                                          \r
143                                         FilterHolder cfh = new FilterHolder(CadiFilter.class);\r
144                                         cfh.setInitParameters(map);\r
145                                          \r
146                                         shand.addFilterWithMapping(cfh, "/*", FilterMapping.ALL);\r
147                                         shand.addServletWithMapping(new MiniJASPIWrap(MyServlet.class),"/*");\r
148                                         // call initialize after start\r
149                                          \r
150                                         ContextHandler ch = new ServletContextHandler();\r
151                                         ch.setContextPath("/caditest");\r
152                                         ch.setHandler(shand);\r
153                                         for( Entry<Object,Object> es : props.entrySet()) {\r
154                                                 ch.getInitParams().put(es.getKey().toString(), es.getValue().toString());\r
155                                         }\r
156                                         //ch.setErrorHandler(new MyErrorHandler());\r
157                                          \r
158                                         // Create Server and Add Context Handler\r
159                                         final Server server = new Server();\r
160                                         ServerConnector http = new ServerConnector(server);\r
161                                         http.setPort(port);\r
162                                         server.addConnector(http);\r
163                                         server.setHandler(ch);\r
164                                  \r
165                                         // Start\r
166                                         server.start();\r
167                                         shand.initialize();\r
168                                          \r
169                                         System.out.println("To test, put http://"+ hostname + ':' + port + "/caditest/testme in a browser or 'curl'");\r
170                                         // if we were really a server, we'd block the main thread with this join...\r
171                                         // server.join();\r
172                                         // But... since we're a test service, we'll block on StdIn\r
173                                         System.out.println("Press <Return> to end service...");\r
174                                         System.in.read();\r
175                                         server.stop();\r
176                                         System.out.println("All done, have a good day!");\r
177                                 } catch (Exception e) {\r
178                                         e.printStackTrace();\r
179                                         System.exit(1);\r
180                                 }\r
181                         }\r
182                         @RolesAllowed({"org.onap.aaf.myapp.myPerm|myInstance|myAction"})\r
183                         public static class MyServlet implements Servlet {\r
184                                 private ServletConfig servletConfig;\r
185                          \r
186                                 public void init(ServletConfig config) throws ServletException {\r
187                                         servletConfig = config;\r
188                                 }\r
189                          \r
190                                 public ServletConfig getServletConfig() {\r
191                                         return servletConfig;\r
192                                 }\r
193                          \r
194                                 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {\r
195                                         HttpServletRequest request;\r
196                                         try {\r
197                                                 request = (HttpServletRequest)req;\r
198                                         } catch (ClassCastException e) {\r
199                                                 throw new ServletException("Only serving HTTP today",e);\r
200                                         }\r
201                                          \r
202                                         res.getOutputStream().print("<html><header><title>CSP Servlet Test</title></header><body><h1>You're good to go!</h1><pre>" +\r
203                                                         request.getUserPrincipal());\r
204                                          \r
205                                         String perm = request.getParameter("PERM");\r
206                                         if(perm!=null)\r
207                                                 if(request.isUserInRole(perm)) {\r
208                                                         if(perm.indexOf('|')<0) \r
209                                                                 res.getOutputStream().print("\nCongrats!, You are in Role " + perm);\r
210                                                           else\r
211                                                                 res.getOutputStream().print("\nCongrats!, You have Permission " + perm);\r
212                                                 } else {\r
213                                                         if(perm.indexOf('|')<0) \r
214                                                                 res.getOutputStream().print("\nSorry, you are NOT in Role " + perm);\r
215                                                           else\r
216                                                                 res.getOutputStream().print("\nSorry, you do NOT have Permission " + perm);\r
217                                                 }\r
218                                          \r
219                                         res.getOutputStream().print("</pre></body></html>");\r
220                                          \r
221                                 }\r
222                          \r
223                                 public String getServletInfo() {\r
224                                         return "MyServlet";\r
225                                 }\r
226                          \r
227                                 public void destroy() {\r
228                                 }\r
229                         }\r
230                 }\r
231  \r
232 Java Direct (AAFLur) Method\r
233 ===========================\r
234 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
235 package org.onap.aaf.example;\r
236 \r
237         .. code:: bash\r
238         \r
239                 import java.util.ArrayList;\r
240                 import java.util.List;\r
241                 import java.util.Properties;\r
242 \r
243                 import org.onap.aaf.cadi.Access;\r
244                 import org.onap.aaf.cadi.Permission;\r
245                 import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn;\r
246                 import org.onap.aaf.cadi.aaf.v2_0.AAFCon;\r
247                 import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;\r
248                 import org.onap.aaf.cadi.config.Config;\r
249                 import org.onap.aaf.cadi.lur.aaf.AAFPermission;\r
250                 import org.onap.aaf.cadi.lur.aaf.test.TestAccess;\r
251 \r
252                 public class ExamplePerm2_0 {\r
253                         public static void main(String args[]) {\r
254                                 // Normally, these should be set in environment.  Setting here for clarity\r
255                                 Properties props = System.getProperties();\r
256                                 props.setProperty("AFT_LATITUDE", "32.780140");\r
257                                 props.setProperty("AFT_LONGITUDE", "-96.800451");\r
258                                 props.setProperty("AFT_ENVIRONMENT", "AFTUAT");\r
259                                 props.setProperty(Config.AAF_URL,\r
260                                 "https://DME2RESOLVE/service=org.onap.aaf.authz.AuthorizationService/version=2.0/envContext=TEST/routeOffer=BAU_SE"\r
261                                                 );\r
262                                 props.setProperty(Config.AAF_USER_EXPIRES,Integer.toString(5*60000));   // 5 minutes for found items to live in cache\r
263                                 props.setProperty(Config.AAF_HIGH_COUNT,Integer.toString(400));         // Maximum number of items in Cache);\r
264                                 props.setProperty(Config.CADI_KEYFILE,"keyfile"); //Note: Be sure to generate with java -jar <cadi_path>/lib/cadi-core*.jar keygen keyfile\r
265                 //              props.setProperty("DME2_EP_REGISTRY_CLASS","DME2FS");\r
266                 //              props.setProperty("AFT_DME2_EP_REGISTRY_FS_DIR","../../authz/dme2reg");\r
267 \r
268                                 \r
269                                 // Link or reuse to your Logging mechanism\r
270                                 Access myAccess = new TestAccess(); // \r
271                                 \r
272                                 // \r
273                                 try {\r
274                                         AAFCon<?> con = new AAFConDME2(myAccess);\r
275                                         \r
276                                         // AAFLur has pool of DME clients as needed, and Caches Client lookups\r
277                                         AAFLurPerm aafLur = con.newLur();\r
278                                         // Note: If you need both Authn and Authz construct the following:\r
279                                         AAFAuthn<?> aafAuthn = con.newAuthn(aafLur);\r
280 \r
281                                         // Do not set Mech ID until after you construct AAFAuthn,\r
282                                         // because we initiate  "401" info to determine the Realm of \r
283                                         // of the service we're after.\r
284                                         con.basicAuth("xxxx@aaf.abc.com", "XXXXXX");\r
285 \r
286                                         try {\r
287                                                 \r
288                                                 // Normally, you obtain Principal from Authentication System.\r
289                                                 // For J2EE, you can ask the HttpServletRequest for getUserPrincipal()\r
290                                                 // If you use CADI as Authenticator, it will get you these Principals from\r
291                                                 // CSP or BasicAuth mechanisms.\r
292                                                 String id = "xxxx@aaf.abc.com"; //"cluster_admin@gridcore.abc.com";\r
293 \r
294                                                 // If Validate succeeds, you will get a Null, otherwise, you will a String for the reason.\r
295                                                 String ok = aafAuthn.validate(id, "XXXXXX");\r
296                                                 if(ok!=null)System.out.println(ok);\r
297                                                 \r
298                                                 ok = aafAuthn.validate(id, "wrongPass");\r
299                                                 if(ok!=null)System.out.println(ok);\r
300 \r
301 \r
302                                                 // AAF Style permissions are in the form\r
303                                                 // Type, Instance, Action \r
304                                                 AAFPermission perm = new AAFPermission("org.onap.aaf.grid.core.coh",":dev_cluster", "WRITE");\r
305                                                 \r
306                                                 // Now you can ask the LUR (Local Representative of the User Repository about Authorization\r
307                                                 // With CADI, in J2EE, you can call isUserInRole("org.onap.aaf.mygroup|mytype|write") on the Request Object \r
308                                                 // instead of creating your own LUR\r
309                                                 System.out.println("Does " + id + " have " + perm);\r
310                                                 if(aafLur.fish(id, perm)) {\r
311                                                         System.out.println("Yes, you have permission");\r
312                                                 } else {\r
313                                                         System.out.println("No, you don't have permission");\r
314                                                 }\r
315 \r
316                                                 System.out.println("Does Bogus have " + perm);\r
317                                                 if(aafLur.fish("Bogus", perm)) {\r
318                                                         System.out.println("Yes, you have permission");\r
319                                                 } else {\r
320                                                         System.out.println("No, you don't have permission");\r
321                                                 }\r
322 \r
323                                                 // Or you can all for all the Permissions available\r
324                                                 List<Permission> perms = new ArrayList<Permission>();\r
325                                                 \r
326                                                 aafLur.fishAll(id,perms);\r
327                                                 for(Permission prm : perms) {\r
328                                                         System.out.println(prm.getKey());\r
329                                                 }\r
330                                                 \r
331                                                 // It might be helpful in some cases to clear the User's identity from the Cache\r
332                                                 aafLur.remove(id);\r
333                                         } finally {\r
334                                                 aafLur.destroy();\r
335                                         }\r
336                                 } catch (Exception e) {\r
337                                         e.printStackTrace();\r
338                                 }\r
339 \r
340                         }\r
341                 }\r
342 \r
343 There are two current AAF Lurs which you can utilize:\r
344 -       Org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm is the default, and will fish based on the Three-fold "Permission" standard in AAF\r
345 To run this code, you will need from a SWM deployment (org.onap.aaf.cadi:cadi, then soft link to jars needed):\r
346 -       cadi-core-<version>.jar\r
347 -       cadi-aaf-<version>-full.jar\r
348    or by Maven\r
349 <dependency>\r
350 <groupId>org.onap.aaf.cadi</groupId>\r
351 <artifactId>cadi-aaf</artifactId>\r
352 <version>THE_LATEST_VERSION</version>\r
353 <classifier>full</classifier> \r
354 </dependency>\r
355    If you need the Java Client definitions only, \r
356  \r
357    Also needed are the DME2 Client libraries:\r
358 -       dme2-<version>.jar\r
359 -       discovery-clt-<version>.jar\r
360 \r