.. 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
=========================

.. code-block:: java

  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)
================================

.. code-block:: java

  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

.. code-block:: java

  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>


