Everybody tries to be unique – to be or to do something to make us unique among others. Even if we are not doing this intentionally this just happens. Everybody also has something which identifies them among others, this is our name, hair color, face, character – in real world we are unique because of all these elements combined togheter, but this is not so simple in Identity Management world. Our identity in digital represenation as it is considered in IdM projects is defined by a set of attriubtes, which also makes it unique among other digital identites which are managed in the same organization, but sudenlly we have to create digital representation of our identity in some directory – this can be LDAP directory, database, application etc. In most cases, in such directory we have to obey to some naming rules\conventions which can cause naming conflicts. We can take some steps to minimize the risk of such conflict and we should always consider possibility of such conflict when new identity representation is being created.
For above reasons in almost every IdM project there is a need to generate unique values which has to be used as DN or login names for users – it can be real pain in .$$ to get unique value for attriubte sometime. Because I work mostly with MIIS and other MS technologies I will use MIIS and .NET routines in my examples presented below, but I think that even if somebody who is reading this is not using MIIS, this post can be also considered as more general.
Consider generating SAM account name value for Active Directory users as an example. SAM account name is a name which is used to unique identify the user in AD domain during the logon process etc. You can construct this value based on many different factors, but most common is using surename and givenName of user, with some constraints like:
- maximum length: max length for attribute is 20 characters, but often shorter value is used
- order of elements and number of characters taken from each component of source attributes.
So lets assume that we have to meet following conditions for sAMAccountName value:
- max length: 20 characters
- if surename is longer then 10 characters, we are using first letter of givenname , '.' and surename, in other case we are trying to use givenname + '.' + surename format,
- if generated value isn't unique we can try to make it unique by appendign number from 0-9 at the end of it.
If we have a new value we have to test its uniquity – we can use Utils.FindMVEntries meathod to perform search through metaverse in hunt for duplicated value for newly generated sAMAccountName value (or any other unique value we are searching for like CN) .
Few notes from the field here. For sAMAccountName value You have to remeber to strip any accent characters from this attribute if You can find there any. There are different methds to do this but I learnt simply trick which maybe I will post here if I get permission from its author :).
For CN value accent characters can be used but it should be stripped when we would like to perform search.
What You may want to consider also is a scope of uniqness for our new value – for sAMAccountName we have to make sure that it is unique in whole domain becasue AD will not let us create value which is used by another account. But … if we will take a look at CN value, it doesn't have to be unique in the moment of creation in whole domain, it has to be unique in its container only. Should we take care to make it unique in whole domain? Yes, if we are considerig possibility that object can be moved to other container – it may conflict there with other value.
How we can generate value unique for whole domain usng provisioning code in MIIS extension? We have to have these attributes in metaverse space available in some way because in most cases unique value will be generated in provisioning code, and this is a place where we can search Metaverse space with FindMVEntries. so maybe we should consider projection to metaverse all objects from connected systems (like AD) and their attributes which may be needed to generate unique value, even if we do not manage these objects directly. Just to get their sAMAccountName or CN value in a role of placeholders in some metaverse atribute. To keep it clear we can project these connectors to other class of MV objects then our base objects.
After all, if we have engine to generate unique value for attribute, we have to put this into work with some routine, which will let us judge if generated value is unique – where uniquity terms are defined by ourselvs. In most cases such routine will perform following steps:
- Generate new value as a proposal
- Search for this value in metaverse using search logic – this is a place when we can set some terms of uniquity for our solution. If we want to make such search effective we should also remeber to hold in some structure values generated in current provisioning turn, because they will not get exported \ imported in this provisioning cycle. Some structure initialized with our provisioning extension is a good place to hold these values.
- If value is unique, use it -> If not, go back to step 1 and try to generate new value.
- If repeating value generation step is not possible bcause we've reached our uniques boundries (we can't add more numbers to generated sAMAccountName because it is getting too long) -> rise an exception.
A the very end, if we have a new name for our digital entity, which we belive should be unique in its new home we can try to export this to its destination. Even if we are strongly convinced that all possible efforts was done to generate new, unique value there can be always conflict at the provisioning\export phase. This is because MIIS lives in "statefull" world, and something can be in connector space which is not present in MV at the time we are performing new object creation.
Because of this we should handle possible ObjectAlreadyExistException with try\catch section:
(...) provisioning code (...)
(...) exception handling routine (...)
Seems obvious – but will let us handle possible conflicts.
One highlight here – If in exception handling routine new exception will be thrown, please make sure that stack information from original exception is attached in its message. This is extremly helpful later in debugging process.
I think that this is all in this part :). I hope I haven't make any of my readers bored to death :). I know that this topic is covered on MSDN and in developer reference (I think I saw it there), but I've tried to put some my additional thoughts in this post. Maybe it will make somebody's first steps with MIIS and IdM easier.
I think I need some non-technical content in this blog as well – as I'm not only tech guy :). And in the tech area I need some more DS related content as it is still something which keeps me in IT area.
Credits: I wasn't born with this all thoughts and knowledge – which in fact still needs some development to be done – in few places I needed a 'push' in right direction, and I had received so many 'pushes' from two very, very bright guys with whom I have a chance to work togheter. So, Janek and Borys – credits for these post are for both of You!!!
7 thoughts on “MIIS newbie tales (part 2) – desire for uniquity.”
Well Tomek, As usual great post, I really enjoyed this on and the code is great too!! You are soon going to become the person I come to ask about MIIS!! Its great to have such quality posters on Dirteam.com! Carlos
I'm struggling with a current re-design of the MetaVerse concepts. Everything works hunky dory today, but because of the the requirement to have ALL the availiable users in the MV to use the findMV function I use 2 seperate MIIS instances. 1 to provision new acounts where the AD accounts are projected into the MV. the 2nd is projected from a unique ID (the Correlation ID…Thanks Markus for the excellent paper) system which all other connected systems will join on. I would like to combine these into a single system, and to do so I'd have to project all of the AD accounts as a different object Type, then join them to the person object based on the uID. This would allow me to use the findMV for uniqueness. This would basically kill the use of the joiner console since all uIDs and AD accounts would already exist in the MV as different object types. Or I am thinking of doing a very naughty thing: Calling a external function to test the name against the AD itself to see if the name is unique. This is normally not a good idea since it's a performance pig. Yet this function would only be called on the provision action which would be trigger only by the provisioning system. This would allow me to only connect in the AD accounts that joined on the MV object. With the amount of new accounts provisoned a week (200-300) this process would only be called that many times out of 10's of thousnds of runs a week. While this seems counter intuituve, it seems like the simpler process to maintain if the external function is coded correctly.
Hi jef, As You can see we all are struggling with similiar dificulties in our projects. Personally, I don't like idea of code which is accessing external data source from MV or MA extensions. Regarding your problem – I think You have to take following approach: – join all AD accounts to aproperiate identites in MV space, flow their samAccountNames and CNs to some multivalued attribute (I'm assuming that user can have more then one AD account) – project all accounts which are not joined to some other MV object type and flow samaccount name and cn to some attributes. Write a piece of code which will search for unique samaccount or CN on base MV object class and this auxiliary class created for uniquity pourposes only. This is simple function which performs two searches and makes decision based on this searches results. Remeber that You have to take under consideration also names form current provisioning cycle. But .. it may be required to develop some way to consider this object projected to MV only for uniqness pourposes as candidates for regular join, of cousre this can be done but this is a story probably for another MIIS newbie tale.
I guess the piece I am struggling with is if I were to project non-joined AD accounts as a secondary object type to maintain their names in the MV, how to remediate them.
The Joiner is nice for "Simple" manual joins, but we had to write custom web consoles for remediation with a bit more logic to help people doing remediation. (IE Joe and Joseph could be considered the same name, etc.). So I suppose I am not losing out on much if I won't be able to use it if all objects are in the MV.
Currently these unjoined accounts do not have the unique ID on them, so they cannot join the "person" object. I suppose it would be as simple as check to see if the unique ID field has changed, disconnect the object from the MV, which would make it possible to have to evaluated to join the main person object once that uID was added to the AD account.
I do something similar today where I only bring in the primary AD ID into the MV object based on rather complex logic (comparisons of last used account, create time, etc.). This is the AD ID thati s provided to all other systems, but all other data can flow back to the connected AD objects that are not primary (IE Admin, secondary accounts).
The difference is those secondary AD objects sit only in the CS, and not in the MV. Thinking about this now, it wouldn't be that much of a different approach except I would have all of the AD accounts as a different object type to use the findMV function.
Unfortunately due to bad historical practices, some unique IDs (people) have upto 174 AD accounts. 🙁 We are in a state of remediation now though. 🙂
I was not thrilled about the external idea which is why I had the second system doing the provisioning of accounts into AD, while the first one simply synchronizes data connected to the unique ID. I was concerned about network issues with calling the external directory at provision time, etc.
I'm doing this exactly in this manner – all AD (and other systems accounts are projected to two different types of objects in MC – person and disconnected person. Disconnectedperson is for any CS object which doesn't meet joining criteria (which is some kind of employeeID). If something changes in EmployeeIDs (for example new employeeID will show up in HR system or employee ID is filled in this CS entry I'm disconnecting it to be once again evaluated for join criteria. It requires very simple provisioning code.
a jaki ładny angielski…. a jaka mądra treść…. a jakie pochwały….. o w mordę…. Nic tylko gratulować! 🙂
Dzieki, mam nadzieję że Tobie zawartość też się na coś przyda.
Comments are closed.