Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java System Access Manager 6 2005Q1 Developer's Guide 

Chapter 10
Using the JAAS Authorization Framework

Previous versions of Access Manager (Identity Server 6.0 and 6.1) provide custom policy APIs to define and evaluate access policies. This model provided centralized management of policies in its own policy store, the Sun ONE or Java Enterprise System (JES) Directory Server. In Sun Java™ System Access Manager 6 2005Q1 and beyond, the authorization segment of the Java Authentication and Authorization Service (JAAS) framework is added to the original model. This new model is based on JAAS 1.0 and Java 2 Platform, Standard Edition (J2SE) 1.3.1.

Access Manager now bridges the gap between J2SE and Access Manager APIs. In this new framework, Access Manager maps its private APIs to JAAS interfaces. This makes it possible for you to use the JAAS interface to access the Access Manager policy framework.

The topics covered in this chapter are:


Overview of JAAS Authorization

JAAS is a set of APIs that enable services to authenticate and enforce access controls upon users. It implements a Java technology version of the standard Pluggable Authentication Module (PAM) framework, and supports user-based authorization. JAAS authorization extends the Java security architecture which uses a security policy to specify what access rights are granted to executing code. That architecture, introduced in the Java 2 platform, is code-based. The permissions are granted based on code characteristics such as where the code is coming from, whether it is digitally signed, and if so, the identity of the signer.

Code Example 10-1 illustrates a Java security policy. This grants the code in the am_services.jar file, located in the current directory, the specified permission. No signer is specified, so it doesn't matter whether the code is signed or not.

Code Example 10-1  Example of a Java Security Policy

grant codebase Cfile:./am_services.jar" {

permission javax.security.auth.AuthPermission

"createLoginContext.AMLoginContext";

};

JAAS authorization adds user centric access control that applies control based on what code is running as well as on who is running it.

By default, JAAS comes with a reference implementation of Policy (com.sun.security.auth.PolicyFile) which is file-based. This implementation parses the Java.policy file ${java.home}/lib/security directory and uses that to direct the associations of permissions to code. You can change the pointer to some other PolicyFile implementation or use a combination of files. By default, two files are consulted to evaluate policy. One is com.sun.security.auth.PolicyFile, mentioned above, and the other is .java.policy as defined in user's home directory.

To make JAAS authorization take place, include a Principal field in the grant statement or statements in your policy file. A Principal field indicates which user executing the code is allowed the designated permissions. The Policy file grant statements can now optionally include one or more Principal fields. Including Principal field in the grant statement indicates that the user represented by the specified Principal, who is executing the specified code, has the designated permissions. See the Principal field example in Code Example 10-2.

Code Example 10-2  A Policy File Grant Statement

grant codebase "file:./am_services.jar",

Principal javax.security.auth.XXXprincipal

"your_user_name@your_domain" {

permission java.util.PropertyPermission "java.home", "read";

permission java.util.PropertyPermission "user.home", "read";

permission java.io.FilePermission "foo.txt", "read";

};

How Policy Enforcement Works

The Java 2 runtime enforces access controls via the java.lang.SecurityManager, which is consulted any time untrusted code attempts to perform a sensitive operation (accesses to the local file system, for example). To determine whether the code has sufficient permissions, the SecurityManager implementation delegates responsibility to the java.security.AccessController, which first obtains an image of the current AccessControlContext, and then ensures that the retrieved AccessControlContext contains sufficient permissions for the operation to be permitted.

JAAS supplements this architecture by providing the method Subject.doAs to dynamically associate an authenticated subject with the current AccessControlContext. As subsequent access control checks are made, the AccessController can base its decisions upon both the executing code itself, and upon the principals associated with the subject. Access Manager provides support for JAAS authentication, which results in the population of the subject with Principals that represents the user.

Code Example 10-3  The Subject.doAs Method

public final class Subject {

...

// associate the subject with the current

// AccessControlContext and execute the action

public static Object doAs(Subject s,

java.security.PrivilegedAction action) { }

}

To illustrate a usage scenario for the doAs method, consider a service that authenticates a remote subject, and then performs some work on behalf of that subject. For security reasons, the server should run in an AccessControlContext bound by the subject's permissions. Using JAAS, the server can ensure this by preparing the work to be performed as a java.security.PrivilegedAction. Then, by invoking the doAs method, the server provides both the authenticated subject and the prepared PrivilegedAction. The doAs implementation associates the subject with the current AccessControlContext and then executes the action. When security checks occur during execution, the Java 2 SecurityManager queries the JAAS policy, updates the current AccessControlContext with the permissions granted to the subject and the executing codesource, and then performs its regular permission checks. When the action is completed, the doAs method removes the subject from the current AccessControlContext, and returns the result back to the caller. Code Example 10-4 illustrates this flow.

Code Example 10-4  Sample Code for Subject.doAS

public static void main(String[] args) {

try {

// Create an SSOToken

AuthContext ac = new AuthContext("dc=iplanet,dc=com");

ac.login();

Callback[] callbacks = null;

if (ac.hasMoreRequirements()) {

callbacks = ac.getRequirements();

if (callbacks != null) {

try {

addLoginCallbackMessage(callbacks); // this method                       sets appropriate responses in the callbacks.

ac.submitRequirements(callbacks);

} catch (Exception e) { }

}

}

if (ac.getStatus() == AuthContext.Status.SUCCESS) {

Subject subject = ac.getSubject(); // get the authenticated                      subject

FilePermission perm = new FilePermission("/tmp/test",                     "read");

Subject.doAs(subject, new PrivilegedExceptionAction() {

/* above statement means execute run() method of the                      Class PrivilegedExceptionAction()

as the specified subject */

public Object run() throws IOException {

// if the above run() was not throwing Exception                          could have created an instance of PrivilegedAction

// instead of PrivilegedExceptionAction here

AccessController.checkPermission(perm);

File = new File("/tmp/test");

return null;

}

});

}

}

In this example, the AccessController is checking the application's current policy implementation. If any permission defined in the policy file implies the requested permission, the method will simply return; otherwise an AccessControlException will be thrown. The check is actually redundant in this example, because the constructor for the default File implementation performs the same check. This samples is meant to illustrate the flow.

How the JS2E Access Controller Works

AccessController works with the java.security.Policy implementation to securely process application requests. In JS2E, a typical checkPermission(Permission p) method call on the AccessController class might result in the following sequence:

  1. The AccessController invokes the getPermisisons() method of the javax.security.auth.policy passing in the subject and the code source.
  2. The getPermissions() method returns a PermissionCollection class instance, which represents a collection of same types of permissions.
  3. The elements() method of the returned PermissionCollection gets called, which returns an enumeration of the permissions held in this PermissionCollection.
  4. For each of the permissions returned in the enumeration (in step 3), the perm.newPermissionCollection() method gets called to obtain the PermissionCollection used to store the permission.
  5. PermissionCollection.add(perm) gets called by the J2SE internal code to store the permission in its PermissionCollection.
  6. The AccessController calls the implies(Permission p) method of the PermissionCollection returned in step 2.
  7. Once the implies() of PermissionCollection is called, it in turn triggers the calling of implies(Permission p) of the individual permission objects contained in the PermissionCollection. These methods return true if the current permission object in the collection implies the specified permission; the methods return false the current permission object in the collection does not imply the specified permission. This outcome is implementation dependent and can be changed.


JAAS Authorization in Access Manager

Access Manager provides a custom implementation of the JAAS javax.security.auth.Policy. The customized implementation leverages the J2SE access controller and security manager to provide policy evaluation for all Access Manager related permissions. The customized implementation also falls back on the J2SE default Policy implementation com.sun.security.auth.PolicyFile for access to system level resources. Access Manager policy does not control access to com.sun.security.auth.PolicyFile.

Figure 10-1 illustrates how the JAAS framework works within the Access Manager policy framework.

Figure 10-1  

In the JAAS authorization framework, both J2SE and JAAS APIs are recognized.

JAAS Authorization Framework

Access Manager uses both JAAS and J2SE's file-based policy for all the resources for which Access Manager does not provide access control. For Access Manager resources such as URLs and so forth, new policy and permissions are defined. This model leverages the best of JAAS and the best of J2SE in one solution. It uses the JAAS framework for its default access control where needed, and then enhances the framework to incorporate the Access Manager policy evaluation. In this way, you can use the Access Manager policy implementation to make policy evaluations pertaining to Access Manager policies, but revert back to the default method of controlling access to resources not under Access Manager control.

Custom APIs

Access Manager provides the following custom APIs:.

For a comprehensive listing of related APIs, see the Javadoc in the following directory: AccessManager-base/SUNWam/docs.

User Interface

The user interface for entering permissions and policy is the Access Manager administration console which works with the policy administration API. Once the policy is defined, the evaluation is done using the J2SE architecture and enhanced policy implementation.

ISPermission covers the case when additional policy services are defined and imported, provided they only have boolean action values. In fact boolean evaluation is all that can be done using JAAS since JAAS permissions have a boolean result.


Enabling the JAAS Authorization Framework

You enable the JAAS authorization framework by resetting policy. Use the Policy.setPolicy(Policy) API to reset policy during run time. In Code Example 10-5, Policy.setPolicy(com.sun.identity.policy.jaas.ISPolicy) resets the policy. In this example, the client application wants to use JAAS authorization API to communicate with the Access Manger and to perform policy evaluation. Access Manager provides the support needed to use Access Manager policy so that policy can be defined through the new ISPermission.

Code Example 10-5  Sample JAAS Authorization Code 

public static void main(String[] args) {

try {

// Create an SSOToken

           AuthContext ac = new AuthContext("dc=iplanet,dc=com");

ac.login();

Callback[] callbacks = null;

if (ac.hasMoreRequirements()) {

callbacks = ac.getRequirements();

if (callbacks != null) {

try {

addLoginCallbackMessage(callbacks); // this method                           sets appropriate responses in the callbacks.

ac.submitRequirements(callbacks);

} catch (Exception e) { }

}

}

if (ac.getStatus() == AuthContext.Status.SUCCESS) {

Subject subject = ac.getSubject(); // get the authenticated                    subject

Policy.setPolicy(new ISPolicy()); // change the                  policy to our own Policy

ISPermission perm = new                          ("iPlanetAMWebAgentService",

"http://www.sun.com:80", "GET");

Subject.doAs(subject, new PrivilegedExceptionAction() {

/* above statement means execute run() method of the                         Class PrivilegedExceptionAction()

as the specified subject */

public Object run() throws Exception {

AccessController.checkPermission(perm);

// the above will return quietly if the Permission                               has been granted else will throw access denied

// Exception, so if the above highlighed                                   ISPermission had not been granted, this                                  code would have

                                   // thrown an Exception.

return null;

}

});

}

}



Previous      Contents      Index      Next     


Part No: 817-7649.   Copyright 2005 Sun Microsystems, Inc. All rights reserved.