Monday, December 29, 2008

Announcement: KeyCenter4NB 0.1

I'm very torn when it comes to choosing my Java development environment. I often swap between Eclipse and Netbeans. In fact, when I create a new project, I ensure that the project structure is compatible between the two, just in case the mood strikes me to swap back and forth. Eclipse is a fine IDE, however it is just a bit too rough around the edges in some respects for me. Netbeans, on the other hand, has some great features (UML, Matisse, a very powerful debugger and profiler, etc.) but I find it's Java editor very lacking and non-intuitive. The other problem I have with Netbeans is the lack of plugins. The Eclipse community has a far greater number of plugins available for it.

Recently, while working on some PKI-related code, I found myself wishing I had a plugin for viewing X.509 certificate details. After looking around, I really couldn't find anything suitable for my needs. I've never been really big on desktop GUI programming, mostly because I've never had the need to do it. All of my professional development has been on the J2EE side of things. However, I decided that if you want something done right you have to do it yourself, and decided I was going to write the plugin I was looking for.

After investigating both the Eclipse and Netbeans platforms, I decided to target Netbeans. I like the fact that Netbeans is pure Swing, and its GUI builder is second to none. I began playing around with module development, and was very pleasantly surprised with the experience. Yes, the Netbeans RCP has a very steep learning curve, and I've not even scratched the surface of what it is capable of. However, I've managed to create a very rough initial version of my plugin, KeyCenter4NB.

Initially, I was just looking for a plugin that would let me view the details of an X.509 certificate. However, the more I got into developing it, the more I wanted to eventually implement. As a result, the initial 0.1 version is just a certificate view. Future releases, though, will include tools for creating and manipulating Java keystores, creating PKCS #10 certificate requests, checking CRLs/OCSP, and other PKI-related functionality that a developer may need to take advantage of. A grand vision I'd like to implement (if I actually get enough time) would be a standalone application based on the Netbeans RCP that focuses on certificate and key management. However, that is a long way away.

In the meantime, check out the KeyCenter4NB project page and download version 0.1. Right now, you must download the .NBM packages and manually install them. I hope to have an update center for the project configured and running shortly. As I mentioned, it's very basic and I'm sure it's rough around the edges. But, I'll continue to update is as I learn more.

Monday, September 22, 2008

Syntax Highlighting in Blogger

Recently, I've gone through and added syntax highlighting to some of my previous posts. This was done for Java, XML, and SQL. There is a great set of CSS files and JavaScript to accomplish this called SyntaxHighlighter. The downside, however, is that Blogger does not make integrating these tools very easy. I tried several times, but always managed to screw something up. As a result, I was very happy to come across a Blogger Widget for SyntaxHighlighter. All you need to do is add this widget to your blogger layout. Remember to leave the title blank so that you don't see an empty section in your sidebar. Once you've added this widget, you can add syntax highlighting similar to what you see here. To highlight Java, for example, edit the HTML of your post and surround your Java code with :

<pre name="code" class="java">

That's all there is to it. A finished example would look like this, once highlighted:

public class MyClass {

private int myInt = -1;

public int getMyInt() {
return this.myInt;

public void setMyInt(int myInt) {
this.myInt = myInt;

Wednesday, July 30, 2008

Intro to JBoss Seam Security, Part 3 -- Authorization Rules with Drools

In previous articles, we have looked at how JBoss Seam handles security, particularly user authentication. Through the use of its Identity and Authenticator APIs, Seam provides an easy way to authenticate a prospective user without forcing a developer to implement hundreds of lines of code. In addition, Seam also provides CAPTCHA support, enabling an application to test for the presence of a human user, rather than a bot attempting to access an application. No doubt, Seam 2.1's forthcoming identity management API will make the process of creating and managing user accounts even easier. (Although, that is an article for another day)

While authentication is vital to application security, it is not the only aspect of security that must be accounted for. Authorization -- the process whereby it is determined what resources or actions a user may access -- takes authentication one step further, and cannot be overlooked. It is easy to come up with examples of where authorization should be determined within an application. A banking site would want to ensure that an authenticated user is, in fact, the owner of the bank account they are trying to access. A health insurance provider needs to check if an individual should be allowed to view recent claims that have been submitted. To accomplish this, some sort of authorization rules need to be established. Java EE already allows for programmtic authorization checks through the use of the HttpServletRequest.isUserInRole() method. Seam, however, takes authorization further and allows for integration within enterprise applications through the use of an authorization rules engine.

Seam uses the Drools business rules engine to allow complex authorization rules to exist outside of the Java code itself. Business rules engines have long been used to drive business operations or make decisions related to a specific business process (i.e. Approve a loan for an individual if they make more than $150,000 per year and have less than $25,000 in existing debt.) Now, these same types of rules can be applied to application security logic. Imagine a site like Facebook and how it approaches security. Facebook has very well-defined rules for how its information can be accessed. A profile is only visible to a member if the profile owner is friends with the member. Picture X can only be viewed by family members and friends, not coworkers. Member A can send a friend request to Member B provided that: 1) Member A != Member B, and 2) Member A is not already friends with Member B. It would be very easy to implement rules like this in Java code, either in the view or business layer. However, in our example application, we will separate these rules from our Java code and implement them using Drools.

Our simple example will be a social network site. Like any social network, ours will have some basic rules established to ensure the security of our site. The rules we will implement are:

  1. Administrators may do whatever they please
  2. A friend request may only be submitted if the sender != recipient
  3. A profile is only visible by its owner and their friends

Our example will consist of two main objects:

public class Member implements Serializable {


public Set<Member>getFriends() {

public void setFriends(Set<Member> friends) {

public class MemberAction {


private Member authenticatedMember = null;

public void viewProfile(Member member) {

public void sendFriendRequest(Member recipient) {

public void deleteProfile(Member member) {

For the sake of time, we will not discuss basic dependency injection concepts. It should be obvious that MemberAction.authenticatedMember is related to the profile of a user who has successfully authenticated against the application. There are two primary ways we can perform an authorization check in the business layer using Seam: 1) Through annotations, or 2) Inline, using Java code. In addition, we can also perform security checks in the view layer to display or hide links or data based on the outcome of the check. We will discuss all of these methods for performing the checks as we move forward.

Before we are able to write and test our security rules, we must first enable them in our Seam configuration, and ensure our rules file is located in the right place. The components.xml file must have the following lines to tell Seam that we wish to use Drools for authorization:

<drools:rule-base name="securityRules">

As you can see, we have configured our security rules file to be located at /META-INF/security.drl. It is important that this file exists, otherwise our applications will not work as we expect. To tackle our first rule, "Administrators may do whatever they please", we need to establish a rule that allows administrators to be granted whatever permissions they request. Since this is a relatively simple rule, it will serve as a good starting point for our introduction into Drools syntax. Our rule will look like this:

package MySecurityRules;


rule AdminsCanDoAnything
c: PermissionCheck(name == "member")
Role(name == "admin")

Let's take a look at the syntax for this rule. On line 1, you will see a package declaration. This is not the same as Java packages. Drools packages are used to group Drools rules together. They are not used for anything else. On lines 2 and 3, you see two import statements. This lets Drools know that we will be referrencing the specified classes as part of our rule. It is imporant to include these lines, otherwise our rule will fail. Line 4 marks the beginning of the rule itself. Our rule is called "AdminsCanDoAnything". There is no specific naming requirement for your rule, other than the fact that it must be unique within the given package. Typically, the rule name is a description of what the rule actually accomplishes. The rule is divided into 2 sections, the "when" and the "then". The "when" section consists of one or more conditions that must be true for this rule to fire. If any of these conditions is not met, the rule will not fire. Once all conditions have been met, the rules engine moves on to the "then" section, and performs whatever commands are specified.

Lines 6 and 7 provide the authorization check itself. Line 6 is the first condition that must be met for this rule to fire. The line:

c: PermissionCheck(name == "member")

can be explained as, "there must exist a PermissionCheck object with a name property of "member" within the current working memory. This object will be called 'c' in this rule." If this condition is met, the engine moves on to line 7. Line 7 specifies that, "there must exist a Role with the name 'admin' within the current memory." By now you're probably wondering, "What is 'the current memory'?" Drools has its own context or working memory that it uses when evaluating a rule. It essentially acts as a session for the rules engine. Before an object can be considered within a rule, it must be added to the working memory. Whenever a permission check is performed via the hasPermission() method, a PermissionCheck object is created and inserted into the working memory. This object contains the name of the object the check corresponds to, and the action that is being attempted. In our example, the name of the object is "member". You'll notice that we have not specified an action in our check. This results in the rule corresponding to all possible actions pertaining to member. In addition, any Roles that a user belongs to will be inserted into the working memory prior to a rule check. This is how we determine the contents of our example security rule. It is also possible to insert an arbitrary object into the working memory by calling

((RuleBasedIdentity) RuleBasedIdentity.instance()).getSecurityContext().insert();

This will come in handy in our next article as we discuss Seam security rules futher. Now that we have defined our authorization rule, we can apply it and perform a permission check. For this example, we want to hide the link for the deleteProfile action from our view layer. Normally, however, we would also apply this permission check in the action itself to prevent users from circumventing our view-layer check. To perform a permission check on our link, we simply add the following to our JSF file:

<s:link value="Delete Profile" action="#{member.deleteProfile(...)}"
rendered="#{s:hasPermission('member', 'deleteProfile', null)}" />

Now, when our view is displayed, the permission check will be performed prior to rendering the link. Since our admin users have been granted all permissions, the link will be rendered. If we wrote an additional rule restricting access to the deleteProfile(), our admins would still be able to view the link, while other users that fail the permission check will not see the link.

In my next article, I will discuss how to implement our two remaining authorization rules, as well as the other ways of performing a permission check within your code.

Saturday, July 26, 2008

Building Seam Apps for Tomcat with JBoss Tools

One of the things I really like about the Seam framework is how much easier J2EE development is, particularly with respect to pulling the various components together. With Seam, it's very easy to build applications that utilize JSF, EJBs, and JPA. However, it's often preferable to develop more lightweight applications. While EJB3 has made enterprise development much more lightweight than in the past, there is still considerable overhead associated with it, particularly when you make use of a full-blown J2EE application server like JBoss. Sometimes, it's better to utilize a simpler approach and deploy your application using a Servlet Container like Tomcat.

The JBoss Tools project goes a long way towards making the actual development process with Seam much more user friendly. JBoss Tools provides a set of Eclipse plugins designed to work seamlessly (pun intended) with the framework. One of the drawbacks of JBoss Tools, however, is its lack of proper integration when creating a project you wish to deploy to Tomcat. In this post, I'll show you the changes you'll need to make to your Eclipse projects if you want to deploy your application to Tomcat.

To start, I'll assume that you have already downloaded Tomcat and defined a Server for it in Eclipse. It's very important to remember that you need Tomcat 6, in order to have support for the Servlet 2.5 specification. Once you've downloaded and setup Tomcat in Eclipse, you're ready to create your JBoss Tools project.

Create your JBoss Tools Seam project, just as you would a regular Seam project, by clicking File->New->Seam Web Project. This will start the new project wizard. However, when selecting your Target Runtime, select your Apache Tomcat 6.0 runtime, as shown in the image below.

Click next, and select whatever project facets you may need. Click next through the wizard and fill in the appropriate fields according to your project needs, until you get to the following screen.

In this screen, be sure to select a WAR file for your deployment, as Tomcat only understands WARs, not EARs. Click Finish, and your project will be created. Now, we need to make a couple of changes to support Tomcat in our project. We'll start by ensuring that the necessary Seam libraries are a part of your project. The following libraries need to be placed in your WEB-INF/lib directory:

  • antlr.jar
  • asm.jar
  • cglib.jar
  • commons-beanutils.jar
  • common-collections.jar
  • commons-digester.jar
  • commons-lang.jar
  • commons-logging.jar
  • dom4j.jar
  • hibernate-annotations.jar
  • hibernate-commons-annotations.jar
  • hibernate-entitymanager.jar
  • hibernate.jar
  • hibernate-validator.jar
  • javassist.jar
  • jboss-archive-browsing.jar
  • jboss-el.jar
  • jboss-seam-debug.jar
  • jboss-seam.jar
  • jboss-seam-ui.jar
  • jsf-api.jar
  • jsf-facelets.jar
  • jsf-impl.jar
  • jstl.jar
  • jta.jar
  • persistence-api.jar
  • richfaces-api.jar
  • richfaces-impl.jar
  • richfaces-ui.jar
Once these libraries are in place, your project will build successfully and deploy correctly to Tomcat. Now, we need to look at the Resource configuration to support JPA for object persistence. First, we need to create a context.xml file and place it your META-INF directory. This is the file that Tomcat uses when deploying your project to setup the context root, as well as any resources that need to be made available to your project. With a JBoss deployment, your database settings are placed in a separate file, like MyProject-ds.xml. With Tomcat, we will place all of these settings in our context.xml file. Once completed, it will look like this:

<?xml version="1.0" encoding="UTF-8"?>
<Context crossContext="true" debug="5" docBase="myproject" path="/myproject" reloadable="true">
<Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" maxActive="20"
maxIdle="10" maxWait="-1" name="jdbc/myproject type="javax.sql.DataSource"
username="myuser" password="mypassword" />

We also need to modify the persistence.xml file used by JPA. The JNDI name that Tomcat utilizes differs from what JBoss uses. Instead of "java:/", our datasource needs to start with "java:comp/env". Our persistence.xml file will now look like this:

<persistence xmlns="" xsi="" schemalocation="" version="1.0">
<persistence-unit name="MyProject" type="RESOURCE_LOCAL">
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
<property name="" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />

Lastly, we need to modify some settings in our components.xml file. First, remove the jndi-pattern="@jndiPattern@" attribute from the following line:

<core:init debug="true" pattern="@jndiPattern@">

At this point, we should be ready to deploy our applicaion and test it out. Take a good look at the log files in case your application doesn't deploy correctly. However, if you followed the above steps, everything should work as expected.

Friday, March 28, 2008

Dogtag -- Open Source PKI from Red Hat

Earlier this month, Red Hat announced they were open-sourcing the PKI platform they purchased from Netscape in 2004. The resulting project, Dogtag, contains an open-source version of the code used to power Red Hat Certificate System, previously known as Netscape Certificate Management Server. While Red Hat is most known for their Linux distribution (and, more recently, their JBoss middleware products), RHCS is the basis for the world's largest PKI, developed and maintained by the U.S. Department of Defense. This PKI is responsible for nearly 10 million certificates, including those issued on the DoD's Common Access Card (CAC).

So what does this mean for the open-source community at-large? Plenty. Up until now, there has been no enterprise-class, open-source PKI solution (despite the efforts of your's truly and the Odyssi PKI project). While the community often argues that PKI is too bloated and unnecessary when compared with PGP or other lightweight products, it serves as the backbone for security in many large-scale enterprises. Being able to deploy an open-source PKI is yet one more component that Red Hat is able to provide in the application stack. This, combined with their support of the FreeIPA project for providing identity, audit, and policy management, means that Red Hat is becoming an even more formidable player in the enterprise space.

I have worked extensively with Netscape CMS, the basis for RHCS. The features, scalability, and security it provides are top-notch. In fact, many of the features in CMS served as the inspiration for things I had planned for Odyssi PKI. Will I continue development of Odyssi PKI now that Dogtag is available? Maybe, maybe not. Life seems to be getting in the way of any development projects for right now. However, in the future I may have time to continue with Odyssi PKI, or even contribute to Dogtag. We'll just have to wait and see.

Thursday, February 7, 2008

Intro to JBoss Seam Security, Part 2 - Advanced Authentication

In my last post, I gave a brief introduction into how JBoss Seam handles user authentication for web applications. By simply creating an authenticator class, it is possible to handle login/logout events for your application. Seam's ability to inject an identity object means that a user's identity can be accessed wherever necessary.

This method works great for simple use cases. But, what if you need more advanced functionality? The ability to enable/disable an account; the ability to manage account creation; the ability to add or remove a role programmatically. Suddenly, there is a lot more code necessary for our application to function appropriately. Thankfully, Seam has an answer to this problem.

The IdentityStore interface defines the methods for creating accounts, changing passwords, and many other account lifecycle functions. By implementing this interface and its corresponding methods, it is possible to hook into existing authentication stores, such as LDAP, and still be able to manage the account via an administrative interface.

Seam also provides a sample implementation that can be used to store accounts and roles in a database, JpaIdentityStore. The JpaIdentityStore class makes use of the Java Persistence API for storing account and role objects in a SQL database. In order to make use of the IdentityStore implementation, we need to tell Seam that we will be using it. In addition, we need to define the class that will be used as our account model object. To do this, we need to add the following line to our components.xml file:

<identity-management:jpa-identity-store name="identityStore" account-class="com.myapp.UserAccountModel"/>

As you can see, we have defined our account model as com.myapp.UserAccountModel. All that is needed is to implement this object and add the appropriate annotations so that JpaIdentityStore is able to make use of our data model.

The IdentityStore interface is simple enough that it can be implemented in a matter of hours. Whether you want to use JNDI, Kerberos, or a custom authentication method, it is simple to get up and running quickly. For more information on the IdentityStore and identity management APIs provided by Seam, take a look at this section in the documentation.

Next time, we'll take a further look at JpaIdentityStore and how to setup and configure it to work with your existing SQL table schema.

Wednesday, January 23, 2008

Intro to JBoss Seam Security, Part 1 - Authentication

Recently, I mentioned how I had just started working with the JBoss Seam application framework. The more I have worked with it, the more impressed I have become at how it makes things that are typically difficult using standard Java EE much simpler and more streamlined. One of the areas in which Seam really shines is security. While Java EE defines JAAS for use in securing applications, it is left up to the developer to ingrain this security down to each facet of the application. With Seam, it is easy to define security constraints at all levels of an application, simply through using annotations. In addition, the complexity of authenticating users with JAAS is reduced through Seam's authenticator mechanism. This article will give an introduction to Seam authentication, and show how to write your own custom authenticator.

Seam's authenticator construct hides the complexity of managing a JAAS configuration, and allows you to implement authentication how you see fit. Perhaps your organization relies on a simple username/password combination for authenticating user accounts in LDAP. Maybe you use a SecureID token, and the accounts are stored in a SQL database. By writing your own authenticator class, or making use of publicly available ones, you can control the way authentication is done in your organization.

To get started with your own authenticator, you must first declare it in the components.xml file. This file manages much of the configuration for Seam. To add your authenticator, you simply define the class and method that will be used for authentication. For example:

<components xmlns=""

<security:identity method="#{authenticator.authenticate}">


You'll notice the #{} syntax used here. This is JBoss' expression language pointing to a class with the instance name of authenticator, where the authenticate method will be used to login a user. Now that we have declared an authenticator to Seam, we're ready to implement it. Our example will be quite simple. If the user enters a username of admin, with a password of password, they will be authenticated successfully. In addition, we will assign them to the role of admin, so that they can perform some sort of administrative function within our application. The implementation of our authenticator would look like this:

public class Authenticator {

private static final String valid_user = "admin";
private static final String valid_password = "password";

public boolean authenticate() {
String username = Identity.instance().getUsername();
String password = Identity.instance().getPassword();

if((username.equals(valid_user)) && (password.equals(valid_password))) {
return true;

return false;

Our example is rather trivial. However, it gives a slight glimpse into how Seam authentication works. The first thing that you should notice is the @Name annotation. This annotation prompts Seam to create a bean with the name specified in the annotation. In this case, the name is authenticator, which is how we arrive at the value specified in our components.xml file. Our authenticate method will return true if authentication was successful, and false otherwise.

So how does the authenticate method get the username and password? This is done via the Identity class. The standard Identity class that comes with Seam is quite extensive, but basically provides support for a username/password combination. It is possible to subclass Identity, however, to support whatever authentication mechanisms you may need. You could implement code to support getting a SecureID token value from a user, or a SPNEGO ticket. All that is needed to make use of the Identity subclass is to add the following annotations to your implementation:

@Install(precedence = APPLICATION)
public class MyCustomIdentity extends Identity
{ ... }

Your custom Identity subclass is now ready for use.

Now that we have our authentication classes in place, we are ready to create our login form. This is trivial to create using Seam, particularly because of Seam's use of the JBoss expression language in forms. Our login form fragment would look like the following:

<h:outputlabel for="name" value="Username">
<h:inputtext id="name" value="#{identity.username}">

<h:outputlabel for="password" value="Password">
<h:inputsecret id="password" value="#{identity.password}">

<h:commandbutton value="Login" action="#{identity.login}">

That's all there is to it. You are now ready to authenticate users via your own custom login form and authenticator. While this is an introduction to the simplified form of authentication in Seam, it should give you a good foundation to learn and explore on your own.

Next time, we will look at how authentication is used throughout an application, not just at the entry point.

Thursday, January 17, 2008

JBoss Seam - J2EE Development Framework

I know I have repeatedly said that an update to OdyssiPKI is forthcoming. But, I keep getting sidetracked by interesting technologies that I just have to check out. With this update of OdyssiPKI, I decided to make it a bit more robust, and to spend more time focusing on the overall design and engineering of the application. With that came the decision to make use of EJB's, particularly EJB3. In addition, I decided to try moving away from Struts and look into Java Server Faces (JSF) for the main user interface. Of course, all these changes mean that there is a lot more that I need to get familiar with before the next release is ready.

The primary motivation for such a radical change in the project design was to make OdyssiPKI a more robust application. Currently, the user interface is very lacking. It is a simple Struts interface, and is generally not very user-friendly. In addition, the backend components of the application are very simple. Transactions, scalability, and enhanced security were not a primary focus of the first release. The combination of EJB3 and JSF makes correcting these issues much easier. The security provided by EJB3 annotations means more fine-grained control. In addition, by utilizing EJBs for the business logic, the scalability of the application is enhanced. Further, anyone who has looked at Woodstock, RichFaces, or MyFaces, and it's spinoff projects has seen what a rich interface JSF is able to provide.

The downside to all of this change? Overhead. EJB3 and JSF add a lot of overhead to the application structure. Annotations, XML files, deployment descriptors, etc. All of this creates a pretty steep learning curve, and means that development takes even longer. It is frustrating, as a developer, to have to spend so much time writing XML files when I'd rather be writing code. This is why I was very intrigued to discover JBoss Seam. Since I was already planning to develop and deploy using JBoss, it seemed like it might be worth investigating this new application framework.

JBoss Seam is an application framework designed specifically for JavaEE applications. It integrates extremely well with JSF and EJBs, as well as other Java technologies, such as Spring and Hibernate. Seam handles dependency injection as well as dependency "outjection" of various components, making it easy to assemble application services. The result? The overhead and time-to-market for JavaEE applications is drastically reduced. Seam is as close to Rapid Application Development (RAD) as I've ever seen when it comes to Java applications. And, the code generation tools included with the Seam distribution make project development even faster.

One of the most interesting tools included with Seam is seam-gen. The seam-gen utility has the ability to generate a complete project structure for Eclipse or NetBeans, simply by running Ant and answering a few questions about the overall structure of your application. Deployment descriptors, a basic interface and project files are automatically generating using the parameters you supply. In addition, you can even generate data models from an existing SQL database. All you need to do is supply the necessary connection parameters.

If you are looking for an application framework that allows you to develop robust applications very quickly, make sure you take a look at Seam. In addition, I highly recommend downloading JBoss Tools. JBoss Tools is a group of Eclipse plugins for working with JBoss, Seam, Hibernate, and other Java technologies. Getting started with Seam in Eclipse is as simple as creating a new "Seam Plugin" and following the wizard. All of the necessary files, projects, and basic classes are created for you automatically.

I'm still experimenting and getting familiar with Seam myself, but will sure to post a tutorial in the near future. In the meantime, here are a few good articles explaining Seam a bit further.

Wednesday, November 14, 2007

The Year of PKI? Finally?

Over on, there is an article saying to Expect more PKI in 2008. Since the late 1990's, several years have been deemed the "Year of PKI". The major push by the U.S. Department of Defense to build the world's largest PKI has provided a lot of momentum and investment in the PKI space. The cost of deploying smartcards across an enterprise for use with PKI, workstation login, and physical security has been greatly reduced due to the economies of scale created by DoD PKI. Microsoft's latest PKI-related products, combined with PKI integration built into Windows Server 2003 has reduced many barriers to entry for even small organizations. However, the question still remains: Will there every be a "Year of PKI?" There are many obstacles that must first be overcome before we can definitively answer that question.

Many organizations have grown comfortable with the username/password combination. Passwords aren't secure? Just change the password policy to lengthen the minimum requirements, add special characters, etc. They see no need to move towards client-side certificates, smartcard login, or other strong authentication mechanisms until a major change in their environment requires such an effort. The same is true for intra-server communication. In most organizations, data being transmitted between web servers, application servers, database servers, etc. goes over the network in plaintext. The additional effort involved in configuring SSL for dozens of servers is often enough to justify overlooking this important security fix.

Ease of Use
In the past, rolling out an enterprise-wide PKI was an enormous undertaking in terms of the amount of work required. If an organization wanted to use client-side certificates for authentication, root certificates had to be manually installed on each workstation. Users were enrolled in a time-consuming, manual process. Additionally, the PKI products themselves were often too difficult to administer. A skilled PKI expert also came with a hefty salary. Today, however, many PKI products have become more administrator-friendly. Microsoft's Certificate Server, included within Windows Server 2003, makes deploying client-side certificates much easier by integrating with an organization's existing Active Directory infrastructure. However, this would require an organization to use Active Directory throughout, which many places are unwilling to do.

By this, I do not mean on interoperability between products. There are numerous well-defined standards governing PKI that even Microsoft adheres to. I am referring to interoperability between disparate PKI setups. A PKI is a hierarchical trust system created by an organization. The root certificate serves as the basis for this trust hierarchy. The problem arises when two organizations making use of PKI want to interoperate with one another. Imagine if two PKI-enabled companies, WidgetWorld and GadgetBarn, wish to interoperate with one another. Each organization has their own root certificate. Establishing a trust between these two companies would involve exchanging root and subordinate CA certificates so that SSL and client certificates can be verified all the way up the trust chain. While there are companies such as Cybertrust or Verisign that offer CA certificate signing using a ubiquitous root, that leads us to our next, and most major obstacle.

Cost $$$
Commercial, hosted PKI solutions are typically very expensive. To have certificates that are globally trusted, however, they are necessary. It is possible to create a PKI that is internal to an organization. But, as we discussed earlier, a problem occurs if you want to extend that trust outside of your organization's boundaries. The inclusion of Microsoft Certificate Server in its Windows Server 2003 product, along with open-source PKI solutions, has greatly reduced the cost of deploying an internal PKI. However, this does not address the cost of implementing, maintaining, and monitoring the PKI. In addition, there are equipment costs associated with the servers, smartcards, and smartcard readers necessary to deploy a full-scale, enterprise-wide PKI.

So, given these issues, will there ever be a "Year of PKI?" The answer is "probably not." However, this does not mean that PKI adoption will not continue to grow within the enterprise arena. As more and more organizations realize the potential severity of a data security breach, they are increasingly looking at strong authentication solutions. The benefits to implementing a PKI begin to look very attractive when weighed against the nightmare of a major security breach. In addition, PKI adoption can enable an organization to implement additional security measures, such as encrypted file systems, 802.1x network authentication, code and e-mail digital signatures, and VPN access.

While it is clear there will be no global explosion of PKI use any time soon, the future of PKI adoption does look very bright. The number of PKI implementations will most likely continue to grow in an increasingly rapid manner. However the amount of effort and investigation required with rolling out a PKI -- as with any other security-related endeavor -- will ensure that the transition will not occur overnight.

Friday, October 5, 2007

PostgreSQL Replication with Slony-I

In an earlier blog post, we looked at synchronous, master-master replication in PostgreSQL using PGCluster. PGCluster's load balanacing and replication features provide PostgreSQL with high availability features that are not included in the core distribution. While PGCluster does provide an adequate solution for many environments, it is not the only replication mechanism available for PostgreSQL. In addition, its drawbacks may be too great to be deployed in many circumstances.

In this post, we look at another replication mechanism available for PostgreSQL, Slony-I. Slony-I is an asynchronous, master-slave replication system. With PGCluster, we had the ability to load balance connections to the PostgreSQL database, knowing that data that is modified in one server will be replicated across to the other server. Additionally, its synchronous nature gave us confidence that, in the event of a failure, all completed transactions will be accounted for. With Slony-I, we run into a very different type of replication. Slony-I is a master-slave system, designed to utilize one master database, and one or more slaves. Data is replicated in a one-way fashion, from the master to the slave(s). It does not include a built-in load balancing feature like PGCluster, and there is no automatic failover from a failed master to one of the slaves. Failover must be manually configured using a third-party utility, such as heartbeat. Slony-I's asynchronous nature means that, in the event of a database failure, there may be uncommitted transactions that have not been replicated across. Slony-I performs batching of transaction replication in order to improve performance. However, if the master fails prior to a batch of transactions being replicated, those transactions are lost.

On the surface, it may appear as though Slony-I is a less-than-ideal choice for database replication. However, upon further investigation, it becomes clear that Slony-I may be an acceptable choice, depending on the needs of your organization. In our example, we have one master and one slave. Our master is on a host called pgmaster, while the slave is on a host called pgslave. The database that we wish to replicate is called repl_test_db. The database consists of a single, basic table, repl_test_tbl.

Before we can begin replicating our data, we need to examine a few of the core concepts involved in Slony-I replication. The first is the notion of a 'cluster'. A cluster is simply a collection of database nodes that are connected together. These are the databases that will eventually be replicated. A 'replication set' describes the actual data (tables, sequences, etc.) that will be replicated. So, while a cluster describes the underlying database that will support replication, a replication set describes the underlying database objects that will be replicated.

To make our replication simpler, we will first declare some environment variables that will be used throughout the commands that we will issue. We will store these environment variables in a shell script called The contents are as follows:







Now that our environment variables have been established, we are ready to begin setting up the necessary databases. Once again, I recommend creating a shell script that will encapsulate all the commands needed to perform our setup steps. This script will first create the repltestdb database on our master host, and then ensure that the plpgsql language is installed. This step is vital, as Slony-I requires that plpgsql be installed in order to run. Once the master database has been setup, our table will be created and populated with some simple test data. From here, we begin to setup the slave host. The slave database is created, and then a pg_dump is performed to copy the initial data from our master database into the slave database. NOTE: It is important that our master and slave databases are able to communicate with each other. This will involve modifying the pg_hba.conf file to ensure that the database permissions are set properly. For more information on how to accomplish this, see the PostgreSQL 8.2 referrence manual, or the post on PGCluster replication.

For our tests, we will use a very simple table consisting of 2 columns. In our next article, we will look at the performance differences between PGCluster and Slony-I when using larger and more complex data sets. For this example, however, our simple setup will be sufficient. The SQL script looks like this:

DROP TABLE IF EXISTS repl_test_tbl;

CREATE SEQUENCE repl_test_tbl_id_seq;
CREATE TABLE repl_test_tbl (
id INTEGER DEFAULT nextval('repl_test_tbl_id_seq') NOT NULL,
my_str VARCHAR(32),

INSERT INTO repl_test_tbl (my_str) VALUES ('This is my #1 string');
INSERT INTO repl_test_tbl (my_str) VALUES ('This is my #2 string');

After our databases have been created and setup, we are ready to start initializing the replication sets. The slonik utility is used to issue commands to the Slony-I replication engine. The easiest way to enter these commands is using a shell script like the one in this example. Our replication script looks like this:


echo Setting PostgreSQL environment variables...
. ./


echo Initializing master database...

echo Initializing master database data...

echo Initializing slave database...

echo Initializing the Slony-I cluster...

slonik <<_eof_
cluster name = ${CLUSTERNAME};
node 1 admin conninfo = 'dbname=${MASTERDB} host=${MASTERHOST} user=${REPLICATIONUSER}';
node 2 admin conninfo = 'dbname=${SLAVEDB} host=${SLAVEHOST} user=${REPLICATIONUSER}';
init cluster (id = 1, comment = 'Master Node');
create set (id = 1, origin = 1, comment = 'Test repl. table');
set add table (set id = 1, origin = 1, id = 1, full qualified name = 'public.repl_test_tbl', comment = 'Test repl. table');
set add sequence (set id = 1, origin = 1, id = 2, full qualified name = 'public.repl_test_tbl_id_seq', comment = 'Test repl. table PK');

store node (id = 2, comment = 'Slave Node');
store path (server = 1, client = 2, conninfo = 'dbname=${MASTERDB} host=${MASTERHOST} user=${REPLICATIONUSER}');
store path (server = 2, client = 1, conninfo = 'dbname=${SLAVEDB} host=${SLAVEHOST} user=${REPLICATIONUSER}');
store listen (origin = 1, provider = 1, receiver = 2);
store listen (origin = 2, provider = 2, receiver = 1);

It is important to run this script as the postgres user, so make sure you su to postgres before running it. In this script, you will notice how we add our repl_test_tbl table to the replication set. It is also important to note that the repl_test_tbl_id_seq sequence must be added to the replication set as well. Slony-I requires sequences to be explicity added to the replication set, and it also requires that every table has a primary key.

Now that our cluster and replication sets have been defined, it is time to start the replication engine and subscribe to the replication set. Subscribing to a replication set tells the database to start replicating to the defined slaves. The slon command is used to start and stop the replication engine. Once again, it is best to make use of our environment variable shell script to make things easier on us. Run the first command as postgres at a command prompt on the master host, and the second set of commands on the slave host:

Master Host:
. ./

Slave Host:
. ./

If all was successful, we are ready to subscribe to the replication sets. The shell script for performing the subscription follows:


. ./
echo Subscribing to replication set...

slonik <<_eof_
cluster name = ${CLUSTERNAME};
node 1 admin conninfo = 'dbname=${MASTERDB} host=${MASTERHOST} user=${REPLICATIONUSER}';
node 2 admin conninfo = 'dbname=${SLAVEDB} host=${SLAVEHOST} user=${REPLICATIONUSER}';
subscribe set (id = 1, provider = 1, receiver = 2, forward = yes);

Once again, run this script as the postgres user. We are now ready to test our data replication. First, connect to the PostgreSQL master and do a SELECT to see the data in our table prior to replication. If you perform the same SELECT on the PostgreSQL slave, you should see the same data. This is the result of the pg_dump that we performed earlier. Now it is time to see if our replication is successful. Once again, connect to the master database, and, this time, INSERT data into our replicated table. If we have configured our replication properly, you should be able to connect to the slave database and see that the newly INSERTed data has been successfully replicated to the slave.

If you followed the steps listed above, you can see our replication works as expected. But, how does this compare to PGCluster for data replication? As evidenced by the number of commands we were required to issue above to get the replication working, it is obvious that Slony-I requires more administration and has a steeper learning curve. Slony-I also requires us to manually define the replication sets and the data to be replicated. With PGCluster, our databases are replicated automatically. This is due to the fact that PGCluster uses rsync as its underlying mechanism to replicate the data. However, this reliance on rsync may prove to reduce performance, particularly with large datasets. Slony-I uses a trigger-based mechanism for replicating the data. In addition, its asynchronous nature may win out in environments that do not need the high availablity that a synchronous, multi-master solution can provide.

So, it is obvious that PGCluster wins out in terms of ease of administration. But what about performance? You'll have to wait until my next article to see how each of these replication mechanisms handle larger datasets, including PGBench.

Friday, September 21, 2007

More PostgreSQL Replication

It appears as though my article on Synchronous Multi-Master Replication in PostgreSQL using PGCluster filled an important need. It has become the most read article on this blog in a very short time. As such, I've started wondering about the other replication mechanisms available for PostgreSQL, as well as for other databases, such as MySQL. While PGCluster does provide a good set of capabilities, it does have its drawbacks and limitations. As a result, the next PostgreSQL mechanism I will be evaluating is Slony-I. Slony-I is an asynchronous, master-slave replication mechanism. While this type of replication does not compare to the synchronous, multi-master capabilities of PGCluster, the Slony-I project is more mature, and the way replication is performed may be a better choice in some environments.

While I've found the official Slony-I documentation to be a bit thin when it comes to providing a good introduction, I did come across a lengthy introduction that has been quite helpful in getting things started. I am still working on my article about Slony-I, but, in the meantime, take a look at the Slony-I introduction to get familiar with some of the concepts used.

Monday, August 27, 2007

PostgreSQL Replication with PGCluster

I don't know why I am fascinated with databases. I don't work with them on a daily basis. I don't know very much about them. I don't have very much experience working with them. My experience is limited to a few simple SQL queries executed on open-source databases. However, for some reason, I have always been intrigued by the idea of large, complex databases. Perhaps it is because I see the business potential in making extremely large amounts of data available for analysis within a business. Or, perhaps it is due to the unique security challenges that exist when trying to make that data available to different groups of entities, each with their own security concerns. Regardless of the reason, I have become particularly interested in high-availability databases and database replication.

In an earlier post, I briefly mentioned the PGCluster project. PGCluster is an extension of the PostgreSQL database, designed to give it synchronous, multi-master replication. Replication is one of the areas in which PostgreSQL is lacking in comparison to other proprietary databases, such as Oracle or MS SQL Server. However, after playing around with PGCluster, I have become very impressed with its capabilities. If development continues, PGCluster could offer a sound solution to a very important problem that large enterprises will encounter if they wish to role out PostgreSQL in a high-availability situation.

To that end, this article will show the basics of setting up a synchronous, multi-master replicated instance of PGCluster. For simplicity and ease of use, I am running this tutorial using virtual instances of CentOS 5 deployed using the VMWare Player. I highly recommend you obtain this free utility, as it gives you the freedom to run virtual machine instances without having to pay too much. Once you have downloaded and installed VMWare Player, you can download a pre-built CentOS 5 instance to run in the player. I made a copy of the CentOS 5 VM in another directory so that I can run 2 separate, virtual instances of it for this tutorial. You will need to configure each VM instance to have bridged network support, utilizing DHCP. In a real-world scenario, you would use static IPs for addressing, but for the purposes of this tutorial it is not necessary. After starting the VM instances for the first time, you will need to install some compiler tools in order to build PGCluster. This includes gcc, bison, and flex, as well as their respective -devel packages. To install these packages, simply run the following from the command prompt in each VM instance:

yum -y install gcc gcc-c++ flex flex-devel bison bison-devel

Once your development environments are setup, you are ready to download and compile PGCluster. There are 2 different methods for building PGCluster. The first involves downloading a patch to the original PostgreSQL source distribution. You simply apply the patch prior to compiling PostgreSQL in order to add the PGCluster support. This method is very useful if there are other patches you wish to install prior to building PostgreSQL. The second method involves downloading the complete PGCluster distribution. This distribution includes the PostgreSQL source tree already patched with PGCluster. We will use the second, full-distribution method for simplicity. As of this writing, the latest version of PGCluster is 1.7.0rc5, and is available for download here. Download the tar/gz file and unpack it on each VM instance. Building PGCluster is as simple as running:

./configure; make; make install.

This will install PGCluster to /usr/local/pgsql, by default. There is more information about the installation process available at the PGCluster website. Now that we have successfully built PGCluster, it's time to start the configuration process.

First, some terminology. PGCluster consists of 3 main components:

  • Clusters
  • Load Balancers
  • Replicators
A Cluster is simply a database instance. The data in the clusters is what is replicated. A Load Balancer exists to share the query load between all the databases in the replication scheme. Lastly, the Replicator is used to replicate, or synchronize, data between all the clusters. In our tutorial, we will build a replication scheme with the following components:
  • Two clusters, clusterdb1 and clusterdb2
  • Once load balancer, pglb
  • Two replicators, pgrepl1 and pgrepl2
Our logical design will look like this when we are finished:

It is possible to install more than one PGCluster component (cluster, load balancer, replicator) on a single system. For our example, we will put 1 cluster on each VM, with the load balancer on VM 1, and the replicators on each VM. In practice, however, you may find you receive better performance by having each node run as a dedicated PGCluster component. When finished, the physical design will look like this:

Prior to configuring PGCluster, it is important to ensure that the hostnames for all the PGCluster components can be resolved to IP addresses. You may do this using DNS, or simply add the required entries to the /etc/hosts file. In our case, clusterdb1, pglb, and pgrepl1 all resolve to Both clusterdb2 and pgrepl2 resolve to

It is also important that PGCluster run as a non-privileged user. In our case, this user is postgres. You can see the steps for creating the postgres user and setting the appropriate file permissions at the PGCluster install page.

PGCluster makes use of several configuration files, each specific to the component you are installing. First, we will configure each of the clusterdb instances. In the /usr/local/pgsql/data directory, you will find 3 files that need to be modified: cluster.conf, postgresql.conf, and pg_hba.conf. The cluster.conf file defines characteristics of the database cluster, as well as the replication server that will be used. The postgresql.conf is the standard PostgreSQL configuration file. The pg_hba.conf file is used for defining PostgreSQL security and access controls. This file must be modified to trust connections originating from all other databases in the cluster. Below you will find the parameters that must be added or defined for each of these files.

<rsync_option>ssh -1</rsync_option>

host all all trust
host all all trust

tcpip_socket = true
port = 5432

Now that the cluster instances have been configured, we can configure the replicators. We have 2 replicators defined, pgrepl1 and pgrepl2. This allows for multi-master replication. The configuration files for each instance follow.

pgreplicate.conf for pgrepl1



pgreplicate.conf for pgrepl2



Once the necessary configuration changes have been made for the clusterdb and replicator instances, we can configure the load balancer. Our load balancer will be located on the same virtual machine as clusterdb1. The configuration file for the load balancer is located in /usr/local/pgsql/etc/pglb.conf. The configuration file follows below.



With our configuration out of the way, we are ready to start the services and begin working with PGCluster. The order in which you start the services is important. The order is as follows:
  1. All replicator instances
  2. All cluster instances
  3. All load balancer instances
To start the replicator services, run the following command as the postgres user on each replicator VM:

/usr/local/pgsql/bin/pgreplicate -D /usr/local/pgsql/etc

To start the clusterdb services, run the following command as the postgres user on each clusterdb VM:

/usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -o "-i" start

Lastly, to start the load balancer service, run the following command as the postgres user on the load balancer VM:

/usr/local/pgsql/bin/pglb -D /usr/local/pgsql/etc

You can find more information on how to start and stop PGCluster services on this page.

With our services started, we can begin testing PGCluster. All changes made to either database, either through a direct connection or one coming in through the load balancer, should be replicated across to all the other databases. The screenshot below shows a database being created. In this case, I ran the command against the clusterdb1 database. You can see the log output for this command in the top left VM. If you look at the lower right VM, you will see the log output for the replication that takes place between the two hosts.

The log output shows our database creation and replication was successful. From here, we can create tables, views, and other SQL objects and know that they will be replicated across to all the other systems we have configured.

If you run into problems, here are some common issues that my be creating the errors you encounter:
  • Make sure that the hostnames used for each cluster, load balancer, and replicator can be resolved to an IP address
  • Your firewall may be blocking incoming connections. Ensure that each host is able to communicate on all the necessary ports
  • Check your pg_hba.conf file if you are getting errors about rejected connections. You must set an entry for each IP address to trust in order for the data to be replicated successfully
This was just a short introduction into data replication using PGCluster. My next experiment will be to try and configure PGCluster for use with SE-PostgreSQL for added security. But, that's a post for another day.

Tuesday, August 7, 2007

Palm CAC Solution -- Mobile Smartcards for the DoD

Recently, Palm announced the availability of a Common Access Card solution for their Treo smartphone line. For those of you not familiar with the CAC, it is a smartcard designed for use within the U.S. Department of Defense. The CAC acts as an individuals ID card, with photos and information about the user's identity, as well as a smartcard with PKI credentials for logging into a network, encrypting e-mail, etc.

Palm's CAC solution is quite interesting, particularly with respect to how the smartphone interacts with the smartcard. Palm has developed a Bluetooth-enabled smartcard reader that also acts as a badge holder. The photo, name, and expiration information is still visible, but the smartcard chip itself makes contact with a reader. This allows your smartphone to make use of the credentials on the card when sending e-mail or accessing a network.

This is a truly innovative way to handle smartcards, and with more and more enterprises evaluating the use of PKI and strong authentication, I can see this being a viable solution for the commercial world, as well. The phone itself doesn't have any bulky externally-attached readers. This makes it possible to maintain the phone's current usability and mobility, without sacrificing the security that smartcards provide.

The possibilities are endless when discussing how this technology could be used within the enterprise. Users can login to the corporate VPN from anywhere in the world, using mobile broadband connections or even WiFi (provided you have an adapter for your phone). E-mails can be digitally signed and encrypted prior to being sent. Given the lack of security in public WiFi hotspots, this is a capability that is long overdue. In addition, being able to encrypt the data on the phone itself, or lockdown access to it without the smartcard, provides the user with confidence that a lost phone will not result in data compromise.

For more information on how this product works, see Palm's Flash demo.

Monday, July 30, 2007

Java - Implement your own Service Provider Interface

As I continue development on the next release of Odyssi PKI, I've tried to apply some of the lessons I've learned regarding extensibility in object-oriented code. Version 0.1 of Odyssi PKI was relatively static, in terms of what formats and technologies were supported. The request types that the CA was able to handle were statically defined. While you could implement the X509CertificateRequest interface to define your own request format, the rest of the CA was unable to handle the request beyond a certain point. This made for a very limited, inflexible design. Want to add XKMS support? Get ready to rework a LOT of code. As a result, this lack of preparation for the future was high on my list of things to redesign for the next release.

As I sought out the best way to handle this problem, I realized that working with X.509 certificate request formats/objects is very similar to the way Java already handles certificates, encryption keys, and signature algorithms. In each case, the algorithms and formats for these objects is implemented through the use of a Service Provider Interface (SPI). In this example, the SPI is the implementation of the Java Cryptography Extension that is configured for the JVM. If your preferred algorithm is not supported, perhaps one of the other JCE implementations has it. All that is needed is to configure the JVM to recognize the JCE implementation, and ensure that it is located on your classpath.

Upon realizing this, I decided that there must be a way to take advantage of this type of design to handle X.509 certificate request objects. I needed to look no further than Java's ServiceLoader class. The ServiceLoader class is used to locate classes that implement a given SPI interface or extend an abstract SPI base class. In our example, we have several classes and interfaces that will be used to handle X.509 certificate request objects. The first interface is X509CertificateRequest. This interface defines several methods that are common to all types of certificate requests: getPublicKey(), getSignatureAlgorithm(), etc. We also define a class called X509CertificateRequestFactory. This class is a factory class that creates X509CertificateRequest objects. It is also the class that will make use of the ServiceLoader object. Lastly, we need to define an interface called X509CertificateRequestFactorySpi. This interface defines the methods that must be present in all of our SPI implementations. We'll look at X509CertificateRequestFactory first, as it is the most important.

The X509CertificateRequestFactory class has a static method called getInstance() that takes as its parameter a certificate request format. This format could be PKCS #10, XKMS, CRMF, or any other format that we like, so long as we have an SPI implementation for it. The constructor for this class is private, and takes a X509CertificateRequestFactorySpi object as its only parameter. This is done because the SPI implementation object will be used by the factory class to provide all of its underlying functionality.

Now that we've discussed the general structure of the factory class, let's look at the SPI interface and the methods it defines. Since the X509CertificateRequestFactorySpi class is used to provide all of the underlying functionality for the request factory, it must provide methods such as getCertificateRequest(...) that will be used to generate the request object itself from another object (byte[], String, XML document, etc.) In addition, another method isSupported() is defined, which takes as its only parameter a String, denoting the request format. This method returns true if the request format is supported by this SPI implementation.

So how do we use the ServiceLoader class? The ServiceLoader class looks for a provider configuration file located in the META-INF/services directory of the SPI implementation's JAR file. This file is the fully-qualified binary name of the services type. That is, if our request factory's full name is net.odyssi.certserv.x509.request.X509CertificateRequestFactory, the provider configuration file would be called net.odyssi.certserv.x509.request.X509CertificateRequestFactory, and would be located in the META-INF/services directory of the implementation JAR file. This file contains the name(s) of the SPI implementation class(es) contained within the JAR. So, for example, if we wanted to support PKCS #10 certificate requests, our provider configuration file may have one entry that reads:


The PKCS10CertificateRequestFactory class provides all of the dirty work in generating an X509CertificateRequest object from an arbitrary source, such as an InputStream or a byte[]. Now that we've defined our provider configuration file with our SPI implementation class, we're ready to put the ServiceLoader class to work.

Within the getInstance() method of the X509CertificateRequestFactory class, we would have the following:

public static X509CertificateRequestFactory getInstance(String format) {

ServiceLoader sl = ServiceLoader.load(X509CertificateRequestFactorySpi.class);
Iterator it = sl.iterator();
while(it.hasNext()) {
X509CertificateRequestFactorySpi impl = (X509CertificateRequestFactorySpi);
if(impl.isSupported(format)) {
return new X509CertificateRequestFactory(impl);

return null;

In this method, the ServiceLoader sl = ServiceLoader.class(X509CertificateRequestFactorySpi.class) line instructs the ServiceLoader to find all implementations of the X509CertificateRequestFactorySpi interface. From here, we iterate through the returned results and see if an implementation can be found for the given request format. The returned X509CertificateFactory would then used the SPI implementation to provide its underlying functionality for getCertificateRequest(...), etc.

The ServiceLoader class provides a great mechanism for adding functionality and future-proofing your applications. Unlike other mechanisms such as Spring's dependency injection, no modifications are necessary for your code to take advantage of the new SPI implementation. The SPI implementation JAR file simply needs to be located on the classpath for the functionality to be available. By making use of a well defined SPI, it is possible to interchange components with your application without losing functionality. It also provides a great way of adding new capabilities to your already existing applications. For more information about ServiceLoader, take a look at the javadocs, or this article.

Thursday, July 26, 2007

PostgreSQL Replication - PGCluster

Earlier, I did an article on MySQL multi-master replication. While MySQL is a very fast database, able to provide the vast majority of features that most people need, there are definite shortcomings. As a result, I've begun looking more and more into PostgreSQL as my database of choice for my development work. The major shortcoming for me, however, has always been PostgreSQL's replication and failover support. The Slony-I project provides replication, however it is asynchronous and master-slave. In many environments, this just isn't good enough. I came across PGCluster, only to see on its project site that the latest code was for PostgreSQL 7.3.

At first, I thought that this was reason enough to abandon PostgreSQL and focus primarily on MySQL. However, I have since found that I am mistaken. The PGCluster site that I initially came across was an old site for the project. The new PGCluster site shows that PGCluster has been updated for PostgreSQL 8.2. This is great news for anyone looking to use PostgreSQL in an enterprise-wide capacity. PGCluster provides synchronous, multi-master replication. It is designed for high-availability, as well as load-balancing. While I haven't had a chance to install the latest version of PGCluster, I will be giving it a long, hard look in the near future.

While working on the Odyssi PKI project's next release, I've spent a bit more time focusing on the database aspect. Certificate Authority servers are typically considered to have high-security requirements, so they are often run using dedicated database servers. You wouldn't typically want your certificate data in the same database server with your general business data. Normally, the database instance is dedicated to the CA, and is hardened for security to prevent compromise. However, in situations where high numbers of certificates are issued, performance and scalability may become a factor. In a hosted PKI environment, for example, large numbers of certificates being issued may put a strain on the database server. In addition, CA servers have high availability requirements, particularly for CRL issuance, etc. The need for failover replication becomes apparent.

With PGCluster, it is possible to implement a database architecture that allows for the performance and reliability needed for this type of scenario. The example provided on the PGCluster website shows a simple replication scenario between 3 servers; two are located in close proximity, with the third connecting remotely over a VPN. When designing a database layout for an Odyssi PKI deployment, you would typically want to have a minimum of 2 databases, acting in a load-balanced, multi-master configuration. This will provide you with failover capability in the event of a server failure, as well as the ability to split processing between servers.

Starting with Odyssi PKI's next release, I plan to include some documentation outlining recommended architecture, best-practices, etc. for designing a PKI. Now that I have discovered PGCluster is not a dead project, I will be sure to use it in my examples.