JBoss.orgCommunity Documentation
The preceding discussion of the general JBoss security layer has stated that the JBossSX security extension framework is an implementation of the security layer interfaces. This is the primary purpose of the JBossSX framework. The details of the implementation are interesting in that it offers a great deal of customization for integration into existing security infrastructures. A security infrastructure can be anything from a database or LDAP server to a sophisticated security software suite. The integration flexibility is achieved using the pluggable authentication model available in the JAAS framework.
The heart of the JBossSX framework is org.jboss.security.plugins.JaasSecurityManager
. This is the default implementation of the AuthenticationManager
and RealmMapping
interfaces. Figure 4.1, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” shows how the JaasSecurityManager
integrates into the EJB and web container layers based on the security-domain
element of the corresponding component deployment descriptor.
Figure 4.1. The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.
Figure 4.1, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” depicts an enterprise application that contains both EJBs and web content secured under the security domain jwdomain
. The EJB and web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At deployment time, the security-domain
element value in the jboss.xml
and jboss-web.xml
descriptors is used to obtain the security manager instance associated with the container. The security interceptor then uses the security manager to perform its role. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container.
The JBossSX JaasSecurityManager
implementation performs security checks based on the information associated with the Subject
instance that results from executing the JAAS login modules configured under the name matching the security-domain
element value. We will drill into the JaasSecurityManager
implementation and its use of JAAS in the following section.
The JaasSecurityManager
uses the JAAS packages to implement the AuthenticationManager
and RealmMapping
interface behavior. In particular, its behavior derives from the execution of the login module instances that are configured under the name that matches the security domain to which the JaasSecurityManager
has been assigned. The login modules implement the security domain's principal authentication and role-mapping behavior. Thus, you can use the JaasSecurityManager
across different security domains simply by plugging in different login module configurations for the domains.
To illustrate the details of the JaasSecurityManager
's usage of the JAAS authentication process, you will walk through a client invocation of an EJB home method invocation. The prerequisite setting is that the EJB has been deployed in the JBoss server and its home interface methods have been secured using method-permission
elements in the ejb-jar.xml
descriptor, and it has been assigned a security domain named jwdomain
using the jboss.xml
descriptor security-domain
element.
Figure 4.2. An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.
Figure 4.2, “An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.” provides a view of the client to server communication we will discuss. The numbered steps shown are:
The client first has to perform a JAAS login to establish the principal and credentials for authentication, and this is labeled Client Side Login in the figure. This is how clients establish their login identities in JBoss. Support for presenting the login information via JNDI InitialContext
properties is provided via an alternate configuration. A JAAS login entails creating a LoginContext
instance and passing the name of the configuration to use. The configuration name is other
. This one-time login associates the login principal and credentials with all subsequent EJB method invocations. Note that the process might not authenticate the user. The nature of the client-side login depends on the login module configuration that the client uses. In this example, the other
client-side login configuration entry is set up to use the ClientLoginModule
module (an org.jboss.security.ClientLoginModule
). This is the default client side module that simply binds the username and password to the JBoss EJB invocation layer for later authentication on the server. The identity of the client is not authenticated on the client.
Later, the client obtains the EJB home interface and attempts to create a bean. This event is labeled as Home Method Invocation. This results in a home interface method invocation being sent to the JBoss server. The invocation includes the method arguments passed by the client along with the user identity and credentials from the client-side JAAS login performed in step 1.
On the server side, the security interceptor first requires authentication of the user invoking the call, which, as on the client side, involves a JAAS login.
The security domain under which the EJB is secured determines the choice of login modules. The security domain name is used as the login configuration entry name passed to the LoginContext
constructor. The EJB security domain is jwdomain
. If the JAAS login authenticates the user, a JAAS Subject
is created that contains the following in its PrincipalsSet
:
A java.security.Principal
that corresponds to the client identity as known in the deployment security environment.
A java.security.acl.Group
named Roles
that contains the role names from the application domain to which the user has been assigned. org.jboss.security.SimplePrincipal
objects are used to represent the role names; SimplePrincipal
is a simple string-based implementation of Principal
. These roles are used to validate the roles assigned to methods in ejb-jar.xml
and the EJBContext.isCallerInRole(String)
method implementation.
An optional java.security.acl.Group
named CallerPrincipal
, which contains a single org.jboss.security.SimplePrincipal
that corresponds to the identity of the application domain's caller. The CallerPrincipal
sole group member will be the value returned by the EJBContext.getCallerPrincipal()
method. The purpose of this mapping is to allow a Principal
as known in the operational security environment to map to a Principal
with a name known to the application. In the absence of a CallerPrincipal
mapping the deployment security environment principal is used as the getCallerPrincipal
method value. That is, the operational principal is the same as the application domain principal.
The final step of the security interceptor check is to verify that the authenticated user has permission to invoke the requested method This is labeled as Server Side Authorization in Figure 4.2, “An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.”. Performing the authorization this entails the following steps:
Obtain the names of the roles allowed to access the EJB method from the EJB container. The role names are determined by ejb-jar.xml
descriptor role-name elements of all method-permission
elements containing the invoked method.
If no roles have been assigned, or the method is specified in an exclude-list
element, then access to the method is denied. Otherwise, the doesUserHaveRole
method is invoked on the security manager by the security interceptor to see if the caller has one of the assigned role names. This method iterates through the role names and checks if the authenticated user's Subject Roles
group contains a SimplePrincipal
with the assigned role name. Access is allowed if any role name is a member of the Roles
group. Access is denied if none of the role names are members.
If the EJB was configured with a custom security proxy, the method invocation is delegated to it. If the security proxy wants to deny access to the caller, it will throw a java.lang.SecurityException
. If no SecurityException
is thrown, access to the EJB method is allowed and the method invocation passes to the next container interceptor. Note that the SecurityProxyInterceptor
handles this check and this interceptor is not shown.
Every secured EJB method invocation, or secured web content access, requires the authentication and authorization of the caller because security information is handled as a stateless attribute of the request that must be presented and validated on each request. This can be an expensive operation if the JAAS login involves client-to-server communication. Because of this, the JaasSecurityManager
supports the notion of an authentication cache that is used to store principal and credential information from previous successful logins. You can specify the authentication cache instance to use as part of the JaasSecurityManager
configuration as you will see when the associated MBean service is discussed in following section. In the absence of any user-defined cache, a default cache that maintains credential information for a configurable period of time is used.
The JaasSecurityManagerService
MBean service manages security managers. Although its name begins with Jaas, the security managers it handles need not use JAAS in their implementation. The name arose from the fact that the default security manager implementation is the JaasSecurityManager
. The primary role of the JaasSecurityManagerService
is to externalize the security manager implementation. You can change the security manager implementation by providing an alternate implementation of the AuthenticationManager
and RealmMapping
interfaces.
The second fundamental role of the JaasSecurityManagerService
is to provide a JNDI javax.naming.spi.ObjectFactory
implementation to allow for simple code-free management of the JNDI name to security manager implementation mapping. It has been mentioned that security is enabled by specifying the JNDI name of the security manager implementation via the security-domain
deployment descriptor element. When you specify a JNDI name, there has to be an object-binding there to use. To simplify the setup of the JNDI name to security manager bindings, the JaasSecurityManagerService
manages the association of security manager instances to names by binding a next naming system reference with itself as the JNDI ObjectFactory under the name java:/jaas
. This allows one to use a naming convention of the form java:/jaas/XYZ
as the value for the security-domain
element, and the security manager instance for the XYZ
security domain will be created as needed for you. The security manager for the domain XYZ
is created on the first lookup against the java:/jaas/XYZ
binding by creating an instance of the class specified by the SecurityManagerClassName
attribute using a constructor that takes the name of the security domain. For example, consider the following container security configuration snippet:
In previous versions of JBoss, the java:/jaas
prefix in each securitydomain
deployment descrptor element was required to correctly bind the JNDI name to the security manager bindings. As of JBoss AS 6, it is possible to specify the name of the securitydomain
only in jboss.xml
and jboss-web.xml
. The java:/jaas
prefix is still supported however, and remains for backwards compatibility.
<jboss> <!-- Configure all containers to be secured under the "hades" security domain --> <security-domain>hades</security-domain> <!-- ... --> </jboss>
Any lookup of the name hades
will return a security manager instance that has been associated with the security domain named hades
. This security manager will implement the AuthenticationManager and RealmMapping security interfaces and will be of the type specified by the JaasSecurityManagerService
SecurityManagerClassName
attribute.
The JaasSecurityManagerService
MBean is configured by default for use in the standard JBoss distribution, and you can often use the default configuration as is. The configurable attributes of the JaasSecurityManagerService
include:
SecurityManagerClassName: The name of the class that provides the security manager implementation. The implementation must support both the org.jboss.security.AuthenticationManager
and org.jboss.security.RealmMapping
interfaces. If not specified this defaults to the JAAS-based org.jboss.security.plugins.JaasSecurityManager
.
CallbackHandlerClassName: The name of the class that provides the javax.security.auth.callback.CallbackHandler
implementation used by the JaasSecurityManager
. You can override the handler used by the JaasSecurityManager
if the default implementation (org.jboss.security.auth.callback.SecurityAssociationHandler
) does not meet your needs. This is a rather deep configuration that generally should not be set unless you know what you are doing.
SecurityProxyFactoryClassName: The name of the class that provides the org.jboss.security.SecurityProxyFactory
implementation. If not specified this defaults to org.jboss.security.SubjectSecurityProxyFactory
.
AuthenticationCacheJndiName: Specifies the location of the security credential cache policy. This is first treated as an ObjectFactory
location capable of returning CachePolicy
instances on a per-security-domain basis. This is done by appending the name of the security domain to this name when looking up the CachePolicy
for a domain. If this fails, the location is treated as a single CachePolicy
for all security domains. As a default, a timed cache policy is used.
DefaultCacheTimeout: Specifies the default timed cache policy timeout in seconds. The default value is 1800 seconds (30 minutes). The value you use for the timeout is a tradeoff between frequent authentication operations and how long credential information may be out of sync with respect to the security information store. If you want to disable caching of security credentials, set this to 0 to force authentication to occur every time. This has no affect if the AuthenticationCacheJndiName
has been changed from the default value.
DefaultCacheResolution: Specifies the default timed cache policy resolution in seconds. This controls the interval at which the cache current timestamp is updated and should be less than the DefaultCacheTimeout
in order for the timeout to be meaningful. The default resolution is 60 seconds(1 minute). This has no affect if the AuthenticationCacheJndiName
has been changed from the default value.
DefaultUnauthenticatedPrincipal: Specifies the principal to use for unauthenticated users. This setting makes it possible to set default permissions for users who have not been authenticated.
DefaultCacheFlushPeriod: Specifies the default period of time in seconds that the authentication cache will flush expired entries. Default value is 3600 or one hour.
The JaasSecurityManagerService
also supports a number of useful operations. These include flushing any security domain authentication cache at runtime, getting the list of active users in a security domain authentication cache, and any of the security manager interface methods.
Flushing a security domain authentication cache can be used to drop all cached credentials when the underlying store has been updated and you want the store state to be used immediately. The MBean operation signature is: public void flushAuthenticationCache(String securityDomain)
.
This can be invoked programmatically using the following code snippet:
MBeanServer server = ...; String jaasMgrName = "jboss.security:service=JaasSecurityManager"; ObjectName jaasMgr = new ObjectName(jaasMgrName); Object[] params = {domainName}; String[] signature = {"java.lang.String"}; server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);
Getting the list of active users provides a snapshot of the Principals
keys in a security domain authentication cache that are not expired. The MBean operation signature is: public List getAuthenticationCachePrincipals(String securityDomain)
.
This can be invoked programmatically using the following code snippet:
MBeanServer server = ...; String jaasMgrName = "jboss.security:service=JaasSecurityManager"; ObjectName jaasMgr = new ObjectName(jaasMgrName); Object[] params = {domainName}; String[] signature = {"java.lang.String"}; List users = (List) server.invoke(jaasMgr, "getAuthenticationCachePrincipals", params, signature);
The security manager has a few additional access methods.
public boolean isValid(String securityDomain, Principal principal, Object credential); public Principal getPrincipal(String securityDomain, Principal principal); public boolean doesUserHaveRole(String securityDomain, Principal principal, Object credential, Set roles); public Set getUserRoles(String securityDomain, Principal principal, Object credential);
They provide access to the corresponding AuthenticationManager
and RealmMapping
interface method of the associated security domain named by the securityDomain
argument.
In AS 6 most MBeans were replaced by Micro Container (MC) Beans. JaasSecurityManagerService
was not removed to maintain compatibility with previous versions but most of its functionalities are done by the JNDIBasedSecurityManagement
MC Bean now. This Bean is located in conf/bootstrap/security.xml
.
In Example 4.1, “Setting custom values for the JNDIBasedSecurityManagement Bean” an example of how to set up the AuthenticationManager
class, CallbackHandler
class and default values for the authentication cache is shown:
Example 4.1. Setting custom values for the JNDIBasedSecurityManagement Bean
<bean name="JNDIBasedSecurityManagement" class="org.jboss.security.integration.JNDIBasedSecurityManagement"> <property name="authenticationMgrClass">org.example.MyAuthenticationManager</property> <property name="defaultCacheTimeout">1800</property> <property name="defaultCacheResolution">60</property> <property name="defaultCacheFlushPeriod">3600</property> <property name="callBackHandler"><inject bean="CallbackHandler"/></property> </bean> <bean name="CallbackHandler" class="org.example.MyCallbackHandler"/>
The org.jboss.security.plugins.JaasSecurityDomain
is an extension of JaasSecurityManager
that adds the notion of a KeyStore
, a JSSE KeyManagerFactory
and a TrustManagerFactory
for supporting SSL and other cryptographic use cases. The additional configurable attributes of the JaasSecurityDomain
include:
keyStoreType: The type of the KeyStore
implementation. This is the type argument passed to the java.security.KeyStore.getInstance(String type)
factory method. The default is JKS
.
keyStoreURL: A URL to the location of the KeyStore
database. This is used to obtain an InputStream
to initialize the KeyStore
. If the string is not a value URL, it is treated as a file.
keyStorePass: The password associated with the KeyStore
database contents. The KeyStorePass
is also used in combination with the Salt
and IterationCount
attributes to create a PBE secret key used with the encode/decode operations. The keyStorePass
attribute value format is one of the following:
The plaintext password for the KeyStore
. The toCharArray()
value of the string is used without any manipulation.
A command to execute to obtain the plaintext password. The format is {EXT}...
where the ...
is the exact command line that will be passed to the Runtime.exec(String)
method to execute a platform-specific command. The first line of the command output is used as the password.
A class to create to obtain the plaintext password. The format is {CLASS}classname[:ctorarg]
where the [:ctorarg]
is an optional string that will be passed to the constructor when instantiating the classname
. The password is obtained from classname by invoking a toCharArray()
method if found, otherwise, the toString()
method is used.
keyStoreAlias: Alias of the KeyStore
containing the certificate to be used.
keyStoreProvider: Security Provider
of the KeyStore
.
keyStoreProviderArgument: Argument to be passed to the constructor of the KeyStore
security Provider
.
keyManagerFactoryProvider: Security Provider
of the KeyManagerFactory
.
keyManagerFactoryAlgorithm: Algorithm of the KeyManagerFactory
.
salt: The PBEParameterSpec
salt value.
iterationCount: The PBEParameterSpec
iteration count value.
trustStoreType: The type of the TrustStore
implementation. This is the type argument passed to the java.security.KeyStore.getInstance(String type)
factory method. The default is JKS
.
trustStoreURL: A URL to the location of the TrustStore
database. This is used to obtain an InputStream
to initialize the KeyStore
. If the string is not a value URL, it is treated as a file.
trustStorePass: The password associated with the trust store database contents. The trustStorePass
has the same configuration options as the keyStorePass
.
trustStoreProvider: Security Provider
of the TrustStore
.
trustStoreProviderArgument: Argument to be passed to the constructor of the TrustStore
security Provider
.
trustManagerFactoryProvider: Security Provider
of the TrustManagerFactory
.
trustManagerFactoryAlgorithm: Algorithm of the TrustManagerFactory
.
In Example 4.2, “JaasSecurityDomain example” an example JaasSecurityDomain
Bean is shown:
Example 4.2. JaasSecurityDomain example
<bean name="example" class="org.jboss.security.plugins.JaasSecurityDomain"> <constructor> <parameter>example</parameter> </constructor> <property name="keyStorePass">changeit</property> <property name="keyStoreURL">resource:localhost.keystore</property> <!-- introduce a JMX annotation to export this bean as an MBean --> <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX (name="jboss.security:service=JaasSecurityDomain,domain=example", exposedInterface=org.jboss.security.plugins.JaasSecurityDomainMBean.class) </annotation> </bean>
To maintain compatibility with previous versions, JaasSecurityDomain
can still be deployed as a MBean.