Zetetic.Ldap - Bringing LDAP + LDIF tools to .NET

2009-08-31 20:00:00 -0400

We’ve just released the Zetetic.Ldap library to github, which makes it, to the best of our collective knowledge, the first and therefore most kickin’est .NET library for working with RFC 2849 LDIF, LDAP schema, and LDAP entry change tracking.

LDIF: This file format is still the best and most universal way to move data in or out of directory systems like OpenLDAP, Active Directory, Fedora or Red Hat Directory Server, etc. Zetetic.Ldap makes it easy to write and read directory entries with LDIF.

LdifWriter ldif = new LdifWriter(@"c:\temp\stuff.ldif"); 
ldif.BeginEntry("cn=joe cool,o=zetetic");
ldif.WriteAttr("givenName", "joe");
ldif.WriteAttr("jpegPhoto", File.ReadAllBytes(@"c:\temp\joe-photo.jpeg");
ldif.WriteAttr("dateCreated", DateTime.Now);
ldif.Close();

Zetetic.Ldap knows how to format binary data, dates, and long fields in the proper way — you don’t have to mess with it!

The same is true for reading entries out of an LDIF file.

LdifEntryReader ldif = new LdifEntryReader(@"c:\temp\stuff.ldif"); 
for (Entry entry = ldif.ReadEntry(); entry != null; entry = ldif.ReadEntry())
Console.WriteLine("Found: {0}", entry.DistinguishedName");
}

We’ve also included a command-line pivoter program that transforms LDIF files into tab-delimited files, for easy loading into Excel, RDBMS, or what-have-you. This can be incredibly useful for analyzing the data in your directory.

Change tracking: Normally, if you’re using Microsoft’s System.DirectoryServices.Protocols classes, you’ve got to manage the concept of preparing specific LDAP modification commands yourself. It can get pretty complicated, and sometimes you have to resort to trial-and-error to learn the right way to delete an attribute, for example, or rename or move an entry. Zetetic.Ldap provides a wrapper around this complexity, and will track your changes until you’re ready to send them to the server.

MutableEntry entry = MutableEntry.CreateUncommitted("cn=frank grimes,o=snpp", "person");
entry.SetAttr("sn", "Grimes");
entry.CommitChanges(ldapConnection);
MutableEntry entry = new MutableEntry(mySearchResult);
entry.ClearAttr("description");
entry.CommitChanges(ldapConnection);

Schema: This part is a little more abstract. Directory servers contain an area that describes the allowable objectClasses (types) and attributes (fields), and those attributes have syntaxes (like string, number, date, etc.). The classes in Zetetic.Ldap.Schema help you work with these data programmatically, so you can quickly discover what the server supports. Moreover, you can find out what kind of value (syntax) each attribute uses conceptually, without delving into the world of OIDs.

Here’s a snippet from the project’s unit tests, showing how to export the basic objectClass definitions from a Microsoft LDAP server.

ISchemaInfo target = new AdsSchemaInfo();
using (LdapConnection conn = new LdapConnection("localhost:20389"))
{
conn.Bind(System.Net.CredentialCache.DefaultNetworkCredentials);
target.Initialize(conn);
}

foreach (ObjectClassSchema o in target.ObjectClasses)
{
System.Console.WriteLine("oc: {0}", o);
foreach (AttributeSchema a in o.MustHave)
System.Console.WriteLine(" must: {0} as {1}", a, a.LangType);

foreach (AttributeSchema a in o.MayHave)
System.Console.WriteLine(" may : {0} as {1}", a, a.LangType);
}

We also included some helpers to manage parsing special attributes like GUIDs, or “pwdLastSet” and “accountExpires,” which are usually treated like DateTimes, but stored as 64-bit integers, sometimes outside the range of what DateTime can handle—I always enjoy telling people, “Oh, it’s simply the number of 100-nanosecond intervals since January 1, 1601 UTC!”

So anyway, when you find yourself working with LDAP or LDIF on .NET, grab the release at github, and drop us a line, we’d love to know how you like it.

Interview with Subvert.ca

2009-08-19 20:00:00 -0400

There’s an extensive email-based interview of us over on Subvert.ca. There’s juicy bits about certain large companies trying to kill off one of our early projects, column fodder, and the approaches we’ve developed for taking on new clients and starting new development projects. Here’s an excerpt:

Many people we speak to find it unusual that we don’t actively prospect, solicit, or answer blind RFPs, etc

Honestly, we like it this way: when we get a referral or start a new project for a past customer, there’s already a relationship in place. The client already knows that they can trust us, and it cuts out the entire “dance” that we’d otherwise have to do to prove ourselves. There are other benefits too.

People only ask us to prepare a proposal when they are seriously considering a project. Plus, we rarely find ourselves as column fodder behind another incumbent company—we call it column fodder when you have no hope of winning a deal and your estimate is just filling in a cell on a spreadsheet for comparison purposes.

This level of trust also means that we can work more closely with our customers to develop requirements. They take our estimates and advice seriously. In the end it works out better for everyone involved.

That's a Good Plan

2009-08-16 20:00:00 -0400


Great blog post from Carl over at nGen Works about what’s he learned over the last six years running his business, in particular this list of goals, or statements of intent:

  1. Understand what we want personally and align company and individual goals as much as possible
  2. Discuss issues openly and honestly
  3. Admit mistakes and fix them
  4. Take the high road in grey areas
  5. Consistently recognize good stuff and hold people accountable for bad stuff
  6. Support each other through successes and failures

Item 1 is not something you often see out of a company, especially the larger sort. Items 2 and 3 are things that people always struggle with, and they are a nice reminder to me who runs a musical operation on the side. It’s always tempting to make unilateral decisions or to try and cover up mistakes, especially public ones, and doing so always comes back to haunt you.


Deep Thought (Sticky Email)

2009-08-16 20:00:00 -0400


Shouldn’t I be able to attach notes to an email, say in Gmail or any other mail client, for internal/personal use? Things to remember, to come back to later? Almost like Stickies, or the Task list? Obviously it would just be a local thing, for organization, but man, that would be handy. Especially in our support bucket.

Maybe that’s one of those things Outlook has always done that I was never privy to, but it strikes me as the kind of thing that’s been missing for a long time. I do remember a time when I had pieces of paper on a desk that I had to deal with, and I would often attach post-it notes to those pieces of paper, writing down reminders about what needed to be done.

Maybe a Firefox plugin like FireGPG to hack into the DOM of a Gmail inbox! Okay, back to work now.


Data Wholesalers & Monopoly

2009-08-13 20:00:00 -0400


Clay writes over on the Sunlight Labs blog:

Once you start editorializing data— well, you’ve lost both accountability and transparency as well as credibility.

Sunlight Labs is a pretty cool project, where their focus is taking all that data the government makes available and digging into it to find out what’s actually going on. And one of the problems they have with a lot of the government projects like Recovery.org is that while they espouse transparency, they don’t actually provide the raw data, they editorialize it and provide websites and displays that spin it to their advantage. When you look at it like that, it’s the opposite of transparency. In fact, if you want to set up your own data mining and digging, and you want FEC data, you’re probably better off getting it from Sunlight, who’ve already taken the time to build machine readable databases for you.

On a related note, there’s an upcoming set of presentations called BigAppsDevCamps, for those who want to use New York City municipal data in their apps. It’s probably of interest to many mobile developers, and I was planning on stopping by if I can. I think that might be an example of government being a good wholesaler, as opposed to a bad retailer. Although that depends on what they make available and how. I don’t like the notion of filing an RFP just to get access, when it’s public data.