Access Control in Java





Access Control in Java

In Sections 14.3 and 14.4, we examined the security options against threats associated with communications over the Internet. In this section, we study the technologies that satisfy the other category of security requirement—access control.

1 Declarative Access Control and Programmatic Access Control

Suppose that our purchase order application receives an XML request. This request has been authenticated by using one of the methods that we described in Section 14.3, so we are confident about the identity of the requester. We consider how we can impose our access control policy on this request. We assume the access control policy we mentioned in Section 14.2.2, which we repeat here for your convenience.

  • All properly authenticated companies can access the product catalog database.

  • All companies in the "trusted" category can submit a new purchase order.

  • A company can review the history of a purchase order that has been issued by the same company.

Assume that our application has three operations—(1) browse the product catalog database, (2) submit a new purchase order, and (3) review the purchase order database—and that these operations are implemented as three servlets, each of which has a distinct URL. How can we implement our access control policy?

One important concept in access control is to use a choke point. A choke point in a system is a position where all the requests must go through. A choke point is a logical place to impose an access control policy. In our system, the two obvious choke points are as follows:

  • When the servlet container authenticates a request

  • When the application accesses a database

In many cases, access control at authentication time is achieved by statically configuring the platform software, such as the servlet container. This is called declarative access control (see Figure). In this case, there is no need for the application program to take care of access control. On the other hand, some policy requires that the application itself be involved in access control decisions. In such a case, it is natural that the access control occurs when the application tries to access a protected resource. This is called programmatic access control (see Figure).

7. Two strategies of access control

graphics/14fig07.gif

We show how we can implement our policy in each case.

2 Declarative Access Control

Our first policy, "All properly authenticated companies can access the product catalog database," is best implemented as declarative access control because all that is needed to make an access control decision is authentication. In this case, we can use the access control mechanism associated with HTTP basic authentication.

To do this, we need to configure the Web server that is a frontend of our servlet container. If the frontend Web server is Apache Web Server, this configuration can be done by placing an appropriate .htaccess file in the directory that corresponds to our servlet.

Role-Based Access Control

What about our second policy, "All companies in the 'trusted' category can submit a new purchase order"?

One straightforward way to enforce this policy would be to prepare another authentication database specifically for the purchase order operation and to register all the "trusted" customers in this database. This is not, however, a desirable solution from a management point of view. For example, when a new customer is registered, you would need to update both databases. In general, the following three items should be separately managed in a corporation:

  • How to authenticate a requester

  • What role the requester is to play

  • Which application should accept what categories of requester

The idea of categorizing subjects and assigning roles to them for separating authentication from declarative access control is called role-based access control (RBAC). Subjects (in our case, requesters) are assigned their roles when authenticated, and our application should make access control decisions based on the roles, not on the identity of the individual.

Apache Tomcat, which we introduced in Chapter 10, has a primitive mechanism to assign roles to a requester. In its authentication database, $TOMCAT_HOME/conf/tomcat-users, we can assign a set of roles to each user, as shown in Listing 14.6.

Listing 14.6 Assigning roles to users, $TOMCAT_HOME/conf/tomcat-users.xml
<tomcat-users>
  <user name="maruyama" password="montelac" roles="none" />
  <user name="kosaka"  password="ymt03" roles="trustedCustomer"  />
  <user name="murata" password="frtnct" roles="administrator,
  trustedCustomer"/>
</tomcat-users>

For each application deployed on a Tomcat Server, the deployment descriptor of the application can specify the roles into which the requesters to the application must be categorized. For example, the deployment descriptor shown in Listing 14.7 requires that any requester to this application must have the trustedCustomer role.

Listing 14.7 Deployment descriptor, webapps/chap14/WEB-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>

    <security-constraint>
      <web-resource-collection>
         <web-resource-name>Protected Area</web-resource-name>
         <url-pattern>/*</url-pattern>
         <http-method>DELETE</http-method>
         <http-method>GET</http-method>
         <http-method>POST</http-method>
         <http-method>PUT</http-method>
      </web-resource-collection>
      <auth-constraint>
         <role-name>tomcat</role-name>
      </auth-constraint>
    </security-constraint>

    <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>XMLJAVA</realm-name>
    </login-config>

</web-app>

Thus, in many cases access control policies can be enforced declaratively by configuring the servlet container. Whenever the policy to implement can be enforced this way, the declarative access control method should be used to clearly separate the enforcement of the access control policies from the application development.

3 Programmatic Access Control

However, some access control policies require information that is available only after executing the application. Consider our third access control policy, "A company can review the history of a purchase order that has been issued by the same company." To implement this policy, the application would need to access the database first, and based on the retrieved data, it would need to make an access control decision. This type of access control cannot be realized in a declarative way.

To make access control decisions within an application, the application must know the identity or the role of the requester. It is desirable that the application be able to obtain this information regardless of whether the authentication method is HTTP basic authentication, SSL/TLS certificate-based client authentication, or any other authentication method. J2EE provides two methods, getUserPrincipal() and isUserInRole(), for HTTPServletRequest objects.

Security Architecture in Java

As long as the application can access the HTTPServletRequest object that represents the current request, it can use getUserPrincipal() and isUser InRole() to make access control decisions. However, this is not always possible at all the choke points where the access control policies are to be enforced. Therefore, the application must pass around the HTTPServletRequest object or the information of the subject either in an additional parameter in many methods or in a global variable. Neither of them is desirable from the application development and maintenance point of view. Therefore, it would be beneficial if a Java thread could be associated with the subject, and an application could query the subject information at any time.

In addition, because Java programs usually run in a single userid of the platform operating system, the built-in access control mechanism to OS-managed resources such as local files and network connections cannot be used directly. Again, if the subject could be used for controlling access to these resources, it would be useful for ensuring that unauthorized requesters could not gain access to these resources accidentally or intentionally.

Java 2 SDK 1.3 provides Java Authentication and Authorization Services (JAAS) as a solution to these requirements. Figure shows Java's security architecture. All the libraries that access protected resources (for example, local file systems) call the checkPermission() method of the class java.security. SecurityManager.

8. Java security architecture

graphics/14fig08.gif

The security manager decides, according to the policies, whether the access is allowed based on the following.

  • Who wrote the classes that are making the call (this information is called the code source principal).

  • Who is the subject associated with the current execution context (called the subject principal).

If the access is denied, the security manager throws an exception.

The reason Java attaches importance to the code source principal is that Java allows programs to be downloaded from the network. The security manager prevents malicious download programs from accessing protected resources via the system libraries by inspecting all the class files that constitute the calling chain up to the checkPermission() call.[7] The security policy for code source principal is managed by the class java.security.Policy, which by default reads a policy file located at $JAVA_HOME/jre/lib/security/java.policy.

[7] If the call chain includes java.security.SecurityManager.doPrivileged(), the security manager does not check the code source principals from the stack bottom to that point. This mechanism allows a trusted library to provide a service to untrusted programs with limited access to the protected resources.

A subject principal is created by a user-supplied class called a login module. The created subject is added to the current execution context by calling javax.security.auth.Subject.doAs(). The following code fragment illustrates how a login module is called to create a subject principal and how the created principal is added to the current execution context.

...
LoginContext lc = new LoginContext("loginModuleFoo");
try {
    lc.login();
} catch (LoginException le) {
    System.out.println("authentication unsuccessful"+le.
    printStackTrace());
}
Subject.doAs(lc.getSubject(), new PrivilegedAction() {
    public Object run() {
        //
        // Run under the authenticated subject
        //
        ...
       return null;
    }
});
 ...

The login module used here (referred to by the name "loginModuleFoo") must be configured in a JVM configuration file. Both creating a subject principal and attaching it to the current execution are protected operations. Therefore, both the login module and the class containing this code fragment must be given permissions for these operations under their code source principal.

Once a subject principal is added to an execution context, an application program does not need to explicitly propagate the information on the subject. At any time, an application program can test whether the current subject is allowed access to protected resources by calling checkPermission(), or it can obtain the subject information with the following code.

AccessControlContext acc = AccessController.getContext();
Subject subj = Subject.getSubject(acc);

In addition, by configuring your JVM through the class java.security.auth.Policy, you can also control access to the standard protected resources, such as local file systems and network connections.

These access control features can be used only when the security manager is enabled. By default, JVM runs without the security manager enabled. To enable the security manager, the java command line must have the following option:[8]

[8] To run Tomcat Server with the security manager enabled, you must add the -security option to the startup.cmd command.

-Djava.security.manager=

4 Security Architecture of EJB

Enterprise JavaBeans (EJB), which we introduced in Chapter 11, also has its own security model, which is consistent with the other pieces in the J2EE framework. Let us briefly touch on it. EJB allows both declarative access control and programmatic access control.

When an EJB component is called from a Web container or from another EJB container, it receives the information of the original requester. For each method of a component, declarative access control policies can be configured based on the subject's role propagated from the caller. For example, if the caller is a Web container, it passes the information on the subject that is obtained by one of the methods described in Section 14.2.2 (for example, HTTP basic authentication) to the called EJB component.

JAAS provides a mechanism for propagating subject information within a Java execution context (that is, a thread). Unfortunately, this mechanism cannot be used for EJB, because EJB components are able to call other EJB components running in other JVMs. Instead, properly configured EJB containers allow called components to share the same context as the caller component. A context may contain the subject information of the original requester.

EJB components manage contexts by means of EJBContext objects. The following two methods are provided so that an EJB component can examine the identity and the role of the subject:

  • getCallerPrincipal()

  • isCallerInRole()

EJB is a large specification, and there are a lot of features related to security. Most of these security features are related to the configuration of EJB containers and are dependent on the implementation of EJB containers. For example, your EJB container may have an ability to map a Kerberos identity to an EJB principal.[9] See the documentation of your EJB container for the details.

[9] Kerberos is a distributed authentication mechanism widely used in intranet installations.


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows