9.6. Data Security for Library Mode
9.6.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 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.
Note
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.
9.6.2. Obtaining a Subject
javax.security.auth.Subject
. The Subject represents information for a single cache entity, such as a person or a service.
Subject subject = SecurityContextAssociation.getSubject();
- Servlets:
ServletRequest.getUserPrincipal()
- EJBs:
EJBContext.getCallerPrincipal()
- MessageDrivenBeans:
MessageDrivenContext.getCallerPrincipal()
mapper
is then used to identify the principals associated with the Subject and convert them into roles that correspond to those you have defined at the container level.
java.security.AccessControlContext
. Either the container sets the Subject on the AccessControlContext
, or the user must map the Principal to an appropriate Subject before wrapping the call to the JBoss Data Grid API using a Security.doAs()
method.
Example 9.7. Obtaining a Subject
import org.infinispan.security.Security; Security.doAs(subject, new PrivilegedExceptionAction<Void>() { public Void run() throws Exception { cache.put("key", "value"); } });
Security.doAs()
method is in place of the typical Subject.doAs() method. Unless the AccessControlContext
must be modified for reasons specific to your application's security model, using Security.doAs()
provides a performance advantage.
Security.getSubject();
, which will retrieve the Subject from either the JBoss Data Grid context, or from the AccessControlContext
.
9.6.3. 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 login method. Failure is represented through a LoginException being thrown by the login 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
login
method can be removed by invoking theLoginContext.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 login 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 login 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 login, 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 login 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.
9.6.4. Authorization Using a SecurityManager
java -Djava.security.manager ...
System.setSecurityManager(new SecurityManager());
9.6.5. Security Manager in Java
9.6.5.1. About the 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.
9.6.5.2. About Java Security Manager Policies
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, on the code's signature, or based on the subject's principals.
java.security.manager
and java.security.policy
.
A security policy's entry consists of the following configuration elements, which are connected to the policytool
:
- CodeBase
- The URL location (excluding the host and domain information) where the code originates from. This parameter is optional.
- SignedBy
- The alias used in the keystore to reference the signer whose private key was used to sign the code. This can be a single value or a comma-separated list of values. This parameter is optional. If omitted, presence or lack of a signature has no impact on the Java Security Manager.
- Principals
- A list of
principal_type
/principal_name
pairs, which must be present within the executing thread's principal set. The Principals entry is optional. If it is omitted, it signifies that the principals of the executing thread will have no impact on the Java Security Manager. - Permissions
- A permission is the access which is granted to the code. Many permissions are provided as part of the Java Enterprise Edition 6 (Java EE 6) specification. This document only covers additional permissions which are provided by JBoss EAP 6.
Important
9.6.5.3. Write a Java Security Manager Policy
An application called policytool
is included with most JDK and JRE distributions, for the purpose of creating and editing Java Security Manager security policies. Detailed information about policytool
is linked from http://docs.oracle.com/javase/6/docs/technotes/tools/.
Procedure 9.1. Setup a new Java Security Manager Policy
Start
policytool
.Start thepolicytool
tool in one of the following ways.Red Hat Enterprise Linux
From your GUI or a command prompt, run/usr/bin/policytool
.Microsoft Windows Server
Runpolicytool.exe
from your Start menu or from thebin\
of your Java installation. The location can vary.
Create a policy.
To create a policy, select. Add the parameters you need, then click .Edit an existing policy
Select the policy from the list of existing policies, and select thebutton. Edit the parameters as needed.Delete an existing policy.
Select the policy from the list of existing policies, and select thebutton.
9.6.5.4. Run Red Hat JBoss Data Grid Server Within the Java Security Manager
domain.sh
or standalone.sh
scripts. The following procedure guides you through the steps of configuring your instance to run within a Java Security Manager policy.
Prerequisites
- Before you following this procedure, you need to write a security policy, using the
policytool
command which is included with your Java Development Kit (JDK). This procedure assumes that your policy is located atJDG_HOME/bin/server.policy
. As an alternative, write the security policy using any text editor and manually save it asJDG_HOME/bin/server.policy
- The domain or standalone server must be completely stopped before you edit any configuration files.
Procedure 9.2. Configure the Security Manager for JBoss Data Grid Server
Open the configuration file.
Open the configuration file for editing. This file is located in one of two places, depending on whether you use a managed domain or standalone server. This is not the executable file used to start the server or domain.Managed Domain
- For Linux:
JDG_HOME/bin/domain.conf
- For Windows:
JDG_HOME\bin\domain.conf.bat
Standalone Server
- For Linux:
JDG_HOME/bin/standalone.conf
- For Windows:
JDG_HOME\bin\standalone.conf.bat
Add the Java options to the file.
To ensure the Java options are used, add them to the code block that begins with:if [ "x$JAVA_OPTS" = "x" ]; then
You can modify the-Djava.security.policy
value to specify the exact location of your security policy. It should go onto one line only, with no line break. Using==
when setting the-Djava.security.policy
property specifies that the security manager will use only the specified policy file. Using=
specifies that the security manager will use the specified policy combined with the policy set in thepolicy.url
section ofJAVA_HOME/lib/security/java.security
.Important
JBoss Enterprise Application Platform releases from 6.2.2 onwards require that the system propertyjboss.modules.policy-permissions
is set to true.Example 9.8. domain.conf
JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy==$PWD/server.policy -Djboss.home.dir=/path/to/JDG_HOME -Djboss.modules.policy-permissions=true"
Example 9.9. domain.conf.bat
set "JAVA_OPTS=%JAVA_OPTS% -Djava.security.manager -Djava.security.policy==\path\to\server.policy -Djboss.home.dir=\path\to\JDG_HOME -Djboss.modules.policy-permissions=true"
Example 9.10. standalone.conf
JAVA_OPTS="$JAVA_OPTS -Djava.security.manager -Djava.security.policy==$PWD/server.policy -Djboss.home.dir=$JBOSS_HOME -Djboss.modules.policy-permissions=true"
Example 9.11. standalone.conf.bat
set "JAVA_OPTS=%JAVA_OPTS% -Djava.security.manager -Djava.security.policy==\path\to\server.policy -Djboss.home.dir=%JBOSS_HOME% -Djboss.modules.policy-permissions=true"
Start the domain or server.
Start the domain or server as normal.