.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0

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>


