From 443034182c2b9c6b53081a31b8c4ef1e15eb89de Mon Sep 17 00:00:00 2001 From: Morgan Richomme Date: Tue, 7 Nov 2017 19:36:00 +0100 Subject: Fix doc8 errors in aaf/authz documentation JIRA: AAF-87 Change-Id: I84c8423b2a875f8577a0b523d964c3f3803cbbba Signed-off-by: Morgan Richomme --- .../AAF-API-Documentation.rst | 469 +++++++------- docs/AAF-API-Documentation/Connecting-to-AAF.rst | 719 ++++++++++----------- 2 files changed, 593 insertions(+), 595 deletions(-) diff --git a/docs/AAF-API-Documentation/AAF-API-Documentation.rst b/docs/AAF-API-Documentation/AAF-API-Documentation.rst index 4594d010..408e4a39 100644 --- a/docs/AAF-API-Documentation/AAF-API-Documentation.rst +++ b/docs/AAF-API-Documentation/AAF-API-Documentation.rst @@ -1,235 +1,234 @@ -AAF 2.0 RESTful interface -========================= - -Accessing RESTful ------------------ - --AAF RESTful service is secured by the following: --The Client must utilize HTTP/S. Non Secure HTTP is not acceptable --The Client MUST supply an Identity validated by one of the following mechanisms - - - Valid Global Login Cookie (CSP) - - BASIC AUTH protocol using CSO Registered MechID, provisioned in AAF - - BASIC AUTH protocol using ATTUID@csp.att.com, Global Login Password - - (Available 3rd Qtr 2015) Valid tGuard Login Cookie - - (Near Future) Application level Certificate - -Responses - -Each API Entity listed shows what structure will be accepted by service (ContentType) or responded with by service (Accept). Therefore, use these in making your call. Critical for PUT/POST. - -Each API call may respond with JSON or XML. Choose the ContentType/Accept that has +json after the type for JSON or +xml after the Type for XML - -XSDs for Versions - -AAF can support multiple Versions of the API. Choose the ContentType/Accept that has the appropriate version=?.? - -All Errors coming from AAF return AT&T Standard Error Message as a String: `JSON <./example/YXBwbGljYXRpb24vRXJyb3IranNvbg==>`__ `XML <./example/YXBwbGljYXRpb24vRXJyb3IreG1s>`__ (does not apply to errors from Container) - -Character Restrictions - -- Character Restrictions must depend on the Enforcement Point used -- Most AAF usage will be AAF Enforcement Point Characters for Instance and Action are: - *a-zA-Z0-9,.()\_-=%* - For Instance, you may declare a multi-dimensional key with : (colon) separator, example: - -Ask for a Consultation on how these are typically used, or, if your tool is the only Enforcement Point, if set may be expanded - -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| Entity | Method | Path Info | Description | -+====================+====================+====================+===================================================+ -| PERMISSION | POST | /authz/perm | Create a Permission | -| | | | Permission consists of: | -| | | | - type - a Namespace qualified identifier | -| | | | specifying what kind of resource is being | -| | | | protected | -| | | | - instance - a key, possibly multi-dimensional | -| | | | that identifies a specific instance of the | -| | | | type | -| | | | - action - what kind of action is allowed | -| | | | Note: instance and action can be an \* | -| | | | Expected HTTP Code | -| | | | 201 | -| | | | Explicit HTTP Error Codes | -| | | | 403, 404, 406, 409 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | PUT | /authz/perm | Set Description for Permission | -| | | | Add Description Data to Perm | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | DELETE | /authz/perm | Delete a Permission | -| | | | Delete the Permission referenced by PermKey. | -| | | | You cannot normally delete a permission which | -| | | | is still granted to roles, however the | -| | | | "force" property allows you to do just that. To | -| | | | do this: Add | -| | | | 'force=true' as a query parameter. | -| | | | **WARNING**: Using force will ungrant this | -| | | | permission from all roles. Use with care. | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | DELETE | /authz/perm/:name/ | Delete a Permission | -| | | :type/:action | Delete the Permission referenced by :type | -| | | | :instance: action | -| | | | You cannot normally delete a permission which | -| | | | is still granted to roles, however the | -| | | | "force" property allows you to do | -| | | | just that. To do this: Add 'force=true' as a | -| | | | query parameter | -| | | | | -| | | | WARNING: Using force will ungrant this permission | -| | | | from all roles. Use with care. | -| | | | ------------------------------------------------- | -| | | | Parameters | -| | | | type : string (Required) | -| | | | instance : string (Required) | -| | | | action : string (Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | PUT | /authz/perm/:type/ | Update a Permission | -| | | :instance/:action | Rename the Permission referenced | -| | | | by :type :instance :action, and rename | -| | | | (copy/delete) to the Permission described in | -| | | | PermRequest | -| | | | | -| | | |---------------------------------------------------| -| | | | Parameters | -| | | | type : string (Required) | -| | | | instance : string (Required) | -| | | | action : string (Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 ,409 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | GET | /authz/perms/:type | Get Permissions by Type | -| | | | | -| | | | List All Permissions that match the :type | -| | | | element of the key | -| | | | ------------------------------------------------- | -| | | | Parameters | -| | | | type : string (Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | GET | /authz/perms/:type | Get Permissions by Key | -| | | /:instance/:action | List Permissions that match key; | -| | | | :type, :instance and :action | -| | | | | -| | | | --------------------------------------------------| -| | | | Parameters | -| | | | type : string (Required) | -| | | | instance : string (Required) | -| | | | action : string (Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | GET | /authz/perms/ns/:n | Get PermsByNS | -| | | s | List All Permissions that are in Namespace :ns | -| | | | --------------------------------------------------| -| | | | Parameters | -| | | | type : ns (Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | GET | /authz/perms/role/ | Get Permissions by Role | -| | | :role | List All Permissions that are granted to :role | -| | | | --------------------------------------------------| -| | | | Parameters | -| | | | role : string (Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | POST | /authz/perms/user/ | Get Permissions by User, Query AAF Perms | -| | | :user | | -| | | | List All Permissions that match user :user | -| | | | | -| | | | 'user' must be expressed as full | -| | | | identity (ex: id@full.domain.com) | -| | | | Present Queries as one or more Permissions (see | -| | | | ContentType Links below for format). If the | -| | | | Caller is Granted this specific Permission, and | -| | | | the Permission is valid for the User, it will be | -| | | | included in response permissions,along with all | -| | | | the normal permissions on the 'GET' version of | -| | | | this call. If it is not valid,or caller does not | -| | | | permission to see, it will be removed from the | -| | | | list. | -| | | | **Note**: This design allows you to make one | -| | | | call for all expected permissions | -| | | | | -| | | | The permission to be included MUST be: | -| | | | .access\|:[:key]\| | -| | | | | -| | | | examples: | -| | | | | -| | | | com.att.myns.access|:ns|write | -| | | | com.att.myns.access\|:role:myrole\|create | -| | | | com.att.myns.access\|:perm:mytype:myinstance: | -| | | | myaction\|read | -| | | | --------------------------------------------------| -| | | | Parameters | -| | | | user:string(Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | GET | /authz/perms/user/ | Get Permissions by User | -| | | :user | | -| | | | List All Permissions that match user :user | -| | | | 'user' must be expressed as full | -| | | | identity (ex:id@full.domain.com) | -| | | | --------------------------------------------------| -| | | | Parameters | -| | | | user:string(Required) | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| ROLE | POST | /authz/role | Create Role | -| | | | | -| | | | Roles are part of Namespaces | -| | | | Examples: | -| | | | | -| | | | - com.att.aaf - The team that created and | -| | | | maintains AAF | -| | | | | -| | | | Roles do not include implied permissions for an | -| | | | App. Instead, they contain explicit Granted | -| | | | Permissions by any Namespace in AAF | -| | | | Restrictions on Role Names: | -| | | | - Must start with valid Namespace name, | -| | | | terminated by .(dot/period) | -| | | | - Allowed Characters are a-zA-Z0-9._- | -| | | | - role names are Case Sensitive | -| | | | Expected HTTP Code | -| | | | 201 | -| | | | Explicit HTTP Error Codes | -| | | | 403, 404, 406, 409 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ -| | PUT | /authz/role | Set Description for role | -| | | | Add Description Data to a Role | -| | | | Expected HTTP Code | -| | | | 200 | -| | | | Explicit HTTP Error Codes | -| | | | 404, 406 | -+--------------------+--------------------+--------------------+---------------------------------------------------+ +AAF 2.0 RESTful interface +========================= + +Accessing RESTful +----------------- + +AAF RESTful service is secured by the following: + + * The Client must utilize HTTP/S. Non Secure HTTP is not acceptable + * The Client MUST supply an Identity validated by one of the following mechanisms: + + * Valid Global Login Cookie (CSP) + * BASIC AUTH protocol using CSO Registered MechID, provisioned in AAF + * BASIC AUTH protocol using ATTUID@csp.att.com, Global Login Password + * (Available 3rd Qtr 2015) Valid tGuard Login Cookie + * (Near Future) Application level Certificate + +Responses + +Each API Entity listed shows what structure will be accepted by service (ContentType) or responded with by service (Accept). Therefore, use these in making your call. Critical for PUT/POST. + +Each API call may respond with JSON or XML. Choose the ContentType/Accept that has +json after the type for JSON or +xml after the Type for XML + +XSDs for Versions + +AAF can support multiple Versions of the API. Choose the ContentType/Accept that has the appropriate version=?.? + +All Errors coming from AAF return AT&T Standard Error Message as a String: `JSON <./example/YXBwbGljYXRpb24vRXJyb3IranNvbg==>`__ `XML <./example/YXBwbGljYXRpb24vRXJyb3IreG1s>`__ (does not apply to errors from Container) + +Character Restrictions + +- Character Restrictions must depend on the Enforcement Point used +- Most AAF usage will be AAF Enforcement Point Characters for Instance and Action are: + *a-zA-Z0-9,.()\_-=%* + For Instance, you may declare a multi-dimensional key with : (colon) separator, example: + +Ask for a Consultation on how these are typically used, or, if your tool is the only Enforcement Point, if set may be expanded + ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| Entity | Method | Path Info | Description | ++====================+====================+====================+===================================================+ +| PERMISSION | POST | /authz/perm | Create a Permission | +| | | | Permission consists of: | +| | | | - type - a Namespace qualified identifier | +| | | | specifying what kind of resource is being | +| | | | protected | +| | | | - instance - a key, possibly multi-dimensional | +| | | | that identifies a specific instance of the | +| | | | type | +| | | | - action - what kind of action is allowed | +| | | | Note: instance and action can be an \* | +| | | | Expected HTTP Code | +| | | | 201 | +| | | | Explicit HTTP Error Codes | +| | | | 403, 404, 406, 409 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | PUT | /authz/perm | Set Description for Permission | +| | | | Add Description Data to Perm | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | DELETE | /authz/perm | Delete a Permission | +| | | | Delete the Permission referenced by PermKey. | +| | | | You cannot normally delete a permission which | +| | | | is still granted to roles, however the | +| | | | "force" property allows you to do just that. To | +| | | | do this: Add | +| | | | 'force=true' as a query parameter. | +| | | | **WARNING**: Using force will ungrant this | +| | | | permission from all roles. Use with care. | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | DELETE | /authz/perm/:name/ | Delete a Permission | +| | | :type/:action | Delete the Permission referenced by :type | +| | | | :instance: action | +| | | | You cannot normally delete a permission which | +| | | | is still granted to roles, however the | +| | | | "force" property allows you to do | +| | | | just that. To do this: Add 'force=true' as a | +| | | | query parameter | +| | | | | +| | | | WARNING: Using force will ungrant this permission | +| | | | from all roles. Use with care. | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | type : string (Required) | +| | | | instance : string (Required) | +| | | | action : string (Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | PUT | /authz/perm/:type/ | Update a Permission | +| | | :instance/:action | Rename the Permission referenced | +| | | | by :type :instance :action, and rename | +| | | | (copy/delete) to the Permission described in | +| | | | PermRequest | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | type : string (Required) | +| | | | instance : string (Required) | +| | | | action : string (Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 ,409 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | GET | /authz/perms/:type | Get Permissions by Type | +| | | | | +| | | | List All Permissions that match the :type | +| | | | element of the key | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | type : string (Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | GET | /authz/perms/:type | Get Permissions by Key | +| | | /:instance/:action | List Permissions that match key; | +| | | | :type, :instance and :action | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | type : string (Required) | +| | | | instance : string (Required) | +| | | | action : string (Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | GET | /authz/perms/ns/:n | Get PermsByNS | +| | | s | List All Permissions that are in Namespace :ns | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | type : ns (Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | GET | /authz/perms/role/ | Get Permissions by Role | +| | | :role | List All Permissions that are granted to :role | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | role : string (Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | POST | /authz/perms/user/ | Get Permissions by User, Query AAF Perms | +| | | :user | | +| | | | List All Permissions that match user :user | +| | | | | +| | | | 'user' must be expressed as full | +| | | | identity (ex: id@full.domain.com) | +| | | | Present Queries as one or more Permissions (see | +| | | | ContentType Links below for format). If the | +| | | | Caller is Granted this specific Permission, and | +| | | | the Permission is valid for the User, it will be | +| | | | included in response permissions,along with all | +| | | | the normal permissions on the 'GET' version of | +| | | | this call. If it is not valid,or caller does not | +| | | | permission to see, it will be removed from the | +| | | | list. | +| | | | **Note**: This design allows you to make one | +| | | | call for all expected permissions | +| | | | | +| | | | The permission to be included MUST be: | +| | | | .access\|:[:key]\| | +| | | | | +| | | | examples: | +| | | | | +| | | | com.att.myns.access|:ns|write | +| | | | com.att.myns.access\|:role:myrole\|create | +| | | | com.att.myns.access\|:perm:mytype:myinstance: | +| | | | myaction\|read | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | user:string(Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | GET | /authz/perms/user/ | Get Permissions by User | +| | | :user | | +| | | | List All Permissions that match user :user | +| | | | 'user' must be expressed as full | +| | | | identity (ex:id@full.domain.com) | +| | | | --------------------------------------------------| +| | | | Parameters | +| | | | user:string(Required) | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| ROLE | POST | /authz/role | Create Role | +| | | | | +| | | | Roles are part of Namespaces | +| | | | Examples: | +| | | | - com.att.aaf | +| | | | - The team that created andmaintains AAF | +| | | | | +| | | | Roles do not include implied permissions for an | +| | | | App. Instead, they contain explicit Granted | +| | | | Permissions by any Namespace in AAF | +| | | | Restrictions on Role Names: | +| | | | - Must start with valid Namespace name, | +| | | | terminated by .(dot/period) | +| | | | - Allowed Characters are a-zA-Z0-9._- | +| | | | - role names are Case Sensitive | +| | | | | +| | | | Expected HTTP Code | +| | | | 201 | +| | | | Explicit HTTP Error Codes | +| | | | 403, 404, 406, 409 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ +| | PUT | /authz/role | Set Description for role | +| | | | Add Description Data to a Role | +| | | | Expected HTTP Code | +| | | | 200 | +| | | | Explicit HTTP Error Codes | +| | | | 404, 406 | ++--------------------+--------------------+--------------------+---------------------------------------------------+ diff --git a/docs/AAF-API-Documentation/Connecting-to-AAF.rst b/docs/AAF-API-Documentation/Connecting-to-AAF.rst index 863c75fd..d2112eee 100644 --- a/docs/AAF-API-Documentation/Connecting-to-AAF.rst +++ b/docs/AAF-API-Documentation/Connecting-to-AAF.rst @@ -1,360 +1,359 @@ -================= -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:///caditest/testme?PERM=org.onap.aaf.myapp.myPerm|*|write - -Sample Servlet (Working example) -================================ - - .. code:: bash - - 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 map = new HashMap(); - try { - FileInputStream fis = new FileInputStream("run/cadi.properties"); - try { - props.load(fis); - String key,value; - for( Entry 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 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 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("
CSP Servlet Test

You're good to go!

" +
-							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("
"); - - } - - 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 /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 perms = new ArrayList(); - - 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-.jar -- cadi-aaf--full.jar - or by Maven - -org.onap.aaf.cadi -cadi-aaf -THE_LATEST_VERSION -full - - If you need the Java Client definitions only, - - Also needed are the DME2 Client libraries: -- dme2-.jar -- discovery-clt-.jar - +================= +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:///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 map = new HashMap(); + try { + FileInputStream fis = new FileInputStream("run/cadi.properties"); + try { + props.load(fis); + String key,value; + for( Entry 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 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 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("
CSP Servlet Test

You're good to go!

" +
+              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("
"); + + } + + 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 /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 perms = new ArrayList(); + + 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-.jar +- cadi-aaf--full.jar +or by Maven + +org.onap.aaf.cadi +cadi-aaf +THE_LATEST_VERSION +full + +If you need the Java Client definitions only, + + Also needed are the DME2 Client libraries: +- dme2-.jar +- discovery-clt-.jar -- cgit 1.2.3-korg