Skip Headers
Oracle® Containers for J2EE Security Guide
10g (10.1.3.5.0)

Part Number E13977-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

18 EJB Security Configuration

This chapter discusses security issues affecting EJBs, covering the following topics:

Note that beginning with OC4J 10.1.3.x implementations, the EJB container supports the OracleAS JAAS Provider.

See Also:

Authenticating and Authorizing EJB Applications

You can define security constraints and J2EE roles in the standard EJB deployment descriptor to protect your EJB methods. These J2EE roles can be linked to roles you define in your application, and then mapped to deployment roles in the security provider, as appropriate. (In the case of EJBs, a deployment role may correspond to a role in the backend database that the EJB will access, for example.) The mapping to deployment roles can be accomplished through Application Server Control during deployment, as described in "Specifying Security Role Mapping through Application Server Control", and results in appropriate configuration in the OC4J-specific deployment descriptors.

For authentication and authorization, this section focuses on XML configuration within the EJB deployment descriptors. EJB authorization is managed as follows:

Note:

RMI lookup authentication is integrated with JAAS custom login modules. Refer to Chapter 9, "Login Modules" for information about login modules.

Figure 18-1 provides an overview of EJB role definitions and role mapping (in this case for the file-based provider).

Figure 18-1 End-to-End Security Role Configuration

Description of Figure 18-1 follows
Description of "Figure 18-1 End-to-End Security Role Configuration"

The steps for EJB authorization are described in the following sections:

Troubleshooting Tips:

  • For an application to access EJBs using RMI, you must grant RMI permission "login" to the appropriate user or role. Refer to "Permitting EJB RMI Client Access".

  • If an application contains an EJB, remote clients must be granted access for read (lookup) and write (bind) operations on the server-side JNDI context of the application, as required. Refer to "Configuring Namespace Access".

Specifying J2EE Roles and Method Permissions in the EJB Deployment Descriptor

As shown in Figure 18-2 below, you can specify the name of a role (such as POMgr) that is defined within your bean implementation, and link this name to the appropriate J2EE user or role (such as myMgr) that is defined in the standard EJB deployment descriptor. (The next step, mapping to a deployment role, is reflected in the OC4J-specific deployment descriptor, as discussed in "Mapping J2EE Roles to Deployment Users and Roles".)

Figure 18-2 Security Role References

Description of Figure 18-2 follows
Description of "Figure 18-2 Security Role References"

The following steps describe this in more detail:

  1. Declare the application logical role, such as POMgr above, with a <role-name> subelement of <security-role-ref> in the <enterprise-beans> section in the standard EJB deployment descriptor. (For this example, assume this role has purchase order authority. A caller would have to be mapped into this role, as confirmed by an isCallerInRole() call, to work with a purchase order.)

    Use a <role-link> subelement of <security-role-ref> to link the application role to a desired J2EE logical role (which you will define in the next step, also in the standard EJB deployment descriptor). This functionality allows you to use your application in various J2EE environments without changing the bean code. The application role POMgr is linked to the J2EE role myMgr:

    <enterprise-beans>
      ...
      <security-role-ref>
       <role-name>POMgr</role-name>
       <role-link>myMgr</role-link>
      </security-role-ref>
      ...
    </enterprise-beans>
    

    (The J2EE role in the <role-link> setting can be the same as a deployment role, or it can be mapped to a deployment role in a later step.)

    Note:

    The <security-role-ref> element is required only when you use security context methods within your bean.
  2. Define the J2EE role and the EJB methods for which it has permissions in the standard EJB deployment descriptor. In this purchase order example, assume any method executed within a bean PurchaseOrder must have authorized itself as myMgr, a J2EE role that is declared through a <role-name> subelement of <security-role>. This is the J2EE role that was linked to the application role POMgr in the previous step. Note that PurchaseOrder is the name declared in the <ejb-name> element, a subelement of the <session> or <entity> element.

    The following example defines the role myMgr and gives it permission to access all methods (as indicated by the "*" symbol) of the EJB PurchaseOrder bean:

    <assembly-descriptor>
     ...
     <security-role>
      <description>Role for purchase order authorization</description>
      <role-name>myMgr</role-name>
     </security-role>
     <method-permission>
      <role-name>myMgr</role-name>
      <method>
       <ejb-name>PurchaseOrder</ejb-name>
       <method-name>*</method-name>
      </method>
     </method-permission>
     ...
    </assembly-descriptor>
    

After performing both steps, you can refer to POMgr within the bean implementation, and OC4J maps POMgr to myMgr.

Note:

If you specify different roles within the <method-permission> element for methods in the same EJB, the resulting permission is a union of all the method permissions defined for the methods of this bean.

Looking more closely at the <method-permission> element: the <method> subelement is used to specify the security role for one or more methods within an interface or implementation. According to the EJB specification, this definition can take one of the following forms:

  • Defining all methods within a bean by specifying the bean name and using the "*" character to denote all methods within the bean, as follows:

    <method-permission>
      <role-name>myMgr</role-name>
      <method>
        <ejb-name>EJBNAME</ejb-name>
        <method-name>*</method-name>
      </method>
    </method-permission>
    
  • Defining a specific method that is uniquely identified within the bean. Use the appropriate interface name and method name, as follows:

    <method-permission>
      <role-name>myMgr</role-name>
      <method>
        <ejb-name>myBean</ejb-name>
        <method-name>myMethodInMyBean</method-name>
      </method>
    </method-permission>
    

    Note:

    If there are multiple methods with the same overloaded name, the element of this style refers to all the methods with the overloaded name.
  • Defining a method with a specific signature among many overloaded versions, as follows:

    <method-permission>
      <role-name>myMgr</role-name>
      <method>
          <ejb-name>myBean</ejb-name>
       <method-name>myMethod</method-name>
       <method-params>
          <method-param>java.lang.String</method-param>
          <method-param>java.lang.String</method-param>
       </method-params>
      </method>
    </method-permission>
    

    The parameters are the fully-qualified Java types of the input parameters of the method. If the method has no input arguments, the <method-params> element contains no subelements.

Specifying Unchecked Security for EJB Methods

If you want certain methods to not be checked for security roles, use the standard EJB deployment descriptor to define these methods as unchecked, as follows:

<method-permission>
  <unchecked/>
  <method>
     <ejb-name>EJBNAME</ejb-name>
     <method-name>*</method-name>
  </method>
</method-permission>

Instead of defining a <role-name> element, you define an empty <unchecked> element. When executing any methods in the EJBNAME bean, the container does not check for security. Unchecked methods always override any other role definitions.

Specifying a Run-As or Caller Security Identity for an EJB

You can specify in the standard EJB deployment descriptor that all methods of an EJB execute under a specific identity. That is, the container does not check different roles for permission to run specific methods; instead, the container executes all of the EJB methods under the specified security identity. You can specify a particular role or the caller identity as the security identity.

Specify the "run-as" security identity in the <security-identity> element, which is in the <enterprise-beans> section. The following example indicates that POMgr is the role under which all the entity bean methods execute:

<enterprise-beans>
 <entity>
  ... 
  <security-identity>
     <run-as>
        <role-name>POMgr</role-name>
     </run-as>
  </security-identity>
  ...
 </entity>
 ...
</enterprise-beans>

Alternatively, the following example demonstrates how to specify that all methods of the bean execute under the identity of the caller:

<enterprise-beans>
 <entity>
 ... 
  <security-identity>
     <use-caller-identity/>
  </security-identity>
...
 </entity>
</enterprise-beans>

Mapping J2EE Roles to Deployment Users and Roles

As noted earlier, you can define J2EE roles and related security constraints in the standard EJB deployment descriptor to protect your EJB methods. These J2EE roles can then be mapped to deployment users and roles that are defined in the security provider. This security role mapping can be accomplished through Application Server Control during deployment, as described in "Specifying Security Role Mapping through Application Server Control".

Mappings are reflected in <security-role-mapping> settings in Oracle-specific descriptors, as shown in the discussion that follows.

See Also:

  • Oracle Containers for J2EE Developer's Guide for information about the orion-application.xml file

  • Oracle Containers for J2EE Enterprise JavaBeans Developer's Guide for information about the orion-ejb-jar.xml file

While we recommend that you use Application Server Control for role mapping, the following discussion provides reference information for the resulting configuration in orion-ejb-jar.xml when you map the J2EE role myMgr to the deployment role managers. Any user that can log in as part of the managers role is considered to have permissions of the myMgr role (which had previously been linked to the POMgr application logical role), and can execute the methods of the PurchaseOrder bean.

In the standard EJB deployment descriptor:

<assembly-descriptor>
   ...
   <security-role>
      <role-name>myMgr</role-name>
   </security-role>
   <method-permission>
      <role-name>myMgr</role-name>
      <method>...</method>
   </method-permission>
   ...
</assembly-descriptor

In the OC4J-specific deployment descriptor:

<assembly-descriptor>
 ...
 <security-role-mapping name="myMgr"> 
  <group name="managers" /> 
 </security-role-mapping>
 ...
</assembly-descriptor>

Alternatively, for mapping to a specific user:

<security-role-mapping name="myMgr"> 
 <user name="guest" /> 
</security-role-mapping> 

For mapping to a specific user within a specific role:

<security-role-mapping name="myMgr"> 
 <group name="managers" />
 <user name="guest" /> 
</security-role-mapping>

Configuring Namespace Access

If an application contains an EJB, remote clients must be given namespace access to read (look up) and write (bind) objects as required on the server-side JNDI context of the application. "Read" and "write" correspond to the lookup() and bind() methods of a javax.naming.Context object, respectively.

The remote client's user credentials (the JNDI properties passed to the remote client context) should map to one of the roles that are granted access to the JNDI context of the application.

The following example, which would appear in orion-application.xml, shows how the namespace access is granted for read operations to roles named managers and developers.

<orion-application ... >
   ...
   <namespace-access>
      <read-access>
         <namespace-resource root="">
            <security-role-mapping name="sr_developer">
               <group name="developers"/>
            </security-role-mapping>
            <security-role-mapping name="myMgr">
               <group name="managers"/>
            </security-role-mapping>
         </namespace-resource>
      </read-access>
   </namespace-access>
   ...
</orion-application>

This assumes the indicated role mappings had already been set up elsewhere in orion-application.xml.

Specifying a Default Role Mapping for Unidentified Methods

If any methods have not been associated with a role mapping, they are mapped to the default security role through the <default-method-access> element in the orion-ejb-jar.xml file. The following is the automatic mapping for any unsecured methods:

<assembly-descriptor>
   ...
   <default-method-access>
      <security-role-mapping name="&lt;default-ejb-caller-role&gt;"
                             impliesAll="true" />
   </default-method-access>
   ...
</assembly-descriptor>

The default role is <default-ejb-caller-role>, specified in the name attribute. You can replace this string with any name for the default role. The impliesAll attribute indicates whether any security role checking occurs for these methods. A "true" setting indicates that no security role checking occurs. A "false" setting indicates that the container will check for this default role on these methods.

In the orion-ejb-jar.xml file, the impliesAll attribute has defaults as follows:

  • If <security-role-mapping> is specified in orion-ejb-jar.xml but impliesAll is not set, then this attribute defaults to "false" and the container checks for this default role on these methods.

  • If <security-role-mapping> is not specified in orion-ejb-jar.xml, the OC4J EJB layer defaults to a "true" setting for impliesAll and no security role checking occurs for these methods.

If the impliesAll attribute is "false", you must map the default role defined in the name attribute to a deployment user or role through the <user> or <group> subelement. The following example shows how all methods not associated with a method permission are mapped to the others role.

<default-method-access>
   <security-role-mapping name="default-role" impliesAll="false" />
      <group name="others" />
   </security-role-mapping>
</default-method-access>

Specifying Credentials in EJB Clients

When you access EJBs in a remote container, you must pass valid credentials to this container.

Note:

RMI lookup authentication is integrated with JAAS custom login modules. Refer to Chapter 9, "Login Modules" for information about login modules.

Credentials in JNDI Properties

When you access EJBs in a remote container, you must pass valid credentials to the container. Standalone clients define their credentials in the jndi.properties file deployed with the client's code, using the following properties:

java.naming.security.principal=username
java.naming.security.credentials=password

For example, if you want to access remote EJBs as POMGR/welcome, set the properties as follows. The java.naming.factory.initial setting indicates that you will use the Oracle JNDI implementation:

java.naming.security.principal=POMGR
java.naming.security.credentials=welcome
java.naming.factory.initial=
                    oracle.j2ee.naming.ApplicationClientInitialContextFactory
java.naming.provider.url=ormi://myhost/ejbsamples

In your application program, authenticate and access the remote EJBs as shown in the following example:

InitialContext ic = new InitialContext();
CustomerHome =
   (CustomerHome)ic.lookup("java:comp/env/purchaseOrderBean"); 

Important:

The jndi.properties file must be accessible from the classpath.

Credentials in the InitialContext

JavaBeans running within the container pass their credentials within the javax.naming.InitialContext instance, which is created to look up the remote EJBs.

For example, to pass JNDI security properties within the Hashtable environment:

Hashtable env = new Hashtable(); 
env.put("java.naming.provider.url", "ormi://myhost/ejbsamples"); 
env.put("java.naming.factory.initial", 
        "oracle.j2ee.naming.ApplicationClientInitialContextFactory"); 
env.put(Context.SECURITY_PRINCIPAL, "guest"); 
env.put(Context.SECURITY_CREDENTIALS, "welcome"); 
Context ic = new InitialContext (env); 
Object homeObject = ic.lookup("java:comp/env/employeeBean");

// Narrow the reference to a TemplateHome.
EmployeeHome empHome =
   (EmployeeHome) PortableRemoteObject.narrow(homeObject, EmployeeHome.class);

Note:

ApplicationClientInitialContextFactory is in the file oc4jclient.jar.

Permitting EJB RMI Client Access

For an application to access EJBs using RMI, you must grant RMI permission "login" to the appropriate user or role. You can accomplish this through the OracleAS JAAS Provider Admintool.

The following example sets this permission for a role (users):

% java -jar jazn.jar -grantperm myrealm -role users \
       com.evermind.server.rmi.RMIPermission login

And this example sets the permission for a user (JDOE_ENDUSER):

% java -jar jazn.jar -grantperm myrealm -user JDOE_ENDUSER \
       com.evermind.server.rmi.RMIPermission login

For the file-based provider, you can also grant this permission to a role through Application Server Control, by selecting the role and checking the "Grant RMI Permission" checkbox. (Also refer to "Create a Role" or "Edit a Role".)

Restart OC4J for changes to take effect.

Granting Permissions in the Browser

If you download the EJB application as a client where the security manager is active, you must grant the following permissions before you can execute:

permission java.net.SocketPermission "*:*", "connect,resolve";
permission java.lang.RuntimePermission "createClassLoader";
permission java.lang.RuntimePermission "getClassLoader";
permission java.util.PropertyPermission "*", "read";
permission java.util.PropertyPermission "LoadBalanceOnLookup", "read,write";

Configuring Anonymous EJB Lookup

Anonymous EJB lookup is a mode you may consider, presumably only during development or very special circumstances. In this mode, you do not specify the principal and credential when creating the InitialContext, and therefore do not have to specify a principal or credential to remotely access EJBs. Your jndi.properties file would look like this:

java.naming.factory.initial=
   oracle.j2ee.naming.ApplicationClientInitialContextFactory
java.naming.provider.url=ormi://localhost:23791/ejb30slsb
java.naming.security.principal= 
java.naming.security.credentials=

Important:

Oracle generally discourages this practice, as it leaves EJBs completely unsecured.

You can enable this mode as follows:

  1. Confirm that the anonymous user is configured in system-jazn-data.xml, and that this user is activated, as described in "Predefined Accounts".

  2. Also in system-jazn-data.xml, under the appropriate realm, assign the anonymous user to a role that has been granted RMI permissions, as described in "Permitting EJB RMI Client Access". For example, assuming the users role is granted RMI permissions:

    <jazn-data>
       ...
       <jazn-realm>
          <realm>
             <name>myrealm</name>
             ...
             <roles>
    
                <role>
                   <name>users</name>
                   <members>
                      <member>
                         <type>user</type>
                         <name>anonymous</name>
                      </member>
                   </members>
                </role>
                ...
             </roles>
             ...
          </realm>
          ...
       </jazn-realm>
       ...
    </jazn-data>
    
  3. Give the role (users in this example) appropriate namespace access so that it can execute read (lookup) and write (bind) operations on the server-side JNDI context of the application. Use configuration such as the following in the orion-application.xml file for the application:

    <orion-application>
       ...
       <namespace-access>
          <read-access>
             <namespace-resource root="">
                <security-role-mapping name="jndi-user-role">
                   <group name="administrators" />
                   <group name="users" />
                </security-role-mapping>
             </namespace-resource>
          </read-access>
          <write-access>
             <namespace-resource root="">
                <security-role-mapping name="jndi-user-role">
                   <group name="administrators" />
                   <group name="users" />
                </security-role-mapping>
             </namespace-resource>
          </write-access>
       </namespace-access>
       ...
    </orion-application>
    

With this configuration, you can access remote EJBs without specifying principals or credentials.

Enabling and Configuring Subject Propagation for ORMI

This section discusses subject propagation in OC4J, and documents how to enable it with ORMI. (It is always used with IIOP, in accordance with the CSIv2 specification.) The following topics are covered:

Important:

  • Subject propagation is a powerful feature that should be used only in environments where the server is secure from untrusted client access. It is therefore advised, in order to ensure proper integrity of client requests, that appropriate safeguards be established before this feature is used in production environments. For example, consider using application or network firewalls, RMI access restrictions (through the <access-mask> element in rmi.xml, as documented in "Configuring ORMIS Access Restrictions"), or RMI subject-propagation restrictions (through the <subject-propagation-mask> element in rmi.xml, as documented in "Removing and Configuring Subject Propagation Restrictions").

  • Subject propagation is supported only between OC4J 10.1.3.x instances.

Overview of Subject Propagation in OC4J

OC4J supports subject propagation, as summarized in Figure 18-3. Through this feature, a Web client can establish its identity to a servlet, and the servlet can then use that identity to communicate with other EJBs and servlets, where the identity is the appropriate subject (javax.security.auth.Subject instance). Similarly, a remote EJB fat client can use this feature in calling to the EJB container.

Figure 18-3 Subject Propagation

Description of Figure 18-3 follows
Description of "Figure 18-3 Subject Propagation"

After the client's current subject is obtained, through a Subject.getSubject() call, subject propagation works as follows:

  1. The subject is serialized over to the RMI server.

  2. The RMI server deserializes the subject and uses it to set up the server-side JAAS context.

Subjects may be propagated through a series of EJB invocations, for example. The EJB incorporates the client identity if the EJB is configured to use the client's identity. The EJB cannot be configured to use run-as mode with a specific role.

Enabling Subject Propagation for ORMI

The following steps are required in order to use subject propagation:

  1. Set the Subject Propagation System Property

  2. Enable JAAS Mode

  3. Grant RMI Permission for Subject Propagation

Set the Subject Propagation System Property

In OC4J, you can use subject propagation with ORMI if you specifically enable it on the client and server. (It is always enabled for IIOP, in accordance with the CSIv2 specification.) You can accomplish this with the following system property setting on the client and on the server:

-Dsubject.propagation=true

In the current release, this setting controls subject propagation at a global OC4J level.

Enable JAAS Mode

For subject propagation to work properly, JAAS mode must be enabled for the Web application where the subject is being propagated from, and for the EJB where the subject is being propagated to. So for each, there must be a setting of jaas-mode="doAs" or jaas-mode="doAsPrivileged" in the <jazn> element of the orion-application.xml file, as discussed in "Introduction to JAAS Mode".

Grant RMI Permission for Subject Propagation

A propagated subject is accepted by the server only if the RMIPermission subject.propagation is granted to the EJB caller. The following example uses the OracleAS JAAS Provider Admintool to grant this permission to the user oc4jadmin, so that this user will have its subject propagated to the server:

% java -jar jazn.jar -grantperm myrealm -user oc4jadmin \
       com.evermind.server.rmi.RMIPermission subject.propagation

You can also grant subject.propagation permission to a role. With the following example, any user in the users role would have its subject propagated to the server:

% java -jar jazn.jar -grantperm myrealm -role users \
       com.evermind.server.rmi.RMIPermission subject.propagation

You can restrict subject propagation by specifying the principal names that the server will accept in the subject. The following example again grants subject.propagation permission to any user in the users role, but the server will filter out all but the developer and manager principals from propagated subjects. (Note that the filtering is according to principal names, not principal types.)

% java -jar jazn.jar -grantperm myrealm -role users \
       com.evermind.server.rmi.RMIPermission subject.propagation developer,manager 

By default, there is no restriction—all principals in the subject are accepted. But you can also explicitly specify this with the subject.propagation parameter "*" (including the quotes):

% java -jar jazn.jar -grantperm myrealm -user oc4jadmin \
       com.evermind.server.rmi.RMIPermission subject.propagation "*"

This is equivalent to the first example above.

Sharing Principal Classes for Subject Propagation

While java.security.Subject is a class provided with the JDK, java.security.Principal is an interface that you can implement as desired. For subject propagation to work properly with ORMI, you must ensure that the remote client, application, and OC4J all have access to any Principal class definitions.

You can accomplish this by putting them in a library that is loaded as an OC4J shared library, as documented in "Tasks to Share a Library".

Removing and Configuring Subject Propagation Restrictions

By default, access to subject propagation is denied to all ORMI clients. You can configure desired access through settings in the <subject-propagation-mask> element and its <host-access> and <ip-access> subelements in rmi.xml.

Subject propagation access can be either exclusive or inclusive:

  • In the exclusive mode, access is denied to all IP addresses or hosts except those specifically included. Use mode="deny" in <subject-propagation-mask>, then specify which particular hosts or IP addresses to allow by using mode="allow" in <host-access> or <ip-access> subelements (or both).

  • In the inclusive mode, access is available to all IP addresses or hosts except those specifically excluded. Use mode="allow" in <subject-propagation-mask>, then specify which particular hosts or IP addresses to deny by using mode="deny" in <host-access> or <ip-access> subelements (or both).

The following example configures an exclusive mode, allowing subject propagation for only localhost and 192.168.1.0. (255.255.255.0 is the applicable subnet mask.)

<rmi-server ... >
   ...
   <subject-propagation-mask default="deny">
      <host-access domain="localhost" mode="allow"/>
      <ip-access ip="192.168.1.0" netmask="255.255.255.0" mode="allow"/>
   </subject-propagation-mask>
   ...
</rmi-server>

The default setting is as follows:

<subject-propagation-mask default="deny"/>