Wednesday, July 6, 2011

ReviewBoard and Microsoft Acitive Directory Authentication

In an effort to get ReviewBoard 1.6 RC1 to use Microsoft Active Directory for user authentication, an obstacle was encountered.  After changing the authentication method from the default Standard Registration to Active Directory with "Use TLS for authentication" enabled, LDAP+TLS communications resulted in an TLS "Unknown CA" fatal alert message.

Before getting into the LDAP+TLS "Unknown CA" fatal message, here are some relevant environment details.  ReviewBoard was installed on a Ubuntu Lucid 10.04 machine with OpenLDAP 2.4.25 client tools installed.  A test site was created using SQLite for the database backend and Lighttpd for the web server.  Active Directory uses certificates generated by an internal certification authority that uses a self-signed root certificate.  The self-signed CA certificate was saved to the /usr/share/ca-certificates/example.com directory, dpkg-reconfigure ca-certificates was executed, the user's $HOME/.ldaprc file was edited to contain TLS_CACERTDIR /usr/share/ca-certificates/example.com and the following test command completed successfully.

ldapsearch -v -d 1 -H ldaps://msad.example.com/ -x -W -D user@example.com -b DC=example,DC=com '(&(objectClass=user)(userPrincipalName=user@example.com))'

Though running OpenLDAP commands from a terminal succeed, ReviewBoard authentication would fail with a "Incorrect username or password." message.  The following test Python script was used to verify there was no issue with Python and LDAP+SSL or LDAP+TLS:

#!/usr/bin/env python

import ldap, ssl
from M2Crypto import X509

host = 'msad.example.com'
# Missing newline before end tag: http://bugs.python.org/issue8086
pem = ssl.get_server_certificate((host, 636)).replace('-----END CERTIFICATE-----', '\n-----END CERTIFICATE-----')
x509 = X509.load_cert_string(pem)
print x509.as_text()
print pem

l = ldap.initialize('ldap://' + host + ':389')
l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
l.start_tls_s()
l.simple_bind_s('user@example.com', 'password')
e = l.search_s('DC=example,DC=com', ldap.SCOPE_SUBTREE, '(&(objectClass=user)(sAMAccountName=user*))')
print e
del l

The solution to the LDAP+TLS "Unknown CA" fatal message during ReviewBoard Active Directory authentication turns out to be pretty simple.  After reviewing the $RB_SITE_HOME/htdocs/reviewboard.fcgi file, it was noted that the HOME environment variable is changed to $RB_SITE_HOME/data.  In this directory, add a ldaprc file containing "TLS_CACERTDIR /usr/share/ca-certificates/example.com".  You should now be able to log in using an Active Directory account.  You can still log in with the built-in administrator account created during installation to perform administrative maintenance.

Saturday, December 13, 2008

Castles In The Air

[Copied from JRoller blog]

When I first read the abstract for Dreaming In Code by Scott Rosenberg, I figured it to be light reading to give my mind a break from other, more technical books on my nightstand.  Little did I realize that once I read past chapter 8, this little book would spark so many questions that I would have sleepless nights wondering "will we ever learn how to create software quickly and efficiently?"

In The Mythical Man-Month, Frederick P. Brooks, Jr. eloquently prosed "The programmer, like the poet, works only slightly removed from pure thought-stuff.  He builds his castles in the air, from air, creating by exertion of the imagination."  Henry David Thoreau is often quoted, "Do not worry if you have built your castles in the air.  They are where they should be.  Now put the foundations under them."

As programmers, we conceive great abstract structures in our imaginations, but are also charged with building the foundations from which these abstractions come into fruition.  Programmers are more like artisans than poets.  The fruits of an artisan's labors will only be enjoyed by others if she limits her abstract scaffolding to only build abstractions which may be transformed into concrete shape with the tools of the day.  The poet is freed from the shackles and limitations of an abstract scaffolding, she is free to create whatever comes to her imagination.

Here en lies the dilemma.  Some of us software-folk are poets, some are master artisans and some are artisans.  The poets create the castles in the air, oblivious of any foundations under them.  They can envision software-thoughts which are unattainable with today's tools, castles which remain suspended in space and time until such time foundations can be created to support these castles.  Master artisans are skilled in creating the artisan's tools, progressing the tools ahead, empowering the artisan to be more efficient and to one day create the poet's castle.  The artisan is a master of the tools and understands how to use and manipulate them to create achievable abstractions, at times using the tools in new and creative ways to make previously unattainable structures attainable.  Business managers and project managers are taught to make S.M.A.R.T. goals to promote success.  The artisan is more likely to practice building S.M.A.R.T. goals in her craft work, where the poet wishes to be removed from such constraints.

As for the Chandler project, it is but one of many projects where poets and artisans, practitioners of free will to create great things, suffered from thoughts and ideas which were to far ahead of the capabilities of existing tools.  There is a fine line poets and artisans must walk in order to create that which may be enjoyed and scrutinized by others.  Will we ever learn how to create software quickly and efficiently?  Sure.  However, with regards to enterprise and commercial software, I respectfully disagree with Frederick Brooks; programmers should not be creating castles in the air.  This type of creativity should be left to the poet, not the artisan.

Tuesday, February 19, 2008

Groovy Performance Woes?

[Copied from JRoller blog]

These days, everyone's got something to say about Groovy. Whether it's "the good, the bad or the ugly," Groovy is making great leaps with all its deserved, or undeserved, publicity. With every tool available to the software developer, there are pros and cons; scenarios in which the tool works miracles or reaps havoc. The main determining factor of success or failure is attitude.

Attitude! "An organismic state of readiness to respond in a characteristic way to a stimulus." (Dictionary.com) It is that which makes or breaks the constructs of our lives. "Everything can be taken from a man but ... the last of the human freedoms - to choose one's attitude in any given set of circumstances, to choose one's own way." (Viktor Emil Frankl) "Happiness is an attitude. We either make ourselves miserable, or happy and strong. The amount of work is the same." (Francesca Reigler) My beautiful wife brought to my attention a website which reminds me time and again just how important attitude is in our everyday life. Attitude is the difference between happiness and misery.

This mindset applies just as whole-heartedly to software development. We can make the best of and improve on the tools we have, or dwell on their problems; "the amount of work is the same." Groovy, as with all tools, has its pros and cons. But I won't go into its cons; there's enough of that out there. I'm here to tell you how Groovy has proven to be a tool capable of great strides. Groovy has provided me with the ability to create a wonderful database migration tool. It has endowed me with a level of flexibility capable of migrating data from legacy mainframe and Windows sources containing some more than 100 million records to a newly created database. Migrating one set of records includes some 100+ SQL statements to read, insert and update records (and that's with query resultset caching enabled for static data). Granted, Groovy isn't doing all of the legwork (Spring Framework, Hibernate and Drools play a big role as well), but it is the glue which ties everything together.

This all happens in a matter of seconds. In three seconds, some 200+ Groovy scripts are executed as data transformation tasks. The first time scripts are encountered, they are dynamically compiled to class files using Groovy's ClassLoader and CompilationUnit. Subsequent script executions do not require compilation, even across JVM instantiations. Roughly 5% of the application time is spent in Java and Groovy code. Most of the rest of the time is spent waiting on I/O requests. That works out to about 150 milliseconds in Java and Groovy code, per set of records being migrated, to massage the data. Considering the volume of data and number of business rules being applied, this is quite an achievement.

I hope to have some time in the near future to put together a small test application demonstrating the use of GroovyClassLoader and CompilationUnit to compare a Groovy application's performance with and without the compilation step. Depending on your requirements, using Groovy as glue code could be just as performant as using Java. Groovy can help reduce a project's total man-hours, decrease other resource consumption, increase productivity and provide flexibility to change in key areas. That is, if you have the right attitude.

Thursday, December 6, 2007

Secure TN3270 z/OS Sessions in Linux

For the past year, I've dual-booted my work laptop in Windows in order to connect to our IBM z/OS mainframe using the secure TN3270 emulator supported in our environment.  Tired of dual-booting, I finally decided to figure out how to avoid booting into Windows.  Quite simple really.  I have already been using x3270 to connect to Unix System Services for z/OS and just read the MANPAGE to find out that I could use:

x3270 L:zos.host.name:23

to make a secure TN3270 connection.  Now I ... finally! ... have no reason to ever boot into Windows.

Saturday, November 10, 2007

Start/Stop OpenVPN with ifupdown

Starting and stopping OpenVPN in Debian or Ubuntu Gutsy when an interface comes up and down is as easy as adding a single line to your /etc/network/interfaces configuration file.  After a while of searching for a clean way to do this, I came upon this mailing list post.  Sure enough, /usr/share/doc/openvpn/README.Debian.gz had all the gory details (nothing in the man pages for interfaces or openvpn).

Quick /etc/network/interfaces example:

iface eth0 inet dhcp

openvpn my-vpn

The my-vpn is used to select the appropriate OpenVPN configuration file (.conf extension) in the /etc/openvpn directory.  After adding the above configuration, ifup eth0 and ifdown eth0 will start/stop the OpenVPN connection.

Friday, October 19, 2007

Driving Down the Developer Path

Sometimes, the world of a developer can seem overwhelming.  With so many choices at our disposal, there are a lot of questions that must be asked and answered.  Which web framework do I use?  Which design pattern is best suited for this problem?  Do I use Java or a dynamic scripting language?  How much test coverage is too much?  Too little?  What shortcuts are acceptable in order to meet deadlines?  Driving down the developer path sometimes reminds me of driving through Manhattan during rush hour on a Friday afternoon; if you're not alert and on your toes you just might find yourself in the middle of a 10 car pile-up.

But not everyone wants to drive in Manhattan during rush hour.  Some like the relaxed and picturesque drive on the roads of a quiet suburb outside of Denver, Colorado, with the convertible top down and the wind blowing through their hair.  Some like the straight lines of Florida roads, in their souped up Corvette, with their radar detector and the occasional opportunity to "let it breath!"  Some like the twists and turns of the Smoky Mountains, on two wheels, staring death right in the eyes at every turn as their knees scrape asphalt.  Some just have all the time in the world and are in no rush to get anywhere, oblivious of the other road patrons around them.

In many ways, software development is like driving.  The language we use, as with the vehicle we drive, is the tool we use to get from point A to point B.  Coupe, sedan, station wagon, minivan, motorcycle; Java, C#, C++, FORTRAN, Python, Perl.  A project that you work on is like taking a road trip.  The project plan and the AAA trip planner serve the function of laying out the optimum path to get you to your goal.  Once you start on your merry way, it's understood that the possibility exists that you will be confronted with some decisions to avoid undesirable situations.  A domain model change can be like an unannounced road construction.  A use-case change can be like a sudden downpour.

There are many analogies between driving to work in the morning and driving down the developer path.  And maybe, taking a moment to stop and think about those analogies will help one to understand what their goals are as a developer.  A vehicle will take you but so far before it's useful life has ended.  The same is true about the development tools you use.  Automobiles pretty much all work the same; you steer, you go and you stop.  Programming languages pretty much all work the same.  Syntax and semantics aside, they all fulfill the ultimate goal of dictating what the computer should do.  Where we fit into the picture is in coming up with paradigms and methodologies that best fit our character, goals, ambitions and dreams.

This is my (hopefully not so feeble) attempt in bringing about thought-provoking and stimulating ideas from the developer community.  What analogies have you been introduced to that helped you to "think outside the box?"  To drive you to "go that extra mile" and come up with some innovative idea that (and it needn't necessarily be an original idea in the community, but original to you) had you say to yourself, "why didn't I think of that before?"

Friday, October 12, 2007

Groovy Class Extension Gotcha

I've recently upgraded Groovy from 1.0-JSR-6 to 1.0 and started getting "No signature of method: static ... for argument types: ..." errors.  Upgrading further to version 1.1-beta3 exhibited the same behavior.  As an example, the following Groovy script will generate an error using Groovy version 1.0:

class S1 {
static String concat(String s, String c) {
  return s + c
}
}

class S2 extends S1 {
  static String concat(String s, Integer i) {
    return s + i
  }
}

println "Calling S2.concat(String,Integer) ..."
println S2.concat('foo', 1)
def m = S2.getMethod('concat', [String, String] as Class[])
println "S2.concat(String,String)=${m}\n\nCalling S2.concat(String,String) ..."
println S2.concat('foo', '1')

After a bit of searching, I found a Groovy Jira issue which explains the Groovy behavior for static method calls on subclasses is that "a static method is callable only on the class it is defined on."  This means care must be taken to ensure subclass inherited static method calls are avoided in certain versions of Groovy.

A number of approaches to get around this are:

  1. If you can, upgrade to Groovy version 1.1-RC1 which allows inherited static method calls.
  2. Change all inherited static method calls to use the class in which the static method is declared.
  3. Change all inherited static method calls to use an instance method call.
  4. Modify the subclass to include static methods delegating to the superclass static methods.
  5. Use Groovy version 1.0-JSR-6.

Java developers are accustomed to subclasses inheriting static methods from their superclass.  So Groovy's behavior with static methods should not be overlooked as a Groovy gotcha.  I've tested this behavior in versions 1.0-JSR-6, 1.0 and 1.1-beta3. 

UPDATE: Moments after posting this blog, Groovy version 1.1-RC1 was released.  I tested version 1.1-RC1 today (2007/10/14) and have found the above snippet will work properly.  Looking at the groovy.lang.MetaClassImpl.invokeStaticMethod() code shows that static methods are now being searched for by traversing up the class hierarchy.