Table of Contents
This chapter describes the purpose of JACC and how to implement Custom JACC Provider to use it in the JEUS security system.
Java Authorization Contract for Containers (JACC) was first introduced in J2EE version 1.5, which is the current version.
JACC serves two basic purposes.
Provide a standardized SPI for EJB and Servlet authorization.
Ensure compatibility between existing J2SE and J2EE security models.
In short, JACC represents a standardized way of implementing an authorization provider that defines and handles authorization for EJBs and Servlets. Thus, if a JACC provider is implemented, it can be used in any JACC-compatible J2EE server.
The entire JACC specification is divided into three parts as follows:
Provider Protocol
Policy Protocol
Policy decision and execution protocol
For more information about JACC specifications (JSR-115), refer to JACC 1.5 specification in http://java.sun.com/j2ee.
The JACC Provider configuration protocol describes how a JACC provider (JACC implementation) is announced and incorporated into the runtime environment of an application server. This protocol defines how JACC providers are registered with J2EE servers. In general, this process is very simple as follows:
The Custom java.security.Policy class name is configured in the javax.security.jacc.policy.provider system properties. The JACC provider contains the Custom java.security.Policy class.
The J2EE server reads this class name and creates a class instance, and then casts it to the java.security.Policy type.
If successful, the default J2SE policy class will be replaced with the new JACC policy class by the java.security.Policy.setPolicy() method.
After the completion of the previous steps, all authorization checks will be performed by the new JACC policy. The current JACC policy object can be obtained using the java.security.Policy.getPolicy() method.
For more information about the JACC Provider configuration protocol, refer to JACC specifications.
The Policy Configuration protocol essentially defines how the security constraints defined in J2EE deployment descriptor file (ejb-jar.xml, web.xml) are to be mapped to the java.security.Permission set defined in the javax.security.jacc package. It also defines how these Permissions are to be added to the JACC provider (Custom java.security.Policy).
This helps the provider to make correct authorization decisions for EJB and Servlet modules.
The Policy Configuration protocol does NOT define how to configure principal-to-role mappings. It only describes how to configure role-to-resource mappings based on the information in the standard J2EE DD file. The principal-to-role mappings are defined according to the JACC provider vendor.
Policy can be configured as follows:
Specify the fully qualified class name of Custom javax.security.jacc.PolicyConfigurationFactory in the javax.security.jacc.PolicyConfigurationFactory.provider system property (“-D” property).
The JACC provider contains Custom javax.security.jacc.PolicyConfigurationFactory class.
The J2EE server reads the property and creates a class instance (PCF).
Deploy the servlet and EJB modules.
The deployment code parses the provided web.xml and ejb-jar.xml DD files and converts the security constraints to JACC permission instances. The permission class is included in the javax.security.jacc package. Each permission instance represents the Role-to-Resource mapping defined in the servlet and EJB.
The deployment code calls the PCF.getPolicyConfiguration() method and receives an instance of the javax.security.jacc.PolicyConfiguration type.
The deployment code adds the role-to-resource permissions created in step 4 to PolicyConfiguration using various PolicyConfiguration methods.
After all permissions have been added, the PolicyConfiguration.commit() method is called.
When a Servlet and/or EJB module is undeployed, PolicyConfiguration.delete() method is called. This removes all the permissions of the Servlet/EJB module.
For more information about the policy configuration process, refer to the JACC specifications.
The policy decision and execution protocol describe how (EJB and Servlet) authorization decisions are to be carried out at runtime. They are applied after the requirements of the previous two protocols have been met.
Essentially, Policy decision and execution work as follows. This section uses a servlet as an example, but it also applies equally to an EJB.
An HTTP request is sent to the Servlet page.
The Servlet container configures some JACC context information using the javax.security.jacc.PolicyContext class.
The Servlet container then constructs two JACC Web permission instances (defined in the javax.security.jacc package). These permission instances represent the permission defined for the current Servlet page.
The Servlet container queries the JACC policy provider to see if the servlet requester has the two permissions mentioned in step 3. There are several ways to interpret the query.
For example, the Policy.implies() method can be used to interpret the query. In this case, all permissions, which are checked by the java.security.ProtectionDomain that is initialized by the principal of the requester, are used as parameters.
The JACC provider receives the request and determines if the requester has the permission to access the servlet page by using the following information: context information set from step 2, the permission instances created in step 3, the current principal(s), the principal-to-role mapping, and the role-to-resource mapping.
If the outcome of the authorization check is positive, the Servlet container will allow access to the Servlet page. Otherwise, an authorization error page will be returned.
For more information about policy decision and execution protocol, refer to the JACC specifications.
This section describes how to develop the Custom JACC provider and some development instructions.
The following is a simple picture that shows the relationships between the classes that need to be implemented for your JACC provider. In the figure, the classes that need to be implemented are labeled using names starting with “MyJACC”. Any name can be chosen for these classes.
The following list shows the classes that are required for a complete implementation of a JACC provider:
The heart of a JACC provider implementation is usually creating a subclass of the java.security.Policy class. The class is used in JACC for authorization purposes.
The usual way of implementing the subclass of java.security.Policy is by defining a new class, we call it MyJACCPolicy here, that extends java.security.Policy. Then, MyJACCPolicy overrides the implies() method in order to implement the policy decision and protocol that are described in "6.2.3. Policy Decision and Execution Protocol". When implementing the implies() method, both the permissions that are added using the PolicyConfiguration interface and the principal-to-role mappings must be considered in order to interpret an authorization query.
MyJACCPolicy must provide a public constructor without parameters, so that the application server can easily create a class instance.
javax.security.jacc.PolicyConfigurationFactory
In order to satisfy the Policy configuration protocol, the application server must be able to add permission instances to JACC java.security.Policy. This is accomplished using the javax.security.jacc.PolicyConfiguration interface. The abstract class, javax.security.jacc.PolicyConfigurationFactory, is used to create the PolicyConfiguration instance.
Thus, in order to create a complete JACC provider, you must implement the getPolicyConfiguration() method in the javax.security.jacc.PolicyConfigurationFactory class. This means that you must create a new subclass of the javax.security.jacc.PolicyConfigurationFactory class. Here, we call the new class MyJACCPolicyConfigurationFactory. MyJACCPolicyConfigurationFactory must be a concrete class with a public no-argument constructor, so that it can be easily instantiated by the application server.
The MyJACCPolicyConfigurationFactory must provide a public no-argument constructor to enable the J2EE server to easily create instances of the class.
javax.security.jacc.PolicyConfiguration
In order to implement the Policy configuration protocol, the application server must be able to add permission instances to the JACC java.security.Policy implementation. This is accomplished through an instance of the javax.security.jacc.PolicyConfiguration interface. An instance of this interface is created through the abstract class, javax.security.jacc.PolicyConfigurationFactory, as already mentioned.
Implementing the javax.security.jacc.PolicyConfiguration interface is thus a requirement to complete a JACC provider. We will call our implementation class MyJACCPolicyConfiguration.
javax.security.jacc.PolicyConfigurationFactory implementation (MyJACCPolicy ConfigurationFactory) should always return an instance of the MyJACCPolicyConfiguration class.
This section briefly explains how to implement each of the classes. For more information about how to implement the javax.security.jacc.PolicyConfiguration class, refer to the Policy Configuration Protocol of the JACC specification, and the J2EE Javadoc for each class.
In general, the JACC Provider and the supporting classes referenced by the JACC provider should be packaged together into a JAR file and be delivered, in a JAR format, to the target application server. We will call the JAR file, “MyJACCProvider.jar”.
The path of the JAR file for the JACC provider must be included in the application server path. If needed, certain system properties can be configured, but the procedure for this varies slightly for different application servers. How to configure this for JEUS will be explained in "6.4. Integrating JACC Providers with the JEUS Security System".
The JEUS security system provides a very simple default JACC provider. In general, it is strongly discouraged to use this default provider as it was mainly developed for test purposes. Instead, the default standard authorization provider described in the earlier chapter is recommended for use.
However, if you wish to use another JACC provider, you must create your own JACC JAR archive and include the JACC provider file in it since there is no support for commercial products.
This section describes how to integrate JACC providers with the JEUS security system.
The process to integrate the JEUS security system with a JACC Provider is as follows.
Implement a Principal-to-Role Mapper
The JACC interface does not contain any implementation related to principal-to-role mapping, but only for role-to-resource mapping. The user must implement a separate JEUS-specific interface to implement the mapping, and JEUS provides the isjeus.security.impl.aznrep.JACCPrincipalRoleMapper interface for this purpose. This interface contains a single method, that needs to be implemented, called addPrincipalRoleMapping(PermissionMap map, String policyId). This method adds the principal-to-role mapping to PolicyConfiguration, which is represented by the policyId.
Note that principal-to-role mappings have application scope in J2EE. This is because all the principal-to-role mappings in an application are merged into a single map. Refer to the API documentation for more information about the PermissionMap class and about the add() method, that is used in merging PermissionMap instances.
The implementation of the JACCPrincipalRoleMapper interface must provide a public no-argument constructor, and it must be added to the JAR file of the JACC Provider. For more information on this, refer to References and Javadoc.
The process of the JACCPrincipalRoleMapper interface creating the principal-to-role mapping is as follows:
The class name that implements the jeus.security.jacc.principalRoleMapper class is configured to the system property, jeus.security.jacc.principalRoleMapper.
The class that implements the jeus.security.impl.aznrep.JACCAuthorizationRepositoryService class reads this property to create an instance by calling the Class.forName(mapperClassname).newInstance() method.
Then the addPrincipalRoleMapping() method of the instance is called to create and add the principal-to-role mappings, that are defined in the JEUS DD file.
Setting the Security Configuration File
The JEUS security system uses two adapter classes to connect JEUS native authorization API with the JACC authorization API.
The roles of the two adapter classes are as follows:
jeus.security.impl.azn.JACCAuthorizationService
implements the container part of the Policy Decision and Execution protocol by invoking the java.security.Policy.getPolicy().implies() method to check for authorization.
jeus.security.impl.aznrep.JACCAuthorizationRepositoryService
implements the Policy Configuration protocol by allowing the container-generated jeus.security.base.Policy instance to be added to the PolicyConfiguration instance, which is a configuration component of the JACC provider.
In order to enable JACC, both of these security Services must be configured in the domain service definition of the domain.xml file.
[Example 6.1] JACC Security Configuration File: <<domain.xml>>
<?xml version="1.0"?> ... <security-domains> <default-application-domain>JACC_DOMAIN</default-application-domain> ... <security-domain> <name>JACC_DOMAIN</name> <authorization> <jacc-service/> </authorization> </security-domain> . . . </security-domains>
Adding the JACC Provider JAR file to the System Path
To add the JACC provider JAR file to the system path, simply place the JAR file in the following directory.
JEUS_HOME/lib/system
Setting Java System Properties
The JACC protocol and JEUS specifies three Java system properties to enable the J2EE server to detect the presence of the JACC provider. These properties are as follows:
javax.security.jacc.policy.provider
The name of the class that represents the JACC Provider, and implements java.security.Policy.
javax.security.jacc.PolicyConfigurationFactory.provider
The name of the class that implements PolicyConfigurationFactory that creates and loads PolicyConfiguration instances.
jeus.security.jacc.principalRoleMapper
The name of the class that implements the jeus.security.impl.aznrep.JACCPrincipalRoleMapper interface, and creates the principal-to-role mapping from JEUS DD file.
The previous three system properties must be configured in the <jvm-option> element of domain.xml.
[Example 6.2] Java System Property Configuration for JACC <<domain.xml>>
<?xml version="1.0"?>
<domain xmlns=“http://www.tmaxsoft.com/xml/ns/jeus”>
<servers> <server> <name>server1</name>
<!-- server JVM option -->
<jvm-config> . . . <jvm-option>
-Djavax.security.jacc.policy.provider= myprovider.MyJACCPolicy
</jvm-option> <jvm-option>
-Djavax.security.jacc.PolicyConfigurationFactory.provider=
myprovider.MyJACCPolicyConfigurationFactory </jvm-option>
<jvm-option> -Djeus.security.jacc.principalRoleMapper=
myprovider.MyJACCPrincipalToRoleMapper </jvm-option>
</jvm-config> . . .
As already mentioned, the default class names for JACC provider are as follows:
Classification | Class Name |
---|---|
Policy | jeus.security.impl.jacc.JACCPolicyWrapper |
PolicyConfigurationFactory | jeus.security.impl.jacc.JACCPolicyConfigurationFactoryImpl |
JACCPrincipalRoleMapper | jeus.security.impl.jacc.JACCDefaultPrincipalRoleMapper |
These classes are packaged and placed in the following location.
JEUS_HOME/lib/system/jeus.jar