5.2 EJB Roles and Security

 < Day Day Up > 

EJB technology defines a set of processes, starting from the application development and following through the administration of the deployed code. The EJB specification describes a set of contracts to enable the development and deployment of software components and also outlines processes that span from software development to deployment. EJB roles take on specific responsibilities at the various stages in the development/deployment/administration process. These roles include responsibility for defining and managing transactional characteristics of each of the components, as well as security. The defined EJB roles with security considerations discussed in this chapter are

  • Enterprise Bean Provider

  • Application Assembler

  • Deployer

  • System Administrator

  • EJB Container Provider

Each of these EJB roles is described with respect to its responsibilities in the definition and management of security.

EJB security is intended to be managed by the EJB container and driven by declarative security policy rather than security policy being hard-coded within the application code. Much of this declarative policy information is encoded within the EJB deployment descriptor. Removing security from the application code greatly reduces the burden on application developers, allowing them to concentrate on modeling business processes. Specifically, most application developers may not be familiar with the intricacies of security and the coding practices that will ensure secure deployed applications. Additionally, application developers are usually unaware of the details of the security environment into which their code is to be deployed. Application code containing security policy decisions for authentication, authorization, secrecy , and integrity usually does not quickly adapt to changes in enterprise security requirements. Externalizing security policy from the EJB code provides greater opportunity for deployment flexibility, code reuse, and portability between container implementations .

EJB delegates security issues to those EJB roles having greater familiarity with the security features of the EJB container and deployment environment. In practice, the effective security policy is defined by the Deployer and the System Administrator, and the EJB container is responsible for enforcement of the policy.

Every enterprise bean goes through the process shown in Figure 5.2.

  1. Enterprise Bean Providers are responsible for writing the enterprise beans that embody the business logic.

  2. Application Assemblers combine, or assemble, a number of EJB components to create an entire application and also provide hints about the security aspects of the enterprise beans being assembled .

  3. Deployers take one or more assembled applications, prepare them, and install them in EJB containers, including setting up resource definitions, such as JNDI and LDAP entries, databases, security attributes, and so on.

  4. System Administrators manage the containers and other J2EE resources, including defining new users, or principals, and their mapping to security roles.

Figure 5.2. Process of EJB Development to Deployment

graphics/05fig02.gif

5.2.1 Enterprise Bean Provider

The Enterprise Bean Provider is the application developer who is an expert in writing code that embodies enterprise rules. As we saw in Section 3.2.1 on page 58, enterprise beans fall into three broad categories:

  1. Nonpersistent beans, or session beans

  2. Persistent beans, or entity beans

  3. Message-oriented beans, or message-driven beans

For entity beans, persistence managed by code in the enterprise bean is called bean-managed persistence (BMP). Persistence managed by the EJB container is called container managed persistence (CMP).

5.2.1.1 Communicating with an Enterprise Bean

All communication between a remote client and an enterprise bean is mediated by RMI-IIOP, as shown in Figure 5.1 on page 159. If the client and the enterprise bean are colocated in the same container, the request is mediated by the container itself. This architecture allows for

  • A clean separation between components

  • Proper transaction management, ensuring that the database ACID properties are preserved

  • Security policy enforcement by performing necessary authentication and authorization, as well as establishing the security context for the EJB method invocation

Figure 5.3 shows the two types of interfaces that each enterprise bean defines as part of the contract between the container and clients .

  1. The first type consists of the home and local home interfaces, which define the enterprise bean life-cycle methods that are used to create, locate, and delete EJB instances. These interfaces include the create, remove, and find methods . All enterprise beans' home interfaces must extend the javax.ejb.EJBHome interface. All enterprise beans' local home interfaces must extend the javax.ejb.EJBLocalHome interface.

  2. The second type of interface specifies the business methods implemented by the enterprise bean and available to the client code. These methods are defined in the remote and local interfaces. All enterprise beans' remote interfaces must extend the javax.ejb.EJBObject interface. All enterprise beans' local interfaces must extend the javax.ejb.EJBLocalObject interface.

Figure 5.3. EJB Interfaces

graphics/05fig03.gif

If the client and the enterprise bean reside in different containers, the enterprise bean must implement the methods exposed in the home and remote interfaces. When the client and the enterprise bean reside in the same container, it is still acceptable, but not necessary, for the enterprise bean to implement the home and remote interfaces. Prior to EJB V2.0, there were no local home or local interfaces.

According to the RMI-IIOP specification, all RMI-IIOP method invocations must follow call- by-value (CBV) semantics. When a method is called by value , the method sees a copy of any primitives passed to it. Therefore, any changes the method makes to those values have no effect on the caller's variables . This requirement also applies to object references passed as parameters. The callee cannot change the caller's referenced fields and objects. For clients and enterprise beans colocated in the same container and when the parameter and return values contain large data structures, CBV marshaling/demarshaling is a significant performance overhead. To overcome this performance bottleneck, EJB V2.0compliant containers now allow enterprise beans to define local home and local interfaces that the container will use to perform call-by-reference (CBR) rather than CBV to bypass marshaling/demarshaling of parameters and return values. When a method is called by reference , the callee sees the caller's original fields and objects passed as parameters, not copies. References to the callee's objects are treated the same way. Thus, any changes the callee makes to the caller's fields and objects affect the caller's original fields and objects. Regardless of whether an enterprise bean is called via a remote, home, local, or local home interface, the container still performs all required security operations, including authorization, as described in Section 5.4 on page 184.

5.2.1.2 Scenario

Listings 5.1, 5.2, and 5.3 show the code fragments for a simple entity bean.

  • Listing 5.1 shows the home interface and the methods to create, locate, and destroy beans of this type.

  • Listing 5.2 shows the remote interface and the methods for performing operations on the bean instances.

  • Listing 5.3 shows the code for implementing the enterprise bean, including the implementations for some of the home methods.

CMP is assumed, to simplify the example. Listing 5.1 shows a simplified example of a home interface.

Listing 5.1. TravelerCreditCardHome.java
 import javax.ejb.EJBHome; import javax.ejb.CreateException; import javax.ejb.FinderException; import javax.ejb.RemoveException; import java.rmi.RemoteException; public interface TravelerCreditCardHome extends EJBHome {    public TravelerCreditCard create       (TravelerId travelerId, String cardNumber)       throws CreateException, RemoteException;    public TravelerCreditCard findByPrimaryKey       (TravelerId travelerId)       throws FinderException, RemoteException;    public void remove(TravelerId travelerId)       throws RemoveException, RemoteException; } 

This interface exhibits three methods.

  1. The first method will create and return a new TravelerCreditCard entry in the database by using a TravelerId as the primary key for the database query/update. This key uniquely encodes a description of a person booking a specific trip and will be sufficient to identify the credit card that will be used for the trip.

  2. The second method takes a TravelerId as the primary key and performs a database query to return TravelerCreditCard .

  3. The third method will locate and delete the record in the database.

In all cases, if an error occurs during the method invocation on the EJBHome object, specific Exceptions are thrown and must be caught by the client. Also note that the primary key class, TravelerId , must be serializable.

Listing 5.2 gives a simplified example of a remote interface.

Listing 5.2. TravelerCreditCardInterface.java
 import javax.ejb.EJBObject; import javax.ejb.EJBException; import java.rmi.RemoteException; public interface TravelerCreditCardInterface    extends EJBObject {    public void debit(double amount) throws EJBException;    public void credit(double amount) throws EJBException;    public double balance() throw EJBException; } 

This interface exhibits three methods.

  1. The first method charges the specified amount to the traveler's credit card and is called when the traveler needs to pay for travel arrangements.

  2. The second method credits the traveler's credit card: for example, when a reservation is canceled .

  3. The third method returns the balancecredits and debitsassociated with the credit card.

In all cases, if an error occurs during the method invocation on the enterprise bean's business methods, an EJBException is thrown and must be caught by the client.

Listing 5.3 shows a simplified example of an entity bean.

Listing 5.3. TravelerCreditCard.java
 import javax.ejb.EntityBean; public class TravelerCreditCard extends javax.ejb.EntityBean {    public double balance; // value managed by the container    public void debit(double amount) throws EJBException;    {       // Implementation code goes here...    }    public void credit(double amount) throws EJBException;    {       // Implementation code goes here...    }    public double balance() throws EJBException;    {       // Implementation code goes here...    }    // Other code goes here... } 

This entity bean exhibits the three implemented business methods as described by the remote interface (see Listing 5.2).

As described on page 76, security in J2EE is largely declarative, defined by the Deployer and the System Administrator, and enforced by the container rather than being encoded in the application. Leaving security out of the application enhances the application's portability. Conversely, portablity of an enterprise bean between container implementations or to newer versions of the container from the same vendor is diminished when the enterprise bean contains code that embodies security policy.

The EJB model has no API to influence the security context and the identity under which an enterprise bean method is executed. [1] Aside from adding optional comments into the EJB deployment descriptor, the Enterprise Bean Provider has no other obligations with respect to security.

[1] JAAS is available inside J2EE. However, using the JAAS API should not affect the security context for the purpose of method invocation, as explained in this chapter.

To call an enterprise bean, a JNDI call locates the target enterprise bean and its stub, as shown in Listing 5.4. The presence of the stub allows RMI calls. It is the responsibility of the Deployer and the System Administrator to determine whether the principal executing the code is authorized to get the stub to invoke the EJB methods. The EJB container is responsible for authenticating the principal making the RMI request and authorizing the principal to invoke the requested method.

Listing 5.4. Code Fragment Performing the JNDI Lookup
 import javax.ejb.EJBException; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import java.rmi.RemoteException; // Other code goes here... InitialContext initialContext = null; try {    initialContext = new InitialContext(); } catch (NamingException ne) {    throw new EJBException       ("Could not create an InitialContext", ne); } // Other code goes here... try {    Object iclu = initialContext.lookup       ("java:comp/env/ejb/TravelerCreditCard",       TravelerCreditCardHome.class);    TravelerCreditCardHome tcc = (TravelerCreditCardHome)       javax.rmi.PortableRemoteObject.narrow(iclu); } catch (NamingException ne) {    throw new EJBException       ("Attempting to get TravelerCreditCardHome", ne); } catch (RemoteException re) {    throw new EJBException       ("Attempting to get TravelerCreditCardHome", re); } 

The code fragment in Listing 5.4 shows the use of JNDI and RMI to locate and obtain the stub code for TravelerCreditCardHome . Note that each Exception is handled for unexpected errors. This makes the code more robust in the presence of network and other failures.

5.2.1.3 Security APIs for Enterprise Beans

Because the Enterprise Bean Provider has no security obligations, gaps do exist in the EJB security model. One of these gaps is the occasional need for instance-level or application-specific authorization. As is described later in this chapter, method-level authorization is provided. However, circumstances arise in which the application needs to apply additional security constraints or needs to obtain information about the security context under which the enterprise bean is executing.

Two APIs for security are found in the javax.ejb.EJBContext interface: EJB methods isCallerInRole() and getCallerPrincipal() .

We introduced the first security- related method, isCallerInRole() , in Chapter 3. This method returns a boolean indicating whether the caller is defined to be a member of an EJB security role. EJB security roles are discussed in Section 5.2.2.1 on page 177. Of the two security-related methods in the EJBContext , isCallerInRole() is the most likely to work across container implementations and yield consistent results. Listing 5.5 shows how to determine whether the caller is a member of the Supervisor security role. The debit() method may be called by a booking agent or a Supervisor. However, the enterprise bean wants to limit the agent's ability to place charges against the credit card. A call to isCallerInRole() will enable the method to determine whether a charge limit should apply.

Listing 5.5. Code Fragment Showing Use of isCallerInRole()
 import javax.ejb.EntityBean; import javax.ejb.EntityContext; public class TravelerCreditCard extends EntityBean {    EntityContext ejbContext;    static double agentLimit = 10000.0;    public void debit(double amount)       throws AgentChargeLimitExceededException    {       // The customer credit card can only be charged up       // to a limit by the booking agent. Higher charges       // must be done by the Supervisor.       if (amount > agentLimit &&          ! ejbContext.isCallerInRole("Supervisor"))          throw new AgentChargeLimitExceededException();       // Other code goes here...    }    // Other code goes here... } 

Application-specific authorization uses the isCallerInRole() method in the EJBContext . This examples shows how application-specific information can be combined with security informationthe Supervisor security roleto constrain authorization to execute a method. The Supervisor role name must be specified in the EJB deployment descriptor.

The isCallerInRole() method takes a single String argumentthe name of an EJB security role. Nominally, this is a problem. Each enterprise bean may use a different security role name to describe the same EJB security role. Or, two different enterprise beans may use the same security role name to describe two different security roles. The EJB container needs to know how to map the application-specified security role names to the runtime security roles. A String value used in an enterprise bean code to describe a role in the isCallerInRole() call is called a role-name . Part of the EJB deployment descriptor provides a mapping from role-name values to identifiers used by the EJB container. This mapping allows the Deployer and the EJB container to map nonidentical role names as may be found in different enterprise beans to a single security role name at deployment and runtime. The same mechanisms can be used to disambiguate the same role-name in different enterprise beans that use the same String value but are intended to have different runtime security roles. This mapping is described in Section 5.2.2.3 on page 179.

A fragment of an EJB deployment descriptor is shown in Listing 5.6, which illustrates an example of a security-role-ref entry defining a security role-name and a description of the purpose of the security role. This description is particularly important when the Enterprise Bean Provider is not also the Application Assembler, because it lets the Application Assembler know the purpose of the security role. This enables the Application Assembler to correctly define the security role mappings between the enterprise beans that are being brought together to form an application.

Listing 5.6. EJB Deployment Descriptor Fragment for Security role-name Definitions
 <enterprise-beans>    ...    <entity>       <ejb-name>TravelerCreditCard</ejb-name>       <ejb-class>          com.travel.booking.TravelerCreditCard       </ejb-class>       ...       <security-role-ref>          <description>             This security role should be assigned to             employees who work in supervisory capacity.             In particular, this role allows them to             authorize large charges on customer             credit cards.          </description>          <role-name>Supervisor</role-name>       </security-role-ref>       ...    </entity>    ... </enterprise-beans> 

In Listing 5.6, the enterprise bean is an entity bean called TravelerCreditCard whose class is specified. The security-role-ref element defines a security role's name and a description of the role's purpose as it is understood by the Enterprise Bean Provider. The role-name is a String value used as a parameter to isCallerInRole() . The description of the role's purpose is important communication between the Enterprise Bean Provider and the Application Assembler and, ultimately, the Deployer. Depending on how isCallerInRole() is used in the enterprise bean, poor communication of the intended use of the security role can have unintended consequences, including incorrect authorizations.

The second security-related method, getCallerPrincipal() , was also introduced in Chapter 3. This method returns a java.security.Principal object representing the caller as authenticated and defined by the EJB container's security subsystem. Listing 5.7 shows an example of obtaining the caller Principal . This method is not guaranteed to provide consistent results across container implementations from different EJB Container Providers, or vendors . In addition, the result of calling getCallerPrincipal() can be deployment specific, even from the same EJB Container Provider, as it depends on the user registry against which the users of the container are authenticated.

The EJB specification states that the Principal is the client's. However, the Deployer, System Administrator, and EJB container are all involved in defining credential mappings that affect the result of calling getCallerPrincipal() . For example, a client that authenticates using an X.509 certificate in its Web browser can be mapped to a Kerberos principal. The enterprise bean's call to getCallerPrincipal() will return the Kerberos Principal , not the X.509 Principal . In a large enterprise or for interenterprise method calls, the identity mappings may be more complex. For this reason, we discourage Enterprise Bean Providers from using getCallerPrincipal() for making authorization decisions. Finally, even if a run-as identity is specified in the EJB deployment descriptor, getCallerPrincipal() returns the client's Principal , not the Principal for the run-as identity.

Listing 5.7. Code Fragment Showing Use of getCallerPrincipal()
 import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.rmi.PortableRemoteObject; import javax.naming.Context; import javax.naming.InitialContext; import java.security.Principal; public class TravelerCreditCard extends EntityBean {    EntityContext ejbContext;    public void debit(double amount)       throws AgentChargeLimitExceededException    {       Context initialContext = new InitialContext();       // Get home interface of the employee database.       Object lookupResult = initialContext.lookup          ("java:/comp/env/ejb/EmployeeRecord");       EmployeeRecordHome employeeRecordHome =          (EmployeeRecordHome)          PortableRemoteObject.narrow          (lookupResult, EmployeeRecordHome.class);       // Get the caller Principal and name.       Principal callerPrincipal =          ejbContext.getCallerPrincipal();       String callerName = callerPrincipal.getName();       // Not likely to be portable or work consistently       // across all deployments.       EmployeeRecord employeeRecord =          employeeRecordHome.          findByPrimaryKey(callerName);       String businessRole =          employeeRecord.getJobTitle();       // The customer credit card can only be charged up       // to a limit by the booking agent. Higher charges       // must be done by the supervisor.       if (amount > agentLimit &&          ! businessRole.equals("Supervisor"))          throw new AgentChargeLimitExceededException();       // Other code goes here...    }    // Other code goes here... } 

The code fragment in Listing 5.7 shows how to get the caller's Principal . The use of getCallerPrincipal() is not likely to be portable and useful for authorization purposes in a container- and deployment-independent manner.

Finally, if you should choose to use getCallerPrincipal() or isCallerInRole() , the client security-context information is not available within all EJB methods. In particular, calling getCallerPrincipal() or isCallerInRole() is not supported if the following method calls are performed from within:

  • The constructors of javax.ejb.EnterpriseBean s: stateful and stateless javax.ejb.SessionBean s, javax.ejb.EntityBean s, and javax.ejb.MessageDrivenBean s

  • The setSessionContext() and ejbRemove() methods in stateless SessionBean s

  • The setSessionContext() method in stateful SessionBean s

  • The setEntityContext() , unsetEntityContext() , ejbActivate() , and ejbPassivate() methods in EntityBean s

Attempts to use isCallerInRole() or getCallerPrincipal() from EJB methods that do not support these calls should result in the throwing of a java.lang.IllegalStateException .

5.2.1.4 EJB Runtime Restrictions

J2SE is a rich programming environment, including extensive support for networking, file I/O, and multithreading. However, in the context of high-performance transaction processing, many of the J2SE features conflict with the transaction-processing objectives. Therefore, a number of programming restrictions must be followed [2] in order to maintain portability of enterprise beans between containers and to preserve security. Some of these restrictions can be enforced by the EJB Container Provider; others are solely the responsibility of the Enterprise Bean Provider.

[2] These runtime restrictions are described in the EJB V2.0 specification, Chapter 24.

  • Home, local, local home, and remote methods must not to write to static fields. This restriction includes modifying values referenced by static fields. The code fragment in Listing 5.8 shows disallowed modifications, both direct and indirect, of static fields.

    Listing 5.8. Enterprise Beans Are Not Allowed to Write to Static Fields
     import javax.ejb.EntityBean; import java.util.Hashtable; public class TravelerCreditCard extends EntityBean {    static EmployeeKey emplKey = null;    static Hashtable lookup = new Hashtable();    // Other code goes here...    public void debit(double amount)       throws AgentChargeLimitExceededException    {       // The following line is an example of a value       // modification of a static field that is not       // allowed.       emplKey = getCallerEmployeeKey();       // The following line is an example of a       // modification of the state of a static field       // that is not allowed.       lookup.put(emplKey.toString(), emplKey);       // Other code goes here...    }    // Other code goes here... } 

    Writing to static fields can result in inconsistency in deployed enterprise beans. In some cases, all instances of an enterprise bean will run in a single container. In other cases, the enterprise bean instances will run in multiple containers. When an enterprise bean is deployed in multiple containers running on different JVMs, writing to static fields can result in memory leaks. This can happen when an enterprise bean loaded in one container in which a static field is updated is passivated serialized to persistent storageand subsequently activated , or deserialized, in a different container.

    If the enterprise bean was written assuming that it would execute in a single JVM and release objects in the static field during its execution and if it is then executed in multiple containers, which are in different JVMs, the values stored in the static field may not be correctly released. An attacker, knowing that an enterprise bean writes values to a static field, can make repeated requests to the enterprise bean in an attempt to a generate lot of garbage in the static field. By doing so, the JVMs can reach their heap capacities and terminate, resulting in a denial of service.

    Reading from static fields is acceptable and is often good software engineering style. For example, static fields can be used to hold references to constant information required by the application.

  • Thread-synchronization primitives must not be used to synchronize the execution of multiple enterprise bean instances. An enterprise bean can be executed concurrently in multiple JVMs. Thread synchronization is not guaranteed to be supported outside the confines of a single JVM; therefore, thread synchronization in an enterprise bean will not have the desired effect. Also, an excessive use of thread synchronization is likely to degrade application performance and could result in deadlocks because the container also performs lockingfor example, to guarantee transaction-processing ACID properties. An attacker, knowing that an application uses synchronization, can rapidly make repeated requests to the method that contains the synchronization. The synchronization forces serialization of the application and can result in a denial-of-service attack.

  • J2SE AWT functionality must not be used to interact with a keyboard or a display. Enterprise beans are intended to be transactional, and the containers are designed to facilitate high-throughput transaction processing. Creation of AWT resources will consume memory and CPU cycles in the JVM running the enterprise beans, thus degrading performance. As such, interaction with a keyboard or a display will interfere with an enterprise bean's performance and throughput objectives. Therefore, containers do not support keyboard or display interactions. Additionally, enterprise beans run in servers. As such, they are not intended to have a keyboard or a display for end-user interaction.

  • Attempts to perform file I/O operations via the java.io package are not allowed, including reading/writing via FileDescriptor s. File system APIs are not well suited for a transaction environment. All I/O operations must be performed through the resource-manager APIs, such as JDBC, JNDI, JMS, and JavaMail. In particular, there is no assumption of an enterprise bean's having an operating system identity, so it is not clear under which principal any operating system resource would be requested. Because this can be a security violation, file I/O operations are prohibited to enterprise beans.

  • The network socket operations listen, accept, and multicast are not allowed. Although enterprise beans are server objects, all inbound communication must be routed through the RMI-IIOP ORB. If an enterprise bean were to become a server via listen/accept operations, it would interfere with the objective of being a server for EJB client requests. Additionally, the security policy is likely to be violated, as all communication with an enterprise bean, including authentication and authorization requests, is supposed to be routed through the RMI-IIOP ORB and its method/role-based authorization mechanisms.

    An enterprise bean is allowed to be a network client. Requests must be made to other enterprise beans via RMI-IIOP, but access to other resource managers supported by EJB containers, including JDBC and JMS, may be over any protocol.

  • Access to an enterprise bean's fields and methods not specified by the enterprise bean's home, local home, local, or remote interfaces are not allowed. This includes access via functions provided in the J2SE java.lang.reflect package. The home, local home, local, or remote EJB interfaces define the supported contract between a client and an enterprise bean. Access to an enterprise bean other than through its defined interfaces can violate security but is also bad software engineering practice, as the implementation of the enterprise bean could change, resulting in unexpected or incorrect values in the referenced fields or methods.

  • The following operations are not allowed: obtaining a java.lang.ClassLoader , including the current ClassLoader ; setting the context ClassLoader and the java.lang.SecurityManager ; creating a new SecurityManager ; stopping the JVM; changing the input, output, or error streams in java.lang.System ; setting network socket factories and URL stream handlers; starting, stopping, suspending, and resuming java.lang.Thread s, or changing Thread names or priorities. These functions are reserved for use by the container. Modification of any of these functions would undermine both security and the container's integrity.

  • Security policy information in the container should not be interrogated or modified. This restriction includes the java.security.Policy implementation (see Section 8.3 on page 261). The container implements security and may use J2SE security mechanisms but may also include mechanisms that are not part of J2SE. There is no guarantee that enterprise beans using the J2SE APIs will get the correct or consistent information about the container's security policies. Interrogating the security policy can also create security exposures, particularly if the results of the interrogation were to be disseminated outside the container: for example, if they were sent to a Web client. This information would enable a malicious entity to better plan an attack against the container and/or enterprise.

  • Loading native libraries is not allowed. Native libraries are not portable across all platforms. Also, native code may deliberately or inadvertently circumvent the container's security policies.

  • The subclass and object-substitution features of the Java Serialization protocol are not to be used (see the Java Object Serialization Specification [3] for details). These features allow modification of values passed during RMI calls, such as calls to other enterprise beans, and can subvert security.

    [3] The Java Object Serialization Specification is available at http://java.sun.com.

  • The this object reference for an enterprise bean must not be passed as an argument or returned as a method result. This restriction can interfere with the container's management of the enterprise bean, perhaps causing unintended modification of the wrong instance of an enterprise bean. Instead, calls to javax.ejb.SessionContext.getEJBObject() or javax.ejb.EntityContext.getEJBOjbect() calls should be used to get the appropriate object to pass or return.

  • Enterprise beans should not be allowed to set system properties by calling System.setProperty() . Instead, reading the value of a system property should be permitted.

The EJB container can enforce some of the preceding programming model restrictions through the use of a J2SE security policy configuration. Such a policy configuration should unconditionally deny java.security.AllPermission , java.awt.AWTPermission , java.io.FilePermission , java.net.NetPermission , java.lang.reflect.ReflectPermission , java.security.SecurityPermission , and java.io.SerializablePermission and grant all code java.util.PropertyPermission "read", "*" , java.lang.RuntimePermission "queuePrintJob" , and java.net.SocketPermission "connect", "*" . These authorizations allow enterprise beans to be portable. However, some containers may allow the Deployer to grant some of the denied permissions.

5.2.2 Application Assembler

Like the Enterprise Bean Provider, the Application Assembler is an expert in modeling business models. Whereas the Enterprise Bean Provider is focused on implementing the business objects and rules, the Application Assembler is combining these business objects and rules into complete applications. The Application Assembler must have a broader perspective, being knowledgable in transaction processing and security issues as they relate to the applications being assembled. This requires having at least some knowledge of the intended target environments into which the application will ultimately be installed.

The Application Assembler's responsibility is to assemble software components into an entire application that models an aspect of an enterprise. Once the Application Assembler has completed the assembly process, a deployment descriptor contains the information needed by a Deployer to install the application in one or more containers. Part of the process is creating a security view of the application. Creation of this view makes it easier to deploy the application, as fewer details of the application need to be known by the Deployer. For security, the Application Assembler

  • Defines a set of security roles for the application. The security roles (see Section 3.7.2 on page 67 and Section 3.8 on page 73) are distinct from EJB/J2EE platform roles (see Section 3.7 on page 64). Because the Application Assembler may not know the details of the deployment environment, the security roles define a logical view of the security environment, particularly, the authorization requirements for an application. Each security role represents a type of user of the application. Thus, security roles are logical roles and are defined independently from users or groups. A mapping of users and groupsprincipalsto security roles is made at deployment time. The security roles defined in a deployment descriptor for an application are limited in scope to the enterprise bean in a single EJB JAR file.

  • Define method permissions, or authorizations, for the EJB methods. These authorizations (see Section 3.7.2.1 on page 68) are for the home, local home, local, and remote methods. Authorizations are defined with respect to the security roles.

The Application Assembler takes one or more enterprise beans from Enterprise Bean Providers and constructs a logical view of authorization requirements for the application. This logical view is provided as guidance to the Deployer and, subsequently, the System Administrator.

5.2.2.1 EJB Security Roles

The deployment descriptor contains a set of security roles whose scope is an EJB JAR file. The definition of a security role is provided in a security-role deployment descriptor element as part of the assembly-descriptor element and includes a description subelement and a role-name subelement. An example of an assembly-descriptor element with two security-role subelements is shown in Listing 5.9.

Listing 5.9. Example of an XML assembly-descriptor Element in a Deployment Descriptor
 <assembly-descriptor>    ...    <security-role>       <description>          This role is for the travel agency office manager or          supervisor who has a master-key authority to perform          any of the transactions allowed by any of the travel          agents. In addition, this role is allowed to perform          a number of financial transactions otherwise not          allowed the travel agents.       </description>       <role-name>Manager</role-name>    </security-role>    <security-role>       <description>          This role is for each of the travel agents who book          reservations and perform most of the financial          transactions associated with the reservations.       </description>       <role-name>Agent</role-name>    </security-role>    ... <assembly-descriptor> 

This deployment descriptor fragment shows the definition of two security roles named Manager and Agent. The security roles scope to the applications in the EJB JAR file to which the deployment descriptor belongs. These security role names will be used in defining method authorizations.

5.2.2.2 EJB Method Authorizations

Now that the security roles are defined, it is possible to specify the authorization requirements for each of the methods of the enterprise beans in the JAR file. In particular, the EJBHome , EJBObject , EJBLocalHome , and EJBLocalObject methods of the session and entity beans need to have their authorization requirements defined in the deployment descriptor. To invoke one of those EJB methods, the calling principal must be a member of one of the security roles defined in the deployment descriptor that is authorized for the requested method.

In the deployment descriptor, each method-permission element contains one or more security roles and EJB methods. This element defines the list of methods that can be accessed by a user granted one or more of the associated security roles. Security roles and methods may appear in more than one method-permission element in the deployment descriptor. The deployment descriptor fragments of Listing 5.10, 5.11, and 5.12 demonstrate how to specify EJB methods in the deployment descriptor. Basically, there are three ways to specify EJB methods.

  1. The EJB name is specified, along with the wildcard character, * , as the method name. This indicates that all methods are included.

    Listing 5.10. How to Include All the Methods of an Enterprise Bean
     <method>    <ejb-name>TravelerCreditCard</ejb-name>    <method-name>*</method-name> </method> 
  2. The EJB name is specified, along with a method name. This indicates that only the specified methods should be included. If the method name is overloaded and multiple methods have the same name, all the methods are included.

    Listing 5.11. How to Include all the Methods with a Given Name in an Enterprise Bean
     <method>    <ejb-name>TravelerCreditCard</ejb-name>    <method-name>debit</method-name> </method> 
  3. The method name and its parameter(s) are specified. If more than one method had the same name, this element disambiguates the methods. The method-param element must be repeated for each of the method's parameters.

Listing 5.12. How to Include a Specific Method of an Enterprise Bean
 <method>    <ejb-name>TravelerCreditCard</ejb-name>    <method-name>debit</method-name>    <method-params>       <method-param>double</method-param>    </method-params> </method> 

The deployment descriptor fragment of Listing 5.13 shows that a principal in the role of an Agent is authorized to debit a customer's credit card. Also, a Manager is authorized to perform any operation on methods in the TravelerCreditCard bean.

Listing 5.13. Deployment Descriptor Fragment Showing how to Assign Security Roles to Methods
 <method-permission>    <role-name>Agent</role-name>    <method>       <ejb-name>TravelerCreditCard</ejb-name>       <method-name>debit</method-name>    </method> </method-permission> <method-permission>    <role-name>Manager</role-name>    <method>       <ejb-name>TravelerCreditCard</ejb-name>       <method-name>*</method-name>    </method> </method-permission> 

If the role-name were to be replaced by an unchecked element, the method(s) are authorized for every security role. Similarly, if role-name were replaced by an exclude-list element, no one would be authorized to call the method, even if there were other declarations containing roles for the same method.

5.2.2.3 Linking EJB Security Roles to Role References

The last step is to link the ejb-jar-scoped security roles, as defined by the Application Assembler, to the role references defined by the Enterprise Bean Provider. This requires mapping the security-role elements to the security-role-ref elements. This is done with the role-link element, as is shown in Listing 5.14.

Listing 5.14. Tying a Security Role to a Security Role Reference
 <enterprise-beans>    ...    <entity>       <ejb-name>TravelerCreditCard</ejb-name>       <ejb-class>          com.travel.booking.TravelerCreditCard       </ejb-class>       ...       <security-role-ref>          <description>             This security role should be assigned to             employees who work in supervisory capacity. In             particular, this role allows them to authorize             large charges on customer credit cards.          </description>          <role-name>Supervisor</role-name>          <role-link>Manager</role-link>       </security-role-ref>       ...    </entity>    ... </enterprise-beans> 

This deployment descriptor fragment is the same as in Listing 5.6 on page 169, with the addition of the role-link element that ties the TravelerCreditCard security role Supervisor to the ejb-jar file's Manager security role. When called by a principal having the Manager role, the method isCallerInRole("Supervisor") returns true . It is the responsibility of the container to map the Manager security role to the role name Supervisor as appropriate during the execution of TravelerCreditCard.

5.2.2.4 EJB Principal Delegation

Sometimes, the Application Assembler knows that after a caller has been authenticated and authorized to execute a method, the method should be run using a specific principal, regardless of who the caller was. This is done by using the run-as element. The run-as identity applies to all methods in an enterprise bean and is used when making subsequent calls from the enterprise bean. The identity of the caller remains unaffected and is still used for authorization to access the enterprise bean's methods. The run-as identity is a logical security role name, as the Application Assembler does not know the deployment environment. The run-as identity refers to one of the security roles defined by the Application Assembler in the deployment descriptor. The Deployer, using the deployment tools, may be required to assign a principal to this security role at deployment time. Listing 5.15 shows a deployment descriptor fragment illustrating how to use the run-as element.

Listing 5.15. Specifying the Identity for Method Execution Using the run-as Element
 <enterprise-beans>    ...    <entity>       <ejb-name>TravelerCreditCard</ejb-name>       ...       <security-identity>          <run-as>             <role-name>Credit-Card-Agent</role-name>          </run-as>       </security-identity>       ...    </entity>    ... </enterprise-beans> 

The role name specified in the role-name element indicates the security role that will be mapped at deployment time to the principal that will be used for execution of the methods in the enterprise bean.

5.2.3 Deployer

To run an enterprise bean, its ejb-jar file must be deployed into an operational environment. That environment includes the EJB container and the security platform in which the enterprise bean will be operating. To deploy the enterprise bean, the Deployer will be using tools supplied by the EJB Container Provider. These tools process the ejb-jar file's deployment descriptor, as prepared by the Application Assembler, and map the users and groups within the operational environment to the security roles described in the deployment descriptor. The steps in the deployment process are as follows .

  1. The Deployer processes the enterprise bean's ejb-jar file, including the deployment descriptor and the security roles and method authorizations as defined by the Application Assembler. The deployment descriptor definitions of security roles and method authorizations are mere recommendations. Ultimately, it is the responsibility of the Deployer to decide whether the Application Assembler's recommendations are reasonable for the deployment environment. The Deployer must make whatever changes are needed to the security role definitions and/or the method authorizations that are appropriate for the deployment environment. The Deployer also specifies which principals are to be granted the security roles.

  2. The Deployer is responsible for configuring the EJB container to install and execute the enterprise bean.

  3. The Deployer configures the network environment to contain the RMI stubs the client needs in order to communicate with the enterprise bean via the EJB container.

  4. Finally, the Deployer provides the necessary directory services, such as JNDI, to enable locating the deployed enterprise bean.

The EJB Container Provider supplies tools for security management at deployment time, as well as for the System Administrator for ongoing security administration of the enterprise beans and container runtime environment. The tools may include support for mapping of principals, such as users and groups, between security realms when more than one security realm is involved in the deployment of the applications. The output of the deployment is container specific.

5.2.4 System Administrator

The Deployer takes one or more assembled ejb-jar files from the Application Assemblers and deploys, or installs , them in one or more EJB containers. This process includes mapping identities from the client to EJB security roles and may include configuration management across multiple security domains. The System Administrator is responsible for overall management of security in the operational environment. In particular, the System Administrator is responsible for configuration of security domains and ongoing user- and group -identity management: defining users and groups, mapping them to the EJB security roles, and providing principal mapping across security domains within the enterprise or between enterprises , as appropriate. When an audit-trail capability is provided by the EJB container, the System Administrator is responsible for management of the facility.

5.2.5 EJB Container Provider

Once an enterprise bean is deployed, it is the responsibility of the container to enforce the security policy defined by the Application Assembler and/or the Deployer. The J2EE specification does not prescribe how containers provide security. However, the container is responsible for principal authentication, access authorization for EJB method calls, resource manager access, and secure communication, including privacy and integrity, with remote clients.

One of the primary responsibilities of the EJB container is the establishment of a security context so that it can be correctly propagated in a chain of EJB calls. In particular, this is necessary to enable the getCallerPrincipal() method in the EJBContext interface to get the correct result when there is a chain of calls between enterprise beans or calls to resource managers. If principal delegation is used to specify an identity under which an enterprise bean's method should execute, the container must support this identity and be able to propagate it for subsequent calls to enterprise beans and resource managers.

Part of the EJB container's establishment of the security context includes support for the EJBContext isCallerInRole() and getCallerPrincipal() methods. For isCallerInRole() , the container must correctly map the role names, as defined by the Enterprise Bean Provider, to the role names defined by the Application Assembler and the Deployer. All the mappings are transparent to the Enterprise Bean Provider and the Application Assembler, thus making their jobs simpler and enabling greater portablity of applications between containers and deployment environments.

 < Day Day Up > 


Enterprise Java Security. Building Secure J2EE Applications
Enterprise Javaв„ў Security: Building Secure J2EEв„ў Applications
ISBN: 0321118898
EAN: 2147483647
Year: 2004
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net