Security Guide
for use with JBoss Enterprise Application Platform 5
Edition 5.2.0
Abstract
Part I. Security Overview
Important
Important
Chapter 1. Java EE Declarative Security Overview
ejb-jar.xml
and web.xml
deployment descriptors. The following sections look at the purpose and usage of the various security elements.
1.1. Security References
Figure 1.1. The <security-role-ref> element
role-nameType
attribute value as an argument to the isCallerInRole(String)
method. By using the isCallerInRole
method, a component can verify whether the caller is in a role that has been declared with a <security-role-ref> or <role-name> element. The <role-name> element value must link to a <security-role> element through the <role-link> element. The typical use of isCallerInRole
is to perform a security check that cannot be defined by using the role-based <method-permissions> elements.
ejb-jar.xml
file.
Example 1.1. ejb-jar.xml descriptor fragment
<!-- A sample ejb-jar.xml fragment --> <ejb-jar> <enterprise-beans> <session> <ejb-name>ASessionBean</ejb-name> ... <security-role-ref> <role-name>TheRoleICheck</role-name> <role-link>TheApplicationRole</role-link> </security-role-ref> </session> </enterprise-beans> ... </ejb-jar>
Note
Example 1.2. web.xml descriptor fragment
<web-app> <servlet> <servlet-name>AServlet</servlet-name> ... <security-role-ref> <role-name>TheServletRole</role-name> <role-link>TheApplicationRole</role-link> </security-role-ref> </servlet> ... </web-app>
1.2. Security Identity
Figure 1.2. The security-identity element
EJBContext.getCallerPrincipal()
method. Rather, the caller's security roles are set to the single role specified by the <run-as> or <role-name> element value.
<!-- A sample ejb-jar.xml fragment --> <ejb-jar> <enterprise-beans> <session> <ejb-name>ASessionBean</ejb-name> <!-- ... --> <security-identity> <use-caller-identity/> </security-identity> </session> <session> <ejb-name>RunAsBean</ejb-name> <!-- ... --> <security-identity> <run-as> <description>A private internal role</description> <role-name>InternalRole</role-name> </run-as> </security-identity> </session> </enterprise-beans> <!-- ... --> </ejb-jar>
anonymous
is assigned to all outgoing calls. If you want another principal to be associated with the call, you must associate a <run-as-principal> with the bean in the jboss.xml
file. The following fragment associates a principal named internal
with RunAsBean
from the prior example.
<session> <ejb-name>RunAsBean</ejb-name> <security-identity> <run-as-principal>internal</run-as-principal> </security-identity> </session>
web.xml
file. The following example shows how to assign the role InternalRole
to a servlet:
<servlet> <servlet-name>AServlet</servlet-name> <!-- ... --> <run-as> <role-name>InternalRole</role-name> </run-as> </servlet>
principal
. The <run-as-principal> element is available in the jboss-web.xml
file to assign a specific principal to go along with the run-as
role. The following fragment shows how to associate a principal named internal
to the servlet above.
<servlet> <servlet-name>AServlet</servlet-name> <run-as-principal>internal</run-as-principal> </servlet>
1.3. Security Roles
Figure 1.3. <security-role> element
ejb-jar.xml
file.
Example 1.3. ejb-jar.xml descriptor fragment
<!-- A sample ejb-jar.xml fragment --> <ejb-jar> <!-- ... --> <assembly-descriptor> <security-role> <description>The single application role</description> <role-name>TheApplicationRole</role-name> </security-role> </assembly-descriptor> </ejb-jar>
web.xml
file.
Example 1.4. example web.xml descriptor fragment
<!-- A sample web.xml fragment --> <web-app> <!-- ... --> <security-role> <description>The single application role</description> <role-name>TheApplicationRole</role-name> </security-role> </web-app>
1.4. EJB method permissions
Figure 1.4. The <method-permission> element
exclude-list
.
Figure 1.5. <method> element
<method> <ejb-name>EJBNAME</ejb-name> <method-name>*</method-name> </method>
<method> <ejb-name>EJBNAME</ejb-name> <method-name>METHOD</method-name> </method>
<method> <ejb-name>EJBNAME</ejb-name> <method-name>METHOD</method-name> <method-params> <method-param>PARAMETER_1</method-param> <!-- ... --> <method-param>PARAMETER_N</method-param> </method-params> </method>
Example 1.5. <method-permission> element usage
<ejb-jar> <assembly-descriptor> <method-permission> <description>The employee and temp-employee roles may access any method of the EmployeeService bean </description> <role-name>employee</role-name> <role-name>temp-employee</role-name> <method> <ejb-name>EmployeeService</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <description>The employee role may access the findByPrimaryKey, getEmployeeInfo, and the updateEmployeeInfo(String) method of the AardvarkPayroll bean </description> <role-name>employee</role-name> <method> <ejb-name>AardvarkPayroll</ejb-name> <method-name>findByPrimaryKey</method-name> </method> <method> <ejb-name>AardvarkPayroll</ejb-name> <method-name>getEmployeeInfo</method-name> </method> <method> <ejb-name>AardvarkPayroll</ejb-name> <method-name>updateEmployeeInfo</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </method> </method-permission> <method-permission> <description>The admin role may access any method of the EmployeeServiceAdmin bean </description> <role-name>admin</role-name> <method> <ejb-name>EmployeeServiceAdmin</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <description>Any authenticated user may access any method of the EmployeeServiceHelp bean</description> <unchecked/> <method> <ejb-name>EmployeeServiceHelp</ejb-name> <method-name>*</method-name> </method> </method-permission> <exclude-list> <description>No fireTheCTO methods of the EmployeeFiring bean may be used in this deployment</description> <method> <ejb-name>EmployeeFiring</ejb-name> <method-name>fireTheCTO</method-name> </method> </exclude-list> </assembly-descriptor> </ejb-jar>
1.5. Enterprise Bean Security Annotations
@DeclareRoles
- Declares each security role declared in the code. For information about configuring roles, refer to the Java EE 5 Tutorial Declaring Security Roles Using Annotations.
@RolesAllowed
,@PermitAll
, and@DenyAll
- Specifies method permissions for annotations. For information about configuring annotation method permissions, refer to the Java EE 5 Tutorial Specifying Method Permissions Using Annotations.
@RunAs
- Configures the propagated security identity of a component. For information about configuring propagated security identities using annotations, refer to the Java EE 5 Tutorial Configuring a Component’s Propagated Security Identity.
1.6. Web Content Security Constraints
web.xml
security-constraint element.
Figure 1.6. <security-constraint> element
NONE
, INTEGRAL
, and CONFIDENTIAL
. A value of NONE
means that the application does not require any transport guarantees. A value of INTEGRAL
means that the application requires the data sent between the client and server to be sent in such a way that it can not be changed in transit. A value of CONFIDENTIAL
means that the application requires the data to be transmitted in a fashion that prevents other entities from observing the contents of the transmission. In most cases, the presence of the INTEGRAL
or CONFIDENTIAL
flag indicates that the use of SSL is required.
Figure 1.7. <login-config> element
BASIC
, DIGEST
, FORM
, and CLIENT-CERT
. The <realm-name> child element specifies the realm name to use in HTTP basic and digest authorization. The <form-login-config> child element specifies the log in as well as error pages that should be used in form-based log in. If the <auth-method> value is not FORM
, then form-login-config
and its child elements are ignored.
/restricted
path requires an AuthorizedUser
role. There is no required transport guarantee and the authentication method used for obtaining the user identity is BASIC HTTP authentication.
1.7. Enabling Form-based Authentication
<auth-method>FORM</auth-method>
in the <login-config> element of the deployment descriptor, web.xml
. The login and error pages are also defined in <login-config>, as follows:
<login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.html</form-login-page> <form-error-page>/error.html</form-error-page> </form-login-config> </login-config>
FormAuthenticator
to direct users to the appropriate page. JBoss Enterprise Application Platform maintains a session pool so that authentication information does not need to be present for each request. When FormAuthenticator
receives a request, it queries org.apache.catalina.session.Manager
for an existing session. If no session exists, a new session is created. FormAuthenticator
then verifies the credentials of the session.
Note
/dev/urandom
(Linux) by default, and hashed with MD5. Checks are performed at session ID creation to ensure that the ID created is unique.
JSESSIONID
. Its value is a hex-string of the session ID. This cookie is configured to be non-persistent. This means that on the client side it will be deleted when the browser exits. On the server side, sessions expire after 60 seconds of inactivity, at which time session objects and their credential information are deleted.
FormAuthenticator
caches the request, creates a new session if necessary, and redirects the user to the login page defined in login-config
. (In the previous example code, the login page is login.html
.) The user then enters their user name and password in the HTML form provided. User name and password are passed to FormAuthenticator
via the j_security_check
form action.
FormAuthenticator
then authenticates the user name and password against the realm attached to the web application context. In JBoss Enterprise Application Platform, the realm is JBossWebRealm
. When authentication is successful, FormAuthenticator
retrieves the saved request from the cache and redirects the user to their original request.
Note
/j_security_check
and at least the j_username
and j_password
parameters exist.
1.8. Enabling Declarative Security
Chapter 2. Introduction to JAAS
2.1. JAAS Core Classes
Subject
(javax.security.auth.Subject
)
Configuration
(javax.security.auth.login.Configuration
)LoginContext
(javax.security.auth.login.LoginContext
)
Principal
(java.security.Principal
)Callback
(javax.security.auth.callback.Callback
)CallbackHandler
(javax.security.auth.callback.CallbackHandler
)LoginModule
(javax.security.auth.spi.LoginModule
)
2.1.1. Subject and Principal Classes
Subject
class is the central class in JAAS. A Subject
represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2 java.security.Principal
interface to represent a principal, which is essentially just a typed name.
public Set getPrincipals() {...} public Set getPrincipals(Class c) {...}
getPrincipals()
returns all principals contained in the subject. getPrincipals(Class c)
returns only those principals that are instances of class c
or one of its subclasses. An empty set is returned if the subject has no matching principals.
java.security.acl.Group
interface is a sub-interface of java.security.Principal
, so an instance in the principals set may represent a logical grouping of other principals or groups of principals.
2.1.2. Subject Authentication
- An application instantiates a
LoginContext
and passes in the name of the login configuration and aCallbackHandler
to populate theCallback
objects, as required by the configurationLoginModule
s. - The
LoginContext
consults aConfiguration
to load all theLoginModules
included in the named login configuration. If no such named configuration exists theother
configuration is used as a default. - The application invokes the
LoginContext.login
method. - The login method invokes all the loaded
LoginModule
s. As eachLoginModule
attempts to authenticate the subject, it invokes the handle method on the associatedCallbackHandler
to obtain the information required for the authentication process. The required information is passed to the handle method in the form of an array ofCallback
objects. Upon success, theLoginModule
s associate relevant principals and credentials with the subject. - The
LoginContext
returns the authentication status to the application. Success is represented by a return from the log in method. Failure is represented through a LoginException being thrown by the log in method. - If authentication succeeds, the application retrieves the authenticated subject using the
LoginContext.getSubject
method. - After the scope of the subject authentication is complete, all principals and related information associated with the subject by the log in method can be removed by invoking the
LoginContext.logout
method.
LoginContext
class provides the basic methods for authenticating subjects and offers a way to develop an application that is independent of the underlying authentication technology. The LoginContext
consults a Configuration
to determine the authentication services configured for a particular application. LoginModule
classes represent the authentication services. Therefore, you can plug different login modules into an application without changing the application itself. The following code shows the steps required by an application to authenticate a subject.
CallbackHandler handler = new MyHandler(); LoginContext lc = new LoginContext("some-config", handler); try { lc.login(); Subject subject = lc.getSubject(); } catch(LoginException e) { System.out.println("authentication failed"); e.printStackTrace(); } // Perform work as authenticated Subject // ... // Scope of work complete, logout to remove authentication info try { lc.logout(); } catch(LoginException e) { System.out.println("logout failed"); e.printStackTrace(); } // A sample MyHandler class class MyHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { if (callbacks[i] instanceof NameCallback) { NameCallback nc = (NameCallback)callbacks[i]; nc.setName(username); } else if (callbacks[i] instanceof PasswordCallback) { PasswordCallback pc = (PasswordCallback)callbacks[i]; pc.setPassword(password); } else { throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback"); } } } }
LoginModule
interface. This allows an administrator to plug different authentication technologies into an application. You can chain together multiple LoginModule
s to allow for more than one authentication technology to participate in the authentication process. For example, one LoginModule
may perform user name/password-based authentication, while another may interface to hardware devices such as smart card readers or biometric authenticators.
LoginModule
is driven by the LoginContext
object against which the client creates and issues the log in method. The process consists of two phases. The steps of the process are as follows:
- The
LoginContext
creates each configuredLoginModule
using its public no-arg constructor. - Each
LoginModule
is initialized with a call to its initialize method. TheSubject
argument is guaranteed to be non-null. The signature of the initialize method is:public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
- The
login
method is called to start the authentication process. For example, a method implementation might prompt the user for a user name and password and then verify the information against data stored in a naming service such as NIS or LDAP. Alternative implementations might interface to smart cards and biometric devices, or simply extract user information from the underlying operating system. The validation of user identity by eachLoginModule
is considered phase 1 of JAAS authentication. The signature of thelogin
method isboolean login() throws LoginException
. ALoginException
indicates failure. A return value of true indicates that the method succeeded, whereas a return value of false indicates that the login module should be ignored. - If the
LoginContext
's overall authentication succeeds,commit
is invoked on eachLoginModule
. If phase 1 succeeds for aLoginModule
, then the commit method continues with phase 2 and associates the relevant principals, public credentials, and/or private credentials with the subject. If phase 1 fails for aLoginModule
, thencommit
removes any previously stored authentication state, such as user names or passwords. The signature of thecommit
method is:boolean commit() throws LoginException
. Failure to complete the commit phase is indicated by throwing aLoginException
. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored. - If the
LoginContext
's overall authentication fails, then theabort
method is invoked on eachLoginModule
. Theabort
method removes or destroys any authentication state created by the log in or initialize methods. The signature of theabort
method isboolean abort() throws LoginException
. Failure to complete theabort
phase is indicated by throwing aLoginException
. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored. - To remove the authentication state after a successful log in, the application invokes
logout
on theLoginContext
. This in turn results in alogout
method invocation on eachLoginModule
. Thelogout
method removes the principals and credentials originally associated with the subject during thecommit
operation. Credentials should be destroyed upon removal. The signature of thelogout
method is:boolean logout() throws LoginException
. Failure to complete the logout process is indicated by throwing aLoginException
. A return of true indicates that the method succeeded, whereas a return of false indicates that the login module should be ignored.
LoginModule
must communicate with the user to obtain authentication information, it uses a CallbackHandler
object. Applications implement the CallbackHandler interface and pass it to the LoginContext
, which send the authentication information directly to the underlying login modules.
CallbackHandler
both to gather input from users, such as a password or smart card PIN, and to supply information to users, such as status information. By allowing the application to specify the CallbackHandler
, underlying LoginModule
s remain independent from the different ways applications interact with users. For example, a CallbackHandler
's implementation for a GUI application might display a window to solicit user input. On the other hand, a CallbackHandler
implementation for a non-GUI environment, such as an application server, might simply obtain credential information by using an application server API. The CallbackHandler interface has one method to implement:
void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
Callback
interface is the last authentication class we will look at. This is a tagging interface for which several default implementations are provided, including the NameCallback
and PasswordCallback
used in an earlier example. A LoginModule
uses a Callback
to request information required by the authentication mechanism. LoginModule
s pass an array of Callback
s directly to the CallbackHandler.handle
method during the authentication's log in phase. If a callbackhandler
does not understand how to use a Callback
object passed into the handle method, it throws an UnsupportedCallbackException
to abort the login call.
Chapter 3. JBoss Security Model
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 Enterprise Application Platform EJB Container Elements.
org.jboss.ejb.Container
, org.jboss.SecurityInterceptor
and org.jboss.SecurityProxyInterceptor
. The other classes are interfaces and classes provided by the JBoss security subsystem.
org.jboss.security.AuthenticationManager
org.jboss.security.AuthorizationManager
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
plug-in. 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 ASP-style application and resource deployments. Ajava.security.KeyStore
, and the Java Secure Socket Extension (JSSE)com.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.
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.
Figure 3.2. JBossSX Framework Implementation Classes and the EAP EJB Container Layer.
3.1. Enabling Declarative Security Revisited
Figure 3.3. jboss.xml and jboss-web.xml Security Element Subsets.
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.
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.
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.
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 do not 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 } }
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.
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>
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")); } }
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 ...
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.
Chapter 4. The JBoss Security Extension Architecture
org.jboss.security.plugins.JaasSecurityManager
. This is the default implementation of the AuthenticationManager
and RealmMapping
interfaces. Figure 4.1, “Relationship between <security-domain> deployment descriptor value, component container, and 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. Relationship between <security-domain> deployment descriptor value, component container, and JaasSecurityManager.
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.
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.
4.1. How the JaasSecurityManager Uses JAAS
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.
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 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. Secured EJB Home Method Authentication and Authorization Invocation Steps.
- The client must perform a JAAS log in 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 log in entails creating aLoginContext
instance and passing in the name of the configuration to use. The configuration name isother
. This one-time log in 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 log in depends on the login module configuration that the client uses. In this example, theother
client-side login configuration entry is set up to use theClientLoginModule
module (anorg.jboss.security.ClientLoginModule
). This is the default client side module that simply binds the user name 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. - 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 server. The invocation includes the method arguments passed by the client, along with the user identity and credentials from the client-side JAAS log in 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 log in.
- 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 isjwdomain
. If the JAAS log in authenticates the user, a JAASSubject
is created that contains the following in itsPrincipalsSet
:- A
java.security.Principal
that corresponds to the client identity as known in the deployment security environment. - A
java.security.acl.Group
namedRoles
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 ofPrincipal
. These roles are used to validate the roles assigned to methods inejb-jar.xml
and theEJBContext.isCallerInRole(String)
method implementation. - An optional
java.security.acl.Group
namedCallerPrincipal
, which contains a singleorg.jboss.security.SimplePrincipal
that corresponds to the identity of the application domain's caller. TheCallerPrincipal
sole group member will be the value returned by theEJBContext.getCallerPrincipal()
method. The purpose of this mapping is to allow aPrincipal
as known in the operational security environment to map to aPrincipal
with a name known to the application. In the absence of aCallerPrincipal
mapping the deployment security environment principal is used as thegetCallerPrincipal
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, “Secured EJB Home Method Authentication and Authorization Invocation Steps.”. 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 SubjectRoles
group contains aSimplePrincipal
with the assigned role name. Access is allowed if any role name is a member of theRoles
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 noSecurityException
is thrown, access to the EJB method is allowed and the method invocation passes to the next container interceptor. Note that theSecurityProxyInterceptor
handles this check and this interceptor is not shown. - For JBoss Web connections, Tomcat manages elements of security constraint, and role verification.When a request is received for a web connection, Tomcat checks the security constraints defined in
web.xml
that match the requested resource and the accessed HTTP method.If a constraint exists for the request, Tomcat calls the JaasSecurityManager to perform the principal authentication, which in turn ensures the user roles are associated with that principal object.Role verification is performed solely by Tomcat, including checks on parameters such asallRoles
, and whetherSTRICT_MODE
is used.
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.
4.2. The JaasSecurityManagerService MBean
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.
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. Security is enabled by specifying the JNDI name of the security manager implementation via the <security-domain> deployment descriptor element.
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 permits 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.
XYZ
is created on the first look up 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.
Important
java:/jaas
prefix in each <security-domain>
deployment descriptor element was required to correctly bind the JNDI name of a security domain to the security manager bindings.
java:/jaas
prefix is not required for security domain declaration. The java:/jaas
prefix is still supported, and remains for backward compatibility.
<jboss> <!-- Configure all containers to be secured under the "customer" security domain --> <security-domain>customer</security-domain> <!-- ... --> </jboss>
customer
will return a security manager instance that has been associated with the security domain named customer
. This security manager will implement the AuthenticationManager and RealmMapping security interfaces and will be of the type specified by the SecurityManagerClassName
attribute of the JaasSecurityManagerService
.
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
andorg.jboss.security.RealmMapping
interfaces. If not specified this defaults to the JAAS-basedorg.jboss.security.plugins.JaasSecurityManager
. - CallbackHandlerClassName
- The name of the class that provides the
javax.security.auth.callback.CallbackHandler
implementation used by theJaasSecurityManager
.Note
You can override the handler used by theJaasSecurityManager
if the default implementation (org.jboss.security.auth.callback.SecurityAssociationHandler
) does not meet your needs. Most implementations will find the default handler is sufficient. - SecurityProxyFactoryClassName
- The name of the class that provides the
org.jboss.security.SecurityProxyFactory
implementation. If not specified this defaults toorg.jboss.security.SubjectSecurityProxyFactory
. - AuthenticationCacheJndiName
- Specifies the location of the security credential cache policy. This is first treated as an
ObjectFactory
location capable of returningCachePolicy
instances on a per-<security-domain> basis. This is done by appending the name of the security domain to this name when looking up theCachePolicy
for a domain. If this fails, the location is treated as a singleCachePolicy
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 trade-off 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 time stamp 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 theAuthenticationCacheJndiName
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.
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.
public void flushAuthenticationCache(String securityDomain)
.
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);
Principals
keys in a security domain authentication cache that are not expired. The MBean operation signature is: public List getAuthenticationCachePrincipals(String securityDomain)
.
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);
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);
AuthenticationManager
and RealmMapping
interface method of the associated security domain named by the securityDomain
argument.
4.3. The JaasSecurityDomain MBean
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 thejava.security.KeyStore.getInstance(String type)
factory method. The default isJKS
. - KeyStoreURL
- A URL to the location of the
KeyStore
database. This is used to obtain anInputStream
to initialize theKeyStore
. If the string does not contain a name/value URL, the value is treated as a file. - KeyStorePass
- The password associated with the
KeyStore
database contents. TheKeyStorePass
is also used in combination with theSalt
andIterationCount
attributes to create a PBE secret key used with the encode/decode operations. TheKeyStorePass
attribute value format is one of the following:- The plain text password for the
KeyStore
. ThetoCharArray()
value of the string is used without any manipulation. - A command to execute to obtain the plain text password. The format is
{EXT}...
where the...
is the exact command line that will be passed to theRuntime.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 plain text password. The format is
{CLASS}classname[:ctorarg]
where the[:ctorarg]
is an optional string that will be passed to the constructor when instantiating theclassname
. The password is obtained from classname by invoking atoCharArray()
method if found, otherwise, thetoString()
method is used.
- KeyStoreAlias
- Alias of the KeyStore with the certificate to be used.
- KeyStoreProvider
- Security provider of the KeyStore.
- 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 thejava.security.KeyStore.getInstance(String type)
factory method. The default isJKS
. - TrustStoreURL
- A URL to the location of the
TrustStore
database. This is used to obtain anInputStream
to initialize theKeyStore
. 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
is a simple password and does not have the same configuration options as theKeyStorePass
. - TrustStoreProvider
- Security provider of the TrustStore.
- TrustManagerFactoryProvider
- Security provider of the TrustManagerFactory.
- TrustManagerFactoryAlgorithm
- Algorithm of the KeyManagerFactory.
- ManagerServiceName
- Sets the JMX object name string of the security manager service MBean. This is used to register the defaults to register the
JaasSecurityDomain
as a the security manager underjava:/jaas/<domain>
where<domain>
is the name passed to the MBean constructor. The name defaults tojboss.security:service=JaasSecurityManager
.
Part II. Application Security
Chapter 5. Overview
- Authentication
- Process by which the server determines whether a user should be able to access a system or operation.
- Authorization
- Process by which the server determines whether an authenticated user has permission to access specific privileges or resources in the system or operation.
- Mapping
- Process by which the server associates authenticated users with predefined authorization profiles.
- Auditing
- Process by which the server monitors authentication and authorization security events.
- Security Domain
- A set of authentication, authorization, and mapping policies which are defined in XML and are available to applications at runtime using Java Naming and Directory Interface (JNDI).
Chapter 6. Security Domain Schema
- 5.1, 5.2
/schema/security-beans_1_0.xsd
inside thejboss-as/lib/jbosssx.jar
- 5.0, 5.0.1
/schema/security-beans_1_0.xsd
inside thejboss-as/common/lib/jbosssx.jar
<application-policy xmlns="urn:jboss:security-beans:1.0" name=""> <authentication> <login-module code="" flag="[required|requisite|sufficient|optional]" extends=""> <module-option name=""></module-option> </login-module> </authentication> <authorization> <policy-module code="" flag="[required|requisite|sufficient|optional]"/> </authorization> <mapping> <mapping-module code="" type="" /> </mapping> </application-policy>
Figure 6.1. Schema of the Security Domain Definition
6.1. Security Domain Elements
- <application-policy>
- The elements of a security domain, regardless of how it is deployed within the system, are contained within the <application-policy> element. The element uses the XML namespace, as declared in the
xmlns
attribute.Thename
attribute sets the name of the security domain referenced by an application. The security domain name is bound in JNDI under thejava:/jaas
context, and is accessed by applications via reference in their deployment descriptors.An <application-policy> element can contain a number of child elements that set the behavior for the security domain and all applications that use it. These elements are described in greater detail in Section 6.1.1, “<authentication>”, Section 6.1.2, “<authorization>”, and Section 6.1.3, “<mapping>”.
6.1.1. <authentication>
- <login-module>
- This element uses the
code
attribute to specify what login module implementation an application can use, and theflag
attribute to tell the application how to parse each login module present in the stack. Theflag
attribute supports the following values:- required
- The module must succeed for authentication to be successful. If any required <login-module> fails, the authentication will fail. The remaining login modules in the stack are called regardless of the outcome of the authentication.
- requisite
- The module is required to succeed. If it succeeds, authentication continues down the stack. If the module fails, control immediately returns to the application.
- sufficient
- The login module is not required to succeed. If it does succeed, control immediately returns to the application. If the module fails, authentication continues down the stack.
- optional
- The login module is not required to succeed. Authentication still continues to proceed down the stack regardless of whether the login module succeeds or fails.
Each <login-module> contains a set of <module-option> elements that further define settings required by the login module implementation. - <module-option>
- Each login module has its own set of configuration options. The name attribute specifies the property required by the login module, and the value is declared in the CDATA of the <module-option> element. Module options depend on what login module you choose. Section 12.1, “Using Modules” covers module options in greater detail.
6.1.2. <authorization>
- <policy-module>
- This element uses the
code
attribute to specify what policy module implementation an application can use, and theflag
attribute to tell the application how to parse each policy module present in the policy stack. Theflag
attribute supports the following values:- required
- The module must succeed for authorization to be successful. If any required <policy-module> fails, the authorization attempt will fail. The remaining modules in the stack are called regardless of the outcome of the module.
- requisite
- The module is required to succeed. If it succeeds, authorization continues down the stack. If it fails, control immediately returns to the application.
- sufficient
- The module is not required to succeed. If it does succeed, control immediately returns to the application. If it fails, authorization continues down the stack.
- optional
- The module is not required to succeed. Authorization still continues to proceed down the stack regardless of whether the module succeeds or fails.
6.1.3. <mapping>
- <mapping-module>
- This element uses the
code
attribute to specify what mapping module implementation an application can use, and thetype
attribute to tell the application how to parse each mapping module present in the policy stack. The type attribute supports the following values:credential
principal
role
attribute
Chapter 7. Authentication
Example 7.1. Single login stack authentication policy
jmx-console
that uses a single login module, UsersRolesLoginModule
(refer to Section 12.1.6, “UsersRolesLoginModule”).
jboss-as/server/$PROFILE/conf/props
directory.
<application-policy xmlns="urn:jboss:security-beans:1.0 name="jmx-console"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">props/jmx-console-users.properties</module-option> <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option> </login-module> </authentication> </application-policy>
Example 7.2. Multiple login stack authentication policy
web-console
that uses two login modules in the authentication login module stack.
LdapLoginModule
(refer to Section 12.1.1, “LdapLoginModule”), whereas the other <login-module> obtains authentication credentials using BaseCertLoginModule
(refer to Section 12.1.8, “BaseCertLoginModule”).
<application-policy xmlns="urn:jboss:security-beans:1.0 name="web-console"> <authentication> <!-- LDAP configuration --> <login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="sufficient" /> <!-- database configuration --> <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule" flag="sufficient" /> </authentication> </application-policy>
7.1. Custom Callback Handlers
- Specify the CallbackHandlerClassName attribute in the
conf/jboss-service.xml
JaasSecurityManagerService MBean definition. - Inject a callback handler instance into the
deploy/security/security-jboss-beans.xml
JNDISecurityManagement bean.
Procedure 7.1. Set callback handler using attributes
jboss-service.xml
configuration file.
Open the configuration file
Navigate to$JBOSS_HOME/server/$PROFILE/conf/
Open thejboss-service.xml
file.By default, thejboss-service.xml
file contains the configuration in Example 7.3, “jboss-service default configuration”Example 7.3. jboss-service default configuration
<?xml version="1.0" encoding="UTF-8"?> ... <!-- ==================================================================== --> <!-- Security --> <!-- ==================================================================== --> <!-- JAAS security manager and realm mapping --> <mbean code="org.jboss.security.plugins.JaasSecurityManagerService" name="jboss.security:service=JaasSecurityManager"> <!-- A flag which indicates whether the SecurityAssociation server mode is set on service creation. This is true by default since the SecurityAssociation should be thread local for multi-threaded server operation.--> <attribute name="ServerMode">true</attribute> <attribute name="SecurityManagerClassName">org.jboss.security.plugins.JaasSecurityManager</attribute> <attribute name="DefaultUnauthenticatedPrincipal">anonymous</attribute> <!-- DefaultCacheTimeout: Specifies the default timed cache policy timeout in seconds. 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.--> <attribute name="DefaultCacheTimeout">1800</attribute> <!-- 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. This has no affect if the AuthenticationCacheJndiName has been changed from the default value.--> <attribute name="DefaultCacheResolution">60</attribute> <!-- DeepCopySubjectMode: This set the copy mode of subjects done by the security managers to be deep copies that makes copies of the subject principals and credentials if they are cloneable. It should be set to true if subject include mutable content that can be corrupted when multiple threads have the same identity and cache flushes/logout clearing the subject in one thread results in subject references affecting other threads.--> <attribute name="DeepCopySubjectMode">false</attribute> </mbean> ...
Append the attribute
To set the custom callback handler, append an <attribute> element as a child of the <mbean> element, and specify the fully qualified name of your callback handler. Refer to Example 7.4, “jboss-service appended callback handler” for an example <attribute> element, with the callback handler specified.Example 7.4. jboss-service appended callback handler
<?xml version="1.0" encoding="UTF-8"?> ... <!-- ==================================================================== --> <!-- Security --> <!-- ==================================================================== --> <!-- JAAS security manager and realm mapping --> <mbean code="org.jboss.security.plugins.JaasSecurityManagerService" name="jboss.security:service=JaasSecurityManager"> <!-- A flag which indicates whether the SecurityAssociation server mode is set on service creation. This is true by default since the SecurityAssociation should be thread local for multi-threaded server operation.--> <attribute name="ServerMode">true</attribute> <attribute name="SecurityManagerClassName">org.jboss.security.plugins.JaasSecurityManager</attribute> <attribute name="DefaultUnauthenticatedPrincipal">anonymous</attribute> <!-- DefaultCacheTimeout: Specifies the default timed cache policy timeout in seconds. 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.--> <attribute name="DefaultCacheTimeout">1800</attribute> <!-- 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. This has no affect if the AuthenticationCacheJndiName has been changed from the default value.--> <attribute name="DefaultCacheResolution">60</attribute> <!-- DeepCopySubjectMode: This set the copy mode of subjects done by the security managers to be deep copies that makes copies of the subject principals and credentials if they are cloneable. It should be set to true if subject include mutable content that can be corrupted when multiple threads have the same identity and cache flushes/logout clearing the subject in one thread results in subject references affecting other threads.--> <attribute name="DeepCopySubjectMode">false</attribute> <attribute name="CallbackHandlerClassName">org.jboss.security.plugins.[Custom_Callback_Handler_Name]</attribute> </mbean> ...
Restart server
You have now configured thejboss-service.xml
file to use a custom callback handler.Restart the server to ensure the new security policy takes effect.
Procedure 7.2. Set security callback handler using injection
Create custom callback instance
You must create an instance of the custom callback handler, and register it.Open the configuration file
Navigate to$JBOSS_HOME/server/$PROFILE/deploy/security/
Open thesecurity-jboss-beans.xml
file.By default, thesecurity-jboss-beans.xml
file contains the JNDIBasedSecurityManagement bean configuration in Example 7.5, “security-jboss-beans default configuration”Example 7.5. security-jboss-beans default configuration
<!-- JNDI Based Security Management --> <bean name="JBossSecuritySubjectFactory" class="org.jboss.security.integration.JBossSecuritySubjectFactory" />
Append the injection property
To inject the callback handler, append a <property> element as a child of the JNDIBasedSecurityManagement <mbean> element. Specify the callback handler using the <property> and <inject> elements described in Example 7.4, “jboss-service appended callback handler”.Example 7.6. security-jboss-beans callback handler
<bean name="JBossSecuritySubjectFactory" class="org.jboss.security.integration.JBossSecuritySubjectFactory"> <property name="securityManagement"> <inject bean="JNDIBasedSecurityManagement" /> </property> </bean>
Restart server
You have now configured thesecurity-jboss-beans.xml
file to inject your custom callback handler.Restart the server to ensure the new security policy takes effect.
Chapter 8. Authorization
jboss-web-policy
and jboss-ejb-policy
authorization configured in jboss-as/server/$PROFILE/deploy/security/security-policies-jboss-beans.xml
is used.
security-policies-jboss-beans.xml
.
jboss.xml
(for EJBs) and jboss-web.xml
(for WAR).
Procedure 8.1. Set authorization policies for all EJB and WAR components
jboss-web-policy
, and jboss-ejb-policy
.
Open the security policy bean
Navigate to$JBOSS_HOME/server/$PROFILE/deploy/security
Open thesecurity-policies-jboss-beans.xml
file.By default, thesecurity-policies-jboss-beans.xml
file contains the configuration in Example 8.1, “security-policies-jboss-beans.xml”.Example 8.1. security-policies-jboss-beans.xml
<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> <application-policy xmlns="urn:jboss:security-beans:1.0" name="jboss-web-policy" extends="other"> <authorization> <policy-module code="org.jboss.security.authorization.modules.DelegatingAuthorizationModule" flag="required"/> </authorization> </application-policy> <application-policy xmlns="urn:jboss:security-beans:1.0" name="jboss-ejb-policy" extends="other"> <authorization> <policy-module code="org.jboss.security.authorization.modules.DelegatingAuthorizationModule" flag="required"/> </authorization> </application-policy> </deployment>
Change the application-policy definitions
To set a single authorization policy for each component using JACC, amend each<policy-module>
code
attribute with the name of the JACC authorization module.<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> <application-policy xmlns="urn:jboss:security-beans:1.0" name="jboss-web-policy" extends="other"> <authorization> <policy-module code="org.jboss.security.authorization.modules.JACCAuthorizationModule" flag="required"/> </authorization> </application-policy> <application-policy xmlns="urn:jboss:security-beans:1.0" name="jboss-ejb-policy" extends="other"> <authorization> <policy-module code="org.jboss.security.authorization.modules.JACCAuthorizationModule" flag="required"/> </authorization> </application-policy> <application-policy xmlns="urn:jboss:security-beans:1.0" name="jacc-test" extends="other"> <authorization> <policy-module code="org.jboss.security.authorization.modules.JACCAuthorizationModule" flag="required"/> </authorization> </application-policy> </deployment>
Restart server
You have now configured thesecurity-policy-jboss-beans.xml
file with JACC authorization enabled for each application policy.Restart the server to ensure the new security policy takes effect.
If applications require more granular security policies, you can declare multiple authorization security policies for each application policy. New security domains can inherit base settings from another security domains, and override specific settings such as the authorization policy module.
Procedure 8.2. Set authorization policies for specific security domains
test-domain
security domain uses the UsersRolesLoginModule
login module and uses JACC authorization. The test-domain-inherited
security domain inherits the login module information from test-domain
, and specifies XACML authorization must be used.
Open the security policy
You can specify the security domain settings in thejboss-as/server/$PROFILE/conf/login-config.xml
file, or create a deployment descriptor file containing the settings. Choose the deployment descriptor if you want to package the security domain settings with your application.Locate and open login-config.xml
Navigate to thelogin-config.xml
file for the server profile you are using and open the file for editing.$JBOSS_HOME/jboss-as/server/$PROFILE/conf/login-config.xml
Create a jboss-beans.xml descriptor
Create a[prefix]-jboss-beans.xml
descriptor, replacing [prefix] with a meaningful name (for example,test-war-jboss-beans.xml
)Save this file in the/deploy
directory of the server profile you are configuring.jboss-as/server/$PROFILE/deploy/[prefix]-jboss-beans.xml
Specify the test-domain security domain
In the target file chosen in step 1, specify thetest-domain
security domain. This domain contains the authentication information, including the <login-module> definition, and the JACC authorization policy module definition.<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> <application-policy xmlns="urn:jboss:security-beans:1.0" name="test-domain"> <authentication> <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required"> <module-option name = "unauthenticatedIdentity">anonymous</module-option> <module-option name="usersProperties">u.properties</module-option> <module-option name="rolesProperties">r.properties</module-option> </login-module> </authentication> <authorization> <policy-module code="org.jboss.security.authorization.modules.JACCAuthorizationModule" flag="required"/> </authorization> </application-policy> </deployment>
Append the test-domain-inherited security domain
Append thetest-domain-inherited
application policy definition after thetest-domain
application policy.Set theextends
attribute toother
, so the login module information is inherited.Specify the XACML authorization module in the<policy-module>
element.<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> <application-policy xmlns="urn:jboss:security-beans:1.0" name="test-domain"> <authentication> <login-module code = "org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required"> <module-option name = "unauthenticatedIdentity">anonymous</module-option> <module-option name="usersProperties">u.properties</module-option> <module-option name="rolesProperties">r.properties</module-option> </login-module> </authentication> <authorization> <policy-module code="org.jboss.security.authorization.modules.JACCAuthorizationModule" flag="required"/> </authorization> </application-policy> <application-policy xmlns="urn:jboss:security-beans:1.0" name="test-domain-inherited" extends="test-domain"> <authorization> <policy-module code="org.jboss.security.authorization.modules.XACMLAuthorizationModule" flag="required"/> </authorization> </application-policy> </deployment>
Restart server
You have now configured the target file with two security domains that use different authorization methods.Restart the server to ensure the new security policy takes effect.
8.1. Module Delegation
*-jboss-beans.xml
) to specify different authorization policies to the standard authentication in your implementation.
org.jboss.security.authorization.modules.AuthorizationModuleDelegate
class provides a number of subclasses that allow you to implement module delegation:
AbstractJACCModuleDelegate
WebPolicyModuleDelegate
EJBPolicyModuleDelegate
WebXACMLPolicyModuleDelegate
WebJACCPolicyModuleDelegate
EJBXACMLPolicyModuleDelegate
EJBJACCPolicyModuleDelegate
org.jboss.security.authorization.modules.AuthorizationModuleDelegate
class.
Example 8.2. Delegation Module Declaration
<application-policy xmlns="urn:jboss:security-beans:1.0" name="test-domain" extends="other"> <authorization> <policy-module code="xxx.yyy.MyAuthorizationModule" flag="required"> <module-option name="delegateMap">web=xxx.yyy.mywebauthorizationdelegate,ejb=xxx.yyy.myejbauthorizationdelegate</module-option> </policy-module> </authorization> </application-policy>
Chapter 9. Mapping
org.jboss.security.mapping.providers.DeploymentRolesMappingProvider
class as the value for the code
attribute in the <mapping-module> element. Additionally, the type
attribute must be set to role
. Refer to Section 6.1.3, “<mapping>” for information about the <mapping> element schema.
Important
Example 9.1. <mapping-module> declaration
<application-policy name="test-domain"> <authentication> ... </authentication> <mapping> <mapping-module code="org.jboss.security.mapping.providers.DeploymentRolesMappingProvider" type="role"/> </mapping> ... </application-policy>
WEB-INF/jboss-web.xml
(.war
or .sar
) file.
Example 9.2. <security-role> declaration
<assembly-descriptor> ... <security-role> <role-name>Support</role-name> <principal-name>Mark</principal-name> <principal-name>Tom</principal-name> </security-role> ... </assembly-descriptor>
WEB-INF/jboss-web.xml
.
Chapter 10. Auditing
Important
Important
Procedure 10.1. Enable the security audit feature
Open the log4j configuration file
Navigate to$JBOSS_HOME/server/$PROFILE/conf/
Open thejboss-log4j.xml
file using a text editor.Uncomment the security audit category
By default, the Security Audit Provider category definition in thejboss-log4j.xml
file is commented out. Uncomment the category definition shown in Example 10.1, “log4j Security Audit Provider category”.Example 10.1. log4j Security Audit Provider category
<?xml version="1.0" encoding="UTF-8"?> <!-- Limit the verbose MC4J EMS (lib used by admin-console) categories --> <category name="org.mc4j.ems"> <priority value="WARN"/> </category> <!-- Show the evolution of the DataSource pool in the logs [inUse/Available/Max] <category name="org.jboss.resource.connectionmanager.JBossManagedConnectionPool"> <priority value="TRACE"/> </category> --> <!-- Category specifically for Security Audit Provider --> <category name="org.jboss.security.audit.providers.LogAuditProvider" additivity="false"> <priority value="TRACE"/> <appender-ref ref="AUDIT"/> </category> <!-- Limit the org.jboss.serial (jboss-serialization) to INFO as its DEBUG is verbose --> <category name="org.jboss.serial"> <priority value="INFO"/> </category>
Uncomment the audit appender
By default, the AUDIT appender definition in thejboss-log4j.xml
file is commented out. Uncomment the appender definition shown in Example 10.1, “log4j Security Audit Provider category”.Example 10.2. log4j Security Audit Provider category
... <!-- Emit events as JMX notifications <appender name="JMX" class="org.jboss.monitor.services.JMXNotificationAppender"> <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/> <param name="Threshold" value="WARN"/> <param name="ObjectName" value="jboss.system:service=Logging,type=JMXNotificationAppender"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%c] %m"/> </layout> </appender> --> <!-- Security AUDIT Appender --> <appender name="AUDIT" class="org.jboss.logging.appender.DailyRollingFileAppender"> <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/> <param name="File" value="${jboss.server.log.dir}/audit.log"/> <param name="Append" value="true"/> <param name="DatePattern" value="'.'yyyy-MM-dd"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %-5p [%c] (%t:%x) %m%n"/> </layout> </appender> <!-- ================ --> <!-- Limit categories --> <!-- ================ --> <!-- Limit the org.apache category to INFO as its DEBUG is verbose --> <category name="org.apache"> <priority value="INFO"/> </category> ...
Save, and restart server
You have now activated the auditing service for your implementation, as configured in thejboss-log4j.xml
file.Restart the server to ensure the new security policy takes effect.Verify security auditing is functioning correctly
Once the audit service is configured and deployed, audit log entries will verify the audit service and EJB invocation success.Theaudit.log
file is located injboss-as/server/$PROFILE/log/
directory.A successful EJB invocation would look similar to the followingaudit.log
output.Example 10.3. Successful EJB Invocation log entry
2008-12-05 16:08:26,719 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (http-127.0.0.1-8080-2:) [Success]policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration@76ed4518; Resource:=[org.jboss.security.authorization.resources.EJBResource:contextMap={policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration@76ed4518}:method=public abstract org.jboss.test.security.interfaces.RunAsServiceRemote org.jboss.test.security.interfaces.RunAsServiceRemoteHome.create() throws java.rmi.RemoteException,javax.ejb.CreateException:ejbMethodInterface=Home:ejbName=RunAs:ejbPrincipal=jduke:MethodRoles=Roles(identitySubstitutionCaller,):securityRoleReferences=null:callerSubject=Subject: Principal: [roles=[identitySubstitutionCaller, extraRunAsRole],principal=runAsUser] Principal: Roles(members:extraRunAsRole,identitySubstitutionCaller) :callerRunAs=[roles=[identitySubstitutionCaller, extraRunAsRole],principal=runAsUser]:callerRunAs=[roles=[identitySubstitutionCaller, extraRunAsRole],principal=runAsUser]:ejbRestrictionEnforcement=false:ejbVersion=null];Source=org.jboss.security.plugins.javaee.EJBAuthorizationHelper;Exception:=;
An unsuccessful EJB invocation would look similar to the followingaudit.log
output.Example 10.4. Unsuccessful EJB Invocation log entry
[Error]policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration@76ed4518;Resource:=[org.jboss.security.authorization.resources.EJBResource:contextMap={policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration@76ed4518}:method=public java.security.Principal org.jboss.test.security.ejb3.SimpleStatelessSessionBean.invokeUnavailableMethod():ejbMethodInterface=Remote:ejbName=SimpleStatelessSessionBean:ejbPrincipal=UserA:MethodRoles=Roles(<NOBODY>,):securityRoleReferences=null:callerSubject=Subject: Principal: UserA Principal: Roles(members:RegularUser,Administrator) :callerRunAs=null:callerRunAs=null:ejbRestrictionEnforcement=false:ejbVersion=null];Source=org.jboss.security.plugins.javaee.EJBAuthorizationHelper;Exception:=Authorization Failed: ;
Procedure 10.2. Enable security auditing for Web containers
Enable EJB security auditing
You must enable security as described in Procedure 10.1, “Enable the security audit feature”.Activate auditing in the server realm
Web container auditing must first be activated in the server realm of theserver.xml
file.Theserver.xml
file is located in thejboss-as/server/$PROFILE/deploy/jbossweb.sar/
directory.The<Realm>
element must have theenableAudit="
attribute set, as per Example 10.5, “server.xml audit activation”.true
"Example 10.5. server.xml audit activation
<Realm className="org.jboss.web.tomcat.security.JBossWebRealm" certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping" allRolesMode="authOnly" enableAudit="
true
"/>Specify auditing levels system property
The auditing levels for Web applications must be specified using the org.jboss.security.web.audit system property in therun.conf
(Linux) orrun.conf.bat
(Microsoft Windows) script.Alternatively, you can specify the system property in thejboss-as/server/$PROFILE/deploy/properties-service.xml
file.Linux
Add the system property into thejboss-as/bin/run.sh
file.## Specify the Security Audit options #System Property setting to configure the web audit: #* off = turn it off #* headers = audit the headers #* cookies = audit the cookie #* parameters = audit the parameters #* attributes = audit the attributes #* headers,cookies,parameters = audit the headers,cookie and # parameters #* headers,cookies = audit the headers and cookies JAVA_OPTS="$JAVA_OPTS -Dorg.jboss.security.web.audit=headers,cookies,parameter"
Microsoft Windows
Add the system property into thejboss-as/bin/run.bat
file.rem Specify the Security Audit options rem System Property setting to configure the web audit rem * off = turn it off rem * headers = audit the headers rem * cookies = audit the cookie rem * parameters = audit the parameters rem * attributes = audit the attributes rem * headers,cookies,parameters = audit the headers,cookie and rem parameters rem * headers,cookies = audit the headers and cookies set JAVA_OPTS=%JAVA_OPTS% " -Dorg.jboss.security.web.audit=headers,cookies,parameter"
properties-service.xml
Update theSystemPropertiesService
class MBean in thejboss-as/server/$PROFILE/deploy/properties-service.xml
file, and declare the java property as an <attribute>. You can uncomment the relevant operating system block in the code sample below.<mbean code="org.jboss.varia.property.SystemPropertiesService" name="jboss:type=Service,name=SystemProperties"> <attribute name="Properties"> org.jboss.security.web.audit=headers,cookies,parameter </attribute> </mbean>
Verify security auditing is functioning correctly
Once the system property is specified in the files, audit log entries will verify Web invocation success.Theaudit.log
file is located injboss-as/server/$PROFILE/log/
directory.A successful Web invocation would look similar to the followingaudit.log
output.Example 10.6. Successful Web Invocation log entry
2008-12-05 16:08:38,997 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (http-127.0.0.1-8080-17:) [Success]policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration@76ed4518;Resource:=[org.jboss.security.authorization.resources.WebResource:contextMap={policyRegistration=org.jboss.security.plugins.JBossPolicyRegistration@76ed4518,securityConstraints=[Lorg.apache.catalina.deploy.SecurityConstraint;@6feeae6, resourcePermissionCheck=true},canonicalRequestURI=/restricted/get-only/x,request=[/web-constraints:cookies=null:headers=user-agent=Jakarta Commons-HttpClient/3.0,authorization=host=localhost:8080,][parameters=],CodeSource=null];securityConstraints=SecurityConstraint[RestrictedAccess - Get Only];Source=org.jboss.security.plugins.javaee.WebAuthorizationHelper;resourcePermissionCheck=true;Exception:=;
An unsuccessful EJB invocation would look similar to the followingaudit.log
output.Example 10.7. Unsuccessful Web Invocation log entry
2008-12-05 16:08:41,561 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (http-127.0.0.1-8080-4:) [Failure]principal=anil;Source=org.jboss.web.tomcat.security.JBossWebRealm;request=[/jaspi-web-basic:cookies=null:headers=user-agent=Jakarta Commons-HttpClient/3.0,authorization=host=localhost:8080,][parameters=][attributes=];2008-12-05 16:07:30,129 TRACE [org.jboss.security.audit.providers.LogAuditProvider] (WorkerThread#1[127.0.0.1:55055]:)
Chapter 11. Deploying Security Domains
- Modular Security Domain
- A security domain deployment method, where the security domain declaration is included in a deployment descriptor . A modular security domain takes the form
*-jboss-beans.xml
. It is included in theMETA-INF
directory of EJB Jars, or theWEB-INF
directory of web application (WAR). - Deployment Descriptor
- A declarative XML configuration file that describes the deployment settings of an application. The way an application is deployed can be changed within this file, eliminating the need to make changes to the underlying code of the application.
- Declare the security domain in the
jboss-as/server/$PROFILE/conf/login-config.xml
file. - Create and deploy a modular security domain.
Procedure 11.1. Modular Security Domain configuration
UsersRolesLoginModule
for the authorization policy, however you are not limited to this login module when creating a modular security domain. Refer to Section 12.1, “Using Modules” for additional login modules shipped with JBoss Enterprise Application Platform.
Create deployment descriptor
You must create a deployment descriptor file to contain the security domain configuration.If you have already created a deployment descriptor for your application, you can skip this step and proceed to step 2.The file name takes the format[domain_name]-jboss-beans.xml
. While the domain_name is arbitrary, you should choose a name that is meaningful to the application ensure the name of the deployment descriptor is unique across the server profile.The file must contain the standard XML declaration, and a correctly configured<deployment>
element.<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> </deployment>
Define application policies
Individual security domains are defined within the <deployment> element.In the example below, two security domains are specified. Each authentication policy uses the same login module, and module parameters.Note
Other login modules are available for use with the Enterprise Application Platform. For more information about the available login modules, refer to Section 12.1, “Using Modules”<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> <application-policy xmlns="urn:jboss:security-beans:1.0" name="web-test"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="unauthenticatedIdentity">anonymous</module-option> <module-option name="usersProperties">u.properties</module-option> <module-option name="rolesProperties">r.properties</module-option> </login-module> </authentication> </application-policy> <application-policy xmlns="urn:jboss:security-beans:1.0" name="ejb-test"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="unauthenticatedIdentity">anonymous</module-option> <module-option name="usersProperties">u.properties</module-option> <module-option name="rolesProperties">r.properties</module-option> </login-module> </authentication> </application-policy> </deployment>
Deploy or package the deployment descriptor
Move the deployment descriptor file to thejboss-as/server/$PROFILE/deploy
directory of the required server profile in your installation.If you are distributing your application to a wider audience, package the deployment descriptor in theMETA-INF
directory of the EJB Jar, or theWEB-INF
directory of your web application (WAR).
Chapter 12. Login Modules
12.1. Using Modules
12.1.1. LdapLoginModule
LdapLoginModule
is a LoginModule
implementation that authenticates against a Lightweight Directory Access Protocol (LDAP) server. Use the LdapLoginModule
if your user name and credentials are stored in an LDAP server that is accessible using a Java Naming and Directory Interface (JNDI) LDAP provider.
Note
- Distinguished Name (DN)
- In Lightweight Directory Access Protocol (LDAP), the distinguished name uniquely identifies an object in a directory. Each distinguished name must have a unique name and location from all other objects, which is achieved using a number of attribute-value pairs (AVPs). The AVPs define information such as common names, organization unit, among others. The combination of these values results in a unique string required by the LDAP.
Note
- java.naming.factory.initial
InitialContextFactory
implementation class name. This defaults to the Sun LDAP provider implementationcom.sun.jndi.ldap.LdapCtxFactory
.- java.naming.provider.url
- LDAP URL for the LDAP server.
- java.naming.security.authentication
- Security protocol level to use. The available values include
none
,simple
, andstrong
. If the property is undefined, the behavior is determined by the service provider. - java.naming.security.protocol
- Transport protocol to use for secure access. Set this configuration option to the type of service provider (for example, SSL). If the property is undefined, the behavior is determined by the service provider.
- java.naming.security.principal
- Specifies the identity of the Principal for authenticating the caller to the service. This is built from other properties as described below.
- java.naming.security.credentials
- Specifies the credentials of the Principal for authenticating the caller to the service. Credentials can take the form of a hashed password, a clear-text password, a key, or a certificate. If the property is undefined, the behavior is determined by the service provider.
- principalDNPrefix
- Prefix added to the user name to form the user distinguished name . See
principalDNSuffix
for more info. - principalDNSuffix
- Suffix added to the user name when forming the user distinguished name. This is useful if you prompt a user for a user name and you do not want the user to have to enter the fully distinguished name. Using this property and
principalDNSuffix
theuserDN
will be formed asprincipalDNPrefix + username + principalDNSuffix
- rolesCtxDN
- Fixed, distinguished name to the context for searching user roles.
- userRolesCtxDNAttributeName
- Name of an attribute in the user object that contains the distinguished name to the context to search for user roles. This differs from
rolesCtxDN
in that the context to search for a user's roles can be unique for each user. - roleAttributeID
- Name of the attribute containing the user roles. If not specified, this defaults to
roles
. - roleAttributeIsDN
- Flag indicating whether the roleAttributeID contains the fully distinguished name of a role object, or the role name. The role name is taken from the value of the roleNameAttributeId attribute of the context name by the distinguished name.If true, the role attribute represents the distinguished name of a role object. If false, the role name is taken from the value of
roleAttributeID
. The default isfalse
.Note
In certain directory schemas (e.g., MS ActiveDirectory), role attributes in the user object are stored as DNs to role objects instead of simple names. For implementations that use this schema type, roleAttributeIsDN must be set totrue
. - roleNameAttributeID
- Name of the attribute of the context pointed to by the roleCtxDN distinguished name value which contains the role name. If the roleAttributeIsDN property is set to
true
, this property is used to find the role object'sname
attribute. The default isgroup
. - uidAttributeID
- Name of the attribute in the object containing the user roles that corresponds to the user ID. This is used to locate the user roles. If not specified this defaults to
uid
. - matchOnUserDN
- Flag that specifies whether the search for user roles should match on the user's fully distinguished name. If
true
, the fulluserDN
is used as the match value. Iffalse
, only the user name is used as the match value against the uidAttributeName attribute. The default value isfalse
. - unauthenticatedIdentity
- Principal name to assign to requests containing no authentication information. This behavior is inherited from the
UsernamePasswordLoginModule
superclass. - allowEmptyPasswords
- A flag indicating if empty (length 0) passwords should be passed to the LDAP server. An empty password is treated as an anonymous log in by some LDAP servers, and this may not be a desirable feature. To reject empty passwords, set this to
false
. If set totrue
, the LDAP server will validate the empty password. The default istrue
. - searchTimeLimit
- The timeout in milliseconds for the user/role searches. Defaults to 10000 (10 seconds).
- searchScope
- Sets the search scope to one of the strings. The default is SUBTREE_SCOPE. Other supported values include:
- OBJECT_SCOPE : only search the named roles context.
- ONELEVEL_SCOPE : search directly under the named roles context.
- SUBTREE_SCOPE : If the roles context is not a DirContext, search only the object. If the roles context is a DirContext, search the subtree rooted at the named object, including the named object itself.
- jaasSecurityDomain
- The JMX ObjectName of the JaasSecurityDomain used to decrypt the java.naming.security.principal. The encrypted form of the password is that returned by the JaasSecurityDomainencrypt64(byte[]) method. The org.jboss.security.plugins.PBEUtils can also be used to generate the encrypted form.
InitialLdapContext
with an environment composed of the LDAP JNDI properties described previously in this section.
InitialLdapContext
instance is created), the user's roles are queried by performing a search on the rolesCtxDN
location with search attributes set to the roleAttributeName and uidAttributeName option values. The roles names are obtaining by invoking the toString
method on the role attributes in the search result set.
Example 12.1. LDAP Login Module Authentication Policy
<application-policy name="testLDAP"> <authentication> <login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required"> <module-option name="java.naming.factory.initial"> com.sun.jndi.ldap.LdapCtxFactory </module-option> <module-option name="java.naming.provider.url"> ldap://ldaphost.jboss.org:1389/ </module-option> <module-option name="java.naming.security.authentication"> simple </module-option> <module-option name="principalDNPrefix">uid=</module-option> <module-option name="principalDNSuffix"> ,ou=People,dc=jboss,dc=org </module-option> <module-option name="rolesCtxDN"> ou=Roles,dc=jboss,dc=org </module-option> <module-option name="uidAttributeID">member</module-option> <module-option name="matchOnUserDN">true</module-option> <module-option name="roleAttributeID">cn</module-option> <module-option name="roleAttributeIsDN">false </module-option> </login-module> </authentication> </application-policy>
java.naming.factory.initial
, java.naming.factory.url
and java.naming.security
options in the testLDAP <login-module> configuration indicate the following conditions:
- The Sun LDAP JNDI provider implementation will be used
- The LDAP server is located on host
ldaphost.jboss.org
on port 1389 - The LDAP simple authentication method will be use to connect to the LDAP server.
jsmith
would map to uid=jsmith,ou=People,dc=jboss,dc=org
.
Note
userPassword
attribute of the user's entry (theduke
in this example). Most LDAP servers operate in this manner, however if your LDAP server handles authentication differently you must ensure LDAP is configured according to your production environment requirements.
rolesCtxDN
for entries whose uidAttributeID match the user. If matchOnUserDN is true, the search will be based on the full DN of the user. Otherwise the search will be based on the actual user name entered. In this example, the search is under ou=Roles,dc=jboss,dc=org
for any entries that have a member
attribute equal to uid=jduke,ou=People,dc=jboss,dc=org
. The search would locate cn=JBossAdmin
under the roles entry.
cn
. The value returned would be JBossAdmin
, so the jsmith
user is assigned to the JBossAdmin
role.
- LDAP Data Interchange Format (LDIF)
- Plain text data interchange format used to represent LDAP directory content and update requests. Directory content is represented as one record for each object or update request. Content consists of add, modify, delete, and rename requests.
Example 12.2. LDIF File Example
dn: dc=jboss,dc=org objectclass: top objectclass: dcObject objectclass: organization dc: jboss o: JBoss dn: ou=People,dc=jboss,dc=org objectclass: top objectclass: organizationalUnit ou: People dn: uid=jsmith,ou=People,dc=jboss,dc=org objectclass: top objectclass: uidObject objectclass: person uid: jsmith cn: John sn: Smith userPassword: theduke dn: ou=Roles,dc=jboss,dc=org objectclass: top objectclass: organizationalUnit ou: Roles dn: cn=JBossAdmin,ou=Roles,dc=jboss,dc=org objectclass: top objectclass: groupOfNames cn: JBossAdmin member: uid=jsmith,ou=People,dc=jboss,dc=org description: the JBossAdmin group
12.1.2. LdapExtLoginModule
- Distinguished Name (DN)
- In Lightweight Directory Access Protocol (LDAP), the distinguished name uniquely identifies an object in a directory. Each distinguished name must have a unique name and location from all other objects, which is achieved using a number of attribute-value pairs (AVPs). The AVPs define information such as common names, organization unit, among others. The combination of these values results in a unique string required by the LDAP.
org.jboss.security.auth.spi.LdapExtLoginModule
searches for the user to bind, as well as the associated roles, for authentication. The roles query recursively follows DNs to navigate a hierarchical role structure.
- Context.INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"
- Context.SECURITY_PROTOCOL = "java.naming.security.protocol"
- Context.PROVIDER_URL = "java.naming.provider.url"
- Context.SECURITY_AUTHENTICATION = "java.naming.security.authentication"
- Context.REFERRAL = "java.naming.referral"
- The initial LDAP server bind is authenticated using the bindDN and bindCredential properties. The bindDN is a user with permissions to search both the baseCtxDN and rolesCtxDN trees for the user and roles. The user DN to authenticate against is queried using the filter specified by the baseFilter property.
- The resulting userDN is authenticated by binding to the LDAP server using the userDN as the InitialLdapContext environment Context.SECURITY_PRINCIPAL. The Context.SECURITY_CREDENTIALS property is either set to the String password obtained by the callback handler.
- If this is successful, the associated user roles are queried using the rolesCtxDN, roleAttributeID, roleAttributeIsDN, roleNameAttributeID, and roleFilter options.
LdapExtLoginModule Properties
- baseCtxDN
- Specifies the fixed DN of the context to start the user search from.
- bindDN
- Specifies the DN used to bind against the LDAP server for the user and role queries. Set bindDN to a DN with read/search permissions on the baseCtxDN and rolesCtxDn properties.
- bindCredential
- The password for the bindDN. bindCredential can be encrypted if jaasSecurityDomain is specified. This property allows an external command to read the password. For example
{EXT}cat file_with_password
. - jaasSecurityDomain
- The JMX ObjectName of the JaasSecurityDomain used to decrypt the
java.naming.security.principal
. The encrypted form of the password is that returned by theJaasSecurityDomainencrypt64(byte[])
method. The org.jboss.security.plugins.PBEUtils can also be used to generate the encrypted form. - baseFilter
- A search filter used to locate the context of the user to authenticate. The input username/userDN as obtained from the login module callback is substituted into the filter anywhere a
{0}
expression exists. This substitution behavior originates from the standardDirContext.search(Name, String, Object[], SearchControls cons)
method. An common example search filter is(uid={0})
. - rolesCtxDN
- The fixed DN of the context to search for user roles. This is not the DN of where the actual roles are; this is the DN of where the objects containing the user roles are. For example, in active directory, this is the DN where the user account is.
- roleFilter
- Search filter used to locate the roles associated with the authenticated user. The input username/userDN as obtained from the login module callback is substituted into the filter anywhere a
{0}
expression exists. The authenticated userDN is substituted into the filter anywhere a{1}
is seen. An example search filter that matches on the input username is(member={0})
. An alternative that matches on the authenticated userDN is(member={1})
. - roleAttributeIsDN
- Flag indicating whether the roleAttributeID contains the full DN of a role object, or the role name. The role name is derived from the value of the roleNameAttributeId attribute of the context name by the distinguished name.If set to
true
, the role attribute represents the distinguished name of a role object. If set tofalse
, the role name is taken from the value ofroleAttributeID
. The default isfalse
.Note
In certain directory schemas (e.g., MS ActiveDirectory), role attributes in the user object are stored as DNs to role objects instead of simple names. For implementations that use this schema type, roleAttributeIsDN must be set totrue
. - roleAttributeID
- Name of the attribute containing the user roles. If roleAttributeIsDN is set to
true
, this property is the DN of the context to query for the roleNameAttributeID attribute. If the roleAttributeIsDN property is set tofalse
, this property is the attribute name of the role name. - roleNameAttributeID
- Name of the attribute of the context pointed to by the roleCtxDN distinguished name value which contains the role name. If the roleAttributeIsDN property is set to
true
, this property is used to find the role object'sname
attribute. The default isgroup
. - roleRecursion
- Specifies how many levels the role search traverses a given matching context. The default is
0
(deactivated). - searchTimeLimit
- The timeout in milliseconds for the user/role searches. Defaults to 10000 (10 seconds).
- searchScope
- Sets the search scope to one of the strings. The default is SUBTREE_SCOPE. Other supported values include:
- OBJECT_SCOPE : only search the named roles context.
- ONELEVEL_SCOPE : search directly under the named roles context.
- SUBTREE_SCOPE : If the roles context is not a DirContext, search only the object. If the roles context is a DirContext, search the subtree rooted at the named object, including the named object itself.
- allowEmptyPasswords
- A flag indicating if
empty(length==0)
passwords should be passed to the LDAP server.An empty password is treated as an anonymous log in by some LDAP servers. If set tofalse
, empty passwords are rejected. If set totrue
, the LDAP server validates the empty password. The default istrue
. - defaultRole
- A role included for all authenticated users.
- parseRoleNameFromDN
- A flag indicating if the DN returned by a query contains the roleNameAttributeID. If set to
true
, the DN is checked for the roleNameAttributeID. If set tofalse
, the DN is not checked for the roleNameAttributeID. This flag can improve the performance of LDAP queries. - parseUsername
- A flag indicating if the DN is to be parsed for the username. If set to
true
, the DN is parsed for the username. If set tofalse
the DN is not parsed for the username. This option is used together with usernameBeginString and usernameEndString. - usernameBeginString
- Defines the string which is to be removed from the start of the DN to reveal the username. This option is used together with usernameEndString.
- usernameEndString
- Defines the string which is to be removed from the end of the DN to reveal the username. This option is used together with usernameBeginString.
- distinguishedNameAttribute
- Defines a distinguished name to provide a unique 'path' to any object in the LDAP database.
Figure 12.1. LDAP Structure Example
Example 12.3. Example 2 LDAP Configuration
version: 1 dn: o=example2,dc=jboss,dc=org objectClass: top objectClass: dcObject objectClass: organization dc: jboss o: JBoss dn: ou=People,o=example2,dc=jboss,dc=org objectClass: top objectClass: organizationalUnit ou: People dn: uid=jduke,ou=People,o=example2,dc=jboss,dc=org objectClass: top objectClass: uidObject objectClass: person objectClass: inetOrgPerson cn: Java Duke employeeNumber: judke-123 sn: Duke uid: jduke userPassword:: dGhlZHVrZQ== dn: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org objectClass: top objectClass: uidObject objectClass: person objectClass: inetOrgPerson cn: Java Duke2 employeeNumber: judke2-123 sn: Duke2 uid: jduke2 userPassword:: dGhlZHVrZTI= dn: ou=Roles,o=example2,dc=jboss,dc=org objectClass: top objectClass: organizationalUnit ou: Roles dn: uid=jduke,ou=Roles,o=example2,dc=jboss,dc=org objectClass: top objectClass: groupUserEx memberOf: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org memberOf: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org uid: jduke dn: uid=jduke2,ou=Roles,o=example2,dc=jboss,dc=org objectClass: top objectClass: groupUserEx memberOf: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org memberOf: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org uid: jduke2 dn: cn=Echo,ou=Roles,o=example2,dc=jboss,dc=org objectClass: top objectClass: groupOfNames cn: Echo description: the echo role member: uid=jduke,ou=People,dc=jboss,dc=org dn: cn=TheDuke,ou=Roles,o=example2,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: TheDuke description: the duke role member: uid=jduke,ou=People,o=example2,dc=jboss,dc=org dn: cn=Echo2,ou=Roles,o=example2,dc=jboss,dc=org objectClass: top objectClass: groupOfNames cn: Echo2 description: the Echo2 role member: uid=jduke2,ou=People,dc=jboss,dc=org dn: cn=TheDuke2,ou=Roles,o=example2,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: TheDuke2 description: the duke2 role member: uid=jduke2,ou=People,o=example2,dc=jboss,dc=org dn: cn=JBossAdmin,ou=Roles,o=example2,dc=jboss,dc=org objectClass: top objectClass: groupOfNames cn: JBossAdmin description: the JBossAdmin group member: uid=jduke,ou=People,dc=jboss,dc=org
testLdapExample2 { org.jboss.security.auth.spi.LdapExtLoginModule java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url="ldap://lamia/" java.naming.security.authentication=simple bindDN="cn=Root,dc=jboss,dc=org" bindCredential=secret1 baseCtxDN="ou=People,o=example2,dc=jboss,dc=org" baseFilter="(uid={0})" rolesCtxDN="ou=Roles,o=example2,dc=jboss,dc=org"; roleFilter="(uid={0})" roleAttributeIsDN="true" roleAttributeID="memberOf" roleNameAttributeID="cn" };
Example 12.4. Example 3 LDAP Configuration
dn: o=example3,dc=jboss,dc=org objectclass: top objectclass: dcObject objectclass: organization dc: jboss o: JBoss dn: ou=People,o=example3,dc=jboss,dc=org objectclass: top objectclass: organizationalUnit ou: People dn: uid=jduke,ou=People,o=example3,dc=jboss,dc=org objectclass: top objectclass: uidObject objectclass: person objectClass: inetOrgPerson uid: jduke employeeNumber: judke-123 cn: Java Duke sn: Duke userPassword: theduke dn: ou=Roles,o=example3,dc=jboss,dc=org objectClass: top objectClass: organizationalUnit ou: Roles dn: uid=jduke,ou=Roles,o=example3,dc=jboss,dc=org objectClass: top objectClass: groupUserEx memberOf: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org memberOf: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org uid: jduke dn: cn=Echo,ou=Roles,o=example3,dc=jboss,dc=org objectClass: top objectClass: groupOfNames cn: Echo description: the JBossAdmin group member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org dn: cn=TheDuke,ou=Roles,o=example3,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: TheDuke member: uid=jduke,ou=People,o=example3,dc=jboss,dc=org
testLdapExample3 { org.jboss.security.auth.spi.LdapExtLoginModule java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url="ldap://lamia/" java.naming.security.authentication=simple bindDN="cn=Root,dc=jboss,dc=org" bindCredential=secret1 baseCtxDN="ou=People,o=example3,dc=jboss,dc=org" baseFilter="(cn={0})" rolesCtxDN="ou=Roles,o=example3,dc=jboss,dc=org"; roleFilter="(member={1})" roleAttributeID="cn" };
Example 12.5. Example 4 LDAP Configuration
dn: o=example4,dc=jboss,dc=org objectclass: top objectclass: dcObject objectclass: organization dc: jboss o: JBoss dn: ou=People,o=example4,dc=jboss,dc=org objectclass: top objectclass: organizationalUnit ou: People dn: uid=jduke,ou=People,o=example4,dc=jboss,dc=org objectClass: top objectClass: uidObject objectClass: person objectClass: inetOrgPerson cn: Java Duke employeeNumber: jduke-123 sn: Duke uid: jduke userPassword:: dGhlZHVrZQ== dn: ou=Roles,o=example4,dc=jboss,dc=org objectClass: top objectClass: organizationalUnit ou: Roles dn: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: RG1 member: cn=empty dn: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: RG2 member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org dn: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: RG3 member: cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org dn: cn=R1,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: R1 member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org dn: cn=R2,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: R2 member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org dn: cn=R3,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: R3 member: cn=RG2,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org dn: cn=R4,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: R4 member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org dn: cn=R5,ou=Roles,o=example4,dc=jboss,dc=org objectClass: groupOfNames objectClass: top cn: R5 member: cn=RG3,cn=RG1,ou=Roles,o=example4,dc=jboss,dc=org member: uid=jduke,ou=People,o=example4,dc=jboss,dc=org
testLdapExample4 { org.jboss.security.auth.spi.LdapExtLoginModule java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory java.naming.provider.url="ldap://lamia/" java.naming.security.authentication=simple bindDN="cn=Root,dc=jboss,dc=org" bindCredential=secret1 baseCtxDN="ou=People,o=example4,dc=jboss,dc=org" baseFilter="(cn={0})" rolesCtxDN="ou=Roles,o=example4,dc=jboss,dc=org"; roleFilter="(member={1})" roleAttributeID="memberOf" };
Example 12.6. Default ActiveDirectory Configuration
<?xml version="1.0" encoding="UTF-8"?> <application-policy name="AD_Default"> <authentication> <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required" > <!-- Some AD configurations may require searching against the Global Catalog on port 3268 instead of the usual port 389. This is most likely when the AD forest includes multiple domains. --> <module-option name="java.naming.provider.url">ldap://ldap.jboss.org:389</module-option> <module-option name="bindDN">JBOSS\someadmin</module-option> <module-option name="bindCredential">password</module-option> <module-option name="baseCtxDN">cn=Users,dc=jboss,dc=org</module-option> <module-option name="baseFilter">(sAMAccountName={0})</module-option> <module-option name="rolesCtxDN">cn=Users,dc=jboss,dc=org</module-option> <module-option name="roleFilter">(sAMAccountName={0})</module-option> <module-option name="roleAttributeID">memberOf</module-option> <module-option name="roleAttributeIsDN">true</module-option> <module-option name="roleNameAttributeID">cn</module-option> <module-option name="searchScope">ONELEVEL_SCOPE</module-option> <module-option name="allowEmptyPasswords">false</module-option> </login-module> </authentication> </application-policy>
Example 12.7. Recursive Roles ActiveDirectory Configuration
<?xml version="1.0" encoding="UTF-8"?> <application-policy name="AD_Recursive"> <authentication> <login-module code="org.jboss.security.auth.spi.LdapExtLoginModule" flag="required" > <module-option name="java.naming.provider.url">ldap://ad.jboss.org:389</module-option> <module-option name="bindDN">JBOSS\searchuser</module-option> <module-option name="bindCredential">password</module-option> <module-option name="baseCtxDN">CN=Users,DC=jboss,DC=org</module-option> <module-option name="baseFilter">(sAMAccountName={0})</module-option> <module-option name="rolesCtxDN">CN=Users,DC=jboss,DC=org</module-option> <module-option name="roleFilter">(member={1})</module-option> <module-option name="roleAttributeID">cn</module-option> <module-option name="roleAttributeIsDN">false</module-option> <module-option name="roleRecursion">2</module-option> <module-option name="searchScope">ONELEVEL_SCOPE</module-option> <module-option name="allowEmptyPasswords">false</module-option> <module-option name="java.naming.referral">follow</module-option> </login-module> </authentication> </application-policy>
12.1.3. Password Stacking
password-stacking
attribute to useFirstPass
. If a previous module configured for password stacking has authenticated the user, all the other stacking modules will consider the user authenticated and only attempt to provide a set of roles for the authorization step.
password-stacking
option is set to useFirstPass
, this module first looks for a shared user name and password under the property names javax.security.auth.login.name and javax.security.auth.login.password respectively in the login module shared state map.
Note
Example 12.8. Password Stacking Sample
<application-policy name="todo"> <authentication> <login-module code="org.jboss.security.auth.spi.LdapLoginModule" flag="required"> <!-- LDAP configuration --> <module-option name="password-stacking">useFirstPass</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <!-- database configuration --> <module-option name="password-stacking">useFirstPass</module-option> </login-module> </authentication> </application-policy>
12.1.4. Password Hashing
Example 12.9. Password Hashing
nobody
and contains based64-encoded, MD5 hashes of the passwords in a usersb64.properties
file. The usersb64.properties
file can be part of the deployment classpath, or be saved in the /conf
directory.
<policy> <application-policy name="testUsersRoles"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">usersb64.properties</module-option> <module-option name="rolesProperties">test-users-roles.properties</module-option> <module-option name="unauthenticatedIdentity">nobody</module-option> <module-option name="hashAlgorithm">MD5</module-option> <module-option name="hashEncoding">base64</module-option> </login-module> </authentication> </application-policy> </policy>
- hashAlgorithm
- Name of the
java.security.MessageDigest
algorithm to use to hash the password. There is no default so this option must be specified to enable hashing. Typical values areMD5
andSHA
. - hashEncoding
- String that specifies one of three encoding types:
base64
,hex
orrfc2617
. The default isbase64
. - hashCharset
- Encoding character set used to convert the clear text password to a byte array. The platform default encoding is the default.
- hashUserPassword
- Specifies the hashing algorithm must be applied to the password the user submits. The hashed user password is compared against the value in the login module, which is expected to be a hash of the password. The default is
true
. - hashStorePassword
- Specifies the hashing algorithm must be applied to the password stored on the server side. This is used for digest authentication, where the user submits a hash of the user password along with a request-specific tokens from the server to be compare. The hash algorithm (for digest, this would be
rfc2617
) is utilized to compute a server-side hash, which should match the hashed value sent from the client.
org.jboss.security.Util
class provides a static helper method that will hash a password using the specified encoding. The following example produces a base64-encoded, MD5 hashed password.
String hashedPassword = Util.createPasswordHash("MD5", Util.BASE64_ENCODING, null, null, "password");
password
- is piped into the OpenSSL digest function then piped into another OpenSSL function to convert into base64-encoded format.
echo -n password | openssl dgst -md5 -binary | openssl base64
X03MO1qnZdYdgyfeuILPmQ==
. This value must be stored in the users properties file specified in the application policy - usersb64.properties
- in the example above.
12.1.5. Unauthenticated Identity
unauthenticatedIdentity
is a login module configuration option that assigns a specific identity (guest, for example) to requests that are made with no associated authentication information. This can be used to allow unprotected servlets to invoke methods on EJBs that do not require a specific role. Such a principal has no associated roles and so can only access either unsecured EJBs or EJB methods that are associated with the unchecked permission constraint.
- unauthenticatedIdentity: This defines the principal name that should be assigned to requests that contain no authentication information.
12.1.6. UsersRolesLoginModule
UsersRolesLoginModule
is a simple login module that supports multiple users and user roles loaded from Java properties files. The user name-to-password mapping file is called users.properties
and the user name-to-roles mapping file is called roles.properties
.
- usersProperties
- Name of the properties resource (file) containing the user name to password mappings. This defaults to
<file_prefix>-users.properties
. - rolesProperties
- Name of the properties resource (file) containing the user name to roles mappings. This defaults to
<file_prefix>-roles.properties
.
Example 12.10. UserRolesLoginModule
<deployment xmlns="urn:jboss:bean-deployer:2.0"> <!-- ejb3 test application-policy definition --> <application-policy xmlns="urn:jboss:security-beans:1.0" name="ejb3-sampleapp"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">ejb3-sampleapp-users.properties</module-option> <module-option name="rolesProperties">ejb3-sampleapp-roles.properties</module-option> </login-module> </authentication> </application-policy> </deployment>
ejb3-sampleapp-users.properties
file uses a username=password
format with each user entry on a separate line:
username1=password1 username2=password2 ...
ejb3-sampleapp-roles.properties
file referenced in Example 12.10, “UserRolesLoginModule” uses the pattern username=role1,role2,
with an optional group name value. For example:
username1=role1,role2,... username1.RoleGroup1=role3,role4,... username2=role1,role3,...
ejb3-sampleapp-roles.properties
is used to assign the user name roles to a particular named group of roles where the XXX
portion of the property name is the group name. The user name=... form is an abbreviation for user name.Roles=..., where the Roles
group name is the standard name the JaasSecurityManager
expects to contain the roles which define the users permissions.
jduke
user name:
jduke=TheDuke,AnimatedCharacter jduke.Roles=TheDuke,AnimatedCharacter
12.1.7. DatabaseServerLoginModule
DatabaseServerLoginModule
is a Java Database Connectivity-based (JDBC) login module that supports authentication and role mapping. Use this login module if you have your user name, password and role information stored in a relational database.
Note
DatabaseServerLoginModule
is based on two logical tables:
Table Principals(PrincipalID text, Password text) Table Roles(PrincipalID text, Role text, RoleGroup text)
Principals
table associates the user PrincipalID
with the valid password and the Roles
table associates the user PrincipalID
with its role sets. The roles used for user permissions must be contained in rows with a RoleGroup
column value of Roles
.
java.sql.ResultSet
has the same logical structure as the Principals
and Roles
tables described previously. The actual names of the tables and columns are not relevant as the results are accessed based on the column index.
Principals
and Roles
, as already declared. The following statements populate the tables with the following data:
PrincipalID
java
with aPassword
ofechoman
in thePrincipals
tablePrincipalID
java
with a role namedEcho
in theRoles
RoleGroup
in theRoles
tablePrincipalID
java
with a role namedcaller_java
in theCallerPrincipal
RoleGroup
in theRoles
table
INSERT INTO Principals VALUES('java', 'echoman') INSERT INTO Roles VALUES('java', 'Echo', 'Roles') INSERT INTO Roles VALUES('java', 'caller_java', 'CallerPrincipal')
- dsJndiName
- The JNDI name for the
DataSource
of the database containing the logicalPrincipals
andRoles
tables. If not specified this defaults tojava:/DefaultDS
. - principalsQuery
- The prepared statement query equivalent to:
select Password from Principals where PrincipalID=?
. If not specified this is the exact prepared statement that will be used. - rolesQuery
- The prepared statement query equivalent to:
select Role, RoleGroup from Roles where PrincipalID=?
. If not specified this is the exact prepared statement that will be used. - ignorePasswordCase
- A boolean flag indicating if the password comparison should ignore case. This can be useful for hashed password encoding where the case of the hashed password is not significant.
- principalClass
- An option that specifies a
Principal
implementation class. This must support a constructor taking a string argument for the principal name. - transactionManagerJndiName
- The JNDI name of the transaction manager used by the login module. If no value is provided, the default
java:/TransactionManager
is used. - suspendResume
- A boolean flag indicating whether an active transaction associated with the current thread should be suspended during a database operation and resumed after the operation is completed. The default value is
true
.
DatabaseServerLoginModule
configuration could be constructed as follows:
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64)) CREATE TABLE UserRoles(username VARCHAR(64), userRoles VARCHAR(32))
login-config.xml
entry would be:
<policy> <application-policy name="testDB"> <authentication> <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <module-option name="dsJndiName">java:/MyDatabaseDS</module-option> <module-option name="principalsQuery">select passwd from Users username where username=?</module-option> <module-option name="rolesQuery">select userRoles, 'Roles' from UserRoles where username=?</module-option> </login-module> </authentication> </application-policy> </policy>
12.1.8. BaseCertLoginModule
BaseCertLoginModule
authenticates users based on X509 certificates. A typical use case for this login module is CLIENT-CERT
authentication in the web tier.
CertRolesLoginModule
and DatabaseCertLoginModule
extend the behavior to obtain the authorization roles from either a properties file or database.
BaseCertLoginModule
needs a KeyStore
to perform user validation. This is obtained through a org.jboss.security.SecurityDomain
implementation. Typically, the SecurityDomain
implementation is configured using the org.jboss.security.plugins.JaasSecurityDomain
MBean as shown in this jboss-service.xml
configuration fragment:
<mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.ch8:service=SecurityDomain"> <constructor> <arg type="java.lang.String" value="jmx-console"/> </constructor> <attribute name="KeyStoreURL">resource:localhost.keystore</attribute> <attribute name="KeyStorePass">unit-tests-server</attribute> </mbean>
jmx-console
, with a SecurityDomain
implementation available through JNDI under the name java:/jaas/jmx-console
. The security domain follows the JBossSX security domain naming pattern.
Procedure 12.1. Secure Web Applications with Certificates and Role-based Authorization
jmx-console.war,
using client certificates and role-based authorization.
Declare Resources and Roles
Modifyweb.xml
to declare the resources to be secured along with the allowed roles and security domain to be used for authentication and authorization.<?xml version="1.0"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> ... <!-- A security constraint that restricts access to the HTML JMX console to users with the role JBossAdmin. Edit the roles to what you want and uncomment the WEB-INF/jboss-web.xml/security-domain element to enable secured access to the HTML JMX console. --> <security-constraint> <web-resource-collection> <web-resource-name>HtmlAdaptor</web-resource-name> <description>An example security config that only allows users with the role JBossAdmin to access the HTML JMX console web application </description> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>JBossAdmin</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> <realm-name>JBoss JMX Console</realm-name> </login-config> <security-role> <role-name>JBossAdmin</role-name> </security-role> </web-app>
Specify the JBoss Security Domain
In thejboss-web.xml
file, specify the required security domain.<jboss-web> <security-domain>jmx-console</security-domain> </jboss-web>
Specify Login Module Configuration
Define the login module configuration for the jmx-console security domain you just specified. This is done in theconf/login-config.xml
file.<application-policy name="jmx-console"> <authentication> <login-module code="org.jboss.security.auth.spi.BaseCertLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="securityDomain">jmx-console</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="password-stacking">useFirstPass</module-option> <module-option name="usersProperties">jmx-console-users.properties</module-option> <module-option name="rolesProperties">jmx-console-roles.properties</module-option> </login-module> </authentication> </application-policy>
BaseCertLoginModule
is used for authentication of the client cert, and the UsersRolesLoginModule
is only used for authorization due to the password-stacking=useFirstPass
option. Both the localhost.keystore
and the jmx-console-roles.properties
require an entry that maps to the principal associated with the client cert.
Example 12.11. Certificate Example
[conf]$ keytool -printcert -file unit-tests-client.export Owner: CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US Issuer: CN=jboss.com, C=US, ST=Washington, L=Snoqualmie Pass, EMAILADDRESS=admin @jboss.com, OU=QA, O=JBoss Inc. Serial number: 100103 Valid from: Wed May 26 07:34:34 PDT 2004 until: Thu May 26 07:34:34 PDT 2005 Certificate fingerprints: MD5: 4A:9C:2B:CD:1B:50:AA:85:DD:89:F6:1D:F5:AF:9E:AB SHA1: DE:DE:86:59:05:6C:00:E8:CC:C0:16:D3:C2:68:BF:95:B8:83:E9:58
localhost.keystore
would need the certificate in Example 12.11, “Certificate Example” stored with an alias of CN=unit-tests-client, OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US
. The jmx-console-roles.properties
would also need an entry for the same entry. Since the DN contains characters that are normally treated as delimiters, you must escape the problem characters using a backslash ('\
') as illustrated below.
# A sample roles.properties file for use with the UsersRolesLoginModule CN\=unit-tests-client,\ OU\=JBoss\ Inc.,\ O\=JBoss\ Inc.,\ ST\=Washington,\ C\=US=JBossAdmin admin=JBossAdmin
12.1.9. IdentityLoginModule
IdentityLoginModule
is a simple login module that associates a hard-coded user name to any subject authenticated against the module. It creates a SimplePrincipal
instance using the name specified by the principal
option.
Note
- principal
- This is the name to use for the
SimplePrincipal
all users are authenticated as. The principal name defaults toguest
if no principal option is specified. - roles
- This is a comma-delimited list of roles that will be assigned to the user.
jduke
and assign role names of TheDuke
, and AnimatedCharacter
:.
<policy> <application-policy name="testIdentity"> <authentication> <login-module code="org.jboss.security.auth.spi.IdentityLoginModule" flag="required"> <module-option name="principal">jduke</module-option> <module-option name="roles">TheDuke,AnimatedCharacter</module-option> </login-module> </authentication> </application-policy> </policy>
12.1.10. RunAsLoginModule
RunAsLoginModule
(org.jboss.security.auth.spi.RunAsLoginModule
) is a helper module that pushes a run as role onto the stack for the duration of the log in phase of authentication, and pops the run as role in either the commit or abort phase.
RunAsLoginModule
must be configured ahead of the login modules that require a run as role established.
- roleName
- Name of the role to use as the run as role during log in phase. If not specified a default of
nobody
is used.
12.1.11. RunAsIdentity Creation
javax.security.auth.Subject
instance or an org.jboss.security.RunAsIdentity
instance. Both these classes store one or more principals that represent the identity and a list of roles that the identity possesses. In the case of the javax.security.auth.Subject
a list of credentials is also stored.
ejb-jar.xml
deployment descriptor, you specify one or more roles that a user must have to access the various EJB methods. A comparison of these lists reveals whether the user has one of the roles necessary to access the EJB method.
Example 12.12. org.jboss.security.RunAsIdentity Creation
ejb-jar.xml
file, you specify a <security-identity> element with a <run-as> role defined as a child of the <session> element.
<session> ... <security-identity> <run-as> <role-name>Admin</role-name> </run-as> </security-identity> ... </session>
<run-as-principal>
element in the jboss-web.xml
file.
<session> ... <security-identity> <run-as-principal>John</run-as-principal> </security-identity> ... </session>
<security-identity>
element in both the ejb-jar.xml
and jboss-web.xml
files are parsed at deployment time. The <run-as>
role name and the <run-as-principal>
name are then stored in the org.jboss.metadata.SecurityIdentityMetaData
class.
Example 12.13. Assigning multiple roles to a RunAsIdentity
jboss-web.xml
deployment descriptor <assembly-descriptor>
element group.
<assembly-descriptor> ... <security-role> <role-name>Support</role-name> <principal-name>John</principal-name> <principal-name>Jill</principal-name> <principal-name>Tony</principal-name> </security-role> ... </assembly-descriptor>
<run-as-principal>
of "Mark" was created. The configuration in this example extends the "Admin" role, by adding the "Support" role. The new role contains extra principals, including the originally defined principal "John".
<security-role>
element in both the ejb-jar.xml
and jboss.xml
files are parsed at deployment time. The <role-name>
and the <principal-name>
data is stored in the org.jboss.metadata.SecurityIdentityMetaData
class.
12.1.12. ClientLoginModule
ClientLoginModule
(org.jboss.security.ClientLoginModule
) is an implementation of LoginModule
for use by JBoss clients for establishing caller identity and credentials. This simply sets the org.jboss.security.SecurityAssociation.principal
to the value of the NameCallback
filled in by the callbackhandler
, and the org.jboss.security.SecurityAssociation.credential
to the value of the PasswordCallback
filled in by the callbackhandler
.
ClientLoginModule
is the only supported mechanism for a client to establish the current thread's caller. Both stand-alone client applications, and server environments (acting as JBoss EJB clients where the security environment has not been configured to use JBossSX transparently) must use ClientLoginModule
.
ClientLoginModule
.
- multi-threaded
- Value that specifies the way login threads connect to principal and credential storage sources. When set to true, each login thread has its own principal and credential storage and each separate thread must perform its own log in. This is useful in client environments where multiple user identities are active in separate threads. When set to false the login identity and credentials are global variables that apply to all threads in the VM. The default setting is
false
. - password-stacking
- Activates client-side authentication of clients using other login modules such as the
LdapLoginModule
. Whenpassword-stacking
option is set touseFirstPass
, the module first looks for a shared user name and password usingjavax.security.auth.login.name
andjavax.security.auth.login.password
respectively in the login module shared state map. This allows a module configured prior to this one to establish a valid JBoss user name and password. - restore-login-identity
- Value that specifies whether the
SecurityAssociation
principal and credential seen on entry to thelogin()
method are saved and restored on either abort or logout. This is necessary if you must change identities and then restore the original caller identity. If set totrue
, the principal and credential information is saved and restored on abort or logout. If set tofalse
, abort and logout clear theSecurityAssociation
. The default value isfalse
.
12.1.13. SPNEGOLoginModule
SPNEGOLoginModule
(org.jboss.security.negotiation.spnego.SPNEGOLoginModule
) is an implementation of LoginModule
that establishes caller identity and credentials with a KDC. The module implements SPNEGO (Simple and Protected GSSAPI Negotiation mechanism) and is a part of the JBoss Negotiation project. This authentication can be used in the chained configuration with the AdvancedLDAPLoginModule to allow cooperation with an LDAP server. For further information on JBoss Negotiation refer to the Negotiation User Guide.
12.1.14. RoleMappingLoginModule
RoleMappingLoginModule
is a login module that supports mapping roles that are the end result of the authentication process to one or more declarative roles; for example, if the authentication process has determined that the user "A" has the roles "ldapAdmin" and "testAdmin", and the declarative role defined in the web.xml
or ejb-jar.xml
file for access is "admin", then this login module maps the "admin" roles to the user "A".
- rolesProperties
- Name of the properties file that defines the addition/substitution rules; the value defines the file in the form as located using Classloader or with its absolute location given by the java.net.url pattern (for example,
file:/rolesMap.properties
) - replaceRole
- Flag determining if the key role is replaced with the mapped roles or the mapped roles are added to the key role (set to
true
to have the key role replaced with the mapped roles)
RoleMappingLoginModule
must be defined as an optional module to a login module configuration as it alters mapping of the previously mapped roles.
<application-policy name="jmx-console"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">props/jmx-console-users.properties</module-option> <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.RoleMappingLoginModule" flag="optional"> <module-option name="rolesProperties">props/rolesMapping-roles.properties</module-option> </login-module> </authentication> </application-policy>
Example 12.14. Properties File used by a RoleMappingLoginModule
ldapAdmin=admin, testAdmin
12.2. Custom Modules
JaasSecurityManager
requires a particular usage pattern of the Subject
principals set. You must understand the JAAS Subject class's information storage features and the expected usage of these features to write a login module that works with the JaasSecurityManager
.
LoginModule
implementations that can help you implement custom login modules.
Subject
by using the following methods:
java.util.Set getPrincipals() java.util.Set getPrincipals(java.lang.Class c) java.util.Set getPrivateCredentials() java.util.Set getPrivateCredentials(java.lang.Class c) java.util.Set getPublicCredentials() java.util.Set getPublicCredentials(java.lang.Class c)
Subject
identities and roles, JBossSX has selected the most logical choice: the principals sets obtained via getPrincipals()
and getPrincipals(java.lang.Class)
. The usage pattern is as follows:
- User identities (for example; user name, social security number, employee ID) are stored as
java.security.Principal
objects in theSubject
Principals
set. ThePrincipal
implementation that represents the user identity must base comparisons and equality on the name of the principal. A suitable implementation is available as theorg.jboss.security.SimplePrincipal
class. OtherPrincipal
instances may be added to theSubject
Principals
set as needed. - Assigned user roles are also stored in the
Principals
set, and are grouped in named role sets usingjava.security.acl.Group
instances. TheGroup
interface defines a collection ofPrincipal
s and/orGroup
s, and is a subinterface ofjava.security.Principal
. - Any number of role sets can be assigned to a
Subject
.
- The JBossSX framework uses two well-known role sets with the names
Roles
andCallerPrincipal
.- The
Roles
group is the collection ofPrincipal
s for the named roles as known in the application domain under which theSubject
has been authenticated. This role set is used by methods like theEJBContext.isCallerInRole(String)
, which EJBs can use to see if the current caller belongs to the named application domain role. The security interceptor logic that performs method permission checks also uses this role set. - The
CallerPrincipal
Group
consists of the singlePrincipal
identity assigned to the user in the application domain. TheEJBContext.getCallerPrincipal()
method uses theCallerPrincipal
to allow the application domain to map from the operation environment identity to a user identity suitable for the application. If aSubject
does not have aCallerPrincipal
Group
, the application identity is the same as operational environment identity.
12.2.1. Subject Usage Pattern Support
Subject
usage patterns described in Section 12.2, “Custom Modules”, JBossSX includes login modules that populate the authenticated Subject
with a template pattern that enforces correct Subject
usage.
The most generic of the two is the org.jboss.security.auth.spi.AbstractServerLoginModule
class.
javax.security.auth.spi.LoginModule
interface and offers abstract methods for the key tasks specific to an operation environment security infrastructure. The key details of the class are highlighted in Example 12.15, “AbstractServerLoginModule Class Fragment”. The JavaDoc comments detail the responsibilities of subclasses.
Important
loginOk
instance variable is pivotal. This must be set to true
if the log in succeeds, or false
by any subclasses that override the log in method. If this variable is incorrectly set, the commit method will not correctly update the subject.
Example 12.15. AbstractServerLoginModule Class Fragment
package org.jboss.security.auth.spi; /** * This class implements the common functionality required for a JAAS * server-side LoginModule and implements the JBossSX standard * Subject usage pattern of storing identities and roles. Subclass * this module to create your own custom LoginModule and override the * login(), getRoleSets(), and getIdentity() methods. */ public abstract class AbstractServerLoginModule implements javax.security.auth.spi.LoginModule { protected Subject subject; protected CallbackHandler callbackHandler; protected Map sharedState; protected Map options; protected Logger log; /** Flag indicating if the shared credential should be used */ protected boolean useFirstPass; /** * Flag indicating if the login phase succeeded. Subclasses that * override the login method must set this to true on successful * completion of login */ protected boolean loginOk; // ... /** * Initialize the login module. This stores the subject, * callbackHandler and sharedState and options for the login * session. Subclasses should override if they need to process * their own options. A call to super.initialize(...) must be * made in the case of an override. * * <p> * The options are checked for the <em>password-stacking</em> parameter. * If this is set to "useFirstPass", the login identity will be taken from the * <code>javax.security.auth.login.name</code> value of the sharedState map, * and the proof of identity from the * <code>javax.security.auth.login.password</code> value of the sharedState map. * * @param subject the Subject to update after a successful login. * @param callbackHandler the CallbackHandler that will be used to obtain the * the user identity and credentials. * @param sharedState a Map shared between all configured login module instances * @param options the parameters passed to the login module. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { // ... } /** * Looks for javax.security.auth.login.name and * javax.security.auth.login.password values in the sharedState * map if the useFirstPass option was true and returns true if * they exist. If they do not or are null this method returns * false. * Note that subclasses that override the login method * must set the loginOk var to true if the login succeeds in * order for the commit phase to populate the Subject. This * implementation sets loginOk to true if the login() method * returns true, otherwise, it sets loginOk to false. */ public boolean login() throws LoginException { // ... } /** * Overridden by subclasses to return the Principal that * corresponds to the user primary identity. */ abstract protected Principal getIdentity(); /** * Overridden by subclasses to return the Groups that correspond * to the role sets assigned to the user. Subclasses should * create at least a Group named "Roles" that contains the roles * assigned to the user. A second common group is * "CallerPrincipal," which provides the application identity of * the user rather than the security domain identity. * * @return Group[] containing the sets of roles */ abstract protected Group[] getRoleSets() throws LoginException; }
The second abstract base login module suitable for custom login modules is the org.jboss.security.auth.spi.UsernamePasswordLoginModule
.
char[]
password as the authentication credentials. It also supports the mapping of anonymous users (indicated by a null user name and password) to a principal with no roles. The key details of the class are highlighted in the following class fragment. The JavaDoc comments detail the responsibilities of subclasses.
Example 12.16. UsernamePasswordLoginModule Class Fragment
package org.jboss.security.auth.spi; /** * An abstract subclass of AbstractServerLoginModule that imposes a * an identity == String username, credentials == String password * view on the login process. Subclasses override the * getUsersPassword() and getUsersRoles() methods to return the * expected password and roles for the user. */ public abstract class UsernamePasswordLoginModule extends AbstractServerLoginModule { /** The login identity */ private Principal identity; /** The proof of login identity */ private char[] credential; /** The principal to use when a null username and password are seen */ private Principal unauthenticatedIdentity; /** * The message digest algorithm used to hash passwords. If null then * plain passwords will be used. */ private String hashAlgorithm = null; /** * The name of the charset/encoding to use when converting the * password String to a byte array. Default is the platform's * default encoding. */ private String hashCharset = null; /** The string encoding format to use. Defaults to base64. */ private String hashEncoding = null; // ... /** * Override the superclass method to look for an * unauthenticatedIdentity property. This method first invokes * the super version. * * @param options, * @option unauthenticatedIdentity: the name of the principal to * assign and authenticate when a null username and password are * seen. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); // Check for unauthenticatedIdentity option. Object option = options.get("unauthenticatedIdentity"); String name = (String) option; if (name != null) { unauthenticatedIdentity = new SimplePrincipal(name); } } // ... /** * A hook that allows subclasses to change the validation of the * input password against the expected password. This version * checks that neither inputPassword or expectedPassword are null * and that inputPassword.equals(expectedPassword) is true; * * @return true if the inputPassword is valid, false otherwise. */ protected boolean validatePassword(String inputPassword, String expectedPassword) { if (inputPassword == null || expectedPassword == null) { return false; } return inputPassword.equals(expectedPassword); } /** * Get the expected password for the current username available * via the getUsername() method. This is called from within the * login() method after the CallbackHandler has returned the * username and candidate password. * * @return the valid password String */ abstract protected String getUsersPassword() throws LoginException; }
The choice of sub-classing the AbstractServerLoginModule
versus UsernamePasswordLoginModule
is based on whether a string-based user name and credentials are usable for the authentication technology you are writing the login module for. If the string-based semantic is valid, then subclass UsernamePasswordLoginModule
, otherwise subclass AbstractServerLoginModule
.
The steps your custom login module must execute depend on which base login module class you choose. When writing a custom login module that integrates with your security infrastructure, you should start by sub-classing AbstractServerLoginModule
or UsernamePasswordLoginModule
to ensure that your login module provides the authenticated Principal
information in the form expected by the JBossSX security manager.
AbstractServerLoginModule
, you must override the following:
void initialize(Subject, CallbackHandler, Map, Map)
: if you have custom options to parse.boolean login()
: to perform the authentication activity. Be sure to set theloginOk
instance variable to true if log in succeeds, false if it fails.Principal getIdentity()
: to return thePrincipal
object for the user authenticated by thelog()
step.Group[] getRoleSets()
: to return at least oneGroup
namedRoles
that contains the roles assigned to thePrincipal
authenticated duringlogin()
. A second commonGroup
is namedCallerPrincipal
and provides the user's application identity rather than the security domain identity.
UsernamePasswordLoginModule
, you must override the following:
void initialize(Subject, CallbackHandler, Map, Map)
: if you have custom options to parse.Group[] getRoleSets()
: to return at least oneGroup
namedRoles
that contains the roles assigned to thePrincipal
authenticated duringlogin()
. A second commonGroup
is namedCallerPrincipal
and provides the user's application identity rather than the security domain identity.String getUsersPassword()
: to return the expected password for the current user name available via thegetUsername()
method. ThegetUsersPassword()
method is called from withinlogin()
after thecallbackhandler
returns the user name and candidate password.
12.2.2. Custom LoginModule Example
UsernamePasswordLoginModule
and obtains a user's password and role names from a JNDI lookup.
password/<username>
(where <username>
is the current user being authenticated). Similarly, a lookup of the form roles/<username>
returns the requested user's roles.
JndiUserAndPass
custom login module.
UsernamePasswordLoginModule
, all JndiUserAndPass
does is obtain the user's password and roles from the JNDI store. The JndiUserAndPass
does not interact with the JAAS LoginModule
operations.
Example 12.17. JndiUserAndPass Custom Login Module
package org.jboss.book.security.ex2; import java.security.acl.Group; import java.util.Map; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.jboss.security.auth.spi.UsernamePasswordLoginModule; /** * An example custom login module that obtains passwords and roles * for a user from a JNDI lookup. * * @author Scott.Stark@jboss.org * @version $Revision: 1.4 $ */ public class JndiUserAndPass extends UsernamePasswordLoginModule { /** The JNDI name to the context that handles the password/username lookup */ private String userPathPrefix; /** The JNDI name to the context that handles the roles/ username lookup */ private String rolesPathPrefix; /** * Override to obtain the userPathPrefix and rolesPathPrefix options. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { super.initialize(subject, callbackHandler, sharedState, options); userPathPrefix = (String) options.get("userPathPrefix"); rolesPathPrefix = (String) options.get("rolesPathPrefix"); } /** * Get the roles the current user belongs to by querying the * rolesPathPrefix + '/' + super.getUsername() JNDI location. */ protected Group[] getRoleSets() throws LoginException { try { InitialContext ctx = new InitialContext(); String rolesPath = rolesPathPrefix + '/' + super.getUsername(); String[] roles = (String[]) ctx.lookup(rolesPath); Group[] groups = {new SimpleGroup("Roles")}; log.info("Getting roles for user="+super.getUsername()); for(int r = 0; r < roles.length; r ++) { SimplePrincipal role = new SimplePrincipal(roles[r]); log.info("Found role="+roles[r]); groups[0].addMember(role); } return groups; } catch(NamingException e) { log.error("Failed to obtain groups for user="+super.getUsername(), e); throw new LoginException(e.toString(true)); } } /** * Get the password of the current user by querying the * userPathPrefix + '/' + super.getUsername() JNDI location. */ protected String getUsersPassword() throws LoginException { try { InitialContext ctx = new InitialContext(); String userPath = userPathPrefix + '/' + super.getUsername(); log.info("Getting password for user="+super.getUsername()); String passwd = (String) ctx.lookup(userPath); log.info("Found password="+passwd); return passwd; } catch(NamingException e) { log.error("Failed to obtain password for user="+super.getUsername(), e); throw new LoginException(e.toString(true)); } } }
org.jboss.book.security.ex2.service.JndiStore
MBean. This service binds an ObjectFactory
that returns a javax.naming.Context
proxy into JNDI. The proxy handles lookup operations done against it by checking the prefix of the lookup name against password
and roles
.
password
, a user's password is being requested. When the name begins with roles
the user's roles are being requested. The example implementation always returns a password of theduke
and an array of roles names equal to {"TheDuke", "Echo"}
regardless of what the user name is. You can experiment with other implementations as you wish.
[examples]$ ant -Dchap=security -Dex=2 run-example ... run-example2: [echo] Waiting for 5 seconds for deploy... [java] [INFO,ExClient] Login with user name=jduke, password=theduke [java] [INFO,ExClient] Looking up EchoBean2 [java] [INFO,ExClient] Created Echo [java] [INFO,ExClient] Echo.echo('Hello') = Hello
JndiUserAndPass
custom login module for the server side authentication of the user is determined by the login configuration for the example security domain. The EJB JAR META-INF/jboss.xml
descriptor sets the security domain.
<?xml version="1.0"?> <jboss> <security-domain>security-ex2</security-domain> </jboss>
META-INF/login-config.xml
descriptor defines the login module configuration.
<application-policy name = "security-ex2"> <authentication> <login-module code="org.jboss.book.security.ex2.JndiUserAndPass" flag="required"> <module-option name="userPathPrefix">/security/store/password</module-option> <module-option name = "rolesPathPrefix">/security/store/roles</module-option> </login-module> </authentication> </application-policy>
Part III. Encryption and Security
Chapter 13. Secure Remote Password Protocol
This document describes a cryptographically strong network authentication mechanism known as the Secure Remote Password (SRP) protocol. This mechanism is suitable for negotiating secure connections using a user-supplied password, while eliminating the security problems traditionally associated with reusable passwords. This system also performs a secure key exchange in the process of authentication, allowing security layers (privacy and/or integrity protection) to be enabled during the session. Trusted key servers and certificate infrastructures are not required, and clients are not required to store or manage any long-term keys. SRP offers both security and deployment advantages over existing challenge-response techniques, making it an ideal drop-in replacement where secure password authentication is needed.
- An implementation of the SRP handshake protocol that is independent of any particular client/server protocol
- An RMI implementation of the handshake protocol as the default client/server SRP implementation
- A client side JAAS
LoginModule
implementation that uses the RMI implementation for use in authenticating clients in a secure fashion - A JMX MBean for managing the RMI server implementation. The MBean allows the RMI server implementation to be plugged into a JMX framework and externalizes the configuration of the verification information store. It also establishes an authentication cache that is bound into the server JNDI namespace.
- A server side JAAS
LoginModule
implementation that uses the authentication cache managed by the SRP JMX MBean.
Figure 13.1. The JBossSX components of the SRP client-server framework.
LoginModule
implementation that communicates with the authentication server through an org.jboss.security.srp.SRPServerInterface
proxy. A client enables authentication using SRP by creating a login configuration entry that includes the org.jboss.security.srp.jaas.SRPLoginModule
. This module supports the following configuration options:
- srpServerJndiName
- JNDI name of the
SRPServerInterface
object used to communicate with the SRP authentication server. If bothsrpServerJndiName
andsrpServerRmiUrl
options are specified,srpServerJndiName
takes priority oversrpServerRmiUrl
. - srpServerRmiUrl
- RMI protocol URL string for the location of the
SRPServerInterface
proxy used to communicate with the SRP authentication server. - externalRandomA
- Flag that specifies whether the random component of the client public key "A" should come from the user callback. This can be used to input a strong cryptographic random number coming from a hardware token. If set to
true
, the feature is activated. - hasAuxChallenge
- Flag that specifies whether a string will be sent to the server as an additional challenge for the server to validate. If the client session supports an encryption cipher then a temporary cipher will be created using the session private key and the challenge object sent as a
javax.crypto.SealedObject
. If set totrue
, the feature is activated. - multipleSessions
- Flag that specifies whether a given client may have multiple SRP log in sessions active. If set to
true
, the feature is activated.
InitialContext
constructor. This is useful if the SRP server interface is not available from the default InitialContext
.
SRPLoginModule
and the standard ClientLoginModule
must be configured to allow SRP authentication credentials to be used for access validation to security Java EE components. An example login configuration is described in Example 13.1, “Login Configuration Entry” .
Example 13.1. Login Configuration Entry
srp { org.jboss.security.srp.jaas.SRPLoginModule required srpServerJndiName="SRPServerInterface" ; org.jboss.security.ClientLoginModule required password-stacking="useFirstPass" ; };
org.jboss.security.srp.SRPService
MBean. The other MBean is org.jboss.security.srp.SRPVerifierStoreService
.
org.jboss.security.srp.SRPService
is responsible for exposing an RMI accessible version of the SRPServerInterface as well as updating the SRP authentication session cache.
- JndiName
- Specifies the name from which the SRPServerInterface proxy should be available. This is the location where the
SRPService
binds the serializable dynamic proxy to theSRPServerInterface
. The default value issrp/SRPServerInterface
. - VerifierSourceJndiName
- Specifies the name of the
SRPVerifierSource
implementation theSRPService
must use. The source JNDI name defaults tosrp/DefaultVerifierSource
. - AuthenticationCacheJndiName
- Specifies the name under which the
org.jboss.util.CachePolicy
authentication implementation used for caching authentication information is bound. The SRP session cache is made available for use through this binding. The authentication JNDI cache defaults tosrp/AuthenticationCache
. - ServerPort
- RMI port for the
SRPRemoteServerInterface
. The default value is 10099. - ClientSocketFactory
- Optional custom
java.rmi.server.RMIClientSocketFactory
implementation class name used during the export of theSRPServerInterface
. The default value isRMIClientSocketFactory
. - ServerSocketFactory
- Optional custom
java.rmi.server.RMIServerSocketFactory
implementation class name used during the export of theSRPServerInterface
. The default value isRMIServerSocketFactory
. - AuthenticationCacheTimeout
- Cache policy timeout (in seconds). The default value is 1800 (30 minutes).
- AuthenticationCacheResolution
- Specifies the timed cache policy resolution (in seconds). This controls the interval between checks for timeouts. The default value is 60 (1 minute).
- RequireAuxChallenge
- Set if the client must supply an auxiliary challenge as part of the verify phase. This gives control over whether the
SRPLoginModule
configuration used by the client must have theuseAuxChallenge
option enabled. - OverwriteSessions
- Specifies whether a successful user authentication for an existing session should overwrite the current session. This controls the behavior of the server SRP session cache when clients have not enabled the multiple session per user mode. If set to
false
, the second user authentication attempt will succeed, however the resulting SRP session will not overwrite the previous SRP session state. The default value isfalse
. - VerifierStoreJndiName
- Specifies the location of the SRP password information store implementation that must be provided and made available through JNDI.
org.jboss.security.srp.SRPVerifierStoreService
is an example MBean service that binds an implementation of the SRPVerifierStore
interface that uses a file of serialized objects as the persistent store. Although not realistic for a production environment, it does allow for testing of the SRP protocol and provides an example of the requirements for an SRPVerifierStore
service.
SRPVerifierStoreService
MBean attributes include the following:
- JndiName
- JNDI name from which the
SRPVerifierStore
implementation should be available. If not specified it defaults tosrp/DefaultVerifierSource
. - StoreFile
- Location of the user password verifier serialized object store file. This can be either a URL or a resource name to be found in the classpath. If not specified it defaults to
SRPVerifierStore.ser
.
SRPVerifierStoreService
MBean also supports addUser
and delUser
operations for addition and deletion of users. The signatures are:
public void addUser(String username, String password) throws IOException; public void delUser(String username) throws IOException;
13.1. Understanding the Algorithm
Note
- The client side
SRPLoginModule
retrieves from the naming service the SRPServerInterface instance for the remote authentication server. - The client side
SRPLoginModule
next requests the SRP parameters associated with the user name attempting the log in. There are a number of parameters involved in the SRP algorithm that must be chosen when the user password is first transformed into the verifier form used by the SRP algorithm. Rather than hard-coding the parameters (which could be done with minimal security risk), the JBossSX implementation allows a user to retrieve this information as part of the exchange protocol. ThegetSRPParameters(username)
call retrieves the SRP parameters for the given user name. - The client side
SRPLoginModule
begins an SRP session by creating anSRPClientSession
object using the login user name, clear-text password, and SRP parameters obtained from step 2. The client then creates a random number A that will be used to build the private SRP session key. The client then initializes the server side of the SRP session by invoking theSRPServerInterface.init
method and passes in the user name and client generated random numberA
. The server returns its own random numberB
. This step corresponds to the exchange of public keys. - The client side
SRPLoginModule
obtains the private SRP session key that has been generated as a result of the previous messages exchanges. This is saved as a private credential in the loginSubject
. The server challenge responseM2
from step 4 is verified by invoking theSRPClientSession.verify
method. If this succeeds, mutual authentication of the client to server, and server to client have been completed. The client sideSRPLoginModule
next creates a challengeM1
to the server by invokingSRPClientSession.response
method passing the server random numberB
as an argument. This challenge is sent to the server via theSRPServerInterface.verify
method and server's response is saved asM2
. This step corresponds to an exchange of challenges. At this point the server has verified that the user is who they say they are. - The client side
SRPLoginModule
saves the login user name andM1
challenge into theLoginModule
sharedState map. This is used as the Principal name and credentials by the standard JBossClientLoginModule
. TheM1
challenge is used in place of the password as proof of identity on any method invocations on Java EE components. TheM1
challenge is a cryptographically strong hash associated with the SRP session. Its interception via a third partly cannot be used to obtain the user's password. - At the end of this authentication protocol, the SRPServerSession has been placed into the SRPService authentication cache for subsequent use by the
SRPCacheLoginModule
.
- Where authentication is performed, the way in which JBoss detaches the method transport protocol from the component container could allow a user to snoop the SRP
M1
challenge and effectively use the challenge to make requests as the associated user name. Custom interceptors can be used to prevent the issue, by encrypting the challenge using the SRP session key. - The SRPService maintains a cache of SRP sessions that time out after a configurable period. Once they time out, any subsequent Java EE component access will fail because there is currently no mechanism for transparently renegotiating the SRP authentication credentials. You must either set the authentication cache timeout quite high, or handle re-authentication in your code on failure.
Note
The SRPService supports timeout durations up to 2,147,483,647 seconds, or approximately 68 years. - There can only be one SRP session for a given user name by default. The session is classed as stateful, because the negotiated SRP session produces a private session key that can be used for encryption and decryption between the client and server. JBoss supports multiple SRP sessions per user, however it is not possible to encrypt data with one session key, and decrypt it with another.
org.jboss.security.srp.jaas.SRPCacheLoginModule
. The SRPCacheLoginModule
has a single configuration option named cacheJndiName
that sets the JNDI location of the SRP authentication CachePolicy
instance. This must correspond to the AuthenticationCacheJndiName
attribute value of the SRPService
MBean.
SRPCacheLoginModule
authenticates user credentials by obtaining the client challenge from the SRPServerSession
object in the authentication cache and comparing this to the challenge passed as the user credentials. Figure 13.2, “SRPCacheLoginModule with SRP Session Cache” illustrates the operation of the SRPCacheLoginModule.login method implementation.
Figure 13.2. SRPCacheLoginModule with SRP Session Cache
13.2. Configure Secure Remote Password Information
SRPVerifierStore
interface that integrates with your existing security information stores. The SRPVerifierStore
interface is shown in Example 13.2, “The SRPVerifierStore interface”.
Note
SRPVerifierStore
interface is not recommended for a production security environment because it requires all password hash information to be available as a file of serialized objects.
Example 13.2. The SRPVerifierStore interface
package org.jboss.security.srp; import java.io.IOException; import java.io.Serializable; import java.security.KeyException; public interface SRPVerifierStore { public static class VerifierInfo implements Serializable { public String username; public byte[] salt; public byte[] g; public byte[] N; } public VerifierInfo getUserVerifier(String username) throws KeyException, IOException; public void setUserVerifier(String username, VerifierInfo info) throws IOException; public void verifyUserChallenge(String username, Object auxChallenge) throws SecurityException; }
SRPVerifierStore
implementation is to provide access to the SRPVerifierStore.VerifierInfo
object for a given user name. The getUserVerifier(String)
method is called by the SRPService
at that start of a user SRP session to obtain the parameters needed by the SRP algorithm. The elements of the VerifierInfo
objects are:
- username
- The user's name or id used to log in.
- verifier
- One-way hash of the password or PIN the user enters as proof of identity. The
org.jboss.security.Util
class has acalculateVerifier
method that performs that password hashing algorithm. The output password takes the formH(salt | H(username | ':' | password))
, whereH
is the SHA secure hash function as defined by RFC2945. The user name is converted from a string to abyte[]
using UTF-8 encoding. - salt
- Random number used to increase the difficulty of a brute force dictionary attack on the verifier password database in the event that the database is compromised. The value should be generated from a cryptographically strong random number algorithm when the user's existing clear-text password is hashed.
- g
- SRP algorithm primitive generator. This can be a well known fixed parameter rather than a per-user setting. The
org.jboss.security.srp.SRPConf
utility class provides several settings forg
, including a suitable default obtained viaSRPConf.getDefaultParams().g()
. - N
- SRP algorithm safe-prime modulus. This can be a well known fixed parameter rather than a per-user setting. The
org.jboss.security.srp.SRPConf
utility class provides several settings forN
including a good default which can obtained viaSRPConf.getDefaultParams().N()
.
Procedure 13.1. Integrate Existing Password Store
Create Hashed Password Information Store
If your passwords are already stored in an irreversible hashed form, then this can only be done on a per-user basis (for example, as part of an upgrade procedure).You can implementsetUserVerifier(String, VerifierInfo)
as anoOp
method, or a method that throws an exception stating that the store is read-only.Create SRPVerifierStore Interface
You must create a customSRPVerifierStore
interface implementation that understands how to obtain theVerifierInfo
from the store you created.TheverifyUserChallenge(String, Object)
can be used to integrate existing hardware token based schemes like SafeWord or Radius into the SRP algorithm. This interface method is called only when the clientSRPLoginModule
configuration specifies thehasAuxChallenge
option.Create JNDI MBean
You must create a MBean that exposes theSRPVerifierStore
interface available to JNDI, and exposes any configurable parameters required.The defaultorg.jboss.security.srp.SRPVerifierStoreService
will allow you to implement this, however you can also implement the MBean using a Java properties file implementation ofSRPVerifierStore
(refer to Section 13.3, “Secure Remote Password Example”).
13.3. Secure Remote Password Example
SecurityConfig
MBean. A custom implementation of the SRPVerifierStore
interface is also used in the example. The interface uses an in-memory store that is seeded from a Java properties file, rather than a serialized object store as used by the SRPVerifierStoreService
.
org.jboss.book.security.ex3.service.PropertiesVerifierStore
. The following shows the contents of the JAR that contains the example EJB and SRP services.
[examples]$ jar tf output/security/security-ex3.jar META-INF/MANIFEST.MF META-INF/ejb-jar.xml META-INF/jboss.xml org/jboss/book/security/ex3/Echo.class org/jboss/book/security/ex3/EchoBean.class org/jboss/book/security/ex3/EchoHome.class roles.properties users.properties security-ex3.sar
jboss-service.xml
descriptor of the security-ex3.sar
is described in Example 13.3, “The security-ex3.sar jboss-service.xml Descriptor”.
Example 13.3. The security-ex3.sar jboss-service.xml Descriptor
<server> <!-- The custom JAAS login configuration that installs a Configuration capable of dynamically updating the config settings --> <mbean code="org.jboss.book.security.service.SecurityConfig" name="jboss.docs.security:service=LoginConfig-EX3"> <attribute name="AuthConfig">META-INF/login-config.xml</attribute> <attribute name="SecurityConfigName">jboss.security:name=SecurityConfig</attribute> </mbean> <!-- The SRP service that provides the SRP RMI server and server side authentication cache --> <mbean code="org.jboss.security.srp.SRPService" name="jboss.docs.security:service=SRPService"> <attribute name="VerifierSourceJndiName">srp-test/security-ex3</attribute> <attribute name="JndiName">srp-test/SRPServerInterface</attribute> <attribute name="AuthenticationCacheJndiName">srp-test/AuthenticationCache</attribute> <attribute name="ServerPort">0</attribute> <depends>jboss.docs.security:service=PropertiesVerifierStore</depends> </mbean> <!-- The SRP store handler service that provides the user password verifier information --> <mbean code="org.jboss.security.ex3.service.PropertiesVerifierStore" name="jboss.docs.security:service=PropertiesVerifierStore"> <attribute name="JndiName">srp-test/security-ex3</attribute> </mbean> </server>
ServiceConfig
and the PropertiesVerifierStore
and SRPService
MBeans. Note that the JndiName
attribute of the PropertiesVerifierStore
is equal to the VerifierSourceJndiName
attribute of the SRPService
, and that the SRPService
depends on the PropertiesVerifierStore
. This is required because the SRPService
needs an implementation of the SRPVerifierStore
interface for accessing user password verification information.
Example 13.4. The client side standard JAAS configuration
srp { org.jboss.security.srp.jaas.SRPLoginModule required srpServerJndiName="srp-test/SRPServerInterface" ; org.jboss.security.ClientLoginModule required password-stacking="useFirstPass" ; };
SRPLoginModule
with a srpServerJndiName
option value that corresponds to the server component SRPService
JndiName attribute value(srp-test/SRPServerInterface
). The ClientLoginModule
must also be configured with the password-stacking="useFirstPass"
value to propagate the user authentication credentials generated by the SRPLoginModule
to the EJB invocation layer.
Example 13.5. The server side XMLLoginConfig configuration
<application-policy name="security-ex3"> <authentication> <login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule" flag = "required"> <module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag = "required"> <module-option name="password-stacking">useFirstPass</module-option> </login-module> </authentication> </application-policy>
- The
cacheJndiName=srp-test/AuthenticationCache
configuration option tells theSRPCacheLoginModule
the location of theCachePolicy
that contains theSRPServerSession
for users who have authenticated against theSRPService
. This value corresponds to theSRPService
AuthenticationCacheJndiName
attribute value. - The configuration includes a
UsersRolesLoginModule
with thepassword-stacking=useFirstPass
configuration option. You must use a second login module with theSRPCacheLoginModule
because SRP is only an authentication technology. To set the principal's roles that in turn determine the associated permissions, a second login module must be configured to accept the authentication credentials validated by theSRPCacheLoginModule
.
UsersRolesLoginModule
is augmenting the SRP authentication with properties file based authorization. The user's roles are obtained from the roles.properties
file included in the EJB JAR.
[examples]$ ant -Dchap=security -Dex=3 run-example ... run-example3: [echo] Waiting for 5 seconds for deploy... [java] Logging in using the 'srp' configuration [java] Created Echo [java] Echo.echo()#1 = This is call 1 [java] Echo.echo()#2 = This is call 2
examples/logs
directory, the ex3-trace.log
file contains a detailed trace of the client side of the SRP algorithm. The traces show step-by-step the construction of the public keys, challenges, session key and verification.
Echo.echo()#2
fails with an authentication exception. The client code sleeps for 15 seconds after making the first call to demonstrate the behavior of the SRPService
cache expiration. The SRPService
cache policy timeout has been set to 10 seconds to force this issue. As discussed in Section 13.3, “Secure Remote Password Example” you must set the cache timeout correctly, or handle re-authentication on failure.
Chapter 14. Java Security Manager
- Java Security Manager
- The Java Security Manager is a class that manages the external boundary of the Java Virtual Machine (JVM) sandbox, controlling how code executing within the JVM can interact with resources outside the JVM. When the Java Security Manager is activated the Java API checks with the security manager for approval before executing a wide range of potentially unsafe operations.
- Security Policy
- A set of defined permissions for different classes of code. The Java Security Manager compares actions requested by applications against the security policy. If an action is allowed by the policy, the Security Manager will permit that action to take place. If the action is not allowed by the policy, the Security Manager will deny that action. The security policy can define permissions based on the location of code or on the code's signature.
java.security.manager
and java.security.policy
.
Security Manager-related options
- java.security.manager
- Use a security manager, optionally specifying which security manager to use. If no argument is supplied with this option the default JDK security manager,
java.lang.SecurityManager
, is used. To use another security manager implementation, supply the fully qualified classname of a subclass ofjava.lang.SecurityManager
with this option. - java.security.policy
- Specifies a policy file to augment or replace the default security policy for the VM. This option takes two forms:
java.security.policy=policyFileURL
- The policy file referenced by policyFileURL will augment the default security policy configured by the VM.
java.security.policy==policyFileURL
- The policy file referenced by policyFileURL will replace the default security policy configured by the VM.
The policyFileURL value can be a URL or a file path.
14.1. Using the Security Manager
jboss-as/bin/server.policy.cert
is included as a starting point.
The file run.conf
(Linux) or run.conf.bat
(Windows) is used to configure the Security Manager and security policy. This file is found in the jboss-as/bin
directory.
run.conf
or run.conf.bat
file from jboss-as/bin/
to the server profile (for example: jboss-as/server/production/run.conf
), and make the configuration changes there. A configuration file in the server profile takes precedence over the global run.conf
/ run.conf.bat
file when the server profile is started.
Procedure 14.1. Activate the Security Manager
run.conf
(Linux), or run.conf.bat
(Windows) in the server profile directory, if one exists there, or in jboss-as/bin
. Refer to Configuration File for details on the location of this file.
Specify the JBoss home directory
Edit the filerun.conf
(Linux), orrun.conf.bat
(Windows). Add thejboss.home.dir
option, specifying the path to thejboss-as
directory of your installation.LinuxJAVA_OPTS="$JAVA_OPTS -Djboss.home.dir=/path/to/jboss-eap-5.1/jboss-as"
WindowsJAVA_OPTS="%JAVA_OPTS% -Djboss.home.dir=c:\path\jboss-eap-5.1\jboss-as"
Specify the server home directory
Add thejboss.server.home.dir
option, specifying the path to your server profile.LinuxJAVA_OPTS="$JAVA_OPTS -Djboss.server.home.dir=path/to/jboss-eap-5.1/jboss-as/server/production"
WindowsJAVA_OPTS="%JAVA_OPTS% -Djboss.server.home.dir=c:\path\to\jboss-eap-5.1\jboss-as\server\production"
Specify the Protocol Handler
Add thejava.protocol.handler.pkgs
option, specifying the JBoss stub handler.LinuxJAVA_OPTS="$JAVA_OPTS -Djava.protocol.handler.pkgs=org.jboss.handlers.stub"
WindowsJAVA_OPTS="%JAVA_OPTS% -Djava.protocol.handler.pkgs=org.jboss.handlers.stub"
Specify the security policy to use
Add the$POLICY
variable, specifying the security policy to use. Add the variable definition before the line that activates the Security Manager.Example 14.1. Use the Platform's included security policy
POLICY="server.policy.cert"
Activate the Security Manager
Uncomment the following line by removing the initial#
:Linux#JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy=$POLICY"
Windows#JAVA_OPTS="%JAVA_OPTS% -Djava.security.manager -Djava.security.policy=%POLICY%"
Result:JBoss Enterprise Application Platform is now configured to start with the Security Manager activated.
Optional: Import Red Hat's JBoss signing key
The included security policy grants permissions to JBoss-signed code. If you use the included policy you must import the JBoss signing key to the JDKcacerts
key store.The following command assumes that the environment variableJAVA_HOME
is set to the location of a JDK supported by JBoss Enterprise Application Platform 5. You configureJAVA_HOME
when you first install JBoss Enterprise Application Platform 5. Refer to the Installation Guide for further information.Note
To ensure the correct JVM is selected, you can use thealternatives
command to select from JDKs installed on your Linux system. Refer to Appendix A, Setting the default JDK with the/usr/sbin/alternatives
Utility.Execute the following command in a terminal, replacing JAVA_HOME with the directory location of your Java installation:Linux[~]$ sudo JAVA_HOME/bin/keytool -import -alias jboss -file JBossPublicKey.RSA \ -keystore JAVA_HOME/jre/lib/security/cacerts
WindowsC:> JAVA_HOME\bin\keytool -import -alias jboss -file JBossPublicKey.RSA -keystore JAVA_HOME\jre\lib\security\cacerts
Although broken across two lines in this documentation, the commands above should be entered on one single line in a terminal.Note
The default password for the cacerts key store ischangeit
.Result:The key used to the sign the JBoss Enterprise Application Platform code is now installed.
14.2. Debugging Security Policy Issues
java.security.debug
option configures the level of security-related information reported.
java -Djava.security.debug=help
will produce help output with the full range of debugging options. Setting the debug level to all
is useful when troubleshooting a security-related failure whose cause is completely unknown, but for general use it will produce too much information. A sensible general default is access:failure
.
Procedure 14.2. Enable general debugging
- Add the following line to the file
run.conf
(Linux), orrun.conf.bat
(Windows):LinuxJAVA_OPTS="$JAVA_OPTS -Djava.security.debug=access:failure"
WindowsJAVA_OPTS="%JAVA_OPTS% -Djava.security.debug=access:failure"
14.2.1. Debugging Security Manager
Note
org.jboss.system.security.DebuggingJavaSecurityManager
prints out the protection domain corresponding to a failing permission. This additional information is very useful information when debugging permissions problems.
Procedure 14.3. Enable the Debugging Security Manager
- Add the following option to
$JBOSS_HOME/bin/run.conf
(Linux) or$JBOSS_HOME/bin/run.conf.bat
. See Configuration File for the location of this file.LinuxJAVA_OPTS="$JAVA_OPTS -Djava.security.manager=org.jboss.system.security.DebuggingJavaSecurityManager"
WindowsJAVA_OPTS="%JAVA_OPTS% -Djava.security.manager=org.jboss.system.security.DebuggingJavaSecurityManager"
- Comment out all other
java.security.manager
references in the file. - Ensure that the file still contains a
java.security.policy
option specifying the policy file to use - Enable general debugging following the instruction in Procedure 14.2, “Enable general debugging”.
Note
14.3. Writing Security Policy for JBoss Enterprise Application Platform
jboss-as/bin/server.policy.cert
is an example security policy for JBoss Enterprise Application Platform. You can use this file as the basis for your own security policy.
policytool
application, included with the JDK, provides a graphical tool for editing and writing security policy.
Important
java.security.AllPermission
: you can potentially allow changes to the system binary, including the JVM runtime environment.
java.lang.RuntimePermissions
are described below.
JBoss-specific Runtime Permissions
org.jboss.security.SecurityAssociation.getPrincipalInfo
- Provides access to the
org.jboss.security.SecurityAssociation getPrincipal()
andgetCredential()
methods. The risk involved with using this runtime permission is the ability to see the current thread caller and credentials. org.jboss.security.SecurityAssociation.getSubject
- Provides access to the
org.jboss.security.SecurityAssociation getSubject()
method. org.jboss.security.SecurityAssociation.setPrincipalInfo
- Provides access to the
org.jboss.security.SecurityAssociation setPrincipal()
,setCredential()
,setSubject()
,pushSubjectContext()
, andpopSubjectContext()
methods. The risk involved with using this runtime permission is the ability to set the current thread caller and credentials. org.jboss.security.SecurityAssociation.setServer
- Provides access to the
org.jboss.security.SecurityAssociation setServer
method. The risk involved with using this runtime permission is the ability to enable or disable multi-thread storage of the caller principal and credential. org.jboss.security.SecurityAssociation.setRunAsRole
- Provides access to the
org.jboss.security.SecurityAssociation pushRunAsRole
andpopRunAsRole
,pushRunAsIdentity
andpopRunAsIdentity
methods. The risk involved with using this runtime permission is the ability to change the current caller run-as role principal. org.jboss.security.SecurityAssociation.accessContextInfo
- Provides access to the
org.jboss.security.SecurityAssociation accessContextInfo, "Get"
andaccessContextInfo, "Set"
methods, allowing you to both set and get the current security context info. org.jboss.naming.JndiPermission
- Provides special permissions to files and directories in a specified JNDI tree path, or recursively to all files and subdirectories. A JndiPermission consists of a pathname and a set of valid permissions related to the file or directory.The available permissions include:
bind
,rebind
,unbind
,lookup
,list
,listBindings
,createSubcontext
, andall
.Pathnames ending in/*
indicate the specified permissions apply to all files and directories of the pathname. Pathnames ending in/-
indicate recursive permissions to all files and subdirectories of the pathname. Pathnames consisting of the special token<<ALL BINDINGS>>
matches any file in any directory. org.jboss.security.srp.SRPPermission
- A custom permission class for protecting access to sensitive SRP information like the private session key and private key. This permission does not have any actions defined. The getSessionKey target provides access to the private session key resulting from the SRP negotiation. Access to this key will allow you to encrypt and decrypt messages that have been encrypted with the session key.
org.hibernate.secure.HibernatePermission
- This permission class provides basic permissions to secure Hibernate sessions. The target for this property is the entity name. The available actions include: insert , delete , update , read , * (all).
org.jboss.metadata.spi.stack.MetaDataStackPermission
- Provides a custom permission class for controlling how callers interact with the metadata stack. The available permissions are:
modify
(push/pop onto the stack),peek
(peek onto the stack), and*
(all). org.jboss.config.spi.ConfigurationPermission
- Secures setting of configuration properties. Defines only permission target names, and no actions. The targets for this property include: <property name> - property which code has permission to set; * - all properties.
org.jboss.kernel.KernelPermission
- Secures access to the kernel configuration. Defines only permission target names and no actions. The targets for this property include: access - access the kernel configuration; configure - configure the kernel (access is implied); * - all of the above.
org.jboss.kernel.plugins.util.KernelLocatorPermission
- Secures access to the kernel. Defines only permission target names and no actions. The targets for this property include: kernel - access the kernel; * - access all areas.
Chapter 15. Securing the EJB RMI transport layer
This chapter describes configuration of two different arrangements for Remote Method Invocation of EJB3s over an encrypted transport: RMI + SSL and RMI via HTTPS. HTTPS is an option as the transport for RMI when firewall configuration prevents use of the RMI ports.
15.1. SSL Encryption overview
15.1.1. Key pairs and Certificates
Public Key Infrastructure relies on a chain of trust to establish the credentials of unknown machines. The use of public keys not only encrypts traffic between machines, but also functions to establish the identity of the machine at the other end of a network connection. A "Web of Trust" is used to verify the identity of servers. A server may be unknown to you, but if its public key is signed by someone that you trust, you extend that trust to the server. Certificate Authorities are commercial entities who verify the identity of customers and issue them signed certificates. The JDK includes a cacerts
file with the certificates of several trusted Certificate Authorities (CAs). Any keys signed by these CAs are automatically trusted. Large organizations may have their own internal Certificate Authority, for example using Red Hat Certificate System. In this case the signing certificate of the internal Certificate Authority is typically installed on clients as part of a Corporate Standard Build, and then all certificates signed with that certificate are trusted. CA-signed certificates are best practice for production scenarios.
cacerts
file of clients, you need to export a certificate for that key on the server, and import that certificate on any client that connects via SSL.
keytool
, a command line tool for generating key pairs and certificates. The certificates generated by keytool
can be sent for signing by a CA or can be distributed to clients as a self-signed certificate.
- Generating a self-signed certificate for development use and importing that certificate to a client is described in Section 15.2.1, “Generate a self-signed certificate with keytool” .
- Generating a certificate and having it signed by a CA for production use is beyond the scope of this edition. Refer to the man page for keytool for further information on performing this task.
15.2. Generate encryption keys and certificate
15.2.1. Generate a self-signed certificate with keytool
15.2.1.1. Generate a key pair
localhost.keystore
. You will need to make this key store available to the EJB3 invoker on the server. The key pair in our example will be saved in the key store under the alias 'ejb-ssl'. We will need this key alias, and the key pair password you supply (if any), when configuring the EJB3 Remoting connector in Create a secure remoting connector for RMI .
Procedure 15.1. Generate a new key pair and add it to the key store "localhost.keystore" in the conf
directory.
- The following command will create a key pair for use with SSL encryption:
keytool -genkey -alias ejb-ssl -keystore localhost.keystore -storepass KEYSTORE_PASSWORD -keypass EJB-SSL_KEYPAIR_PASSWORD -dname "CN=SERVER_NAME,OU=QE,O=example.com,L=Brno,C=CZ"
Result:A key pair will be added to the key store
localhost.keystore
under the aliasejb-ssl
.The parameters for this command are explained inkeytool
parameters
keytool
parameters
- alias
- An alphanumeric token used to identify the key pair within the key store. A key store can contain multiple keys. The alias provides a means to uniquely identify a key pair within a key store. The alias for a key pair must by unique within a key store.
- keystore
- The key store that will be used to store the key pair. This can be a relative or absolute file path.
- storepass
- The password for key store. If the key store already exists, this must be the existing password for the key store. If the key store specified does not already exist, it will be created and this password will be the new password. This password is needed to access the key store to retrieve or store keys and certificates.
- keypass
- The password for the new key pair. This password must be supplied to use the key pair in the future.
- dname
- The identifying details of the certificate.
- CN
- Common Name: the name of the server. This must match the server name as returned to clients in a JNDI lookup. If a client attempts to make an SSL connection to the server using one name from JNDI, and receives a certificate with a different name, the connection will fail.
- OU
- Organizational Unit: the name of the organizational unit that is responsible for the server.
- O
- Organization: The name of the organization, sometimes expressed as a URL.
- L
- Location: the location of the server.
- C
- Country: two letter country code
Note
keytool
adds the key pair to a new key store called keystore
in the current user's home directory. This key store file is a hidden file.
15.2.1.2. Export a self-signed certificate
ejb-ssl
key from the key store named localhost.keystore
.
Procedure 15.2. Export a certificate
- Issue the following command:
keytool -export -alias ejb-ssl -file mycert.cer -keystore localhost.keystore
- Enter the key store passwordResult:
A certificate is exported to the file
mycert.cer
.
15.2.2. Configure a client to accept a self-signed server certificate
Procedure 15.3. Import the certificate to the trust store "localhost.truststore"
- Issue the following command on the client:
keytool -import -alias ejb-ssl -file mycert.cer -keystore localhost.truststore
- Enter the password for this trust store if it already exists; otherwise enter and re-enter the password for a new trust store.
- Verify the details of the certificate. If it is the correct one, type 'yes' to import it to the trust store.Result:
The certificate is imported to the trust store, and a secure connection can now be established with a server that uses this certificate.
Now that you have imported the self-signed server certificate to a trust store on the client, you must instruct the client to use this trust store. Do this by passing the localhost.truststore
location to the application using the javax.net.ssl.trustStore
property, and the trust store password using the javax.net.ssl.trustStorePassword
property. Example 15.1, “Invoking the com.acme.Runclient application with a specific trust store” is an example command that invokes the application com.acme.RunClient , a hypothetical application that makes remote method calls to an EJB on a JBoss Application Server. This command is run from the root of the application's package directory (the directory containing com
directory in the file path com/acme/RunClient.class
).
Example 15.1. Invoking the com.acme.Runclient application with a specific trust store
java -cp $JBOSS_HOME/client/jbossall-client.jar:. -Djavax.net.ssl.trustStore=${resources}/localhost.truststore \ -Djavax.net.ssl.trustStorePassword=TRUSTSTORE_PASSWORD com.acme.RunClient
15.3. EJB3 RMI + SSL Configuration
Procedure 15.4. Configure RMI + SSL for EJB3 Overview
- Generate encryption keys and certificate
- Configure a secure remote connector for RMI
- Annotate EJB3 beans to use the secure RMI connector
The file ejb3-connectors-jboss-beans.xml
in a JBoss Application Server profile deploy
directory contains JBoss Remoting connector definitions for EJB3 remote method invocation.
Example 15.2. Sample Secure EJB3 Connector
ejb3-connectors-jboss-beans.xml
file. Both beans are required to configure a secure connector for EJB3 using the key pair created in Procedure 15.1, “Generate a new key pair and add it to the key store "localhost.keystore" in the conf
directory.”.
keyPassword
property in the sample configuration is the key pair password specified when the key pair was created.
<bean name="EJB3SSLRemotingConnector" class="org.jboss.remoting.transport.Connector"> <property name="invokerLocator">sslsocket://${jboss.bind.address}:3843</property> <property name="serverConfiguration"> <inject bean="ServerConfiguration" /> </property> <property name="serverSocketFactory"> <inject bean="sslServerSocketFactory" /> </property> </bean> <bean name="sslServerSocketFactory" class="org.jboss.security.ssl.DomainServerSocketFactory"> <constructor> <parameter><inject bean="EJB3SSLDomain"/></parameter> </constructor> </bean> <bean name="EJB3SSLDomain" class="org.jboss.security.plugins.JaasSecurityDomain"> <constructor> <parameter>EJB3SSLDomain</parameter> </constructor> <property name="keyStoreURL">resource:localhost.keystore</property> <property name="keyStorePass">KEYSTORE_PASSWORD</property> </bean>
Note
localhost.keystore
) may contain multiple key pairs. The EJB connector will use the key pair with the defined keyAlias (ejb-ssl
).
All EJB3 beans use the unsecured RMI connector by default. To enable remote invocation of a bean via SSL, annotate the bean with @org.jboss.annotation.ejb.RemoteBinding
.
Example 15.3. EJB3 bean annotation to enable secure remote invocation
StatefulSSL
. The proxy implementing the remote interface, returned to a client when the bean is requested from JNDI, communicates with the server via SSL.
@RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL") @Remote(BusinessInterface.class) public class StatefulBean implements BusinessInterface { ... }
Note
You can enable both secure and insecure remote method invocation of the same EJB3 bean. Example 15.4, “EJB3 Bean annotation for secure and unsecured invocation” demonstrates the annotations to do this.
Example 15.4. EJB3 Bean annotation for secure and unsecured invocation
@RemoteBindings({ @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843", jndiBinding="StatefulSSL") @RemoteBinding(jndiBinding="StatefulNormal") }) @Remote(BusinessInterface.class) public class StatefulBean implements BusinessInterface { ... }
Note
0.0.0.0
, meaning "all interfaces". Change this to the value of the ${jboss.bind.address} system property.
StatefulNormal
from JNDI, the returned proxy implementing the remote interface communicates with the server via the unencrypted socket protocol; and if StatefulSSL
is requested, the returned proxy implementing the remote interface communicates with the server via SSL.
15.4. EJB3 RMI via HTTPS Configuration
Procedure 15.5. Configure EJB3 RMI via HTTPS Overview
- Generate encryption keys and certificates.
- Configure RMI via HTTPS web connector.
- Configure Servlets.
- Configure secure remoting connector for RMI via HTTPS.
- Configure EJB3 beans for HTTPS transport.
- Configure clients for RMI via HTTPS.
Procedure 15.6. Configure RMI via HTTPS web connector
- Edit the file
jboss-as/server/$PROFILE/deploy/jbossweb.sar/server.xml
and uncomment the HTTPS connector.<!-- SSL/TLS Connector configuration using the admin devl guide keystore --> <Connector protocol="HTTP/1.1" SSLEnabled="true" port="8443" address="${jboss.bind.address}" scheme="https" secure="true" clientAuth="false" keystoreFile="${jboss.server.home.dir}/conf/localhost.keystore" keystorePass="KEYSTORE_PASSWORD" sslProtocol = "TLS" />
You create a web connector to accept SSL connections.
Procedure 15.7. Configure Servlets
ServletServerInvoker
.
- Create a directory named
servlet-invoker.war
injboss-as/server/$PROFILE/deploy/
. - Create a
WEB-INF
directory in theservlet-invoker.war
directory. - Create a file named
web.xml
in thatWEB-INF
directory, with the following content:<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>ServerInvokerServlet</servlet-name> <description>The ServerInvokerServlet receives requests via HTTP protocol from within a web container and passes it onto the ServletServerInvoker for processing. </description> <servlet-class>org.jboss.remoting.transport.servlet.web.ServerInvokerServlet</servlet-class> <init-param> <param-name>locatorUrl</param-name> <param-value>servlet://${jboss.bind.address}:8080/servlet-invoker/ServerInvokerServlet</param-value> <description>The servlet server invoker</description> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>SSLServerInvokerServlet</servlet-name> <description>The ServerInvokerServlet receives requests via HTTPS protocol from within a web container and passes it onto the ServletServerInvoker for processing. </description> <servlet-class>org.jboss.remoting.transport.servlet.web.ServerInvokerServlet</servlet-class> <init-param> <param-name>locatorUrl</param-name> <param-value>sslservlet://${jboss.bind.address}:8443/servlet-invoker/SSLServerInvokerServlet</param-value> <description>The servlet server invoker</description> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ServerInvokerServlet</servlet-name> <url-pattern>/ServerInvokerServlet/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>SSLServerInvokerServlet</servlet-name> <url-pattern>/SSLServerInvokerServlet/*</url-pattern> </servlet-mapping> </web-app>
Result:You create a servlet to forward SSL requests from the web container to a server invoker.
locatorUrl
is used to connect the servlet to the remoting connector through the " InvokerLocator
attribute of the remoting connector we define in Procedure 15.8, “Configure secure remoting connector for RMI via HTTPS” .
Procedure 15.8. Configure secure remoting connector for RMI via HTTPS
- Create a file named
servlet-invoker-service.xml
injboss-as/server/$PROFILE/deploy/
, with the following content:<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="org.jboss.remoting.transport.Connector" name="jboss.remoting:service=connector,transport=servlet" display-name="Servlet transport Connector"> <attribute name="InvokerLocator">servlet://${jboss.bind.address}:8080/servlet-invoker/ServerInvokerServlet</attribute> <attribute name="Configuration"> <handlers> <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler> </handlers> </attribute> </mbean> <mbean code="org.jboss.remoting.transport.Connector" name="jboss.remoting:service=connector,transport=sslservlet" display-name="Servlet transport Connector"> <attribute name="InvokerLocator">sslservlet://${jboss.bind.address}:8443/servlet-invoker/SSLServerInvokerServlet</attribute> <attribute name="Configuration"> <handlers> <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler> </handlers> </attribute> </mbean> </server>
You create a remoting connector that can receive requests from a servlet, and invoke methods of an EJB3.
Procedure 15.9. Configure EJB3 beans for HTTPS transport
- Annotate the bean for RMI via HTTPS:
Example 15.5. Annotating an EJB3 for RMI via HTTPS
// RMI tunneled over HTTPS @Stateless @RemoteBinding(clientBindUrl = "https://0.0.0.0:8443/servlet-invoker/SSLServerInvokerServlet") @Remote(Calculator.class) @SecurityDomain("other") public class CalculatorHttpsBean implements Calculator { ....
Result:The EJB3 is now available for remote invocation via HTTPS.
Optionally, you can annotate the bean for invocation via RMI via HTTP. This can be useful for testing, as it allows you to tunnel RMI calls through firewalls that block RMI ports, but removes the extra layer of the security configuration.
Example 15.6. Annotating a bean for RMI via HTTP
// RMI tunneled over HTTP @Stateless @RemoteBinding(clientBindUrl = "http://0.0.0.0:8080/servlet-invoker/ServerInvokerServlet") @Remote(Calculator.class) @SecurityDomain("other") public class CalculatorHttpBean extends CalculatorImpl { ....
The EJB client should use the following properties for the JNDI lookup when looking up beans:
Client access to RMI via HTTP(S)
- HTTPS
Properties props = new Properties(); props.put("java.naming.factory.initial", "org.jboss.naming.HttpNamingContextFactory"); props.put("java.naming.provider.url", "https://localhost:8443/invoker/JNDIFactory"); props.put("java.naming.factory.url.pkgs", "org.jboss.naming"); Context ctx = new InitialContext(props); props.put(Context.SECURITY_PRINCIPAL, username); props.put(Context.SECURITY_CREDENTIALS, password); Calculator calculator = (Calculator) ctx.lookup(jndiName); // use the bean to do any operations
- HTTP
Properties props = new Properties(); props.put("java.naming.factory.initial", "org.jboss.naming.HttpNamingContextFactory"); props.put("java.naming.provider.url", "http://localhost:8080/invoker/JNDIFactory"); props.put("java.naming.factory.url.pkgs", "org.jboss.naming"); Context ctx = new InitialContext(props); props.put(Context.SECURITY_PRINCIPAL, username); props.put(Context.SECURITY_CREDENTIALS, password); Calculator calculator = (Calculator) ctx.lookup(jndiName); // use the bean to do any operations
jboss-as/$PROFILE/deploy/http-invoker.sar/invoker.war/WEB-INF/jboss-web.xml
.
15.5. EJB2 RMI + SSL Configuration
Procedure 15.10. Configure SSL for EJB2 Overview
- Generate encryption keys and certificate
- Configure Unified Invoker for SSL
EJB2 remote invocation uses a single unified invoker, which runs by default on port 4446. The configuration of the unified invoker used for EJB2 remote method invocation is defined in the $JBOSS_HOME/server/deploy/remoting-jboss-beans.xml
file of a JBoss Application Server profile. Add the following SSL Socket Factory bean and an SSL Domain bean in this file.
Example 15.7. SSL Server Factory for EJB2
<bean name="sslServerSocketFactoryEJB2" class="org.jboss.security.ssl.DomainServerSocketFactory"> <constructor> <parameter><inject bean="EJB2SSLDomain"/></parameter> </constructor> </bean> <bean name="EJB2SSLDomain" class="org.jboss.security.plugins.JaasSecurityDomain"> <constructor> <parameter>EJB2SSLDomain</parameter> </constructor> <property name="keyStoreURL">resource:localhost.keystore</property> <property name="keyStorePass">changeit</property> <property name="keyAlias">ejb-ssl</property> <property name="keyPassword">EJB-SSL_KEYPAIR_PASSWORD</property> </bean>
$JBOSS_HOME/server/$PROFILE/conf/jboss-service.xml
file of a JBoss Application Server profile:
Example 15.8. SSLSocketBuilder configuration
<!-- This section is for custom (SSL) server socket factory --> <mbean code="org.jboss.remoting.security.SSLSocketBuilder" name="jboss.remoting:service=SocketBuilder,type=SSL" display-name="SSL Server Socket Factory Builder"> <!-- IMPORTANT - If making ANY customizations, this MUST be set to false. --> <!-- Otherwise, will used default settings and the following attributes will be ignored. --> <attribute name="UseSSLServerSocketFactory">false</attribute> <!-- This is the url string to the key store to use --> <attribute name="KeyStoreURL">localhost.keystore</attribute> <!-- The password for the key store --> <attribute name="KeyStorePassword">sslsocket</attribute> <!-- The password for the keys (will use KeystorePassword if this is not set explicitly. --> <attribute name="KeyPassword">sslsocket</attribute> <!-- The protocol for the SSLContext. Default is TLS. --> <attribute name="SecureSocketProtocol">TLS</attribute> <!-- The algorithm for the key manager factory. Default is SunX509. --> <attribute name="KeyManagementAlgorithm">SunX509</attribute> <!-- The type to be used for the key store. --> <!-- Defaults to JKS. Some acceptable values are JKS (Java Keystore - Sun's keystore format), --> <!-- JCEKS (Java Cryptography Extension keystore - More secure version of JKS), and --> <!-- PKCS12 (Public-Key Cryptography Standards #12 keystore - RSA's Personal Information Exchange Syntax Standard). --> <!-- These are not case sensitive. --> <attribute name="KeyStoreType">JKS</attribute> </mbean> <mbean code="org.jboss.remoting.security.SSLServerSocketFactoryService" name="jboss.remoting:service=ServerSocketFactory,type=SSL" display-name="SSL Server Socket Factory"> <depends optional-attribute-name="SSLSocketBuilder" proxy-type="attribute">jboss.remoting:service=SocketBuilder,type=SSL</depends> </mbean>
In the deploy/remoting-jboss-beans.xml
file in the JBoss Application Server profile, update the code to reflect the information below:
Example 15.9. SSL Transport for Beans
... <bean name="UnifiedInvokerConnector" class="org.jboss.remoting.transport.Connector"> <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.remoting:service=Connector,transport=socket", exposedInterface=org.jboss.remoting.transport.ConnectorMBean.class,registerDirectly=true) </annotation> <property name="serverConfiguration"><inject bean="UnifiedInvokerConfiguration"/></property> <property name="serverSocketFactory"><inject bean="sslServerSocketFactoryEJB2"/></property> <!-- add this to configure the SSL socket for the UnifiedInvoker --> </bean> ... <bean name="UnifiedInvokerConfiguration" class="org.jboss.remoting.ServerConfiguration"> <constructor> <!-- transport: Others include sslsocket, bisocket, sslbisocket, http, https, rmi, sslrmi, servlet, sslservlet. --> <parameter>sslsocket</parameter><!-- changed from socket to sslsocket --> </constructor> ... </bean> ...
Chapter 16. Masking Passwords in XML Configuration
16.1. Password Masking Overview
Note
Procedure 16.1. Masking a clear text password overview
- Generate a key pair to use to encrypt passwords.
- Encrypt the key store password.
- Create password masks.
- Replace clear text passwords with their password masks.
16.2. Generate a key store and a masked password
jboss
in a key store at jboss-as/bin/password/password.keystore
.
Procedure 16.2. Generate a key pair and key store for password masking
- At the command line, change directory to the
jboss-as/bin/password
directory. - Use
keytool
to generate the key pair with the following command:keytool -genkey -alias jboss -keyalg RSA -keysize 1024 -keystore password.keystore
Important:You must specify the same password for the key store and key pair
- Optional:
Make the resulting password.keystore readable by the JBoss Application Server process owner only.
On Unix-based systems this is accomplished by using thechown
command to change ownership to the JBoss Application Server process owner, andchmod 600 password.keystore
to make the file readable only by the owner.This step is recommended to increase the security of your server.Note: the JBoss Application Server process owner should not have interactive console log in access. In that case you will be performing these operations as another user. Creating masked passwords requires read access to the key store, so you may wish to complete configuration of masked passwords before restricting the key store file permissions.
keytool
command, refer to Section 15.1, “SSL Encryption overview”.
16.3. Encrypt the key store password
password_tool
. This tool will encrypt and store your key store password. Your key store password will then be available to the JBoss Password Tool for masking passwords, and to the JBoss Application Server for decrypting them at run time.
Procedure 16.3. Encrypt the key store password
- At the command line, change to the
jboss-as/bin
directory. - Run the password tool, using the command
./password_tool.sh
for Unix-based systems, orpassword_tool.bat
for Windows-based systems.Result:The JBoss Password Tool will start, and will report '
Keystore is null. Please specify keystore below:
'. - Select '
0: Encrypt Keystore Password
' by pressing 0, then Enter.Result:The password tool responds with '
Enter keystore password
'. - Enter the key store password you specified in Procedure 16.2, “Generate a key pair and key store for password masking”.Result:
The password tool responds with '
Enter Salt (String should be at least 8 characters)
'. - Enter a random string of characters to aid with encryption strength.Result:
The password tool responds with '
Enter Iterator Count (integer value)
'. - Enter a whole number to aid with encryption strength.Result:
The password tool responds with: '
Keystore Password encrypted into password/jboss_keystore_pass.dat
'. - Select '
5:Exit
' to exit.Result:The password tool will exit with the message: '
Keystore is null. Cannot store.
'. This is normal. - Optional:
Make the resulting file
password/jboss_keystore_pass.dat
readable by the JBoss Application Server process owner only.On Unix-based systems this is accomplished by using thechown
command to change ownership to the JBoss Application Server process owner, andchmod 600 jboss-keystore_pass.dat
to make the file readable only by the owner.This step is recommended to increase the security of your server. Be aware that if this encrypted key is compromised, the security offered by password masking is significantly reduced. This file should be stored on a secure file system.Note: the JBoss Application Server process owner should not have interactive console log in access. In this case you will be performing these operations as another user. Creating masked passwords requires read access to the key store, so you may wish to complete configuration of masked passwords before restricting the key store file permissions.
You should only perform this key store password encryption procedure once. If you make a mistake entering the keystore password, or you change the key store at a later date, you should delete the jboss-keystore_pass.dat
file and repeat the procedure. Be aware that if you change the key store any masked passwords that were previously generated will no longer function.
16.4. Create password masks
jboss-as/bin/password/jboss_password_enc.dat
. This file is encrypted using a key pair you provide to the password tool, and it contains the passwords that will be masked in configuration files. Passwords are stored and retrieved from this file by 'domain', an arbitrary unique identifier that you specify to the Password Tool when storing the password, and that you specify as part of the annotation that replaces that clear text password in configuration files. This allows the JBoss Application Server to retrieve the correct password from the file at run time.
Note
jboss-as/bin/password/password.keystore
) and encrypted key store password file (jboss-as/bin/password/jboss_keystore_pass.dat
) readable by your user, and the encrypted passwords file jboss-as/bin/password/jboss_password_enc.dat
(if it already exists) read and writable, while you perform this operation.
Procedure 16.4. Create password masks
Prerequisites:
- At the command line, change to the
jboss-as/bin
directory. - Run the password tool, using the command
./password_tool.sh
for Unix-based systems, orpassword_tool.bat
for Windows-based systems.Result:The JBoss Password Tool will start, and will report '
Keystore is null. Please specify keystore below:
'. - Select '
1:Specify KeyStore
' by pressing 1 then Enter.Result:The password tool responds with '
Enter Keystore location including the file name
'. - Enter the path to the key store you created in Procedure 16.2, “Generate a key pair and key store for password masking”. You can specify an absolute path, or the path relative to
jboss-as/bin
. This should bepassword/password.keystore
, unless you have performed an advanced installation and changed the defaults as per Section 16.6, “Changing the password masking defaults”.Result:The password tool responds with '
Enter Keystore alias
'. - Enter the key alias. This should be
jboss
, unless you have performed an advanced installation and changed the defaults as per Section 16.6, “Changing the password masking defaults”.Result:If the key store and key alias are accessible, the password tool will respond with some log4j WARNING messages, then the line '
Loading domains [
', followed by any existing password masks, and the main menu. - Select '
2:Create Password
' by pressing 2, then EnterResult:The password tool responds with: '
Enter security domain:
'. - Enter a name for the password mask. This is an arbitrary unique name that you will use to identify the password mask in configuration files.Result:
The password tool responds with: '
Enter passwd:
'. - Enter the password that you wish to mask.Result:
The password tool responds with: '
Password created for domain:mask name
' - Repeat the password mask creation process to create masks for all passwords you wish to mask.
- Exit the program by choosing '
5:Exit
'
16.5. Replace clear text passwords with their password masks
Example 16.1. General form of password mask annotation
<annotation>@org.jboss.security.integration.password.Password(securityDomain=MASK_NAME, methodName=setPROPERTY_NAME)</annotation>
deploy/messaging/messaging-jboss-beans.xml
. If you create a password mask named "messaging", then the before and after snippet of the configuration file looks like this:
Example 16.2. JBoss Messaging Microcontainer Bean Configuration Before
<property name="suckerPassword">CHANGE ME!!</property>
Example 16.3. JBoss Messaging Microcontainer Bean Configuration After
<annotation>@org.jboss.security.integration.password.Password(securityDomain=messaging, methodName=setSuckerPassword)</annotation>
16.6. Changing the password masking defaults
jboss-as/bin/password/password.keystore
, and the key alias jboss
. If you store the key pair used for password masking elsewhere, or under a different alias, you will need to update the server profiles with the new location or key alias.
deploy/security/security-jboss-beans.xml
under each of the included JBoss Application Server server profiles.
Example 16.4. Password Masking defaults in security-jboss-beans.xml
<!-- Password Mask Management Bean--> <bean name="JBossSecurityPasswordMaskManagement" class="org.jboss.security.integration.password.PasswordMaskManagement" > <property name="keyStoreLocation">password/password.keystore</property> <property name="keyStoreAlias">jboss</property> <property name="passwordEncryptedFileName">password/jboss_password_enc.dat</property> <property name="keyStorePasswordEncryptedFileName">password/jboss_keystore_pass.dat</property> </bean>
Chapter 17. Encrypting Data Source Passwords
*-ds.xml
data source files. These database connection details include clear text passwords. You can increase the security of your server by replacing clear text passwords in data source files with encrypted passwords.
SecureIdentityLoginModule
is described in Section 17.1, “Secured Identity”.
JaasSecurityDomainIdentityLoginModule
is described in Section 17.2, “Configured Identity with Password Based Encryption (PBE)”.
17.1. Secured Identity
org.jboss.resource.security.SecureIdentityLoginModule
can be used to both encrypt database passwords and to provide a decrypted version of the password when the data source configuration is required by the server. The SecureIdentityLoginModule
uses a hard-coded password to encrypt/decrypt the data source password.
Procedure 17.1. Overview: Using SecureIdentityLoginModule to encrypt a data source password
- Encrypt the data source password.
- Create an application authentication policy with the encrypted password.
- Configure the data source to use the application authentication policy.
17.1.1. Encrypt the data source password
SecureIdentityLoginModule
main method by passing in the clear text password. The SecureIdentityLoginModule is provided by jbosssx.jar
.
Procedure 17.2. Encrypt a data source password - Platform versions 5.0 and 5.0.1
- Change directory to the
jboss-as
directory - Invoke the SecureIdentityLoginModule with the following command, supplying the clear text password as PASSWORD:Linux command
java -cp client/jboss-logging-spi.jar:common/lib/jbosssx.jar \ org.jboss.resource.security.SecureIdentityLoginModule PASSWORD
Windows command:java -cp client\jboss-logging-spi.jar;common\lib\jbosssx.jar \ org.jboss.resource.security.SecureIdentityLoginModule PASSWORD
Result:The command will return an encrypted password.
Procedure 17.3. Encrypt a data source password - Platform version 5.1 and later
- Change directory to the
jboss-as
directory - Linux command
java -cp client/jboss-logging-spi.jar:lib/jbosssx.jar \ org.jboss.resource.security.SecureIdentityLoginModule PASSWORD
Windows command:java -cp client\jboss-logging-spi.jar;lib\jbosssx.jar \ org.jboss.resource.security.SecureIdentityLoginModule PASSWORD
Result:The command will return an encrypted password.
17.1.2. Create an application authentication policy with the encrypted password
conf/login-config.xml
file, where application authentication policies are defined for that profile. To create an application authentication policy for your encrypted password, add a new <application-policy> element to the <policy> element.
login-config.xml
file showing an application authentication policy of name "EncryptDBPassword".
Example 17.1. Example application authentication policy with encrypted data source password
<policy> ... <!-- Example usage of the SecureIdentityLoginModule --> <application-policy name="EncryptDBPassword"> <authentication> <login-module code="org.jboss.resource.security.SecureIdentityLoginModule" flag="required"> <module-option name="username">admin</module-option> <module-option name="password">5dfc52b51bd35553df8592078de921bc</module-option> <module-option name="managedConnectionFactoryName">jboss.jca:name=PostgresDS,service=LocalTxCM</module-option> </login-module> </authentication> </application-policy> </policy>
SecureIdentityLoginModule module options
- user name
- Specify the user name to use when establishing a connection to the database.
- password
- Provide the encrypted password generated in Section 17.1.1, “Encrypt the data source password”.
- managedConnectionFactoryName
- jboss.jca:name
- Nominate a Java Naming and Directory Interface (JNDI) name for this data source.
- jboss.jca:service
- Specify the transaction type
Transaction types
- NoTxCM
- No transaction support
- LocalTxCM
- Single resource transaction support
- TxCM
- Single resource or distributed transaction support
- XATxCM
- Distributed transaction support
17.1.3. Configure the data source to use the application authentication policy
*-ds.xml
file. Remove the <user-name> and <password> elements from this file, and replace them with a <security-domain> element. This element will contain the application authentication policy name specified following Section 17.1.2, “Create an application authentication policy with the encrypted password”.
Example 17.2. Example data source file using secured identity
<?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <jndi-name>PostgresDS</jndi-name> <connection-url>jdbc:postgresql://127.0.0.1:5432/test?protocolVersion=2</connection-url> <driver-class>org.postgresql.Driver</driver-class> <min-pool-size>1</min-pool-size> <max-pool-size>20</max-pool-size> <!-- REPLACED WITH security-domain BELOW <user-name>admin</user-name> <password>password</password> --> <security-domain>EncryptDBPassword</security-domain> <metadata> <type-mapping>PostgreSQL 8.0</type-mapping> </metadata> </local-tx-datasource> </datasources>
17.2. Configured Identity with Password Based Encryption (PBE)
org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule
is a login module for statically defining a data source using a password that has been encrypted by a JaasSecurityDomain. The base64 format of the data source password may be generated using PBEUtils:
Procedure 17.4. Encrypt password with PBEUtils - Platforms version 5.0 and 5.0.1
- Execute the command:
java -cp jboss-as/common/lib/jbosssx.jar org.jboss.security.plugins.PBEUtils \ salt count domain-password data-source-password
Result:The encrypted password is displayed
Procedure 17.5. Encrypt password with PBEUtils - Platform version 5.1
- Execute the command:
java -cp jboss-as/lib/jbosssx.jar org.jboss.security.plugins.PBEUtils \ salt count domain-password data-source-password
Result:The encrypted password is displayed
PBEUtils
are:
- salt
- The Salt attribute from the JaasSecurityDomain (Must only be eight characters long).
- count
- The IterationCount attribute from the JaasSecurity domain.
- domain-password
- The plain text password that maps to the KeyStorePass attribute from the JaasSecurityDomain.
- data-source-password
- The plain text password for the data source that should be encrypted with the JaasSecurityDomain password.
Example 17.3. PBEUtils command example
java -cp jbosssx.jar org.jboss.security.plugins.PBEUtils abcdefgh 13 master password Encoded password: 3zbEkBDfpQAASa3H39pIyP
$JBOSS_HOME/server/$PROFILE/conf/login-config.xml
file.
<application-policy name="EncryptedHsqlDbRealm"> <authentication> <login-module code= "org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule" flag = "required"> <module-option name="username">sa</module-option> <module-option name="password">E5gtGMKcXPP</module-option> <module-option name="managedConnectionFactoryName"> jboss.jca:service=LocalTxCM,name=DefaultDS </module-option> <module-option name="jaasSecurityDomain"> jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword </module-option> </login-module> </authentication> </application-policy>
$JBOSS_HOME/docs/examples/jca/hsqldb-encrypted-ds.xml
illustrates that data source configuration along with the JaasSecurityDomain configuration for the keystore:
Example 17.4. FilePassword command example
.../conf/server.password
. You first need to run the following command, which will store the encryption details and obfuscated master password:
java -cp jboss-as/lib/jbosssx.jar org.jboss.security.plugins.FilePassword salt count master_password password_file For example: java -cp jboss-as/lib/jbosssx.jar org.jboss.security.plugins.FilePassword abcdefgh 13 master jboss-as/server/$PROFILE/conf/server.password
<?xml version="1.0" encoding="UTF-8"?> <!-- The Hypersonic embedded database JCA connection factory config that illustrates the use of the JaasSecurityDomainIdentityLoginModule to use encrypted password in the data source configuration. $Id: hsqldb-encrypted-ds.xml,v 1.1.2.1 2004/06/04 02:20:52 starksm Exp $ --> <datasources> ... <application-policy name="EncryptedHsqlDbRealm"> <authentication> <login-module code="org.jboss.resource.security.JaasSecurityDomainIdentityLoginModule" flag = "required"> <module-option name="username">sa</module-option> <module-option name="password">E5gtGMKcXPP</module-option> <module-option name="managedConnectionFactoryName"> jboss.jca:service=LocalTxCM,name=DefaultDS </module-option> <module-option name="jaasSecurityDomain"> jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword </module-option> </login-module> </authentication> </application-policy> <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=JaasSecurityDomain, domain=ServerMasterPassword"> <constructor> <arg type="java.lang.String" value="ServerMasterPassword"></arg> </constructor> <!-- The opaque master password file used to decrypt the encrypted database password key --> <attribute name="KeyStorePass">{CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/server.password</attribute> <attribute name="Salt">abcdefgh</attribute> <attribute name="IterationCount">13</attribute> </mbean> <!-- This mbean can be used when using in process persistent db --> <mbean code="org.jboss.jdbc.HypersonicDatabase" name="jboss:service=Hypersonic,database=localDB"> <attribute name="Database">localDB</attribute> <attribute name="InProcessMode">true</attribute> </mbean> ... </datasources>
Warning
Note
java.security.InvalidAlgorithmParameterException: Parameters missing
is raised when the following MBean is not yet started as a service:
(jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword)
hsqldb-encrypted-ds.xml
code shown previously.
<depends>jboss.security:service=JaasSecurityDomain,domain=ServerMasterPassword</depends>
Chapter 18. Encrypting the Keystore Password in a Tomcat Connector
server.xml
file.
Procedure 18.1. Encrypt Tomcat Container Keystore Password
Append connector element
Add a connector element inserver.xml
in$JBOSS_HOME/server/$PROFILE/deploy/jbossweb.sar
<!-- SSL/TLS Connector with encrypted keystore password configuration --> <Connector port="8443" address="${jboss.bind.address}" maxThreads="100" minSpareThreads="5" maxSpareThreads="15" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS" securityDomain="java:/jaas/encrypt-keystore-password" SSLImplementation="org.jboss.net.ssl.JBossImplementation" > </Connector>
.Configure JaasSecurityDomain MBean
Set the JaasSecurityDomain MBean in the$JBOSS_HOME/server/$PROFILE/deploy/security-service.xml
file.If the file does not exist, create it. The code sample in Example 18.1, “security-service.xml” shows the content you need to add to a newly-createdservice-security.xml
file. If thesecurity-service.xml
file exists, append the <mbean> element block to the file.Example 18.1. security-service.xml
<server> <mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=PBESecurityDomain"> <constructor> <arg type="java.lang.String" value="encrypt-keystore-password"></arg> </constructor> <attribute name="KeyStoreURL">resource:localhost.keystore</attribute> <attribute name="KeyStorePass">{CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/keystore.password</attribute> <attribute name="Salt">welcometojboss</attribute> <attribute name="IterationCount">13</attribute> </mbean> </server>
Note
If the keystore contains multiple certificates, you can use the ServerAlias property. The property value specifies the alias of the certificate retrieved by the SSL connector.<attribute name="ServerAlias">ssl</attribute>
The Salt and IterationCount are the variables that define the strength of your encrypted password, so you can vary it from what is shown. Ensure you record the new values, and use when generating the encrypted password.Note
The Salt must be at least eight characters long.Generate encrypted password
The <mbean> configuration specifies that the keystore is stored in thejboss-as/server/$PROFILE/conf/localhost.keystore
file. The <mbean> also specifies the encrypted password file is stored injboss-as/server/$PROFILE/conf/keystore.password
file.You must create thelocalhost.keystore
file.Execute the following command in thejboss-as/server/$PROFILE/conf
directory.[conf]$ java -cp $JBOSS_HOME/lib/jbosssx.jar \org.jboss.security.plugins.FilePassword welcometojboss 13 unit-tests-server keystore.password
This command uses jbosssx.jar as the classpath (-cp
) and the FilePassword security plug-in to create akeystore.password
file with the password set asunit-tests-server
. To verify you have permission to create akeystore.password
file, you supply the salt and iteration parameters configured in the <mbean> <attribute> elements of the JaasSecurityDomain.You execute this command in the/conf
directory so thekeystore.password
file is saved to this directory.Update the Tomcat service MBean
Navigate to$JBOSS_HOME/server/$PROFILE/deploy/jbossweb.sar/META-INF/
.Openjboss-beans.xml
and append the following <depends> tag to theWebServer
end of the file. Adding the <depends> tag specifies that Tomcat must start afterjboss.security:service=PBESecurityDomain
.<bean name="WebServer" class="org.jboss.web.tomcat.service.deployers.TomcatService"> ... <depends>jboss.security:service=PBESecurityDomain</depends> ...
Example 18.2. JaasSecurityDomain definition for pkcs12 keystores
<mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=PBESecurityDomain"> <constructor> <arg type="java.lang.String" value="encrypt-keystore-password"></arg> </constructor> <attribute name="KeyStoreType">pkcs12</attribute> <attribute name="KeyStoreURL">resource:localhost.keystore</attribute> <attribute name="KeyStorePass">{CLASS}org.jboss.security.plugins.FilePassword:${jboss.server.home.dir}/conf/keystore.password</attribute> <attribute name="Salt">welcometojboss</attribute> <attribute name="IterationCount">13</attribute> </mbean>
18.1. Medium Security Usecase
server.xml
) or wants to make use of a predefined JaasSecurityDomain.
Procedure 18.2. Predefined JaasSecurityDomain
Update jboss-service.xml to add a connector
Navigate to$JBOSS_HOME/server/
, and add the following code block to the$PROFILE
/deploy/jbossweb.sar/META-INFjboss-service.xml
file.<mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=SecurityDomain"> <constructor> <arg type="java.lang.String" value="jbosstest-ssl"></arg> </constructor> <attribute name="KeyStoreURL">resource:localhost.keystore</attribute> <attribute name="KeyStorePass">unit-tests-server</attribute> </mbean>
Add a <depends> tag to the Tomcat service
Navigate to$JBOSS_HOME/server/$PROFILE/deploy/jbossweb.sar
.Openserver.xml
and append the following <depends> element toward the end of the file:<depends>jboss.security:service=SecurityDomain</depends> </mbean> </server>
Define the JaasSecurityDomain MBean in a *-service.xml file
security-service.xml
in the deploy directory, for example.<mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=SecurityDomain"> <constructor> <arg type="java.lang.String" value="jbosstest-ssl"></arg> </constructor> <attribute name="KeyStoreURL">resource:localhost.keystore</attribute> <attribute name="KeyStorePass">unit-tests-server</attribute> </mbean>
Note
Chapter 19. Using LdapExtLoginModule with JaasSecurityDomain
Procedure 19.1.
Define JaasSecurityDomain MBean
Define the JaasSecurityDomain MBean used to decrypt the encrypted version of the password. You can add the MBean toJBOSS_HOME/server/PROFILE/conf/jboss-service.xml
, or to a *-service.xml
deployment descriptor in theJBOSS_HOME/server/
folder.PROFILE
/deploy<mbean code="org.jboss.security.plugins.JaasSecurityDomain" name="jboss.security:service=JaasSecurityDomain,domain=jmx-console"> <constructor> <arg type="java.lang.String" value="jmx-console"></arg> </constructor> <attribute name="KeyStorePass">some_password</attribute> <attribute name="Salt">abcdefgh</attribute> <attribute name="IterationCount">66</attribute> </mbean>
Note
The default cipher algorithm used by the JaasSecurityDomain implementation isPBEwithMD5andDES
. Other cipher algorithms includeDES
,TripleDES
,Blowfish
, andPBEWithMD5AndTripleDES
. All algorithms are symmetric algorithms. You specify a cipher algorithm by appending an <attribute> element with theCypherElement
attribute set to one of these values.Adjust password, salt, and iteration count
Step One contains a simple configuration where the required password, Salt, and Iteration Count used for the encryption or decryption are contained within the MBean definition.Ensure you change the KeyStorePass, Salt, and IterationCount values suitable for your own deployment.Start the platform
Start the server after configuring the MBean, password, salt, and iteration counts. Ensure you start the platform by specifying the server profile containing the configuration.[bin]$ ./run.sh -c PROFILE
Open the JMX Console
Navigate to the JMX Console (http://localhost:8080/jmx-console/ by default) and select theorg.jboss.security.plugins.JaasSecurityDomain
MBean.Invoke the LdapExtLoginModule
- On the
org.jboss.security.plugins.JaasSecurityDomain
page, find theencode64(String password)
method. - Pass the plain text version of the
password
the LdapExtLoginModule will use to this method. - Invoke the
encode64(String password)
method. - The return value is the encrypted version of the password encoded as Base64.
Configure Login Module
Within the login module configuration, the following module-options should be set:<module-option name="jaasSecurityDomain">jboss.security:service=JaasSecurityDomain,domain=jmx-console</module-option> <module-option name="bindCredential">2gx7gcAxcDuaHaJMgO5AVo</module-option>
The first option specifies the JaasSecurityDomain configured in Step 1 is used to decrypt the password.ThebindCredential
is replaced with the encrypted Base64 password obtained in Step 5.
Chapter 20. Firewalls
Port | Type | Description | Service |
---|---|---|---|
1090 | TCP | RMI/JRMP port for connecting to the JMX MBeanServer | jboss.remoting:service=JMXConnectorServer,protocol=rmi |
1098 | TCP | Naming service port for RMI requests from client proxies | jboss:service=Naming |
1099 | TCP | Naming service port | jboss:service=Naming |
1100 | TCP | Port for the HA-JNDI service | jboss:service=HAJNDI |
1101 | TCP | HA-JNDI service port for RMI requests from client proxies | jboss:service=HAJNDI |
1102 | UDP | HA-JNDI multicast port for auto-discovery requests | jboss:service=HAJNDI |
1161 | UDP | Port for the SNMP adaptor MBean | jboss.jmx:name=SnmpAgent,service=snmp,type=adaptor |
1162 | UDP | Port for the SNMP trap receiver | jboss.jmx:name=SnmpAgent,service=trapd,type=logger |
3528 | TCP | IIOP port for the Corba ORB | jboss:service=CorbaORB |
3873 | TCP | EJB3 Remoting Connector Port | jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3 |
4444 | TCP | Port for the legacy RMI/JRMP invoker | jboss:service=invoker,type=jrmp |
4445 | TCP | Port for the legacy Pooled invoker | jboss:service=invoker,type=pooled |
4446 | TCP | Port for JBoss Remoting Connector of UnifiedInvoker | UnifiedInvokerConnector |
4447 | TCP | Port for the high-availability version of the legacy RMI/JRMP invoker | jboss:service=invoker,type=jrmpha |
4448 | TCP | Port for the high-availability version of the legacy Pooled invoker | jboss:service=invoker,type=pooledha |
4457 | TCP | Port for JBoss Messaging | jboss.messaging:service=Connector,transport=bisocket |
4458 | TCP | Recommended secondary binding port for JBoss Messaging. For more information, see the Configuring the Remoting Connector section of the Messaging User Guide. | jboss.messaging:service=Connector,transport=bisocket |
4712 | TCP | Port for JBoss TS Recovery Manager | TransactionManager |
4713 | TCP | Port for JBossTS Transaction Status Manager | TransactionManager |
4714 | TCP | Port for provision of unique process id for JBossTS | TransactionManager |
5445 | TCP | Port for HornetQ | HornetQ |
5446 | TCP | SSL port for HornetQ | HornetQ |
5455 | TCP | HornetQ batch port; refer to Configuring the Netty transport in HornetQ User Guide | HornetQ |
5465 | TCP | HornetQ backup server port | HornetQ |
5466 | TCP | Backup SSL port for HornetQ | HornetQ |
5475 | TCP | Backup batch port for HornetQ | HornetQ |
7500 | TCP | Multicast port on which JGroups listens for diagnostic requests from its Probe utility | JGroups |
7600 | TCP | Port used for the JGroups tcp stack | JGroups |
7650 | TCP | Port used by the JGroups tcp-sync stack | JGroups |
7900 | TCP | Port used by the JGroups jbm-data . This port is used by cluster nodes to communicate with each other and is not usually firewalled. If this option is desirable, keep in mind that other UDP ports may also need to be opened. | JGroups |
8009 | TCP | Port for AJP connector | jboss:service=WebService |
8080 | TCP | JBoss Web HTTP connector port (drives also the values for the HTTPS and AJP sockets) | jboss.web:service=WebServer |
8083 | TCP | Port for dynamic class and resource loading | jboss:service=WebService |
8443 | TCP | Port for JBoss Web HTTPS connector | jboss.web:service=WebServer |
45688 | UDP | Multicast port for JGroups udp stack communication | JGroups |
45689 | UDP | Multicast port for communication of the JGroups udp-async stack | JGroups |
45699 | UDP | Multicast port for communication of the JGroups udp-sync stack | JGroups |
45700 | TCP | Multicast port on which JGroups tcp stack performs discovery | JGroups |
45701 | TCP | Multicast port on which JGroups tcp-sync stack performs discovery | JGroups |
45710 | UDP | Multicast port on which JGroups jbm-data stack performs discovery | JGroups |
53200 | TCP | Port used by the FD_SOCK protocol in the JGroups jbm_control stack | JGroups |
54200 – 54206 | TCP | Range of ports used by the FD_SOCK protocol in the JGroups tcp stack | JGroups |
54225 – 54231 | TCP | Range of ports used by the FD_SOCK protocol in the JGroups tcp-async stack | JGroups |
55200 | UDP | Port for JGroups udp stack | JGroups |
55225 | UDP | Port used by the JGroups udp-async stack | JGroups |
55250 | UDP | Port used by the JGroups udp-sync stack | JGroups |
57600 – 57606 | TCP | Range of ports used by the FD_SOCK protocol in the JGroups tcp stack | JGroups |
57650 – 57656 | TCP | Range of ports used by the FD_SOCK protocol in the JGroups tcp-sync stack | JGroups |
57900 | TCP | Port used by the FD_SOCK protocol in the JGroups jbm-data stack | JGroups |
Chapter 21. Securing the Administrative Access Points
21.1. JMX Console
jmx-console.war
file located in the deploy directory. It provides with an HTML view into the JMX Microkernel and allows you to perform administrative actions such as shutting down the server, stopping services and deploying new services, among other things.
jmx-console
security domain to allow access. Follow Task: Create jmx-console, admin-console, and http invoker user account to allow access to it. In order to remove it, delete the jmx-console
folder from the deploy
directory.
21.2. Admin Console
admin-console
directory from the deploy
directory.
Task: Create jmx-console, admin-console, and http invoker user account
jmx-console
security domain which is defined in $JBOSS_HOME/server/$PROFILE/conf/login-config.xml
.
Procedure 21.1.
- Add a username and password to
$JBOSS_HOME/server/$PROFILE/conf/props/jmx-console-users.properties
. - Create a username = password pair.
Important
The commentedadmin=admin
username and password pair is an example of the username/password definition syntax. Do not use this for your user account. - Grant permissions to the user:
- Edit the file
$JBOSS_HOME/server/$PROFILE/conf/props/jmx-console-roles.properties
. - Create an entry for the user of the form:
username=JBossAdmin,HttpInvoker
- Grant the user permission to access the JMX Console and Admin Console.
- Grant the user permission to access the HTTP Invoker.
21.3. Web Console
web-console
security domain which is defined in $JBOSS_HOME/server/$PROFILE/conf/login-config.xml
.
web-console
security domain uses the same security configuration as the jmx-console
domain. You can follow Task: Create jmx-console, admin-console, and http invoker user account to allow access to it.
21.4. HTTP Invoker
jmx-console
security domain. The instructions in Task: Create jmx-console, admin-console, and http invoker user account will allow access to it.
Task: Allow access to the HTTP Invoker from remote hosts
hostName
property to invoker you wish to use; Pooled or non-Pooled. Be aware that myservice.example.com must resolve to an IP Address served by this machine.
Procedure 21.2.
- Choose the appropriate bean from the options below and copy it in your invoker:
<!-- RMI/JRMP invoker --> <bean class="org.jboss.services.binding.ServiceBindingMetadata"> <property name="serviceName">jboss:service=invoker,type=jrmp</property> <property name="port">4444</property> <property name="description">Socket for the legacy RMI/JRMP invoker</property> <property name="hostName">myservice.example.com</property> </bean>
<!-- Pooled invoker --> <bean class="org.jboss.services.binding.ServiceBindingMetadata"> <property name="serviceName">jboss:service=invoker,type=pooled</property> <property name="port">4445</property> <property name="description">Socket for the legacy Pooled invoker</property> <property name="hostName">myservice.example.com</property> </bean>
21.5. JMX Invoker
21.6. Remote Access to Services, Detached Invokers
Figure 21.1. The main components in the detached invoker architecture
Invoker
interface illustrates the generic invoke operation.
package org.jboss.invocation; import java.rmi.Remote; import org.jboss.proxy.Interceptor; import org.jboss.util.id.GUID; public interface Invoker extends Remote { GUID ID = new GUID(); String getServerHostName() throws Exception; Object invoke(Invocation invocation) throws Exception; }
Remote
to be compatible with RMI, but this does not mean that an invoker must expose an RMI service stub. The detached invoker service acts as a transport gateway that accepts invocations represented as the org.jboss.invocation.Invocation
object over its specific transport. The invoker service unmarshals the invocation, forwards the invocation onto the destination MBean service represented by the Target MBean in Figure 21.1, “The main components in the detached invoker architecture”, and marshals the return value or exception resulting from the forwarded call back to the client.
Invocation
object is just a representation of a method invocation context. This includes the target MBean name, the method, the method arguments, a context of information associated with the proxy by the proxy factory, and an arbitrary map of data associated with the invocation by the client proxy interceptors.
- Create a dynamic proxy that implements the interface the target MBean wishes to expose.
- Associate the client proxy interceptors with the dynamic proxy handler.
- Associate the invocation context with the dynamic proxy. This includes the target MBean, detached invoker stub and the proxy JNDI name.
- Make the proxy available to clients by binding the proxy into JNDI.
- Define a JMX operation matching the signature:
public Object invoke(org.jboss.invocation.Invocation) throws Exception
- Create a
HashMap<Long, Method>
mapping from the exposed interfacejava.lang.reflect.Method
s to the long hash representation using theorg.jboss.invocation.MarshalledInvocation.calculateHash
method. - Implement the
invoke(Invocation)
JMX operation and use the interface method hash mapping to transform from the long hash representation of the invoked method to thejava.lang.reflect.Method
of the exposed interface. Reflection is used to perform the actual invocation on the object associated with the MBean service that actually implements the exposed interface.
21.6.1. A Detached Invoker Example, the MBeanServer Invoker Adaptor Service
org.jboss.jmx.connector.invoker.InvokerAdaptorService
and its configuration for access via RMI/JRMP as an example of the steps required to provide remote access to an MBean service.
Example 21.1. The InvokerAdaptorService MBean
InvokerAdaptorService
is a simple MBean service that exists to fulfill the target MBean role in the detached invoker pattern.
package org.jboss.jmx.connector.invoker; public interface InvokerAdaptorServiceMBean extends org.jboss.system.ServiceMBean { Class getExportedInterface(); void setExportedInterface(Class exportedInterface); Object invoke(org.jboss.invocation.Invocation invocation) throws Exception; } package org.jboss.jmx.connector.invoker; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.management.MBeanServer; import javax.management.ObjectName; import org.jboss.invocation.Invocation; import org.jboss.invocation.MarshalledInvocation; import org.jboss.mx.server.ServerConstants; import org.jboss.system.ServiceMBeanSupport; import org.jboss.system.Registry; public class InvokerAdaptorService extends ServiceMBeanSupport implements InvokerAdaptorServiceMBean, ServerConstants { private static ObjectName mbeanRegistry; static { try { mbeanRegistry = new ObjectName(MBEAN_REGISTRY); } catch (Exception e) { throw new RuntimeException(e.toString()); } } private Map marshalledInvocationMapping = new HashMap(); private Class exportedInterface; public Class getExportedInterface() { return exportedInterface; } public void setExportedInterface(Class exportedInterface) { this.exportedInterface = exportedInterface; } protected void startService() throws Exception { // Build the interface method map Method[] methods = exportedInterface.getMethods(); HashMap tmpMap = new HashMap(methods.length); for (int m = 0; m < methods.length; m ++) { Method method = methods[m]; Long hash = new Long(MarshalledInvocation.calculateHash(method)); tmpMap.put(hash, method); } marshalledInvocationMapping = Collections.unmodifiableMap(tmpMap); // Place our ObjectName hash into the Registry so invokers can // resolve it Registry.bind(new Integer(serviceName.hashCode()), serviceName); } protected void stopService() throws Exception { Registry.unbind(new Integer(serviceName.hashCode())); } public Object invoke(Invocation invocation) throws Exception { // Make sure we have the correct classloader before unmarshalling Thread thread = Thread.currentThread(); ClassLoader oldCL = thread.getContextClassLoader(); // Get the MBean this operation applies to ClassLoader newCL = null; ObjectName objectName = (ObjectName) invocation.getValue("JMX_OBJECT_NAME"); if (objectName != null) { // Obtain the ClassLoader associated with the MBean deployment newCL = (ClassLoader) server.invoke(mbeanRegistry, "getValue", new Object[] { objectName, CLASSLOADER }, new String[] { ObjectName.class.getName(), "java.lang.String" }); } if (newCL != null && newCL != oldCL) { thread.setContextClassLoader(newCL); } try { // Set the method hash to Method mapping if (invocation instanceof MarshalledInvocation) { MarshalledInvocation mi = (MarshalledInvocation) invocation; mi.setMethodMap(marshalledInvocationMapping); } // Invoke the MBeanServer method via reflection Method method = invocation.getMethod(); Object[] args = invocation.getArguments(); Object value = null; try { String name = method.getName(); Class[] sig = method.getParameterTypes(); Method mbeanServerMethod = MBeanServer.class.getMethod(name, sig); value = mbeanServerMethod.invoke(server, args); } catch(InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof Exception) { throw (Exception) t; } else { throw new UndeclaredThrowableException(t, method.toString()); } } return value; } finally { if (newCL != null && newCL != oldCL) { thread.setContextClassLoader(oldCL); } } } }
InvokerAdaptorServiceMBean
, the code has been split into logical blocks, with commentary about how each block operates.
Example 21.2. Block One
package org.jboss.jmx.connector.invoker; public interface InvokerAdaptorServiceMBean extends org.jboss.system.ServiceMBean { Class getExportedInterface(); void setExportedInterface(Class exportedInterface); Object invoke(org.jboss.invocation.Invocation invocation) throws Exception; } package org.jboss.jmx.connector.invoker; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.UndeclaredThrowableException; import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.management.MBeanServer; import javax.management.ObjectName; import org.jboss.invocation.Invocation; import org.jboss.invocation.MarshalledInvocation; import org.jboss.mx.server.ServerConstants; import org.jboss.system.ServiceMBeanSupport; import org.jboss.system.Registry; public class InvokerAdaptorService extends ServiceMBeanSupport implements InvokerAdaptorServiceMBean, ServerConstants { private static ObjectName mbeanRegistry; static { try { mbeanRegistry = new ObjectName(MBEAN_REGISTRY); } catch (Exception e) { throw new RuntimeException(e.toString()); } } private Map marshalledInvocationMapping = new HashMap(); private Class exportedInterface; public Class getExportedInterface() { return exportedInterface; } public void setExportedInterface(Class exportedInterface) { this.exportedInterface = exportedInterface; } ...
InvokerAdaptorServiceMBean
Standard MBean interface of the InvokerAdaptorService
has a single ExportedInterface
attribute and a single invoke(Invocation)
operation.
ExportedInterface
- The attribute allows customization of the type of interface the service exposes to clients. This must be compatible with the
MBeanServer
class in terms of method name and signature. invoke(Invocation)
- The operation is the required entry point that target MBean services must expose to participate in the detached invoker pattern. This operation is invoked by the detached invoker services that have been configured to provide access to the
InvokerAdaptorService
.
Example 21.3. Block Two
protected void startService() throws Exception { // Build the interface method map Method[] methods = exportedInterface.getMethods(); HashMap tmpMap = new HashMap(methods.length); for (int m = 0; m < methods.length; m ++) { Method method = methods[m]; Long hash = new Long(MarshalledInvocation.calculateHash(method)); tmpMap.put(hash, method); } marshalledInvocationMapping = Collections.unmodifiableMap(tmpMap); // Place our ObjectName hash into the Registry so invokers can // resolve it Registry.bind(new Integer(serviceName.hashCode()), serviceName); } protected void stopService() throws Exception { Registry.unbind(new Integer(serviceName.hashCode())); }
exportedInterface
Class using the org.jboss.invocation.MarshalledInvocation.calculateHash(Method)
utility method.
java.lang.reflect.Method
instances are not serializable, a MarshalledInvocation
version of the non-serializable Invocation
class is used to marshal the invocation between the client and server. The MarshalledInvocation
replaces the Method instances with their corresponding hash representation. On the server side, the MarshalledInvocation
must be told what the hash to Method mapping is.
InvokerAdaptorService
service name and its hash code representation. This is used by detached invokers to determine what the target MBean ObjectName
of an Invocation
is.
Invocation
, its store as its hashCode because ObjectName
s are relatively expensive objects to create. The org.jboss.system.Registry
is a global map like construct that invokers use to store the hash code to ObjectName
mappings in.
Example 21.4. Block Three
public Object invoke(Invocation invocation) throws Exception { // Make sure we have the correct classloader before unmarshalling Thread thread = Thread.currentThread(); ClassLoader oldCL = thread.getContextClassLoader(); // Get the MBean this operation applies to ClassLoader newCL = null; ObjectName objectName = (ObjectName) invocation.getValue("JMX_OBJECT_NAME"); if (objectName != null) { // Obtain the ClassLoader associated with the MBean deployment newCL = (ClassLoader) server.invoke(mbeanRegistry, "getValue", new Object[] { objectName, CLASSLOADER }, new String[] { ObjectName.class.getName(), "java.lang.String" }); } if (newCL != null && newCL != oldCL) { thread.setContextClassLoader(newCL); }
org.jboss.mx.server.registry.BasicMBeanRegistry
, a JBoss JMX implementation-specific class.
Example 21.5. Block Four
... try { // Set the method hash to Method mapping if (invocation instanceof MarshalledInvocation) { MarshalledInvocation mi = (MarshalledInvocation) invocation; mi.setMethodMap(marshalledInvocationMapping); } ...
ExposedInterface
class method hash to method mapping if the invocation argument is of type MarshalledInvocation
. The method mapping calculated in Example 21.3, “Block Two”is used here.
ExposedInterface
method to the matching method of the MBeanServer class. The InvokerServiceAdaptor
decouples the ExposedInterface
from the MBeanServer
class in that it allows an arbitrary interface. This is required because the standard java.lang.reflect.Proxy
class can only proxy interfaces. It also allows you to only expose a subset of the MBeanServer methods and add transport specific exceptions such as java.rmi.RemoteException
to the ExposedInterface
method signatures.
Example 21.6. Block Five
... // Invoke the MBeanServer method via reflection Method method = invocation.getMethod(); Object[] args = invocation.getArguments(); Object value = null; try { String name = method.getName(); Class[] sig = method.getParameterTypes(); Method mbeanServerMethod = MBeanServer.class.getMethod(name, sig); value = mbeanServerMethod.invoke(server, args); } catch(InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof Exception) { throw (Exception) t; } else { throw new UndeclaredThrowableException(t, method.toString()); } } return value; } finally { if (newCL != null && newCL != oldCL) { thread.setContextClassLoader(oldCL); } } } }
InvokerAdaptorService
MBeanServer instance to which the was deployed. The server instance variable is inherited from the ServiceMBeanSupport
superclass.
Note
InvokerAdaptorService
MBean does not deal directly with any transport specific details. There is the calculation of the method hash to Method mapping, but this is a transport independent detail.
InvokerAdaptorService
may be used to expose the same org.jboss.jmx.adaptor.rmi.RMIAdaptor
interface via RMI/JRMP as seen in Connecting to JMX Using RMI.
InvokerAdaptorService
configurations found in the default setup in the jmx-invoker-adaptor-service.sar
deployment. Example 21.7, “Default jmx-invoker-adaptor-server.sar deployment descriptor” shows the jboss-service.xml
descriptor for this deployment.
Example 21.7. Default jmx-invoker-adaptor-server.sar deployment descriptor
<server> <!-- The JRMP invoker proxy configuration for the InvokerAdaptorService --> <mbean code="org.jboss.invocation.jrmp.server.JRMPProxyFactory" name="jboss.jmx:type=adaptor,name=Invoker,protocol=jrmp,service=proxyFactory"> <!-- Use the standard JRMPInvoker from conf/jboss-service.xml --> <attribute name="InvokerName">jboss:service=invoker,type=jrmp</attribute> <!-- The target MBean is the InvokerAdaptorService configured below --> <attribute name="TargetName">jboss.jmx:type=adaptor,name=Invoker</attribute> <!-- Where to bind the RMIAdaptor proxy --> <attribute name="JndiName">jmx/invoker/RMIAdaptor</attribute> <!-- The RMI compatible MBeanServer interface --> <attribute name="ExportedInterface">org.jboss.jmx.adaptor.rmi.RMIAdaptor</attribute> <attribute name="ClientInterceptors"> <iterceptors> <interceptor>org.jboss.proxy.ClientMethodInterceptor</interceptor> <interceptor> org.jboss.jmx.connector.invoker.client.InvokerAdaptorClientInterceptor </interceptor> <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor> </iterceptors> </attribute> <depends>jboss:service=invoker,type=jrmp</depends> </mbean> <!-- This is the service that handles the RMIAdaptor invocations by routing them to the MBeanServer the service is deployed under. --> <mbean code="org.jboss.jmx.connector.invoker.InvokerAdaptorService" name="jboss.jmx:type=adaptor,name=Invoker"> <attribute name="ExportedInterface">org.jboss.jmx.adaptor.rmi.RMIAdaptor</attribute> </mbean> </server>
org.jboss.invocation.jrmp.server.JRMPProxyFactory
, is the proxy factory MBean service that creates proxies for the RMI/JRMP protocol. The configuration of this service as shown in Example 21.7, “Default jmx-invoker-adaptor-server.sar deployment descriptor” states that the JRMPInvoker will be used as the detached invoker, the InvokerAdaptorService
is the target mbean to which requests will be forwarded, that the proxy will expose the RMIAdaptor
interface, the proxy will be bound into JNDI under the name jmx/invoker/RMIAdaptor
, and the proxy will contain 3 interceptors: ClientMethodInterceptor
, InvokerAdaptorClientInterceptor
, InvokerInterceptor
. The configuration of the InvokerAdaptorService
simply sets the RMIAdaptor interface that the service is exposing.
InvokerAdaptorService
via RMI/JRMP is the detached invoker. The detached invoker we will use is the standard RMI/JRMP invoker used by the EJB containers for home and remote invocations, and this is the org.jboss.invocation.jrmp.server.JRMPInvoker
MBean service configured in the conf/jboss-service.xml
descriptor. That we can use the same service instance emphasizes the detached nature of the invokers. The JRMPInvoker simply acts as the RMI/JRMP endpoint for all RMI/JRMP proxies regardless of the interface(s) the proxies expose or the service the proxies utilize.
21.7. Disabling Authentication
Note
jbossas-5-disableauth.patch
patch available in the source files (src/build
). First, copy the patch file to the jboss-as
directory and run the following command to apply the patch from the jboss-as
directory: patch -p0 -i ./jbossas-5-disableauth.patch
21.7.1. JMX Console
$JBOSS_HOME/server/PROFILE/deploy/jmx-console.war/WEB-INF/web.xml
file as shown in Example 21.8, “HtmlAdaptor securite-constraint Commented out”.
Example 21.8. HtmlAdaptor securite-constraint Commented out
<!--
<security-constraint> <web-resource-collection> <web-resource-name>HtmlAdaptor</web-resource-name> <description> An example security config that only allows users with the role JBossAdmin to access the HTML JMX console web application </description> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>JBossAdmin</role-name> </auth-constraint> </security-constraint>-->
21.7.2. Web Console
$JBOSS_HOME/server/PROFILE/deploy/management/console-mgr.sar/web-console.war/WEB-INF/web.xml
file as shown in Example 21.9, “Web Console security-constraint Commented out”.
Example 21.9. Web Console security-constraint Commented out
<!--
<security-constraint> <web-resource-collection> <web-resource-name>HtmlAdaptor</web-resource-name> <description> An example security config that only allows users with the role JBossAdmin to access the HTML JMX console web application </description> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>JBossAdmin</role-name> </auth-constraint> </security-constraint>-->
21.7.3. JMX Invoker
JNDIFactory
, EJBInvokerServlet
, and JMXInvokerServlet
from the security realm in the $JBOSS_HOME/server/PROFILE/deploy/httpha-invoker.sar/invoker.war/WEB-INF/web.xml
file as shown in Example 21.10, “JMX Invoker Authentication Disabled”.
Example 21.10. JMX Invoker Authentication Disabled
<security-constraint> <web-resource-collection> <web-resource-name>HttpInvokers</web-resource-name> <description> An example security config that only allows users with the role HttpInvoker to access the HTTP invoker servlets </description> <!-- <url-pattern>/restricted/*</url-pattern> <url-pattern>/JNDIFactory/*</url-pattern> <url-pattern>/EJBInvokerServlet/*</url-pattern> <url-pattern>/JMXInvokerServlet/*</url-pattern> --> </web-resource-collection> <auth-constraint> <role-name>HttpInvoker</role-name> </auth-constraint> </security-constraint>
21.7.4. JMX Invoker
- Open for editing the
$JBOSS_HOME/server/PROFILE/deploy/jmx-invoker-service.xml
file. - Locate the
org.jboss.jmx.connector.invoker.InvokerAdaptorService
MBean code. - Comment out the <interceptor> block that specifies the
AuthenticationInterceptor
module, the security interceptor, as shown in Example 21.11, “JMXInvoker Authentication Interceptor Commented out”.Example 21.11. JMXInvoker Authentication Interceptor Commented out
<descriptors> <interceptors> <!--Uncomment to require authenticated users-->
<!--
<interceptor code="org.jboss.jmx.connector.invoker.AuthenticationInterceptor" securityDomain="java:/jaas/jmx-console"/>-->
<!--Interceptor that deals with non-serializable results--> <interceptor code="org.jboss.jmx.connector.invoker.SerializableInterceptor"; policyClass="StripModelMBeanInfoPolicy"/> </interceptors> </descriptors>
21.7.5. ProfileService
ProfileService
comment out the contents of the serverProxyInterceptors element in the $JBOSS_HOME/server/PROFILE/deploy/profileservice-jboss-beans.xml
file as show in Example 21.12, “ProfileService AuthenticationInterceptor Commented out”.
Example 21.12. ProfileService AuthenticationInterceptor Commented out
<property name="serverProxyInterceptors"> <list> <!-- comment this list to disable auth checks for the profileservice --><!--
<bean class="org.jboss.aspects.security.AuthenticationInterceptor"> <constructor> <parameter> <value-factory bean="JNDIBasedSecurityManagement" method="getAuthenticationManager" parameter="jmx-console"/> </parameter> </constructor> </bean> <bean class="org.jboss.aspects.security.RoleBasedAuthorizationInterceptor"> <constructor> <parameter> <value-factory bean="JNDIBasedSecurityManagement" method="getAuthenticationManager" parameter="jmx-console"/> </parameter> <parameter> <value-factory bean="JNDIBasedSecurityManagement" method="getAuthenticationManager" parameter="jmx-console"/> </parameter> </constructor> </bean>-->
</list> </property>
21.7.6. JBossWS
$JBOSS_HOME/server/PROFILE/deploy/jbossws.sar/jbossws-management.war/WEB-INF/web.xml
file as shown in Example 21.13, “JBossWS securite-constraint Commented out”.
Example 21.13. JBossWS securite-constraint Commented out
<!--
<security-constraint> <web-resource-collection> <web-resource-name>ContextServlet</web-resource-name> <description> An example security config that only allows users with the role 'friend' to access the JBossWS console web application </description> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <role-name>friend</role-name> </auth-constraint> </security-constraint>-->
Appendix A. Setting the default JDK with the /usr/sbin/alternatives
Utility
/usr/sbin/alternatives
is a tool for managing different software packages that provide the same functionality. Red Hat Enterprise Linux uses /usr/sbin/alternatives
to ensure that only one Java Development Kit is set as the system default at one time.
Important
/usr/sbin/alternatives
may contain conflicting configurations. Refer to Procedure A.1, “Using /usr/sbin/alternatives
to Set the Default JDK” for syntax of the /usr/sbin/alternatives
command.
Procedure A.1. Using /usr/sbin/alternatives
to Set the Default JDK
Become the root user.
/usr/sbin/alternatives
needs to be run with root privileges. Use thesu
command or other mechanism to gain these privileges.Set
java
.Input this command:/usr/sbin/alternatives --config java
Next, follow the on-screen directions to ensure that the correct version ofjava
is selected. Table A.1, “java
alternative commands” shows the relevant command settings for each of the different JDKs.Table A.1. java alternative commands JDK alternative command OpenJDK 1.6 /usr/lib/jvm/jre-1.6.0-openjdk/bin/java
Sun Microsystems JDK 1.6 /usr/lib/jvm/jre-1.6.0-sun/bin/java
Set
javac
.Enter this command:/usr/sbin/alternatives --config javac
Follow the on-screen directions to ensure that the correct version ofjavac
is selected. Table A.2, “javac
alternative commands” shows the appropriate command settings for the different JDKs.Table A.2. javac alternative commands JDK alternative command OpenJDK 1.6 /usr/lib/jvm/java-1.6.0-openjdk/bin/javac
Sun Microsystems JDK 1.6 /usr/lib/jvm/java-1.6.0-sun/bin/javac
Extra Step: Set
java_sdk_1.6.0
.The Sun Microsystems JDK 1.6 requires an additional command be run:/usr/sbin/alternatives --config java_sdk_1.6.0
Follow the on-screen directions to ensure that the correctjava_sdk
is selected. It is/usr/lib/jvm/java-1.6.0-sun
.
Appendix B. Revision History
Revision History | |||
---|---|---|---|
Revision 5.2.0-100.400 | 2013-10-31 | ||
| |||
Revision 5.2.0-100 | Wed 23 Jan 2013 | ||
| |||
Revision 5.1.2-103 | Mon 30 Jan 2012 | ||
| |||
Revision 5.1.2-100 | Thu 8 December 2011 | ||
|