So we deployed an ADXSTUDIO site onto ADAM (see my earlier post) but the out-the-box permissions editor didn't support ADAM, only full AD. We managed however to override the default permissions editor with our own - more on how we did that with ADXSTUDIO later.
For now I'd like to take our experiences and do a short blog series on writing your own permissions editor for AD or ADAM by using ONLY the DirectoryServices namespace in .NET2. The Microsoft documentation is pretty poor on the DirectoryServices side of things and badly lacking in examples and explanations. There's plenty of tidbits in blogs here and there and even a couple of books on the subject, but all of them are lacking in bringing together exactly what you need to know and why. So, by trial, error and sheer pigheadedness, I had to get to the bottom of it all. I'd like to share it with you and hopefully it will be of use.
To set expectations - I'm not going to plaster my blog with code samples. You're a coder - you write code. You can do that yourself. What I will do is explain what classes you need, why you need them and what you do with them. This will apply equally to doing most things with AD/ADAM permissions, not just writing a permissions editor.
So firstly let's do a quick glossary/terminology check. There's a lot of acronyms etc. that fly around when talking about permissions and you probably know some or most of them already, but let's summarise them so that we're all starting from the same point:
- AD - Active Directory, Microsoft's LDAP implementation - I might call it 'full AD' by which I mean that it is a domain-wide AD implementation. AD is licensed by CAL and cost can be high
- ADAM (or AD/AM) - Active Directory Application Mode - a FREE version of AD which runs as a standalone 'instance' as opposed to a domain. It is effectively an LDAP provider for use by an application rather than an enterprise. You can have multiple ADAM 'instances' per server, but an ADAM instance cannot talk to other 'instances' or join a full AD farm. Otherwise, it is identical to AD in terms of API calls.
- CAL - Client Access License, a way of licensing per-user and typically how Windows Server 2003 / AD is licensed
- ACE - Access Control Entry - something attached to an object which says that somebody can (or cannot) do something with it. ACE's can be applied to files, websites and AD objects but we're only bothered about ACE's on AD objects. A typical ACE might be something like 'User [John Doe] can [Read the contents] of the AD container [Computers]'
- ACL - Access Control List - A list containing a number of ACE's. All objects in AD have an ACL which contains the ACE's that apply to that object.
- DACL - Discretionary Access Control List - There are two ACL's on all AD objects and this is the main one - A strange name for the general permissions on who can do what on the object like read the object, write the object, create children of the object, delete the object etc.
- SACL - System Access Control List - This is the second ACL on all AD objects and it's actually to do with writing/reading audit entries for the object. We won't be worrying about this one too much
- LDAP - Lightweight Directory Access Protocol - a standards-defined way of storing information in a directory repository. Usually used just for users and domains but actually a very efficient way of storing many types of hierarchical data.
- AD Schema - the definition of all the object types in the actual AD repository for a domain (or instance, if using ADAM)
That should be all we need to know for the moment... lets start thinking about what our .NET namespace is.
System.DirectoryServices
The key class that we'll be using as we go through these blog posts is the DirectoryEntry class. Every object within the AD repository is represented as a DirectoryEntry. How does this work when AD stores everything from computer definitions to users to documents? Well, the DirectoryEntry class has a property called 'SchemaClassName' which defines what sort of entry it is. This SchemaClassName will map to an object that you can look up in the AD schema. So the DirectoryEntry is really just a generic container for various types of data in AD.
A DirectoryEntry has lots of properties and methods, some of which we'll cover as we go, but for now suffice it to say that if you want to write some samples and tests then you can get a DirectoryEntry with literally one line of code using its constuctor, like so (replacing the options in square brackets with their values:
DirectoryEntry oEntry = new DirectoryEntry([LDAP path], [username], [password]);
e.g.
DirectoryEntry oEntry = new DirectoryEntry("LDAP://localhost/CN=SomeContainer,OU=mydomain,OU=com", "administrator", "password99");
Remember to add the 'using' statement to DirectoryServices and include any relevant DLL references when playing with examples.
Next post - Part 2 - How to read, filter and understand the ACL for a DirectoryEntry object