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