Axmor Software - Custom Solutions CompanyServicesTechnologiesQualityCase StudyContact

Technologies


Realize My Ideas
Requirements Definition Services
Secure My Solution
Software Security Services

Build a secure enterprise infrastructure with Geronimo


A real-world demonstration of Geronimo's robust security features

Ivan Dubrov, System Architect, Axmor
Artem Papkov, Solution Architect, IBM
James Smith, Manager and Managing Consultant, IBM

Originally published by IBM developerWorks in July 2005

Developing secure Java™ 2 Platform, Enterprise Edition (J2EE) applications is an essential consideration for an enterprise of any size. In this article, the IBM Advanced Technology Solutions team provides a thorough overview of the Apache Geronimo application server's security features and demonstrates how to use these features to secure enterprise applications. Learn how to build security into a real-world Geronimo application using an example that emulates a banking scenario.

The business scenario

A modern enterprise is usually a complex system that faces a lot of opportunities and challenges every day. Many of these challenges can put an enterprise's IT infrastructure at risk, so ensuring the highest possible level of IT security is crucial. The Apache Geronimo application server supports small-to-medium-sized enterprise applications and provides robust, security-minded support for the latest J2EE specification. Using the Geronimo application server lets you build a secure enterprise infrastructure conforming to the latest standards. To demonstrate the security features of Geronimo, a team of IBM experts has implemented an emulator of a simple banking scenario to show the technical capabilities of Geronimo in a real-world business situation.

The banking business scenario used for the example implements a funds transfer use case. Both retail bank customers who need to transfer funds from their account and auditors who supervise all transactions (referred to as the users) can access the application. The main security assumption is that retail bank customers may not see other users' accounts, while auditors have access to all transactions being executed by the application -- enabling them to function as administrators, or super users.

The application allows retail bank customers to:

  • Log in to enter credentials for authentication and account access authorization.
  • View account information.
  • Initiate a transfer by selecting an amount of funds and the destination of the transfer.
  • Review the status and history of initiated transactions.

The application allows bank auditors to:

  • Log in to enter credentials for authentication and authorization as a super user.
  • Review all transactions being processed by the system.

The screen shot shown in Figure 1 demonstrates the interface displayed to a retail bank customer upon initiating the fund transfer.

Figure 1. Fund transfer initiation interface
Figure 1. Fund transfer initiation interface

This article focuses on describing the protection of confidential information and resistance to man-in-the-middle attacks in which the intruder intercepts and modifies traffic between the server and the client. Transaction confidentiality is achieved with authentication and authorization facilities. These facilities exist on both the transport and the application levels. HTTPS acts as the authentication and authorization facility at the transport level, and J2EE security acts as such for the application level.

Figure 2 shows a high-level system view of the application.

Figure 2. System view of the application
Figure 2. System view of the application

The client component, shown in Figure 2, represents a computer with a Web browser used to access the application. The client interacts with the Web interface through the HTTPS protocol. This protocol is used to provide confidentiality of secure information, such as user credentials and transaction information, and protection from man-in-the-middle attacks. Access to specific pages is restricted with J2EE declarative and programmatic security to protect the pages from unauthorized access.

The Web interface consists of several Web pages and Java servlets. Servlets redirect all requests to the business logic layer using remote Enterprise JavaBeans (EJB) calls. All business logic EJB methods are secured with J2EE declarative and programmatic security to protect them from unauthorized access in case they are invoked by some component different from the Web interface of the application.

Business logic components consist of a stateless EJB and several data JavaBeans. The stateless EJB accesses the persistence layer using local EJB calls and, therefore, methods of entity beans are not protected with J2EE security.

The persistence layer consists of several Container-Managed Persistence (CMP) EJBs. The database is accessed through Java Database Connectivity (JDBC). Security of the database access relies on a JDBC driver and a database implementation. For the purposes of this article, the database management system is collocated with the application server. Therefore, the application assumes an exclusive access to the database.

The database server used in the solution is deployed onto the Apache Derby database management system embedded into Geronimo (see Resources for a link to the Apache Derby site). The database contains business information, such as account number, as well as security-related data, such as user credentials.

Set up the Geronimo application server for security

This section describes the steps you'll need to follow for configuring the Geronimo application server security. This includes setting up HTTPS support and configuring J2EE Web and EJB security.

HTTPS configuration

As the first step, configuration of the HTTPS transport for the Web container is required. HTTPS is an implementation of the HTTP protocol over the Secure Sockets Layer/Transport Layer Security (SSL/TLS) protocols (see Resources for more information).

The solution uses HTTPS transport for protecting important information, such as user credentials, while it's being passed between the server and a client. Because the most recent snapshots of the Geronimo application server come preconfigured with the HTTPS transport, you only need to place a correct certificate into Geronimo's certificate store. The default certificate supplied with the Geronimo distribution is self-signed and can be used in application development.

More information about certificates is available in the manual for the Sun Java keytool utility (see Resources). Place the certificate file in the var/security subdirectory of the Geronimo installation.

Configure general security

Once you've configured HTTPS transport, you must configure security in the Geronimo-specific deployment descriptors (deployment plans). You can do this by updating the application-wide deployment plan, EJB module deployment plan, or the Web module deployment plan.

First, declare mapping between application roles and specific principals. For each security role, a corresponding principal class and its name must be declared. The code sample in Listing 1 provides an example of such a configuration.

Note the following in Listing 1:

  • The principal org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal with the name auditor is mapped to the auditor application role.
  • The principal org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal with the name user is mapped to the user application role.
  • The principal org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal with the name system is used as a default principal when a user is not authenticated.

Listing 1. Mapping application roles to specific principals
<security xmlns="http://geronimo.apache.org/xml/ns/security">
  <default-principal realm-name="WorkdevRealm">
   <principal name="system"
    class=
    "org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal" />
  </default-principal>
  <role-mappings>
    <role role-name="user">
     <realm realm-name="WorkdevRealm">
      <principal name="user"
       class=
       "org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal" 
      />
     </realm>
    </role>
    <role role-name="auditor">
     <realm realm-name="WorkdevRealm">
      <principal name="auditor"
       class=
       "org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal"
      />
      </realm>
     </role>
  </role-mappings>
</security>
Configure the security realm

The next step is configuring the security realm, which defines mapping between user credentials (user name and password) and user roles. The roles are used later when checking whether the user is authorized to access a particular resource (such as viewing a Web page).

Configuring a security realm involves configuring three GBeans (see Resources for a link to a description of GBeans): one for login module, one for login module usage, and one for the realm itself.

The login module provides a particular part of authentication. Listing 2 shows an example of configuring an SQL login module.

In Listing 2, workdev-sql-login is the login module that is configured to use an SQL database as a source for credentials. Two SQL queries are specified -- one for selecting a list of users and corresponding passwords and another for selecting mappings between user names and group names.

Listing 2. Configuring an SQL login module
<gbean name="workdev-sql-login" class=
  "org.apache.geronimo.security.jaas.LoginModuleGBean">
    <attribute name="loginModuleClass">
        org.apache.geronimo.security.realm.providers.SQLLoginModule
    </attribute>
    <attribute name="serverSide">true</attribute>
    <attribute name="options" type="java.util.Properties">
               jdbcUser=
               jdbcPassword=
               jdbcDriver=org.apache.derby.jdbc.EmbeddedDriver
               userSelect=SELECT USER_NAME, PASSWORD FROM USERS
               groupSelect=SELECT g.GROUP_NAME AS groupname, 
               u.USER_NAME AS username FROM USERS u, 
               GROUPS g WHERE u.GROUP_ID = g.GROUP_ID
              jdbcURL=jdbc:derby:WorkingDevelopersDB
    </attribute>
    <attribute name="loginDomainName">WorkdevRealm</attribute>
</gbean>

The database is accessed using the JDBC driver specified in the JDBC URL. Geronimo is supplied with Apache Derby, an embedded relational database that is used in the sample application for storing user credentials. It's important to note that the solution accesses this database in two different ways -- from the SQL login module and from the EJB module using the DataSource that is deployed as a part of the application. Because a single Derby database instance is limited to allowing simultaneous access only through JDBC drivers loaded by the same class loader, the database configuration and SQL login module configuration must be deployed as parts of a single application.

Another GBean is configured to specify that login modules are used in the realm. This GBean lists login modules and declares the required login modules. Listing 3 shows an example of such a configuration:

Listing 3. Login modules configuration
<gbean name="workdev-sql-modules"
    class="org.apache.geronimo.security.jaas.JaasLoginModuleUse">
    <attribute name="controlFlag">REQUIRED</attribute>
    <reference name="LoginModule">
      <name>workdev-sql-login</name>
    </reference>
</gbean>

The controlFlag attribute states that this login module is required to return a valid result for the user to be authenticated. The LoginModule attribute reference points to the login module configuration.

Another GBean defines the security realm itself. Configuration consists of specifying the realm's name and referencing a GBean that configures the list of login modules that the realm consists of. Listing 4 shows an example of such a configuration.

Listing 4. Defining a realm
<gbean name="workdev-sql-realm"
    class="org.apache.geronimo.security.realm.GenericSecurityRealm">
    <attribute name="realmName">WorkdevRealm</attribute>
    <reference name="LoginModuleConfiguration">
        <name>workdev-sql-modules</name>
    </reference>
</gbean>

After these configuration steps are completed, you can configure J2EE security facilities to protect application components.

Configure Web-tier J2EE security

Geronimo supports declarative and programmatic security for the Web tier. The following sections describe these two types of security.

Declarative security

Securing the Web tier declaratively means explicitly specifying pages that require user authentication.

To use the declarative security approach, you must specify all possible security roles in the web.xml deployment descriptor. Listing 5 shows an example of such a specification.

Listing 5. Declarative security
<security-role>
	<description>Usual user</description>
	<role-name>user</role-name>
</security-role>

The security-role XML element contains a declaration of a single security role. The description element contains a textual description of the role, while the role-name element defines the role name itself.

Once declared, a role can be used to restrict access to specific Web pages. This is achieved through the security-constraint element in the Web deployment descriptor. This element describes the collection of pages to be secured and associated security constraints. Listing 6 shows an example of securing all pages using a URL mask of /user/*.

Listing 6. Specifying security constraints
<security-constraint>
<web-resource-collection>
		<web-resource-name>UserArea</web-resource-name>
		<description>User accessible pages</description>
		<url-pattern>/user/*</url-pattern>
	</web-resource-collection>
	<auth-constraint>
		<description></description>
		<role-name>user</role-name>
	</auth-constraint>
</security-constraint>

The web-resource-name element contains a name of the Web resource. The description element contains the textual description of the collection. And the web-resource-collection element specifies a pattern for pages to secure, which is the most important information in the collection definition.

The auth-constraint element is used to specify constraints for an authenticated user account that must be met prior to accessing protected pages. This element contains the description of the constraint and the name of the role (previously defined in the deployment descriptor).

Programmatic security

Programmatic security implemented in Geronimo works in the same way as described in the J2EE 1.4 specification. However, currently it contains some design flaws related to passing security context, which we'll discuss later.

In the implemented solution, programmatic security is used to implement of a servlet that redirects users to an appropriate page upon successful authorization. The goal of the servlet is validating whether a user role is authenticated and rerouting auditors to auditor's pages. All other users are redirected to the transfer page.

Listing 7 demonstrates the business logic implemented in the servlet.

Listing 7. Programmatic security example
if(req.isUserInRole("user")) {
       resp.sendRedirect("user/transfer");
} else if(req.isUserInRole("auditor")) {
       resp.sendRedirect("auditor/viewOrders");
}

For the security implementation to function correctly, the servlet is put into the secured area that only authenticated auditors and users can access. This is achieved in a way similar to the one described above for pages accessible only by users.

EJB security

Geronimo supports J2EE EJB declarative and programmatic security. In the sample application described in this article, the business logic EJB is secured so that only authenticated users can invoke specific EJB methods. You can do this through declarative or programmatic security.

Declarative security

Securing EJB methods declaratively is done according to the J2EE specification. First, security roles are declared in the EJB deployment descriptor similar to the example shown in Listing 8.

Listing 8. Declaring security roles
<security-role>
    <description>User role</description>
    <role-name>user</role-name>
</security-role>

Afterward, permissions required for executing a particular method are declared. The following code sample from the EJB deployment descriptor, shown in Listing 9, can serve as an example.

Listing 9. Setting permissions for EJB methods
<method-permission>
    <role-name>user</role-name>
    <method>
        <ejb-name>BusinessLogic</ejb-name>
        <method-intf>Remote</method-intf>
        <method-name>getOwnOrders</method-name>
        <method-params>
             <method-param>java.lang.String</method-param>
        </method-params>
    </method>
</method-permission>

In Listing 9, only authorized retail bank customers can invoke this method.

When it comes to CMP EJBs, their methods are marked unchecked, so permissions are not checked during the call. Listing 10 shows an example of this kind of configuration.

Listing 10. Marking EJB methods unchecked
<method-permission>
    <unchecked/>
    <method>
        <ejb-name>User</ejb-name>
        <method-name>*</method-name>
    </method>
</method-permission>

This configuration is still secure, because application CMP EJBs provide only local interfaces and, therefore, can only be accessed from the same EJB container. (This process doesn't work on the Geronimo snapshot from 31 May 2005. See Resources for a link to the Apache issues site, which provides more details on JIRA issue 661 and the proposed solution.)

Programmatic security

An EJB can obtain its caller principal through its context using the EJBContext.getCallerPrincipal() method. However, at the time of this writing, Geronimo contained a design flaw related to this functionality. The principal class returned by Geronimo does not contain all security information that is available in the Web container. In particular, a user name cannot be determined by the principal object, although it is available in the Web container. To overcome this problem, the sample application passes the user name explicitly when calling an EJB method. (See Resources for a link to the Apache issues site, which provides more details on JIRA issue 668.)

Conclusions

This article has described how to use security facilities provided by the Geronimo application server to build secure applications. Geronimo provides a number of facilities for securing applications at multiple levels, both declaratively and programmatically. Geronimo also provides robust functionality for building secure applications for small-to-medium-sized enterprises. It uses the latest standards and relies on J2EE specifications to provide application-level security facilities.

However, a stable release of the application server is not yet available; therefore, Geronimo still contains some issues related to J2EE support. One such issue is related to the EJB container and its inability to determine some types of caller principal information, such as user name. Also, it's worth noting that Geronimo still lacks official reference documentation, so it's somewhat difficult to find information quickly. However, because Geronimo is open source, the lack of documentation supporting it is compensated for by source code availability and user group support.

Overall, the Geronimo application server has demonstrated robust support for J2EE standards and is finding its home in small-to-medium enterprise IT.

Resources

About the authors

Ivan Dubrov is a software engineer at Axmor. He holds a bachelor of science (cum laude) degree in computer science from Novosibirsk State University. For the last year he took part in more than five Axmor projects as a system architect and a software engineer.

Artem Papkov is currently a solution architect with IBM's Client Innovation Team, working with customers and Business Partners to adopt emerging technologies, such as SOA and Web services. After graduating from the Belarusian State University of Informatics and Radioelectronics in 1998 with master's degree in computer science, he joined IBM in Research Triangle Park, NC in 2000. His experience includes software development of multitier solutions using emerging technologies, architecture design, and integration of Internet-based solutions. For the past three years he has been focused on working closely with customers, helping them adopt Web services as IBM's strategic integration technology and SOA as the integration approach.

Jim Smith has over 18 years of experience in software development. He started his career at Sandia National Labs, Livermore California, designing high-speed data acquisition systems and distributed computing systems, using a myriad of existing legacy code. With deep experience in Java language and customer-facing skills, Jim moved to the Emerging Internet Technologies team focusing on making Java solutions real for IBM customers. Jim was one of the founders of Advanced Technology Solutions (ATS), a global software services and development organization with a mission to develop, refine, and franchise advanced technologies and lightweight business processes for IBM, development labs, Business Partners, and customers, resulting in faster adoption and deployment of standard technologies and IBM products. Currently, Jim manages the organization.

Contact Us
Want to know your options? Let's talk about your project.
Examine Your Values
Custom Software DevelopmentJava Programming.NET ProgrammingMobile DevelopmentPDA DevelopmentSoftware ResourcesSite MapContact

Phone in Russia: +7 383 332 8831, Phone in USA: +1 (877) 772 9667
info@axmor.com
Copyright © 2003-2008 Axmor Software - America Inc.