[Java programming language only]

Client authorization programming

WebSphere® eXtreme Scale supports Java™ Authentication and Authorization Service (JAAS) authorization that is ready to use and also supports custom authorization using the ObjectGridAuthorization interface.

The ObjectGridAuthorization plug-in is used to authorize ObjectGrid, ObjectMap, and JavaMap accesses to the Principals represented by a Subject object in a custom way. A typical implementation of this plug-in is to retrieve the Principals from the Subject object, and then check whether the specified permissions are granted to the Principals.

A permission passed to the checkPermission(Subject, Permission) method can be one of the following permissions:

  • MapPermission
  • ObjectGridPermission
  • ServerMapPermission
  • AgentPermission

Refer to ObjectGridAuthorization API documentation for more details.

MapPermission

The com.ibm.websphere.objectgrid.security.MapPermission public class represents permissions to the ObjectGrid resources, specifically the methods of ObjectMap or JavaMap interfaces. WebSphere eXtreme Scale defines the following permission strings to access the methods of ObjectMap and JavaMap:

  • read: Permission to read the data from the map. The integer constant is defined as MapPermission.READ.
  • write: Permission to update the data in the map. The integer constant is defined as MapPermission.WRITE.
  • insert: Permission to insert the data into the map. The integer constant is defined as MapPermission.INSERT.
  • remove: Permission to remove the data from the map. The integer constant is defined as MapPermission.REMOVE.
  • invalidate: Permission to invalidate the data from the map. The integer constant is defined as MapPermission.INVALIDATE.
  • all: All above permissions: read, write, insert, remote, and invalidate. The integer constant is defined as MapPermission.ALL.

Refer to MapPermission API documentation for more details.

You can construct a MapPermission object by passing the fully qualified ObjectGrid map name (in format [ObjectGrid_name].[ObjectMap_name]) and the permission string or integer value. A permission string can be a comma-delimited string of the previous permission strings such as read, insert, or it can be all. A permission integer value can be any previously mentioned permission integer constants or a mathematical value of several integer permission constants, such as MapPermission.READ|MapPermission.WRITE.

The authorization occurs when an ObjectMap or JavaMap method is called. The run time checks different permissions for different methods. If the required permissions are not granted to the client, an AccessControlException results.

Table 1. List of methods and the required MapPermission. For each read, write, insert, remove, or invalidate permission, several ObjectMap or JavaMap methods apply.
Permission ObjectMap/JavaMap
read Boolean containsKey(Object)
Boolean equals(Object)
Object get(Object)
Object get(Object, Serializable)
List getAll(List)
List getAll(List keyList, Serializable)
List getAllForUpdate(List)
List getAllForUpdate(List, Serializable)
Object getForUpdate(Object)
Object getForUpdate(Object, Serializable)
public Object getNextKey(long)
write Object put(Object key, Object value)
void put(Object, Object, Serializable)
void putAll(Map)
void putAll(Map, Serializable)
void update(Object, Object)
void update(Object, Object, Serializable)
insert public void insert (Object, Object)
void insert(Object, Object, Serializable)
remove Object remove (Object)
void removeAll(Collection)
void clear()
invalidate public void invalidate (Object, Boolean)
void invalidateAll(Collection, Boolean)
void invalidateUsingKeyword(Serializable)
int setTimeToLive(int)

Authorization is based solely on which method is used, rather than what the method really does. For example, a put method can insert or update a record based on whether the record exists. However, the insert or update cases are not distinguished.

[Version 8.6 and later]
[Version 8.6 and later]Deprecated featureNote: The setPutMode(PutMode.UPSERT) method is added to change the default behavior of the ObjectMap and JavaMap put() and putAll() methods to behave like ObjectMap.upsert() and upsertAll() methods.

The PutMode.UPSERT method replaces the setPutMode(PutMode.INSERTUPDATE) method. Use the PutMode.UPSERT method to tell the BackingMap and loader that an entry in the data grid needs to place the key and value into the grid. The BackingMap and loader does either an insert or an update to place the value into the grid and loader. If you run the upsert API within your applications, then the loader gets an UPSERT LogElement type, which allows loaders to do database merge or upsert calls instead of using insert or update.

An operation type can be achieved by combinations of other types. For example, an update can be achieved by a remove and then an insert. Consider these combinations when designing your authorization policies.

ObjectGridPermission

A com.ibm.websphere.objectgrid.security.ObjectGridPermission represents permissions to the ObjectGrid:
  • Query: permission to create an object query or entity query. The integer constant is defined as ObjectGridPermission.QUERY.
  • Dynamic map: permission to create a dynamic map based on the map template. The integer constant is defined as ObjectGridPermission.DYNAMIC_MAP.
Refer to ObjectGridPermission API documentation for more details.

The following table summarizes the methods and the required ObjectGridPermission:

Table 2. List of methods and the required ObjectGridPermission . For a query or dynamicmap permission action, an ObjectGrid method applies.
Permission action Methods
query com.ibm.websphere.objectgrid.Session.createObjectQuery(String)
query com.ibm.websphere.objectgrid.em.EntityManager.createQuery(String)
dynamicmap com.ibm.websphere.objectgrid.Session.getMap(String)

ServerMapPermission

An ServerMapPermission represents permissions to an ObjectMap hosted in a server. The name of the permission is the full name of the ObjectGrid map name. It has the following actions:

  • replicate: permission to replicate a server map to near cache
  • dynamicIndex: permission for a client to create or remove a dynamic index on a server
Refer to ServerMapPermission API documentation for more details. The detailed methods, which require different ServerMapPermission, are listed in the following table:
Table 3. Permissions to a server-hosted ObjectMap. For a replicate or dynamicIndex permission action, an ObjectGrid method applies.
Permission action Methods
replicate com.ibm.websphere.objectgrid.ClientReplicableMap.enableClientReplication(Mode, int[], ReplicationMapListener)
dynamicIndex com.ibm.websphere.objectgrid.BackingMap.createDynamicIndex(String, Boolean, String, DynamicIndexCallback)
dynamicIndex com.ibm.websphere.objectgrid.BackingMap.removeDynamicIndex(String)

AgentPermission

An AgentPermission represents permissions to the datagrid agents. The name of the permission is the full name of the ObjectGrid map, and the action is a comma-delimited string of agent implementation class names or package names.

Refer to AgentPermission API documentation for more information.

The following methods in the class com.ibm.websphere.objectgrid.datagrid.AgentManager require AgentPermission.
com.ibm.websphere.objectgrid.datagrid.AgentManager#callMapAgent(MapGridAgent, Collection)
com.ibm.websphere.objectgrid.datagrid.AgentManager#callMapAgent(MapGridAgent)
com.ibm.websphere.objectgrid.datagrid.AgentManager#callReduceAgent(ReduceGridAgent, Collection)
com.ibm.websphere.objectgrid.datagrid.AgentManager#callReduceAgent(ReduceGridAgent, Collection)

Authorization mechanisms

WebSphere eXtreme Scale supports two kinds of authorization mechanisms: Java Authentication and Authorization Service (JAAS) authorization and custom authorization. These mechanisms apply to all authorizations. JAAS authorization augments the Java security policies with user-centric access controls. Permissions can be granted based not just on what code is running, but also on who is running it. JAAS authorization is part of the SDK Version 5 and later.

Additionally, WebSphere eXtreme Scale also supports custom authorization with the following plug-in:

  • ObjectGridAuthorization: custom way to authorize access to all artifacts.

You can implement your own authorization mechanism if you do not want to use JAAS authorization. By using a custom authorization mechanism, you can use the policy database, policy server, or Tivoli® Access Manager to manage the authorizations.

You can configure the authorization mechanism in two ways:

  • XML configuration

    You can use the ObjectGrid XML file to define an ObjectGrid and set the authorization mechanism to either AUTHORIZATION_MECHANISM_JAAS or AUTHORIZATION_MECHANISM_CUSTOM. Here is the secure-objectgrid-definition.xml file that is used in the enterprise application ObjectGridSample:

    <objectGrids>
    	<objectGrid name="secureClusterObjectGrid" securityEnabled="true"	
    		authorizationMechanism="AUTHORIZATION_MECHANISM_JAAS">
    		<bean id="TransactionCallback"
    classname="com.ibm.websphere.samples.objectgrid.HeapTransactionCallback" />
    ...
    </objectGrids>
    
  • Programmatic configuration

    If you want to create an ObjectGrid using method ObjectGrid.setAuthorizationMechanism(int), you can call the following method to set the authorization mechanism. Calling this method applies only to the local WebSphere eXtreme Scale programming model when you directly instantiate the ObjectGrid instance:

    /**
     * Set the authorization Mechanism. The default is 
     * com.ibm.websphere.objectgrid.security.SecurityConstants.
     * AUTHORIZATION_MECHANISM_JAAS.
     * @param authMechanism the map authorization mechanism
    */
    void setAuthorizationMechanism(int authMechanism);

JAAS authorization

A javax.security.auth.Subject object represents an authenticated user. A Subject consists of a set of principals, and each Principal represents an identity for that user. For example, a Subject can have a name principal, for example, Joe Smith, and a group principal, for example, manager.

Using the JAAS authorization policy, permissions can be granted to specific Principals. WebSphere eXtreme Scale associates the Subject with the current access control context. For each call to the ObjectMap or Javamap method, the Java runtime automatically determines if the policy grants the required permission only to a specific Principal and if so, the operation is allowed only if the Subject associated with the access control context contains the designated Principal.

You must be familiar with the policy syntax of the policy file. For detailed description of JAAS authorization, refer to the JAAS Reference Guide.

WebSphere eXtreme Scale has a special code base that is used for checking the JAAS authorization to the ObjectMap and JavaMap method calls. This special code base is http://www.ibm.com/com/ibm/ws/objectgrid/security/PrivilegedAction. Use this code base when granting ObjectMap or JavaMap permissions to principals. This special code was created because the Java archive (JAR) file for eXtreme Scale is granted with all permissions.

The template of the policy to grant the MapPermission permission is:

grant codeBase "http://www.ibm.com/com/ibm/ws/objectgrid/security/PrivilegedAction" 
   <Principal field(s)>{
    permission com.ibm.websphere.objectgrid.security.MapPermission 
               "[ObjectGrid_name].[ObjectMap_name]", "action";
    ....
    permission com.ibm.websphere.objectgrid.security.MapPermission 
               "[ObjectGrid_name].[ObjectMap_name]", "action";
  };
A Principal field looks like the following example:
principal Principal_class "principal_name"

In this policy, only insert and read permissions are granted to these four maps to a certain principal. The other policy file, fullAccessAuth.policy, grants all permissions to these maps to a principal. Before running the application, change the principal_name and principal class to appropriate values. The value of the principal_name depends on the user registry. For example, if local OS is used as user registry, the machine name is MACH1, the user ID is user1, and the principal_name is MACH1/user1.

The JAAS authorization policy can be put directly into the Java policy file, or it can be put in a separate JAAS authorization file and then set in either of two ways:

  • Use the following JVM argument:
    -Djava.security.policy=file:[JAAS_AUTH_POLICY_FILE]
  • Use the following property in the java.security file:
    -Dauth.policy.url.x=file:[JAAS_AUTH_POLICY_FILE]

Custom ObjectGrid authorization

ObjectGridAuthorization plug-in is used to authorize ObjectGrid, ObjectMap, and JavaMap accesses to the Principals represented by a Subject object in a custom way. A typical implementation of this plug-in is to retrieve the Principals from the Subject object, and then check whether or not the specified permissions are granted to the Principals.

A permission passed to the checkPermission(Subject, Permission) method could be one of the following:

  • MapPermission
  • ObjectGridPermission
  • AgentPermission
  • ServerMapPermission

Refer to ObjectGridAuthorization API documentation for more details.

The ObjectGridAuthorization plug-in can be configured in the following ways:

  • XML configuration

    You can use the ObjectGrid XML file to define an ObjectAuthorization plug-in. Here is an example:

    <objectGrids>
    	<objectGrid name="secureClusterObjectGrid" securityEnabled="true"
    		authorizationMechanism="AUTHORIZATION_MECHANISM_CUSTOM">
    ...
    		<bean id="ObjectGridAuthorization"
    className="com.acme.ObjectGridAuthorizationImpl" />
    </objectGrids>
    
  • Programmatic configuration

    If you want to create an ObjectGrid using the API method ObjectGrid.setObjectGridAuthorization(ObjectGridAuthorization), you can call the following method to set the authorization plug-in. This method only applies to the local eXtreme Scale programming model when you directly instantiate the ObjectGrid instance.

    Attention: In the following example, some lines of code are continued on the next line for publication purposes.
    /**
         * Sets the <code>ObjectGridAuthorization</code> for this ObjectGrid instance. 
         * <p>
         * Passing <code>null</code> to this method removes a previously set 
         * <code>ObjectGridAuthorization</code> object from an earlier invocation of this method
         * and indicates that this <code>ObjectGrid</code> is not associated with a
         * <code>ObjectGridAuthorization</code> object.
         * <p>
         * This method should only be used when ObjectGrid security is enabled. If 
         * the ObjectGrid security is disabled, the provided <code>ObjectGridAuthorization</code> object 
         * will not be used.
         * <p>
         * A <code>ObjectGridAuthorization</code> plug-in can be used to authorize
         * access to the ObjectGrid and maps. Please refer to <code>ObjectGridAuthorization</code> for more details.
         *    
         * <p>
         * As of XD 6.1, the <code>setMapAuthorization</code> is deprecated and 
         * <code>setObjectGridAuthorization</code> is recommended for use. However, 
         * if both <code>MapAuthorization</code> plug-in and <code>ObjectGridAuthorization</code> plug-in 
         * are used, ObjectGrid will use the provided <code>MapAuthorization</code> to authorize map accesses,
         * even though it is deprecated.
         * <p>
         * Note, to avoid an <code>IllegalStateException</code>, this method must be
         * called prior to the <code>initialize()</code> method.  Also, keep in mind 
         * that the <code>getSession</code> methods implicitly call the 
         * <code>initialize()</code> method if it has yet to be called by the 
         * application.
         * 
         * @param ogAuthorization the <code>ObjectGridAuthorization</code> plug-in 
         * 
         * @throws IllegalStateException if this method is called after the 
         *         <code>initialize()</code> method is called.
         * 
         * @see #initialize()
         * @see ObjectGridAuthorization    
         * @since WAS XD 6.1     
         */
        void setObjectGridAuthorization(ObjectGridAuthorization ogAuthorization);

Implementing ObjectGridAuthorization

The Boolean checkPermission(Subject subject, Permission permission) method of the ObjectGridAuthorization interface is called by theWebSphere eXtreme Scale run time to check whether the passed-in subject object has the passed-in permission. The implementation of the ObjectGridAuthorization interface returns true if the object has the permission, and false if not.

A typical implementation of this plug-in is to retrieve the principals from the Subject object and check whether the specified permissions are granted to the principals by consulting specific policies. These policies are defined by users. For example, the policies can be defined in a database, a plain file, or a Tivoli Access Manager policy server.

For example, we can use Tivoli Access Manager policy server to manage the authorization policy and use its API to authorize the access. For how to use Tivoli Access Manager Authorization APIs, refer to the IBM® Tivoli Access Manager Authorization Java Classes Developer Reference for more details.

This sample implementation has the following assumptions:

  • Check authorization for MapPermission only. For other permissions, always return true.
  • The Subject object contains a com.tivoli.mts.PDPrincipal principal.
  • The Tivoli Access Manager policy server has defined the following permissions for the ObjectMap or JavaMap name object. The object that is defined in the policy server must have the same name as the ObjectMap or JavaMap name in the format of [ObjectGrid_name].[ObjectMap_name]. The permission is the first character of the permission strings that are defined in the MapPermission permission. For example, the permission "r" that is defined in the policy server represents the read permission to the ObjectMap map.

The following code snippet demonstrates how to implement the checkPermission method:

/**
* @see com.ibm.websphere.objectgrid.security.plugins.
* 		MapAuthorization#checkPermission
* (javax.security.auth.Subject, com.ibm.websphere.objectgrid.security.
* 		MapPermission)
*/
public boolean checkPermission(final Subject subject, 
	Permission p) {
  
  // For non-MapPermission, we always authorize.
  if (!(p instanceof MapPermission)){
    return true;
  }

  MapPermission permission = (MapPermission) p;

  String[] str = permission.getParsedNames();
  
  StringBuffer pdPermissionStr = new StringBuffer(5); 
  for (int i=0; i<str.length; i++) {
    pdPermissionStr.append(str[i].substring(0,1));
  }
  
  PDPermission pdPerm = new PDPermission(permission.getName(), 
		pdPermissionStr.toString());
  
  Set principals = subject.getPrincipals();
  
  Iterator iter= principals.iterator(); 
  while(iter.hasNext()) {
    try {
      PDPrincipal principal = (PDPrincipal) iter.next();
      if (principal.implies(pdPerm)) {
        return true;
      }
    }
    catch (ClassCastException cce) {
      // Handle exception
    }
  }
  return false;
}