As we are scaling our server-side infrastructure at GinzaMetrics, a relatively minor problem initially became a major pain: the proliferation of internal web panels for the various tools we use.
Right now we use Icinga for monitoring, Munin for basic server health metrics, Resque-web for managing job queues, Jenkins to run our test suite and build Ubuntu packages; in the near future we plan to introduce also Rundeck as a command-and-control panel, Logstash to gather log messages from all the processes and machines, Graphite for custom metrics, and that is probably not going to be the end of it. We also use Github, Google Apps, Exceptional, and Trello, but because these are hosted, we don’t have to worry about managing these services.
Still, we have a bunch of internal services that shouldn’t be public, but authenticating the access is not trivial. Regular htpasswd is tricky to synchronize, and makes it hard for users to change their passwords.
LDAP? No. Just no.
We’ve tried OpenID with mod_auth_openid for Apache, and didn’t like that either: you have to authenticate to every server separately, have to reauthenticate often, it’s hard to log out, and – which is the biggest problem – we found no public OpenID provider that would be reliable enough, and didn’t want to run our own. Being locked out of monitoring panel because of MyOpenID is down again is not a good thing. Then there are complex identity management or SSO solutions like FreeIPA, Shibboleth, CAS, and so on – these are very complex and seem like an overkill for a startup of less than 10 people.
During the search, I found something promising: GodAuth script for Apache’s mod_perl. It gave us precisely what we needed: a transparent authentication for Apache, shared within a single subdomain, based on a signed domain cookie – which means authenticating once to all services, and an easy, shared logout.
However, it seemed more like a proof-of-concept sketch than an actual solution. The installation setup is fully manual: put this file here, add that path there, copy Perl/regexp based config somewhere else, and so on. There is no actual login application, only the cookie verification part. Also, it doesn’t have one feature that we need: when user is logged in, we need the application to see the REMOTE_USER environment variable as if the user has been authenticated with a regular HTTP auth. This allows us to integrate the login name in all the underlying programs without need to modify them – they either use HTTP auth as default authentication scheme, or can be configured to just trust the frontend HTTP server about user’s identity.
So I took GodAuth, forked it, and released a new, polished, easier to install, REMOTE_USER supporting version – with the actual login application on top of it. This is big enough deviation from the original, so I’ve decided to give it its own name: Odin Authenticator.
The basis is the same: authentication ticket an HTTP cookie set for a common subdomain, HMAC-signed with a shared secret, detailing user’s name, roles, and a timestamp. An “authorizer” webapp on root of the subdomain verifies user’s identity (in case of published sample authorizer app, by calling out to Google Apps and checking if user is logged in under a configured domain – this avoids the “yet another password” problem, and makes it easy for user to change the password). The mod_perl handler is hosted on CPAN as the Apache2::Authen::OdinAuth module to make installation simpler. Configuration is a YAML file, not a Perl module (it’s still regexp-based, though – I still need to think about it and probably redesign it a bit to roll it into Apache’s main config).
The software is far from complete (and it goes without saying that it’s released “as is”, without any warranty; the crypto part looks good to us, but we can’t promise that it’s really bulletproof). Some things to look into and fix/extend are Apache handler configuration (which I’ve already mentioned), authorized webapp and making it more flexible, supporting different sources of identity and multi-factor authentication, role-based access control (or maybe we should just push it off to Apache by mimicking HTTP auth even more?). More eyeballs on the crypto part would sure be useful.
Get Odin at http://ginzamarkets.github.com/odin_authenticator/ and have fun using it! We do.
A deck we used to announce Odin at a Ruby / Python in Warsaw this week: