=================
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:: bash

    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:: 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
package org.onap.aaf.example;

  .. code:: bash

    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>cadi-aaf</artifactId>
<version>THE_LATEST_VERSION</version>
<classifier>full</classifier>
</dependency>
If you need the Java Client definitions only,

   Also needed are the DME2 Client libraries:
-  dme2-<version>.jar
-  discovery-clt-<version>.jar
