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 (Java EE) 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 Java EE 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.
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 Java EE security acts as such for the application level.
Figure 2 shows a high-level 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 Java EE 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 Java EE 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 Java EE 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 Java EE 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.
<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.
<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:
<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.
<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 Java EE security facilities to protect application components.
Configure Web-tier Java EE 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.
<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/*.
<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 Java EE 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.
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 Java EE 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 Java EE specification. First, security roles are declared in the EJB deployment descriptor similar to the example shown in Listing 8.
<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.
<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.
<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 Java EE 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 Java EE 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 Java EE standards and is finding its home in small-to-medium enterprise IT.
- Participate in the discussion forum.
- Visit the Apache site for Geronimo documentation.
- The Geronimo Wiki gives you information about compiling Geronimo from source code.
- Get information on RFC2818, which describes HTTP over TLS.
- Take a look at the specification for SSL Version 3.
- Get information on RFC 2246, which describes the TLS specification.
- Learn more about JIRA issue 661, including details and the proposed solution to the unchecked permissions bug.
- Learn more about JIRA issue 668, including details and the proposed solution to the lost security context information (user name).
- See the information page for Sun's keytool, a key and certificate management utility.
- Get details on Geronimo's GBean architecture.
- Get acquainted with the Apache Derby Incubator project.
- Read the two-part series on Geronimo. Part 1, "The Java EE 1.4 engine that could" is an introduction and conceptual overview to Geronimo. Part 2, "Tame this Java EE 1.4 bronco" covers Geronimo configuration, deployment, management, and provides hands-on examples of deploying Web applications and EJBs (developerWorks, May 2005).
- Download Gluecode Standard Edition, a free application server based on Apache Geronimo.
- Visit the official site for the Geronimo project to access the latest source code, binaries, and an active community on the mailing lists and wiki.
- See the Apache Geronimo project area for a complete listing of free open source resources from developerWorks.
- Browse all the Apache articles and free Apache tutorials available in the developerWorks Open source area.
- Get involved in the developerWorks community by participating in
developerWorks
blogs.
- Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
- Innovate your next open source development project with IBM trial software, available for download or on DVD.
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.
|