Liz Douglass

Archive for the ‘Ruby’ Category

Things I like about Buildr

with 3 comments

A few months ago the idea of myself writing such words (“Things I like about Buildr“) seemed very unlikely and I dare say that my project buddies may be surprised at the statement. Buildr, for those unfamiliar, is a build tool for Java applications that is written in Ruby. It’s key benefit is its concise and extensible nature. A bit of the wow factor of Buildr is a bit lost on me because I’ve not yet used Maven and I’ve only used Ant in some pretty straightforward ways… and I’d not used Rake prior to using Buildr. (So a strong starting point I’m sure you’d agree. Hhhmm, anyway…)

Our project buildfile started off looking very much like the example in the Buildr documentation, but has since grown significantly in functionality but not proportionally in size. We have complimented the Buildr functionality with handfuls of Rake tasks that perform other bits and pieces associated with our build, such as:

  • Deploying a WAR package to a Tomcat server
  • Starting and stopping database and Selenium servers
  • Updating and rolling back our HSQLDB and Oracle databases using LiquiBase
  • Checking the contents of the build artifacts produced using the Buildr check functionality

The time we’ve spent trawling through the documentation and getting ankle deep in the source has paid off. I want to capture how we’ve set up some of these build activities. So without further introduction and in no particular order, here are some of my favourites (drumroll):

1. Pretty packaging

In my earlier post I described how we used One-JAR to create a single JAR containing all the bits required to update/rollback a database using LiquiBase. Below is the sub-project task that is used to package the lot. The nicest things about this sub-project are how easily we’ve packaged the included JARs, and how easily we’ve added entries into the manifest file:

        define "assembly" do
            package(:jar).path("lib").tap do | p |
                p.include artifact(LIQUIBASE_JAR).to_s
                p.include artifact(HSQLDB_CLIENT_JAR).to_s
            end
            package(:jar).path("main").tap do | p |
                p.include project('database-migration').package(:jar)
            end
            package(:jar).include file('../changelog.xml')
            package(:jar).with :manifest=>manifest.merge(
                    'One-Jar-Main-Class'=>'my.package.DatabaseMigration',
                            'Main-Class'=>'com.simontuffs.onejar.Boot'
            )
        end

2. Delightful dependencies

Some of our rake tasks require us to depend on the existence of a WAR or JAR that has been packaged in one of our buildfile sub-projects. For example, the task that deploys to a Tomcat server depends on a WAR file being generated from one of our sub-projects. Thanks to Buildr, you can do something like this:

task :foo => ['rake:MyProject:MySubProject:package'] do

Note that it is also possible and extemely easy to refer to an artifact that one of your projects has created by using syntax like this:

"#{GROUP}:MyProject-MySubProject:war:#{VERSION_NUMBER}"

3. Fabulous filtering

We are using HSQLDB for development because it’s really light. Our application also needs to support Oracle though, and hence we wanted to run some of our acceptance tests using both databases. To achieve this we created another Buildr sub-project that runs some of the tests against Oracle (we already had the one that runs all the acceptance tests with HSQLDB). There are two things about this sub-project (below) that impress me. The first is that we reuse code using Buildr’s filter task. The second is how easily we can run only a subset of the tests using ‘test.include’:

            define 'my-sub-project' do
                filter(project('bar').compile.sources).into(_('my_directory_1')).run
                filter(project('bar').test.compile.sources).into(_('my_directory_2')).run
                compile.from(_('my_directory_1'))
                compile.into(_('target/classes'))
                test.compile.from(_('my_directory_2'))
                test.compile.into(_('target/test/classes'))
                test.compile.with _('target/classes')
                test.using :properties => { :my_property => property_value }
                test.include '*only_these_tests*'
                test.setup(
                    ...
                )
                test.teardown(
                    ...
                )
            end

4. Cheeky checking

Buildr callbacks can be used to extend projects. We’ve combined the after-define callback with the handy project check task to test that we’ve built what we expect to and created a number of modules like this one:

module CheckJarExists
    include Extension

    after_define do |project|
        project.enhance do
            project.check_jar_exists project
        end
    end

    def check_jar_exists project
        project.check project.package(:jar), 'should exist' do
            puts 'checking jar package exists....'
            it.should exist
        end
    end
end

And just in-case you’re like me and unsure of how to include this module in a project task, here’s how we did it:

define "subproject" do
      extend CheckJarExists
      package(:jar)
end

I’m sure there’s lots more favourites out there in the deep blue Buildr sea… happy fishing!

Advertisements

Written by lizdouglass

December 20, 2008 at 11:34 pm

Posted in Building, JARs, Java, Ruby

Tagged with , , , , , ,

Verifying encrypted passwords in OpenDS

leave a comment »

On our project we are using OpenDS as our LDAP directory service, as Damana and Mark have blogged about. A couple of weeks ago we wanted to add the ability to store encrypted passwords for our users. We discovered that OpenDS can do this for us (yay), meaning that we can enter new users into our system along with their clear text password and OpenDS will handle the encryption for us. This discovery lead to the question… how do we verify that the encrypted value actually matches the clear/plain text version we entered? There were a couple of testing alternatives that we considered:

1. Export the data for all users with the passwords in plain/clear text and verify that each matches the input value
2. Reverse engineer the clear/plain text password from the encrypted password
3. Attempt to log on as the user with their clear/plain text password

Option 1 sounded like it would minimise our testing time so we went investigated this one first. Other tests already in our code base use the OpenDS ldapsearch command line utility to query the contents of the directory server. This utility was an obvious place to start… except the search results returned did not include the password field at all… hmph…

We found out that the ldapsearch utility also has bindDN and bindPassword arguments and that it is possible to bind as the Directory Manager and see the encrypted value of the password for each user. Whilst it’s all well and good to verify that the passwords are stored in encrypted format, how do we check that they are not gibberish? The ldapsearch utility just did not have what we were after. We were hopeful that we could export the contents of the whole system (including the passwords in plain text) using another of the provided utilities, but weren’t successful in finding a way to do this.

Turning to alternative number 2 we hit upon another command line utility called encode-password. Initially we tried to use this utility to convert the known encrypted password back into plain text, but soon realised that the list of available encryption schemes did not include the SHA1 algorithm that we were using to encrypt the passwords! Then we discovered that the same utility has something called verify password mode (drumroll):

Validate password mode: Determine whether a given clear-text password is correct for a provided encoded password. In this mode, both a clear-text password (either from –clearPassword or –clearPasswordFile) and an encoded password (either from –encodedPassword or –encodedPasswordFile) are required

That meant that in our tests we could do something like this:

encode-password --clearPassword #{clear_text_password} --encodedPassword #{encrypted_password}

And then verify that the returned result was:

The provided clear-text and encoded passwords match

We ended up using this tool as well as alternative number 3 for testing (our earlier discovery of the ability to bind as a particular user in the ldapsearch utility meant that we could effectively test a users ability to ‘login’ using their plain text password and query their own details).

Written by lizdouglass

November 16, 2008 at 10:05 am