-
Language:
English
-
Language:
English
Red Hat Training
A Red Hat training course is available for JBoss Enterprise Application Platform Common Criteria Certification
Chapter 3. JBoss Security Model
Similar to the rest of the JBoss architecture, security at the lowest level is defined as a set of interfaces for which alternate implementations may be provided. The following interfaces define the JBoss server security layer:
org.jboss.security.AuthenticationManager
org.jboss.security.RealmMapping
org.jboss.security.SecurityProxy
org.jboss.security.AuthorizationManager
org.jboss.security.AuditManager
org.jboss.security.MappingManager
Figure 3.1, “Security Model Interface Relationships to JBoss Server EJB Container Elements.” shows a class diagram of the security interfaces and their relationship to the EJB container architecture.
Figure 3.1. Security Model Interface Relationships to JBoss Server EJB Container Elements.
The EJB Container layer is represented by the classes -
org.jboss.ejb.Container
, org.jboss.SecurityInterceptor
and org.jboss.SecurityProxyInterceptor
. The other classes are interfaces and classes provided by the JBoss security subsystem.
The two interfaces required for the J2EE security model implementation are:
org.jboss.security.AuthenticationManager
org.jboss.security.AuthorizationManager
The roles of the security interfaces presented in Figure 3.1, “Security Model Interface Relationships to JBoss Server EJB Container Elements.” are summarized below.
Security Interface Roles
- AuthenticationManager
- This interface is responsible for validating credentials associated with Principals. Principals are identities, such as user names, employee numbers, and social security numbers. Credentials are proof of the identity, such as passwords, session keys, and digital signatures. The
isValid
method is invoked to determine whether a user identity and associated credentials as known in the operational environment are valid proof of the user's identity. - AuthorizationManager
- This interface is responsible for the access control mandated by the Java EE specifications. The implementation of this interface provides the ability to stack a set of Policy Providers useful for pluggable authorization.
- SecurityProxy
- This interface describes the requirements for a custom
SecurityProxyInterceptor
plugin. ASecurityProxy
allows for the externalization of custom security checks on a per-method basis for both the EJB home and remote interface methods. - AuditManager
- This interface is responsible for providing an audit trail of security events.
- MappingManager
- This interface is responsible for providing mapping of Principal, Role, and Attributes. The implementation of AuthorizationManager may internally call the mapping manager to map roles before performing access control.
- SecurityDomain
- This is an extension of the
AuthenticationManager
, RealmMapping, andSubjectSecurityManager
interfaces.SecurityDomain
is the recommended way to implement security in components, because of the advantages the JAAS Subject offers, and the increased support offered to to ASP-style application and resource deployments. Ajava.security.KeyStore
, and the JSSEcom.sun.net.ssl.KeyManagerFactory
andcom.sun.net.ssl.TrustManagerFactory
interfaces are included in the class. - RealmMapping
- This interface is responsible for principal mapping and role mapping. The
getPrincipal
method takes a user identity as known in the operational environment and returns the application domain identity. ThedoesUserHaveRole
method validates that the user identity in the operation environment has been assigned the indicated role from the application domain.
Note that the
AuthenticationManager
, RealmMapping
and SecurityProxy
interfaces have no association to JAAS related classes. Although the JBossSX framework is heavily dependent on JAAS, the basic security interfaces required for implementation of the Java EE security model are not. The JBossSX framework is simply an implementation of the basic security plug-in interfaces that are based on JAAS.
The component diagram in Figure 3.2, “JBossSX Framework Implementation Classes and the JBoss Server EJB Container Layer.” illustrates this fact. The implication of this plug-in architecture is that you are free to replace the JAAS-based JBossSX implementation classes with your own non-JAAS custom security manager implementation. You'll see how to do this when you look at the JBossSX MBeans available for JBossSX configuration in Figure 3.2, “JBossSX Framework Implementation Classes and the JBoss Server EJB Container Layer.”.
Figure 3.2. JBossSX Framework Implementation Classes and the JBoss Server EJB Container Layer.
3.1. Enabling Declarative Security Revisited
Earlier in this chapter, the discussion of the Java EE standard security model ended with a requirement for the use of JBoss server-specific deployment descriptor to enable security. The details of this configuration are presented here. Figure 3.3, “jboss.xml and jboss-web.xml Security Element Subsets.” shows the JBoss-specific EJB and web application deployment descriptor's security-related elements.
Figure 3.3. jboss.xml and jboss-web.xml Security Element Subsets.
The value of a <security-domain> element specifies the JNDI name of the security manager interface implementation that JBoss uses for the EJB and web containers. This is an object that implements both of the
AuthenticationManager
and RealmMapping
interfaces. When specified as a top-level element, it defines what security domain is specified for all EJBs in the deployment unit. This is the typical usage because mixing security managers within a deployment unit complicates inter-component operation and administration.
To specify the security domain for an individual EJB, you specify the <security-domain> at the container configuration level. This will override any top-level <security-domain> element.
The <unauthenticated-principal> element specifies the name to use for the
Principal
object returned by the EJBContext.getUserPrincipal
method when an unauthenticated user invokes an EJB. Note that this conveys no special permissions to an unauthenticated caller. Its primary purpose is to allow unsecured servlets and JSP pages to invoke unsecured EJBs and allow the target EJB to obtain a non-null Principal
for the caller using the getUserPrincipal
method. This is a J2EE specification requirement.
The <security-proxy> element identifies a custom security proxy implementation. It allows per-request security checks outside the scope of the EJB declarative security model, without embedding security logic into the EJB implementation. You can use an implementation of the
org.jboss.security.SecurityProxy
interface. Alternatively, you can use a common interface that uses an object to implement methods in the home, remote, local home, or local interfaces of the EJB. If the given class does not implement the SecurityProxy
interface, the instance must be wrapped in a SecurityProxy
implementation that delegates the method invocations to the object. The org.jboss.security.SubjectSecurityProxy
is an example SecurityProxy
implementation used by the default JBossSX installation.
Take a look at a simple example of a custom
SecurityProxy
in the context of a trivial stateless session bean. The custom SecurityProxy
validates that no one invokes the bean's echo
method with a four-letter word as its argument. This is a check that is not possible with role-based security; you cannot define a FourLetterEchoInvoker
role because the security context is the method argument, not a property of the caller. The code for the custom SecurityProxy
is given in Example 3.1, “Custom EchoSecurityProxy Implementation.”
Example 3.1. Custom EchoSecurityProxy Implementation.
package org.jboss.book.security.ex1; import java.lang.reflect.Method; import javax.ejb.EJBContext; import org.apache.log4j.Category; import org.jboss.security.SecurityProxy; /** A simple example of a custom SecurityProxy implementation * that demonstrates method argument based security checks. * @author Scott.Stark@jboss.org * @version $Revision: 1.4 $ */ public class EchoSecurityProxy implements SecurityProxy { Category log = Category.getInstance(EchoSecurityProxy.class); Method echo; public void init(Class beanHome, Class beanRemote, Object securityMgr) throws InstantiationException { log.debug("init, beanHome="+beanHome + ", beanRemote="+beanRemote + ", securityMgr="+securityMgr); // Get the echo method for equality testing in invoke try { Class[] params = {String.class}; echo = beanRemote.getDeclaredMethod("echo", params); } catch(Exception e) { String msg = "Failed to find an echo(String) method"; log.error(msg, e); throw new InstantiationException(msg); } } public void setEJBContext(EJBContext ctx) { log.debug("setEJBContext, ctx="+ctx); } public void invokeHome(Method m, Object[] args) throws SecurityException { // We don't validate access to home methods } public void invoke(Method m, Object[] args, Object bean) throws SecurityException { log.debug("invoke, m="+m); // Check for the echo method if (m.equals(echo)) { // Validate that the msg arg is not 4 letter word String arg = (String) args[0]; if (arg == null || arg.length() == 4) throw new SecurityException("No 4 letter words"); } // We are not responsible for doing the invoke } }
The
EchoSecurityProxy
checks that the method to be invoked on the bean instance corresponds to the echo(String)
method loaded the init method. If there is a match, the method argument is obtained and its length compared against 4 or null. Either case results in a SecurityException
being thrown.
Certainly this is a contrived example, but only in its application. It is a common requirement that applications must perform security checks based on the value of method arguments. The point of the example is to demonstrate how custom security beyond the scope of the standard declarative security model can be introduced independent of the bean implementation. This allows the specification and coding of the security requirements to be delegated to security experts. Since the security proxy layer can be done independent of the bean implementation, security can be changed to match the deployment environment requirements.
The associated
jboss.xml
descriptor that installs the EchoSecurityProxy
as the custom proxy for the EchoBean
is given in Example 3.2, “jboss.xml descriptor”.
Example 3.2. jboss.xml descriptor
<jboss> <security-domain>java:/jaas/other</security-domain> <enterprise-beans> <session> <ejb-name>EchoBean</ejb-name> <security-proxy>org.jboss.book.security.ex1.EchoSecurityProxy</security-proxy> </session> </enterprise-beans> </jboss>
Now test the custom proxy by running a client that attempts to invoke the
EchoBean.echo
method with the arguments Hello
and Four
as illustrated in this fragment:
public class ExClient { public static void main(String args[]) throws Exception { Logger log = Logger.getLogger("ExClient"); log.info("Looking up EchoBean"); InitialContext iniCtx = new InitialContext(); Object ref = iniCtx.lookup("EchoBean"); EchoHome home = (EchoHome) ref; Echo echo = home.create(); log.info("Created Echo"); log.info("Echo.echo('Hello') = "+echo.echo("Hello")); log.info("Echo.echo('Four') = "+echo.echo("Four")); } }
The first call should succeed, while the second should fail due to the fact that
Four
is a four-letter word. Run the client as follows using Ant from the examples directory:
[examples]$ ant -Dchap=security -Dex=1 run-example run-example1: ... [echo] Waiting for 5 seconds for deploy... [java] [INFO,ExClient] Looking up EchoBean [java] [INFO,ExClient] Created Echo [java] [INFO,ExClient] Echo.echo('Hello') = Hello [java] Exception in thread "main" java.rmi.AccessException: SecurityException; nested exception is: [java] java.lang.SecurityException: No 4 letter words ... [java] Caused by: java.lang.SecurityException: No 4 letter words ...
The result is that the
echo('Hello')
method call succeeds as expected and the echo('Four')
method call results in a rather messy looking exception, which is also expected. The above output has been truncated to fit in the book. The key part to the exception is that the SecurityException("No 4 letter words")
generated by the EchoSecurityProxy
was thrown to abort the attempted method invocation as desired.