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